This is the mail archive of the cygwin-xfree@cygwin.com mailing list for the Cygwin XFree86 project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] systray icon


Hello everybody,

Here is another patch which adds the "-systray" option. With this option on, instead of adding buttons to the taskbar, it adds icons to the notification area (a.k.a. systray).
To work, there must be a "X.ico" (see attachment) in the same directory than XWin.exe

Left click on the icon shows the window if it was hidden, hide it otherwise.
Right click displays the system menu (there isn't one in fullscreen)

Notes:
- I added a file (winsystray.c) so "make depend" is in order.
- The patch also changes the title to include the screen number. To get the screen number, I'm searching the g_ScreenInfo array. I'm sure there must be a better way to get this number (search for "HACK", there are 3 places).
- The option doesn't work well in fullscreen mode. For some reason, when one click on the systray icon, the application isn't activated (doesn't switch to fullscreen, no WM_ACTIVATEAPP received) but the application still captures the mouse event, it's as if the desktop doesn't respond anymore. For those who try and/or want to fix it (I don't have the beginning of an idea for that so help is welcome), to recover from the "freeze", open the start menu with the "Windows" key, then click outside the menu.
- I fixed a couple typos (CYGDEGUG and missing '\n' for "-lesspointer" usage)
- X.ico would be better off added as a resource to the application instead of an external file (or both if we want to allow customization). Can we do that with cygwin?
- An improvment would be to add the screen number to the icon itself. It would be better than waiting for the tooltip.
- I would like to change the left click behavior. I want it to put the window to the foreground if it was not (hidden behind another window), hide it otherwise. However, when one click on the systray, the systray become the foreground window. Does someone know how to get the handle of the previous foreground window?

Jehan

diff -Naur xc/programs/Xserver/hw/xwin/Imakefile xc/programs/Xserver/hw/xwin/Imakefile
--- xc/programs/Xserver/hw/xwin/Imakefile	2001-11-11 14:45:57.000000000 -0800
+++ xc/programs/Xserver/hw/xwin/Imakefile	2002-06-22 11:08:20.000000000 -0700
@@ -41,7 +41,8 @@
 	winlayer.c \
 	winerror.c \
 	winengine.c \
-	wincreatewnd.c
+	wincreatewnd.c \
+	winsystray.c
 
 OBJS =	InitInput.o \
 	InitOutput.o \
@@ -75,7 +76,8 @@
 	winlayer.o \
 	winerror.o \
 	winengine.o \
-	wincreatewnd.o
+	wincreatewnd.o \
+	winsystray.o
 
 INCLUDES = -I. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
 	   -I$(SERVERSRC)/fb -I$(SERVERSRC)/mi \
diff -Naur xc/programs/Xserver/hw/xwin/InitOutput.c xc/programs/Xserver/hw/xwin/InitOutput.c
--- xc/programs/Xserver/hw/xwin/InitOutput.c	2002-06-14 05:30:20.000000000 -0700
+++ xc/programs/Xserver/hw/xwin/InitOutput.c	2002-06-23 16:35:16.000000000 -0700
@@ -91,6 +91,8 @@
       g_ScreenInfo[i].fFullScreen = FALSE;
       g_ScreenInfo[i].fDecoration = TRUE;
       g_ScreenInfo[i].fLessPointer = FALSE;
+      g_ScreenInfo[i].fSystray = FALSE;
+      g_ScreenInfo[i].uTaskbarRestart = 0;
       g_ScreenInfo[i].iE3BTimeout = WIN_E3B_OFF;
       g_ScreenInfo[i].dwWidth_mm = (dwWidth / WIN_DEFAULT_DPI)
 	* 25.4;
@@ -224,14 +226,18 @@
 	  "\tSet screen scr_num's width and height\n");
 
   ErrorF ("-lesspointer\n"
-	  "\tHide the windows mouse pointer when it is over an inactive "
-          "\tXFree86 window.  This prevents ghost cursors appearing where the "
+	  "\tHide the windows mouse pointer when it is over an inactive\n"
+          "\tXFree86 window.  This prevents ghost cursors appearing where the\n"
           "\tWindows cursor is drawn overtop of the X cursor\n");
 
   ErrorF ("-nodecoration\n"
           "\tDo not draw a window border, title bar, etc.  Windowed\n"
 	  "\tmode only.\n");
 
+  ErrorF ("-systray\n"
+          "\tPut an icon in the status area of the taskbar (a.k.a. systray)\n"
+          "\tand don't show the taskbar button.\n");
+
   ErrorF ("-[no]unixkill\n"
           "\tCtrl+Alt+Backspace exits the X Server\n");
 
@@ -499,6 +505,32 @@
     }
 
   /*
+   * Look for the '-systray' argument
+   */
+  if (strcmp(argv[i], "-systray") == 0)
+    {
+      /* Is this parameter attached to a screen or is it global? */
+      if (-1 == g_iLastScreen)
+	{
+	  int			j;
+
+	  /* Parameter is for all screens */
+	  for (j = 0; j < MAXSCREENS; j++)
+	    {
+	      g_ScreenInfo[j].fSystray = TRUE;
+	    }
+	}
+      else
+	{
+	  /* Parameter is for a single screen */
+	  g_ScreenInfo[g_iLastScreen].fSystray = TRUE;
+	}
+
+      /* Indicate that we have processed this argument */
+      return 1;
+    }
+
+  /*
    * Look for the '-ignoreinput' argument
    */
   if (strcmp(argv[i], "-ignoreinput") == 0)
diff -Naur xc/programs/Xserver/hw/xwin/XWin.man xc/programs/Xserver/hw/xwin/XWin.man
--- xc/programs/Xserver/hw/xwin/XWin.man	2002-06-12 21:39:08.000000000 -0700
+++ xc/programs/Xserver/hw/xwin/XWin.man	2002-06-23 14:31:51.000000000 -0700
@@ -50,6 +50,10 @@
 .B \-nodecoration
 Draw the Cygwin/XFree86 window without a border or title bar.
 .TP 8
+.B \-systray
+Put an icon in the status area of the taskbar (a.k.a. systray) and don't
+show the taskbar button.
+.TP 8
 .B \-lesspointer
 Hide the Windows mouse pointer when over an inactive XFree86 window
 .TP 8
diff -Naur xc/programs/Xserver/hw/xwin/win.h xc/programs/Xserver/hw/xwin/win.h
--- xc/programs/Xserver/hw/xwin/win.h	2002-06-13 07:06:00.000000000 -0700
+++ xc/programs/Xserver/hw/xwin/win.h	2002-06-23 16:38:50.000000000 -0700
@@ -54,12 +54,15 @@
 #define CYGDEBUG		NO
 
 /* Constant strings */
+#define WINDOW_SYSTRAY_CLASS	"cygwin/xfree86 Systray"
 #define WINDOW_CLASS		"cygwin/xfree86"
-#define WINDOW_TITLE		"Cygwin/XFree86"
+#define WINDOW_TITLE		"Cygwin/XFree86 Screen" /* followed by number */
 #define WIN_SCR_PROP		"cyg_screen_prop"
 #define WIN_MSG_QUEUE_FNAME	"/dev/windows"
 #define WIN_LOG_FNAME		"/tmp/XWin.log"
 
+#define WINDOW_TITLE_MAX_LENGTH 255
+
 #define NEED_EVENTS
 
 #define WIN_DEFAULT_WIDTH	640
@@ -118,6 +121,11 @@
 
 #define WIN_MAX_KEYS_PER_KEY	4
 
+#define WIN_SYSTRAY_UID		1
+#define WIN_SYSTRAY_MSG		(WM_USER+1)
+#define X_ICON			"X.ico"
+
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdio.h>
@@ -331,6 +339,8 @@
   Bool			fFullScreen;
   Bool			fDecoration;
   Bool			fLessPointer;
+  Bool			fSystray;
+  UINT			uTaskbarRestart;
   int			iE3BTimeout;
   /* Windows (Alt+F4) and Unix (Ctrl+Alt+Backspace) Killkey */
   Bool                  fUseWinKillKey;
@@ -382,6 +392,9 @@
   HDC			hdcScreen;
   HDC			hdcShadow;
   HWND			hwndScreen;
+
+  /* In systray mode, owner of the window */
+  HWND                  hwndScreenOwner;
   
   /* Privates used by shadow fb and primary fb DirectDraw servers */
   LPDIRECTDRAW		pdd;
@@ -1170,6 +1183,13 @@
 
 
 /*
+ * winsystray.c
+ */
+Bool winSystrayAddIcon (HWND hwnd, UINT uID, LPSTR lpszTip); 
+Bool winSystrayRemoveIcon (HWND hwnd, UINT uID); 
+
+
+/*
  * winwakeup.c
  */
 
@@ -1213,6 +1233,10 @@
  */
 
 LRESULT CALLBACK
+winWindowProcInvisible (HWND hWnd, UINT message, 
+			WPARAM wParam, LPARAM lParam);
+
+LRESULT CALLBACK
 winWindowProc (HWND hWnd, UINT message, 
 	       WPARAM wParam, LPARAM lParam);
 
diff -Naur xc/programs/Xserver/hw/xwin/wincreatewnd.c xc/programs/Xserver/hw/xwin/wincreatewnd.c
--- xc/programs/Xserver/hw/xwin/wincreatewnd.c	2002-06-21 21:04:32.000000000 -0700
+++ xc/programs/Xserver/hw/xwin/wincreatewnd.c	2002-06-23 16:19:03.000000000 -0700
@@ -53,12 +53,47 @@
   int			iWidth = pScreenInfo->dwWidth;
   int			iHeight = pScreenInfo->dwHeight;
   HWND			*phwnd = &pScreenPriv->hwndScreen;
+  HWND			*phwndOwner = &pScreenPriv->hwndScreenOwner;
   WNDCLASS		wc;
+  char			title[WINDOW_TITLE_MAX_LENGTH];
 
 #if CYGDEBUG
   ErrorF ("winCreateBoundingWindowFullScreen ()\n");
 #endif
 
+  
+  /* Build the title for this screen */
+  /* HACK: there must be another/better way to do it (querying X? Or
+     should we add the number to the screenInfo structure?) */
+  int screenNum = 0;
+  for (screenNum = 0; screenNum < MAXSCREENS; screenNum++) {
+    if (g_ScreenInfo+screenNum == pScreenInfo) 
+      break;
+  }
+  snprintf(title, WINDOW_TITLE_MAX_LENGTH, "%s %d", WINDOW_TITLE, screenNum);
+  
+  /*
+   * Remove taskbar button if we use the systray by setting the owner to
+   * an invisible window (must not be the Windows desktop window)
+   */
+  *phwndOwner = NULL;
+  if (pScreenInfo->fSystray)
+    {
+      wc.style = CS_HREDRAW | CS_VREDRAW;
+      wc.lpfnWndProc = winWindowProcInvisible;
+      wc.cbClsExtra = 0;
+      wc.cbWndExtra = 0;
+      wc.hInstance = GetModuleHandle (NULL);
+      wc.hIcon = 0;
+      wc.hCursor = 0;
+      wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
+      wc.lpszMenuName = NULL;
+      wc.lpszClassName = WINDOW_SYSTRAY_CLASS;
+      RegisterClass (&wc);
+        
+      *phwndOwner = CreateWindowExA(0, WINDOW_SYSTRAY_CLASS, "", 0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle (NULL), NULL);
+    }
+
   /* Setup our window class */
   wc.style = CS_HREDRAW | CS_VREDRAW;
   wc.lpfnWndProc = winWindowProc;
@@ -75,17 +110,33 @@
   /* Create the window */
   *phwnd = CreateWindowExA (WS_EX_TOPMOST,	/* Extended styles */
 			    WINDOW_CLASS,	/* Class name */
-			    WINDOW_TITLE,	/* Window name */
+			    title,		/* Window name */
 			    WS_POPUP,
 			    0,			/* Horizontal position */
 			    0,			/* Vertical position */
 			    iWidth,		/* Right edge */ 
 			    iHeight,		/* Bottom edge */
-			    (HWND) NULL,	/* No parent or owner window */
+			    (HWND) *phwndOwner,	/* Owner window */
 			    (HMENU) NULL,	/* No menu */
 			    GetModuleHandle (NULL),/* Instance handle */
 			    pScreenPriv);	/* ScreenPrivates */
 
+  if (*phwnd == NULL)
+    {
+      ErrorF ("winCreateBoundingWindowFullScreen () CreateWindowEx () failed\n");
+      return FALSE;
+    }
+    
+  /*
+   * If displaying an icon in the systray, register to get message if
+   * taskbar crashes and add the icon 
+   */
+  if (pScreenInfo->fSystray) 
+    {
+      winSystrayAddIcon(*phwnd, WIN_SYSTRAY_UID, title);
+      pScreenInfo->uTaskbarRestart = RegisterWindowMessage("TaskbarCreated");
+    }
+
   /* Branch on the server engine */
   switch (pScreenInfo->dwEngine)
     {
@@ -122,9 +173,12 @@
   int			iWidth = pScreenInfo->dwWidth;
   int			iHeight = pScreenInfo->dwHeight;
   HWND			*phwnd = &pScreenPriv->hwndScreen;
+  HWND			*phwndOwner = &pScreenPriv->hwndScreenOwner;
   WNDCLASS		wc;
   RECT			rcClient, rcWorkArea;
   DWORD			dwWindowStyle;
+  char			title[WINDOW_TITLE_MAX_LENGTH];
+  int			screenNum;
   
   /* Initialize window style */
   dwWindowStyle = WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX;
@@ -134,6 +188,29 @@
     dwWindowStyle |= WS_CAPTION;
   else
     dwWindowStyle |= WS_POPUP;
+    
+  /*
+   * Remove taskbar button if we use the systray by setting the owner to
+   * an invisible window (must not be the Windows desktop window)
+   */
+  *phwndOwner = NULL;
+  if (pScreenInfo->fSystray)
+    {
+      wc.style = CS_HREDRAW | CS_VREDRAW;
+      wc.lpfnWndProc = winWindowProcInvisible;
+      wc.cbClsExtra = 0;
+      wc.cbWndExtra = 0;
+      wc.hInstance = GetModuleHandle (NULL);
+      wc.hIcon = 0;
+      wc.hCursor = 0;
+      wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
+      wc.lpszMenuName = NULL;
+      wc.lpszClassName = WINDOW_SYSTRAY_CLASS;
+      RegisterClass (&wc);
+        
+      *phwndOwner = CreateWindowExA(0, WINDOW_SYSTRAY_CLASS, "", 0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle (NULL), NULL);
+    }
+
 
   /* Setup our window class */
   wc.style = CS_HREDRAW | CS_VREDRAW;
@@ -173,16 +250,26 @@
 	  pScreenInfo->dwWidth, pScreenInfo->dwHeight);
 #endif
 
+  /* Build the title for this screen */
+  /* HACK: there must be another/better way to do it (querying X? Or
+     should we add the number to the screenInfo structure?) */
+  for (screenNum = 0; screenNum < MAXSCREENS; screenNum++) {
+    if (g_ScreenInfo+screenNum == pScreenInfo) 
+      break;
+  }
+  snprintf(title, WINDOW_TITLE_MAX_LENGTH, "%s %d", WINDOW_TITLE, screenNum);
+  
+  
   /* Create the window */
   *phwnd = CreateWindowExA (0,			/* Extended styles */
 			    WINDOW_CLASS,	/* Class name */
-			    WINDOW_TITLE,	/* Window name */
+			    title,		/* Window name */
 			    dwWindowStyle,
 			    rcWorkArea.left,	/* Horizontal position */
 			    rcWorkArea.top,	/* Vertical position */
 			    iWidth,		/* Right edge */
 			    iHeight,		/* Bottom edge */
-			    (HWND) NULL,	/* No parent or owner window */
+			    (HWND) *phwndOwner,	/* Owner window */
 			    (HMENU) NULL,	/* No menu */
 			    GetModuleHandle (NULL),/* Instance handle */
 			    pScreenPriv);	/* ScreenPrivates */
@@ -196,6 +283,16 @@
   ErrorF ("winCreateBoundingWindowWindowed () - CreateWindowEx () returned\n");
 #endif
 
+  /*
+   * If displaying an icon in the systray, register to get message if
+   * taskbar crashes and add the icon 
+   */
+  if (pScreenInfo->fSystray) 
+    {
+      winSystrayAddIcon(*phwnd, WIN_SYSTRAY_UID, title);
+      pScreenInfo->uTaskbarRestart = RegisterWindowMessage("TaskbarCreated");
+    }
+    
   /* Get the client area coordinates */
   if (!GetClientRect (*phwnd, &rcClient))
     {
diff -Naur xc/programs/Xserver/hw/xwin/winnativegdi.c xc/programs/Xserver/hw/xwin/winnativegdi.c
--- xc/programs/Xserver/hw/xwin/winnativegdi.c	2001-11-21 00:51:24.000000000 -0800
+++ xc/programs/Xserver/hw/xwin/winnativegdi.c	2002-06-22 16:06:30.000000000 -0700
@@ -68,6 +68,10 @@
   /* Kill our window */
   if (pScreenPriv->hwndScreen)
     {
+      /* Remove icon from the status area */
+      if (pScreenInfo->fSystray) 
+          winSystrayRemoveIcon(pScreenPriv->hwndScreen, WIN_SYSTRAY_UID);
+
       DestroyWindow (pScreenPriv->hwndScreen);
       pScreenPriv->hwndScreen = NULL;
     }
diff -Naur xc/programs/Xserver/hw/xwin/winpfbdd.c xc/programs/Xserver/hw/xwin/winpfbdd.c
--- xc/programs/Xserver/hw/xwin/winpfbdd.c	2002-04-12 21:58:55.000000000 -0700
+++ xc/programs/Xserver/hw/xwin/winpfbdd.c	2002-06-22 16:06:12.000000000 -0700
@@ -277,6 +277,10 @@
   /* Kill our window */
   if (pScreenPriv->hwndScreen)
     {
+      /* Remove icon from the status area */
+      if (pScreenInfo->fSystray) 
+          winSystrayRemoveIcon(pScreenPriv->hwndScreen, WIN_SYSTRAY_UID);
+
       DestroyWindow (pScreenPriv->hwndScreen);
       pScreenPriv->hwndScreen = NULL;
     }
diff -Naur xc/programs/Xserver/hw/xwin/winshaddd.c xc/programs/Xserver/hw/xwin/winshaddd.c
--- xc/programs/Xserver/hw/xwin/winshaddd.c	2002-04-12 21:58:56.000000000 -0700
+++ xc/programs/Xserver/hw/xwin/winshaddd.c	2002-06-22 16:06:00.000000000 -0700
@@ -539,6 +539,10 @@
   /* Kill our window */
   if (pScreenPriv->hwndScreen)
     {
+      /* Remove icon from the status area */
+      if (pScreenInfo->fSystray) 
+          winSystrayRemoveIcon(pScreenPriv->hwndScreen, WIN_SYSTRAY_UID);
+
       DestroyWindow (pScreenPriv->hwndScreen);
       pScreenPriv->hwndScreen = NULL;
     }
diff -Naur xc/programs/Xserver/hw/xwin/winshadddnl.c xc/programs/Xserver/hw/xwin/winshadddnl.c
--- xc/programs/Xserver/hw/xwin/winshadddnl.c	2002-06-07 18:32:13.000000000 -0700
+++ xc/programs/Xserver/hw/xwin/winshadddnl.c	2002-06-22 16:06:38.000000000 -0700
@@ -515,6 +515,10 @@
   /* Kill our window */
   if (pScreenPriv->hwndScreen)
     {
+      /* Remove icon from the status area */
+      if (pScreenInfo->fSystray) 
+          winSystrayRemoveIcon(pScreenPriv->hwndScreen, WIN_SYSTRAY_UID);
+
       DestroyWindow (pScreenPriv->hwndScreen);
       pScreenPriv->hwndScreen = NULL;
     }
diff -Naur xc/programs/Xserver/hw/xwin/winshadgdi.c xc/programs/Xserver/hw/xwin/winshadgdi.c
--- xc/programs/Xserver/hw/xwin/winshadgdi.c	2001-11-21 00:51:24.000000000 -0800
+++ xc/programs/Xserver/hw/xwin/winshadgdi.c	2002-06-22 16:06:24.000000000 -0700
@@ -369,6 +369,10 @@
   /* Kill our window */
   if (pScreenPriv->hwndScreen)
     {
+      /* Remove icon from the status area */
+      if (pScreenInfo->fSystray) 
+          winSystrayRemoveIcon(pScreenPriv->hwndScreen, WIN_SYSTRAY_UID);
+
       DestroyWindow (pScreenPriv->hwndScreen);
       pScreenPriv->hwndScreen = NULL;
     }
diff -Naur xc/programs/Xserver/hw/xwin/winsystray.c xc/programs/Xserver/hw/xwin/winsystray.c
--- xc/programs/Xserver/hw/xwin/winsystray.c	1969-12-31 16:00:00.000000000 -0800
+++ xc/programs/Xserver/hw/xwin/winsystray.c	2002-06-22 15:50:26.000000000 -0700
@@ -0,0 +1,97 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors:	Dakshinamurthy Karra
+ *		Suhaib M Siddiqi
+ *		Peter Busch
+ *		Harold L Hunt II
+ */
+ 
+ 
+#include "win.h"
+#include <shellapi.h>
+
+
+Bool winSystrayAddIcon(HWND hwnd, UINT uID, LPSTR lpszTip) 
+{ 
+    Bool res; 
+    NOTIFYICONDATA tnid; 
+    HICON hIcon;
+    char moduleFullPath[MAX_PATH];
+    char modulePath[MAX_PATH];
+    char *filePart;
+   
+    /* Load the icon from the same directory than the executable */
+    GetModuleFileName(NULL, moduleFullPath, MAX_PATH);
+    GetFullPathName(moduleFullPath, MAX_PATH, modulePath, &filePart);
+    *filePart = '\0'; // remove the filename from the path
+    strncat(modulePath, X_ICON, min(MAX_PATH-strlen(modulePath), strlen(X_ICON)));
+    
+#if CYGDEBUG
+      ErrorF ("winSystrayAddIcon () - Try to load X icon at:  %s\n", modulePath);
+#endif
+
+    hIcon = (HICON)LoadImage(NULL, modulePath, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_LOADFROMFILE);
+    if (hIcon == NULL) {
+#if CYGDEBUG
+      ErrorF ("winSystrayAddIcon () - Failed to load systray icon: 0x%x\n", GetLastError());
+#endif
+      
+      return FALSE;
+    }
+ 
+    /* Add the icon to the taskbar */
+    tnid.cbSize = sizeof(NOTIFYICONDATA); 
+    tnid.hWnd = hwnd; 
+    tnid.uID = uID; 
+    tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; 
+    tnid.uCallbackMessage = WIN_SYSTRAY_MSG; 
+    tnid.hIcon = hIcon; 
+    if (lpszTip) 
+        lstrcpyn(tnid.szTip, lpszTip, sizeof(tnid.szTip)); 
+    else 
+        tnid.szTip[0] = '\0'; 
+ 
+    res = Shell_NotifyIcon(NIM_ADD, &tnid); 
+ 
+    DestroyIcon(hIcon); 
+ 
+    return res; 
+} 
+
+Bool winSystrayRemoveIcon(HWND hwnd, UINT uID) 
+{ 
+    BOOL res; 
+    NOTIFYICONDATA tnid; 
+ 
+    tnid.cbSize = sizeof(NOTIFYICONDATA); 
+    tnid.hWnd = hwnd; 
+    tnid.uID = uID; 
+         
+    res = Shell_NotifyIcon(NIM_DELETE, &tnid); 
+    return TRUE; 
+} 
diff -Naur xc/programs/Xserver/hw/xwin/winwndproc.c xc/programs/Xserver/hw/xwin/winwndproc.c
--- xc/programs/Xserver/hw/xwin/winwndproc.c	2002-06-16 21:12:57.000000000 -0700
+++ xc/programs/Xserver/hw/xwin/winwndproc.c	2002-06-23 16:40:04.000000000 -0700
@@ -36,6 +36,25 @@
 
 
 /*
+ * Processes Windows messages for the owner of the X root windows.
+ * We don't care about this window, we don't do anything with it, we just
+ * need the callback for RegisterClass.
+ */
+LRESULT CALLBACK
+winWindowProcInvisible (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message)
+    {
+    case WM_CLOSE:
+      /* Tell X that we are giving up */
+      GiveUp (0);
+      return 0;
+    }
+      
+  return DefWindowProc (hwnd, message, wParam, lParam);
+}
+
+/*
  * Called by winWakeupHandler
  * Processes current Windows message
  */
@@ -65,7 +84,7 @@
   if ((s_pScreenPriv == NULL || hwnd != s_hwndLastPrivates)
       && (s_pScreenPriv = GetProp (hwnd, WIN_SCR_PROP)) != NULL)
     {
-#if CYGDEGUG
+#if CYGDEBUG
       ErrorF ("winWindowProc () - Setting privates handle\n");
 #endif
       s_pScreenInfo = s_pScreenPriv->pScreenInfo;
@@ -424,7 +443,7 @@
 	break;
 
 #if CYGDEBUG
-      ErrorF ("winWindowProc () - WM_ACTIVATE\n");
+      ErrorF ("winWindowProc () - WM_ACTIVATE: %d\n", LOWORD(wParam));
 #endif
       /*
        * Focus is being changed to another window.
@@ -450,7 +469,7 @@
 	break;
 
 #if CYGDEBUG
-      ErrorF ("winWindowProc () - WM_ACTIVATEAPP\n");
+      ErrorF ("winWindowProc () - WM_ACTIVATEAPP: %d\n", wParam);
 #endif
       /* Activate or deactivate */
       s_pScreenPriv->fActive = wParam;
@@ -472,6 +491,115 @@
       /* Tell X that we are giving up */
       GiveUp (0);
       return 0;
+      
+    case WM_SIZE:
+      /*
+       * If we are using the systray and are minimizing a window, we must hide
+       * it or we'll have a small titlebar above the taskbar near the Start
+       * button
+       */
+      if ((s_pScreenInfo->fSystray) && (wParam  == SIZE_MINIMIZED))
+        {
+          ShowWindow(hwnd, SW_HIDE);
+          return 0;
+        }
+      else
+        break;
+      
+    case WIN_SYSTRAY_MSG:
+      if (lParam == WM_LBUTTONUP) 
+        {
+          /*
+           * For now, if the window is visible, hide it, if it's not, show it.
+           * A better way would be: if it's not in the foreground, bring it to
+           * the foreground, otherwise hide it. That way, if the window is
+           * hidden behind other applications, we'll show it. But I don't how
+           * to get the window that was in foreground before the user clicked 
+           * on the systray. And since a lot of the program I have that uses 
+           * the systray don't do behave differently, I'm not sure that it's 
+           * possible to do.
+           */
+          if (IsWindowVisible(hwnd))
+            ShowWindow(hwnd, SW_MINIMIZE);
+          else
+            {
+              ShowWindow (hwnd, SW_NORMAL);
+              SetForegroundWindow(hwnd);
+              
+              /*
+               * TODO: In fullscreen mode, the system doesn't switch back to
+               * fullscreen and doesn't send WM_ACTIVATEAPP (bug in Windows?)
+               */
+            }
+        }
+      else if (lParam == WM_RBUTTONUP)
+        {
+          /* Show the system menu */
+          HMENU hSysMenu;
+          POINT cursor;
+          
+          /*
+           * Call SetForeground window before showing the menu so the menu
+           * will be hidden if the user activate another application
+           */
+          SetForegroundWindow(hwnd);
+          
+          hSysMenu = GetSystemMenu(hwnd, FALSE);
+          
+          /* The menu is not "refreshed" when we get it */
+          EnableMenuItem(hSysMenu, 2, MF_GRAYED | MF_BYPOSITION); /* No resize */
+          EnableMenuItem(hSysMenu, 4, MF_GRAYED | MF_BYPOSITION); /* No maximize */
+          if (IsWindowVisible(hwnd))
+            {
+              EnableMenuItem(hSysMenu, 0, MF_GRAYED | MF_BYPOSITION); /* No restore */
+              EnableMenuItem(hSysMenu, 1, MF_ENABLED | MF_BYPOSITION); /* Move */
+              EnableMenuItem(hSysMenu, 3, MF_ENABLED | MF_BYPOSITION); /* Minimize */
+            }
+          else
+            {
+              EnableMenuItem(hSysMenu, 0, MF_ENABLED | MF_BYPOSITION); /* Restore */
+              EnableMenuItem(hSysMenu, 1, MF_GRAYED | MF_BYPOSITION); /* No move */
+              EnableMenuItem(hSysMenu, 3, MF_GRAYED | MF_BYPOSITION); /* No minimize */
+            }
+          
+          GetCursorPos(&cursor);
+          TrackPopupMenu(hSysMenu, 0, cursor.x, cursor.y, 0, hwnd, NULL);
+        }
+      return 0;
+      
+    case WM_COMMAND:
+      /* 0xF000 and above are predefined window menu */
+      if (wParam >= 0xF000)
+        {
+          SendMessage(hwnd, WM_SYSCOMMAND, wParam, 0);
+          return 0;
+        }
+      break;
+      
+    default:
+      if ((s_pScreenInfo != NULL) && (message == s_pScreenInfo->uTaskbarRestart))
+        {
+          char screenNumber[WINDOW_TITLE_MAX_LENGTH];
+          int screenNum;
+
+#if CYGDEBUG
+      ErrorF ("winWindowProc () - Re-add systray icon\n");
+#endif
+
+          /* Get the screen number for the tooltip */
+          /* HACK: there must be another/better way to do it (querying X?) */
+          for (screenNum = 0; screenNum < MAXSCREENS; screenNum++) {
+            if ((g_ScreenInfo+screenNum) == s_pScreenInfo) 
+              break;
+          }
+
+          // Taskbar has been restart, we need to add the icon again
+          snprintf(screenNumber, WINDOW_TITLE_MAX_LENGTH, "%s %d", WINDOW_TITLE, screenNum);
+          winSystrayAddIcon(hwnd, WIN_SYSTRAY_UID, screenNumber);
+          
+          return 0;
+        }
+      break;
     }
 
   return DefWindowProc (hwnd, message, wParam, lParam);

image/icon


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]