Re: XEMBED System Tray (resend)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Of course, the fact that it doesn't seem to build anymore might have
something to do with that. Not sure what happened there.....

This one hopefully works....

On Thu, 2003-08-21 at 15:20, Mike Hearn wrote:
> [ this version of the patch was dropped, so bumping it to the top of the queue again ]
> 
> Last time I submitted this, it was dropped because of the non-thread
> safe global array. Doing some more work on this last night, I realised
> it was pointless anyway, as the tray applet will destroy any windows
> when it's deleted (ie if you remove it then readd it, we'd have to
> reconstruct any tray windows). I talked to andersca - he said that the
> EggTrayIcon code doesn't deal with this situation either, and that the
> upcoming XFIXES extension would let us deal with that scenario more
> intelligently.
> 
> Therefore, I removed the relevant code, as it was unlikely to work
> properly without a lot more work.
> 
> ChangeLog:
> Implement support for XEMBED system tray areas
Index: dlls/shell32/systray.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/systray.c,v
retrieving revision 1.20
diff -u -r1.20 systray.c
--- dlls/shell32/systray.c	24 Nov 2002 22:16:29 -0000	1.20
+++ dlls/shell32/systray.c	21 Aug 2003 16:39:29 -0000
@@ -1,11 +1,11 @@
 /*
- *	Systray
+ * System tray handling code (client side)
  *
- *	Copyright 1999 Kai Morich	<kai.morich@bigfoot.de>
+ * Copyright 1999 Kai Morich   <kai.morich@bigfoot.de>
+ * Copyright 2003 Mike Hearn   <mike@theoretic.com>
  *
- *  Manage the systray window. That it actually appears in the docking
- *  area of KDE or GNOME is delegated to windows/x11drv/wnd.c,
- *  X11DRV_WND_DockWindow.
+ * This code creates a window with the WS_EX_TRAYWINDOW style. The actual
+ * environment integration code is handled inside the X11 driver.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -37,21 +37,21 @@
 #include "commctrl.h"
 #include "wine/debug.h"
 
-WINE_DEFAULT_DEBUG_CHANNEL(shell);
+WINE_DEFAULT_DEBUG_CHANNEL(systray);
 
 typedef struct SystrayItem {
   HWND                  hWnd;
   HWND                  hWndToolTip;
   NOTIFYICONDATAA       notifyIcon;
+  CRITICAL_SECTION      lock;
   struct SystrayItem    *nextTrayItem;
 } SystrayItem;
 
-static SystrayItem *systray=NULL;
-static int firstSystray=TRUE; /* defer creation of window class until first systray item is created */
+static SystrayItem *systray = NULL;
+static int          firstSystray = TRUE; /* defer creation of window class until first systray item is created */
 
 static BOOL SYSTRAY_Delete(PNOTIFYICONDATAA pnid);
 
-
 #define ICON_SIZE GetSystemMetrics(SM_CXSMICON)
 /* space around icon (forces icon to center of KDE systray area) */
 #define ICON_BORDER  4
@@ -69,21 +69,26 @@
 {
   HDC hdc;
   PAINTSTRUCT ps;
-
+  TRACE("hwnd=%p, msg=0x%x\n", hWnd, message);
   switch (message) {
   case WM_PAINT:
   {
     RECT rc;
     SystrayItem  *ptrayItem = systray;
-
+    int top;
+    EnterCriticalSection(&ptrayItem->lock);
+    
     while (ptrayItem) {
       if (ptrayItem->hWnd==hWnd) {
 	if (ptrayItem->notifyIcon.hIcon) {
 	  hdc = BeginPaint(hWnd, &ps);
 	  GetClientRect(hWnd, &rc);
-	  if (!DrawIconEx(hdc, rc.left+ICON_BORDER, rc.top+ICON_BORDER, ptrayItem->notifyIcon.hIcon,
+	  /* calculate top so we can deal with arbitrary sized trays */
+	  top = ((rc.bottom-rc.top)/2) - ((ICON_SIZE)/2);
+	  if (!DrawIconEx(hdc, (ICON_BORDER/2), top, ptrayItem->notifyIcon.hIcon,
 			  ICON_SIZE, ICON_SIZE, 0, 0, DI_DEFAULTSIZE|DI_NORMAL)) {
 	    ERR("Paint(SystrayWindow %p) failed -> removing SystrayItem %p\n", hWnd, ptrayItem);
+	    LeaveCriticalSection(&ptrayItem->lock);
 	    SYSTRAY_Delete(&ptrayItem->notifyIcon);
 	  }
 	}
@@ -92,10 +97,10 @@
       ptrayItem = ptrayItem->nextTrayItem;
     }
     EndPaint(hWnd, &ps);
+    LeaveCriticalSection(&ptrayItem->lock);
   }
   break;
 
-  case WM_MOUSEMOVE:
   case WM_LBUTTONDOWN:
   case WM_LBUTTONUP:
   case WM_RBUTTONDOWN:
@@ -105,7 +110,7 @@
   {
     MSG msg;
     SystrayItem *ptrayItem = systray;
-
+    /* relay the event to the tooltip */
     while ( ptrayItem ) {
       if (ptrayItem->hWnd == hWnd) {
         msg.hwnd=hWnd;
@@ -121,14 +126,14 @@
       ptrayItem = ptrayItem->nextTrayItem;
     }
   }
-  /* fall through */
+  /* fall through, so the message is sent to the callback as well */
 
   case WM_LBUTTONDBLCLK:
   case WM_RBUTTONDBLCLK:
   case WM_MBUTTONDBLCLK:
   {
     SystrayItem *ptrayItem = systray;
-
+    /* iterate over the currently active tray items */
     while (ptrayItem) {
       if (ptrayItem->hWnd == hWnd) {
 	if (ptrayItem->notifyIcon.hWnd && ptrayItem->notifyIcon.uCallbackMessage) {
@@ -145,6 +150,14 @@
   }
   break;
 
+  case WM_NOTIFYFORMAT:
+  {
+    TRACE("Received WM_NOTIFYFORMAT, showing the tray window\n");
+    ShowWindow(hWnd, SW_SHOW);
+    return (DefWindowProcA(hWnd, message, wParam, lParam));
+  }
+
+  
   default:
     return (DefWindowProcA(hWnd, message, wParam, lParam));
   }
@@ -176,30 +189,21 @@
 }
 
 
-BOOL SYSTRAY_ItemInit(SystrayItem *ptrayItem)
-{
+DWORD WINAPI SYSTRAY_ThreadProc(LPVOID p1) {
+  SystrayItem *ptrayItem = (SystrayItem *)p1;
+  MSG msg;
   RECT rect;
-
-  /* Register the class if this is our first tray item. */
-  if ( firstSystray ) {
-    firstSystray = FALSE;
-    if ( !SYSTRAY_RegisterClass() ) {
-      ERR( "RegisterClass(WineSystray) failed\n" );
-      return FALSE;
-    }
-  }
-
+  
   /* Initialize the window size. */
   rect.left   = 0;
   rect.top    = 0;
   rect.right  = ICON_SIZE+2*ICON_BORDER;
   rect.bottom = ICON_SIZE+2*ICON_BORDER;
 
-  ZeroMemory( ptrayItem, sizeof(SystrayItem) );
   /* Create tray window for icon. */
   ptrayItem->hWnd = CreateWindowExA( WS_EX_TRAYWINDOW,
                                 "WineSystray", "Wine-Systray",
-                                WS_VISIBLE,
+                                0,
                                 CW_USEDEFAULT, CW_USEDEFAULT,
                                 rect.right-rect.left, rect.bottom-rect.top,
                                 0, 0, 0, 0 );
@@ -217,31 +221,72 @@
     ERR( "CreateWindow(TOOLTIP) failed\n" );
     return FALSE;
   }
+
+  /* Enter the message loop */
+  while (GetMessageA (&msg, 0, 0, 0) > 0) {
+    TranslateMessage (&msg);
+    DispatchMessageA (&msg);
+  }
+  
+  TRACE("Shutting down system tray thread\n");
+  if(ptrayItem->notifyIcon.hIcon)
+     DestroyIcon(ptrayItem->notifyIcon.hIcon);
+  if(ptrayItem->hWndToolTip)
+     DestroyWindow(ptrayItem->hWndToolTip);
+ 
+  return 0;
+}
+
+BOOL SYSTRAY_ItemInit(SystrayItem *ptrayItem)
+{
+  DWORD threadID;
+  
+  /* Register the class if this is our first tray item. */
+  if ( firstSystray ) {
+    firstSystray = FALSE;
+    if ( !SYSTRAY_RegisterClass() ) {
+      ERR( "RegisterClass(WineSystray) failed\n" );
+      return FALSE;
+    }
+  }
+
+  ZeroMemory( ptrayItem, sizeof(SystrayItem) );
+
+  /* We need to run the system tray window in a separate thread, as otherwise if the originating thread
+     stops processing messages, the tray window will hang. If another part of the application then does
+     for instance a FindWindow call, this can deadlock the application. */
+  InitializeCriticalSection(&ptrayItem->lock);
+  if (!CreateThread(NULL, 0, SYSTRAY_ThreadProc, (LPVOID) ptrayItem, 0, &threadID)) {
+    ERR("Could not create system tray item thread\n");
+    return FALSE;
+  }
   return TRUE;
 }
 
 
 static void SYSTRAY_ItemTerm(SystrayItem *ptrayItem)
 {
-  if(ptrayItem->notifyIcon.hIcon)
-     DestroyIcon(ptrayItem->notifyIcon.hIcon);
-  if(ptrayItem->hWndToolTip)
-      DestroyWindow(ptrayItem->hWndToolTip);
-  if(ptrayItem->hWnd)
-    DestroyWindow(ptrayItem->hWnd);
+  /* MSDN says we shouldn't do this, but I can't see another way to make GetMessage() return zero */
+  PostMessageA(ptrayItem->hWnd, WM_QUIT, 0, 0);
+  DeleteCriticalSection(&ptrayItem->lock);
   return;
 }
 
 
 void SYSTRAY_ItemSetMessage(SystrayItem *ptrayItem, UINT uCallbackMessage)
 {
+  EnterCriticalSection(&ptrayItem->lock);
   ptrayItem->notifyIcon.uCallbackMessage = uCallbackMessage;
+  LeaveCriticalSection(&ptrayItem->lock);
 }
 
 
 void SYSTRAY_ItemSetIcon(SystrayItem *ptrayItem, HICON hIcon)
 {
+  EnterCriticalSection(&ptrayItem->lock);
   ptrayItem->notifyIcon.hIcon = CopyIcon(hIcon);
+  LeaveCriticalSection(&ptrayItem->lock);
+  
   InvalidateRect(ptrayItem->hWnd, NULL, TRUE);
 }
 
@@ -250,9 +295,11 @@
 {
   TTTOOLINFOA ti;
 
-  strncpy(ptrayItem->notifyIcon.szTip, szTip, sizeof(ptrayItem->notifyIcon.szTip));
+  EnterCriticalSection(&ptrayItem->lock);  
+  strncpy(ptrayItem->notifyIcon.szTip, szTip, sizeof(ptrayItem->notifyIcon.szTip)); 
   ptrayItem->notifyIcon.szTip[sizeof(ptrayItem->notifyIcon.szTip)-1]=0;
-
+  LeaveCriticalSection(&ptrayItem->lock);
+  
   ti.cbSize = sizeof(TTTOOLINFOA);
   ti.uFlags = 0;
   ti.hwnd = ptrayItem->hWnd;
Index: dlls/x11drv/window.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/window.c,v
retrieving revision 1.55
diff -u -r1.55 window.c
--- dlls/x11drv/window.c	9 Jul 2003 04:22:57 -0000	1.55
+++ dlls/x11drv/window.c	21 Aug 2003 16:39:36 -0000
@@ -4,6 +4,7 @@
  * Copyright 1993, 1994, 1995, 1996, 2001 Alexandre Julliard
  * Copyright 1993 David Metcalfe
  * Copyright 1995, 1996 Alex Korobka
+ * Copyright 2003 Mike Hearn
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -24,6 +25,7 @@
 
 #include <stdlib.h>
 #include <unistd.h>
+#include <stdio.h>
 
 #include "ts_xlib.h"
 #include <X11/Xresource.h>
@@ -42,6 +44,7 @@
 #include "mwm.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
+WINE_DECLARE_DEBUG_CHANNEL(systray);
 
 extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP );
 
@@ -55,6 +58,7 @@
 Atom wmProtocols = None;
 Atom wmDeleteWindow = None;
 Atom wmTakeFocus = None;
+Atom wmManager = None;
 Atom dndProtocol = None;
 Atom dndSelection = None;
 Atom wmChangeState = None;
@@ -62,12 +66,23 @@
 Atom kwmDockWindow = None;
 Atom netwmPid = None;
 Atom netwmPing = None;
+Atom netSysTraySelection = None;
+Atom netSysTrayOpcode = None;
+Atom xembedInfo = None;
+Atom xembed = None;
 Atom _kde_net_wm_system_tray_window_for = None; /* KDE 2 Final */
 
+Window systrayWindow;
+
 static LPCSTR whole_window_atom;
 static LPCSTR client_window_atom;
 static LPCSTR icon_window_atom;
 
+#define SYSTEM_TRAY_REQUEST_DOCK    0
+#define SYSTEM_TRAY_BEGIN_MESSAGE   1
+#define SYSTEM_TRAY_CANCEL_MESSAGE  2
+
+
 /***********************************************************************
  *		is_window_managed
  *
@@ -315,11 +330,59 @@
             size_hints->min_height = size_hints->max_height;
             size_hints->flags |= PMinSize | PMaxSize;
         }
+	if (win->dwExStyle & WS_EX_TRAYWINDOW) {
+	  /* force the window to be the correct width */
+	  size_hints->min_width = GetSystemMetrics(SM_CXSMICON) + 5; /* give some padding to make icons not bunched up */
+	}
         XSetWMNormalHints( display, data->whole_window, size_hints );
         XFree( size_hints );
     }
 }
 
+/***********************************************************************
+ *              X11DRV_systray_dock_window
+ *
+ * Docks the given X window with the NETWM system tray.
+ */
+BOOL CALLBACK X11DRV_systray_dock_window( HWND hwnd, Display *display ) {
+  WND* win = WIN_GetPtr((HWND)hwnd);
+  struct x11drv_win_data *data = win->pDriverData;  
+  XEvent ev;
+  unsigned long info[2];
+  LONG exstyle;
+
+  /* is the window a tray window? */
+  if (IsWindowUnicode(hwnd))
+    exstyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
+  else
+    exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
+  if ( !(exstyle & WS_EX_TRAYWINDOW) ) return TRUE;
+  
+  TRACE_(systray)("Docking tray icon 0x%x\n", (int)hwnd);
+  wine_tsx11_lock();
+  
+  /* set XEMBED protocol data on the window */
+  info[0] = 0; /* protocol version */
+  info[1] = 0; /* mapped = true */
+  XChangeProperty(display, data->whole_window, xembedInfo, xembedInfo, 32, PropModeReplace, (unsigned char*)info, 2);
+
+  /* send the docking request message */
+  memset(&ev, 0, sizeof(ev));
+  ev.xclient.type = ClientMessage;
+  ev.xclient.window = systrayWindow;
+  ev.xclient.message_type = netSysTrayOpcode;
+  ev.xclient.format = 32;
+  ev.xclient.data.l[0] = CurrentTime;
+  ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
+  ev.xclient.data.l[2] = data->whole_window;
+  XSendEvent(display, systrayWindow, False, NoEventMask, &ev);
+  XSync(display, False);
+  wine_tsx11_unlock();
+
+  WIN_ReleasePtr(win);
+  return TRUE;
+}
+
 
 /***********************************************************************
  *              X11DRV_set_wm_hints
@@ -365,16 +428,19 @@
     /* size hints */
     set_size_hints( display, win );
 
-    /* systray properties (KDE only for now) */
+    /* systray properties */
     if (win->dwExStyle & WS_EX_TRAYWINDOW)
     {
         int val = 1;
-        if (kwmDockWindow != None)
+
+	if (systrayWindow == None) {
+	  if (kwmDockWindow != None)
             XChangeProperty( display, data->whole_window, kwmDockWindow, kwmDockWindow,
                              32, PropModeReplace, (char*)&val, 1 );
-        if (_kde_net_wm_system_tray_window_for != None)
+	  if (_kde_net_wm_system_tray_window_for != None)
             XChangeProperty( display, data->whole_window, _kde_net_wm_system_tray_window_for,
                              XA_WINDOW, 32, PropModeReplace, (char*)&data->whole_window, 1 );
+	}
     }
 
     /* set the WM_CLIENT_MACHINE and WM_LOCALE_NAME properties */
@@ -403,7 +469,7 @@
         if (win->dwStyle & WS_SYSMENU)  mwm_hints.decorations |= MWM_DECOR_MENU;
         if (win->dwStyle & WS_MINIMIZEBOX) mwm_hints.decorations |= MWM_DECOR_MINIMIZE;
         if (win->dwStyle & WS_MAXIMIZEBOX) mwm_hints.decorations |= MWM_DECOR_MAXIMIZE;
-
+	
         XChangeProperty( display, data->whole_window, mwmHints, mwmHints, 32,
                          PropModeReplace, (char*)&mwm_hints, sizeof(mwm_hints)/sizeof(long) );
     }
@@ -542,6 +608,7 @@
                 /* should use stack_mode Below but most window managers don't get it right */
                 /* so move it above the next one in Z order */
                 HWND next = GetWindow( win->hwndSelf, GW_HWNDNEXT );
+
                 while (next && !(GetWindowLongW( next, GWL_STYLE ) & WS_VISIBLE))
                     next = GetWindow( next, GW_HWNDNEXT );
                 if (next)
@@ -651,7 +718,8 @@
 static void create_desktop( Display *display, WND *wndPtr )
 {
     X11DRV_WND_DATA *data = wndPtr->pDriverData;
-
+    char *buffer;
+    
     wine_tsx11_lock();
     winContext     = XUniqueContext();
     wmProtocols    = XInternAtom( display, "WM_PROTOCOLS", False );
@@ -665,6 +733,18 @@
     _kde_net_wm_system_tray_window_for = XInternAtom( display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False );
     netwmPid = XInternAtom( display, "_NET_WM_PID", False );
     netwmPing = XInternAtom( display, "_NET_WM_PING", False );
+    xembedInfo = XInternAtom( display, "_XEMBED_INFO", False );
+    xembed = XInternAtom( display, "_XEMBED", False );
+    systrayWindow = None;
+    
+    /* get system tray atoms */
+    buffer = malloc(sizeof(char)*20);
+    sprintf(buffer, "_NET_SYSTEM_TRAY_S%d", DefaultScreen(display));
+    netSysTraySelection = XInternAtom(display, buffer, False);
+    free(buffer);
+    netSysTrayOpcode = XInternAtom(display, "_NET_SYSTEM_TRAY_OPCODE", False);
+    wmManager = XInternAtom(display, "MANAGER", False);
+    
     wine_tsx11_unlock();
 
     whole_window_atom  = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_whole_window" ));
@@ -679,6 +759,8 @@
     SetPropA( wndPtr->hwndSelf, "__wine_x11_visual_id", (HANDLE)XVisualIDFromVisual(visual) );
 
     if (root_window != DefaultRootWindow(display)) X11DRV_create_desktop_thread();
+    /* notify us of manager events, so we can monitor for system tray managers */
+    if (root_window == DefaultRootWindow(display)) XSelectInput(display, root_window, StructureNotifyMask);
 }
 
 
@@ -949,7 +1031,7 @@
     }
 
     /* Send the WM_GETMINMAXINFO message and fix the size if needed */
-    if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
+    if (((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD))) && !(cs->dwExStyle & WS_EX_TRAYWINDOW))
     {
         POINT maxSize, maxPos, minTrack, maxTrack;
 
@@ -1044,7 +1126,7 @@
     }
 
     /* Show the window, maximizing or minimizing if needed */
-
+    
     if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
     {
         extern UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ); /*FIXME*/
@@ -1064,6 +1146,13 @@
      * we do a proper ShowWindow later on */
     if (wndPtr->dwStyle & WS_VISIBLE) cs->style |= WS_VISIBLE;
 
+    /* if it's a tray window, dock it */
+    if (wndPtr->dwExStyle & WS_EX_TRAYWINDOW) {
+      /* get the tray window if present */
+      systrayWindow = XGetSelectionOwner(display, netSysTraySelection);
+      if (systrayWindow != None)
+	X11DRV_systray_dock_window(hwnd, display);
+    }
     WIN_ReleaseWndPtr( wndPtr );
     return TRUE;
 
@@ -1231,8 +1320,9 @@
 
         /* we must not use CurrentTime (ICCCM), so try to use last message time instead */
         /* FIXME: this is not entirely correct */
+        /* NOTE - not using CurrentTime here causes focus problems with some fullscreen apps */
         XSetInputFocus( display, win, RevertToParent,
-                        /*CurrentTime*/ GetMessageTime() + X11DRV_server_startticks );
+                        CurrentTime /* GetMessageTime() + X11DRV_server_startticks */ );
         if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
             XInstallColormap( display, X11DRV_PALETTE_PaletteXColormap );
     }
Index: dlls/x11drv/event.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/event.c,v
retrieving revision 1.22
diff -u -r1.22 event.c
--- dlls/x11drv/event.c	8 Jul 2003 21:02:51 -0000	1.22
+++ dlls/x11drv/event.c	21 Aug 2003 16:39:41 -0000
@@ -3,6 +3,7 @@
  *
  * Copyright 1993 Alexandre Julliard
  *	     1999 Noel Borthwick
+ *           2003 Mike Hearn
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -34,6 +35,7 @@
 
 #include <assert.h>
 #include <string.h>
+#include <stdio.h>
 #include "wine/winuser16.h"
 #include "shlobj.h"  /* DROPFILES */
 
@@ -47,6 +49,7 @@
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(event);
+WINE_DECLARE_DEBUG_CHANNEL(systray);
 WINE_DECLARE_DEBUG_CHANNEL(clipboard);
 
 /* X context to associate a hwnd to an X window */
@@ -54,9 +57,14 @@
 
 extern Atom wmProtocols;
 extern Atom wmDeleteWindow;
+extern Atom wmManager;
 extern Atom dndProtocol;
 extern Atom dndSelection;
 extern Atom netwmPing;
+extern Atom netSysTraySelection;
+extern Atom xembed;
+
+extern Window systrayWindow;
 
 #define DndNotDnd       -1    /* OffiX drag&drop */
 #define DndUnknown      0
@@ -106,6 +114,7 @@
 extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
 extern void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
 extern void X11DRV_MappingNotify( XMappingEvent *event );
+extern void X11DRV_systray_dock_all( Display* display );
 
 #ifdef HAVE_LIBXXF86DGA2
 static int DGAMotionEventType;
@@ -275,7 +284,10 @@
   wine_tsx11_unlock();
   if (!hWnd && event->xany.window == root_window) hWnd = GetDesktopWindow();
 
-  if (!hWnd && event->type != PropertyNotify && event->type != MappingNotify)
+  if ( !hWnd && event->xany.window != root_window
+             && event->type != PropertyNotify
+             && event->type != MappingNotify
+             && event->type != ClientMessage)
       WARN( "Got event %s for unknown Window %08lx\n",
             event_names[event->type], event->xany.window );
   else
@@ -338,7 +350,6 @@
       break;
 
     case ClientMessage:
-      if (!hWnd) return;
       EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
       break;
 
@@ -1202,8 +1213,49 @@
  */
 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
 {
+  TRACE("called\n");
   if (event->message_type != None && event->format == 32) {
-    if (event->message_type == wmProtocols)
+    if (event->message_type == wmManager) {
+	if (event->data.l[1] == netSysTraySelection) {
+	    TRACE_(systray)("New NETWM systray manager detected, id=%ld\n", event->data.l[2]);
+	    /* NOTE: It turns out that the ability to detect when a new tray applet joins the
+	     * desktop is not as helpful as you might think. In order to do something useful with it,
+	     * we would need to be able to "store" icons unmapped as children of the root window while
+	     * no tray applet is available.
+	     *
+	     * The basic problem is that tray icons are always destroyed when the applet is removed.
+	     * This is apparently an issue with X itself, which the upcoming XFIXES extension should hopefully
+	     * address. The EggTrayIcon code which will be soon moving into GTK+ doesn't attempt to handle this
+	     * situation, so for now neither do we.
+	     *
+	     * This is theoretically fixable in Wine with enough work, we just have to modify the code in
+	     * shell32/systray.c to save the image and recreate the window on demand. Exactly how the
+	     * communication between the x11drv and shell32 takes place is left as an excercise for the
+	     * reader.
+	     *                         -mike (3rd August 2003)
+	     */
+	}
+    } else if (event->message_type == xembed) {
+        char* opcode;
+	switch (event->data.l[1]) {
+	  case 0: opcode = "XEMBED_EMBEDDED_NOTIFY"; break;
+	  case 1: opcode = "XEMBED_WINDOW_ACTIVATE"; break;
+	  case 2: opcode = "XEMBED_WINDOW_DEACTIVATE"; break;
+	  case 3: opcode = "XEMBED_REQUEST_FOCUS"; break;
+	  case 4: opcode = "XEMBED_FOCUS_IN"; break;
+	  case 5: opcode = "XEMBED_FOCUS_OUT"; break;
+	  case 6: opcode = "XEMBED_FOCUS_NEXT"; break;
+	  case 7: opcode = "XEMEBD_FOCUS_PREV"; break;
+	  case 10: opcode = "XEMBED_MODALITY_ON"; break;
+	  case 11: opcode = "XEMBED_MODALITY_OFF"; break;
+	  case 12: opcode = "XEMBED_REGISTER_ACCELERATOR"; break;
+	  case 13: opcode = "XEMBED_UNREGISTER_ACCELERATOR"; break;
+	  case 14: opcode = "XEMBED_ACTIVATE_ACCELERATOR"; break;
+	  default: opcode = "[Unknown opcode]"; break;
+	}
+        TRACE_(systray)("XEmbed message, opcode is %s : %ld\n", opcode, event->data.l[1]);
+	/* we currently don't handle these messages */
+    } else if (event->message_type == wmProtocols)
         handle_wm_protocols_message( hWnd, event );
     else if (event->message_type == dndProtocol)
     {

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux