This is the mail archive of the
cygwin-xfree@cygwin.com
mailing list for the Cygwin XFree86 project.
[PATCH] systray icon
- From: Jehan Bing <jehan at bravobrava dot com>
- To: Cygwin XFree <cygwin-xfree at cygwin dot com>
- Date: Sun, 23 Jun 2002 17:17:53 -0700
- Subject: [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);