systray
Martin Fuchs
martin-fuchs at gmx.net
Wed Mar 31 14:00:07 CST 2004
Here is again the new systray implementation, now completely replacing the old code, without asking for desktop mode and without alloca().
Changelog:
- new implementation of SHELL_NotifyIcon() to behave the same way as native shell32
Index: shell32_main.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32_main.c,v
retrieving revision 1.130
diff -u -p -d -r1.130 shell32_main.c
--- shell32_main.c 22 Mar 2004 20:43:07 -0000 1.130
+++ shell32_main.c 31 Mar 2004 19:56:31 -0000
@@ -927,7 +927,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,
InitCommonControlsEx(NULL);
SIC_Initialize();
- SYSTRAY_Init();
InitChangeNotifications();
break;
Index: shell32_main.h
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32_main.h,v
retrieving revision 1.85
diff -u -p -d -r1.85 shell32_main.h
--- shell32_main.h 27 Mar 2004 01:42:22 -0000 1.85
+++ shell32_main.h 31 Mar 2004 19:56:32 -0000
@@ -134,9 +134,6 @@ HRESULT WINAPI Shell_MergeMenus (HMENU h
(((kst) & MK_SHIFT) ? DROPEFFECT_LINK : DROPEFFECT_COPY):\
DROPEFFECT_MOVE)
-/* Systray */
-BOOL SYSTRAY_Init(void);
-
/* OLE32 */
extern HINSTANCE hShellOle32;
Index: systray.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/systray.c,v
retrieving revision 1.26
diff -u -p -d -r1.26 systray.c
--- systray.c 27 Feb 2004 21:30:16 -0000 1.26
+++ systray.c 31 Mar 2004 19:56:31 -0000
@@ -1,11 +1,8 @@
/*
- * Systray
- *
- * Copyright 1999 Kai Morich <kai.morich at bigfoot.de>
+ * Copyright 2004 Martin Fuchs
*
- * Manage the systray window. That it actually appears in the docking
- * area of KDE is handled in dlls/x11drv/window.c,
- * X11DRV_set_wm_hints using KWM_DOCKWINDOW.
+ * Pass on icon notification messages to the systray implementation
+ * in the currently running shell.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,377 +19,63 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "config.h"
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
+#include <malloc.h>
#include "windef.h"
#include "winbase.h"
-#include "winnls.h"
-#include "wingdi.h"
#include "winuser.h"
-#include "shlobj.h"
#include "shellapi.h"
-#include "shell32_main.h"
-#include "commctrl.h"
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(shell);
-
-typedef struct SystrayItem {
- HWND hWnd;
- HWND hWndToolTip;
- NOTIFYICONDATAA notifyIcon;
- struct SystrayItem *nextTrayItem;
-} SystrayItem;
-
-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
-
-
-
-static BOOL SYSTRAY_ItemIsEqual(PNOTIFYICONDATAA pnid1, PNOTIFYICONDATAA pnid2)
-{
- if (pnid1->hWnd != pnid2->hWnd) return FALSE;
- if (pnid1->uID != pnid2->uID) return FALSE;
- return TRUE;
-}
-
-static LRESULT CALLBACK SYSTRAY_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- HDC hdc;
- PAINTSTRUCT ps;
-
- switch (message) {
- case WM_PAINT:
- {
- RECT rc;
- SystrayItem *ptrayItem = systray;
-
- 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,
- ICON_SIZE, ICON_SIZE, 0, 0, DI_DEFAULTSIZE|DI_NORMAL)) {
- ERR("Paint(SystrayWindow %p) failed -> removing SystrayItem %p\n", hWnd, ptrayItem);
- SYSTRAY_Delete(&ptrayItem->notifyIcon);
- }
- }
- break;
- }
- ptrayItem = ptrayItem->nextTrayItem;
- }
- EndPaint(hWnd, &ps);
- }
- break;
-
- case WM_MOUSEMOVE:
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONUP:
- case WM_MBUTTONDOWN:
- case WM_MBUTTONUP:
- {
- MSG msg;
- SystrayItem *ptrayItem = systray;
-
- while ( ptrayItem ) {
- if (ptrayItem->hWnd == hWnd) {
- msg.hwnd=hWnd;
- msg.message=message;
- msg.wParam=wParam;
- msg.lParam=lParam;
- msg.time = GetMessageTime ();
- msg.pt.x = LOWORD(GetMessagePos ());
- msg.pt.y = HIWORD(GetMessagePos ());
-
- SendMessageA(ptrayItem->hWndToolTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
- }
- ptrayItem = ptrayItem->nextTrayItem;
- }
- }
- /* fall through */
-
- case WM_LBUTTONDBLCLK:
- case WM_RBUTTONDBLCLK:
- case WM_MBUTTONDBLCLK:
- {
- SystrayItem *ptrayItem = systray;
-
- while (ptrayItem) {
- if (ptrayItem->hWnd == hWnd) {
- if (ptrayItem->notifyIcon.hWnd && ptrayItem->notifyIcon.uCallbackMessage) {
- if (!PostMessageA(ptrayItem->notifyIcon.hWnd, ptrayItem->notifyIcon.uCallbackMessage,
- (WPARAM)ptrayItem->notifyIcon.uID, (LPARAM)message)) {
- ERR("PostMessage(SystrayWindow %p) failed -> removing SystrayItem %p\n", hWnd, ptrayItem);
- SYSTRAY_Delete(&ptrayItem->notifyIcon);
- }
- }
- break;
- }
- ptrayItem = ptrayItem->nextTrayItem;
- }
- }
- break;
-
- default:
- return (DefWindowProcA(hWnd, message, wParam, lParam));
- }
- return (0);
-
-}
-
-
-BOOL SYSTRAY_RegisterClass(void)
-{
- WNDCLASSA wc;
-
- wc.style = CS_SAVEBITS|CS_DBLCLKS;
- wc.lpfnWndProc = (WNDPROC)SYSTRAY_WndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = 0;
- wc.hIcon = 0;
- wc.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
- wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = "WineSystray";
-
- if (!RegisterClassA(&wc)) {
- ERR("RegisterClass(WineSystray) failed\n");
- return FALSE;
- }
- return TRUE;
-}
-
-
-BOOL SYSTRAY_ItemInit(SystrayItem *ptrayItem)
-{
- 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,
- CW_USEDEFAULT, CW_USEDEFAULT,
- rect.right-rect.left, rect.bottom-rect.top,
- 0, 0, 0, 0 );
- if ( !ptrayItem->hWnd ) {
- ERR( "CreateWindow(WineSystray) failed\n" );
- return FALSE;
- }
-
- /* Create tooltip for icon. */
- ptrayItem->hWndToolTip = CreateWindowA( TOOLTIPS_CLASSA,NULL,TTS_ALWAYSTIP,
- CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT,
- ptrayItem->hWnd, 0, 0, 0 );
- if ( !ptrayItem->hWndToolTip ) {
- ERR( "CreateWindow(TOOLTIP) failed\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);
- return;
-}
-
-
-void SYSTRAY_ItemSetMessage(SystrayItem *ptrayItem, UINT uCallbackMessage)
-{
- ptrayItem->notifyIcon.uCallbackMessage = uCallbackMessage;
-}
-
-
-void SYSTRAY_ItemSetIcon(SystrayItem *ptrayItem, HICON hIcon)
-{
- if(ptrayItem->notifyIcon.hIcon)
- DestroyIcon(ptrayItem->notifyIcon.hIcon);
- ptrayItem->notifyIcon.hIcon = CopyIcon(hIcon);
- InvalidateRect(ptrayItem->hWnd, NULL, TRUE);
-}
-
-
-void SYSTRAY_ItemSetTip(SystrayItem *ptrayItem, CHAR* szTip, int modify)
-{
- TTTOOLINFOA ti;
-
- strncpy(ptrayItem->notifyIcon.szTip, szTip, sizeof(ptrayItem->notifyIconszTip));
- ptrayItem->notifyIcon.szTip[sizeof(ptrayItem->notifyIcon.szTip)-1]=0;
-
- ti.cbSize = sizeof(TTTOOLINFOA);
- ti.uFlags = 0;
- ti.hwnd = ptrayItem->hWnd;
- ti.hinst = 0;
- ti.uId = 0;
- ti.lpszText = ptrayItem->notifyIcon.szTip;
- ti.rect.left = 0;
- ti.rect.top = 0;
- ti.rect.right = ICON_SIZE+2*ICON_BORDER;
- ti.rect.bottom = ICON_SIZE+2*ICON_BORDER;
-
- if(modify)
- SendMessageA(ptrayItem->hWndToolTip, TTM_UPDATETIPTEXTA, 0, (LPARAM)&ti);
- else
- SendMessageA(ptrayItem->hWndToolTip, TTM_ADDTOOLA, 0, (LPARAM)&ti);
-}
-
-
-static BOOL SYSTRAY_Add(PNOTIFYICONDATAA pnid)
-{
- SystrayItem **ptrayItem = &systray;
-
- /* Find last element. */
- while( *ptrayItem ) {
- if ( SYSTRAY_ItemIsEqual(pnid, &(*ptrayItem)->notifyIcon) )
- return FALSE;
- ptrayItem = &((*ptrayItem)->nextTrayItem);
- }
- /* Allocate SystrayItem for element and add to end of list. */
- (*ptrayItem) = ( SystrayItem *)malloc( sizeof(SystrayItem) );
-
- /* Initialize and set data for the tray element. */
- SYSTRAY_ItemInit( (*ptrayItem) );
- (*ptrayItem)->notifyIcon.uID = pnid->uID; /* only needed for callback message */
- (*ptrayItem)->notifyIcon.hWnd = pnid->hWnd; /* only needed for callback message */
- SYSTRAY_ItemSetIcon (*ptrayItem, (pnid->uFlags&NIF_ICON) ?pnid->hIcon :0);
- SYSTRAY_ItemSetMessage(*ptrayItem, (pnid->uFlags&NIF_MESSAGE)?pnid->uCallbackMessage:0);
- SYSTRAY_ItemSetTip (*ptrayItem, (pnid->uFlags&NIF_TIP) ?pnid->szTip :"", FALSE);
-
- TRACE("%p: %p %s\n", (*ptrayItem), (*ptrayItem)->notifyIcon.hWnd,
- (*ptrayItem)->notifyIcon.szTip);
- return TRUE;
-}
+ /* copy data structure for tray notifications */
+typedef struct TrayNotifyCDS_Dummy {
+ DWORD cookie;
+ DWORD notify_code;
+ DWORD nicon_data[1]; // placeholder for NOTIFYICONDATA structure
+} TrayNotifyCDS_Dummy;
-static BOOL SYSTRAY_Modify(PNOTIFYICONDATAA pnid)
+/* The only difference between Shell_NotifyIconA and Shell_NotifyIconW is the call to SendMessageA/W. */
+static BOOL SHELL_NotifyIconAW(DWORD dwMessage, void* pnid, HWND nid_hwnd, int nid_size, BOOL unicode)
{
- SystrayItem *ptrayItem = systray;
-
- while ( ptrayItem ) {
- if ( SYSTRAY_ItemIsEqual(pnid, &ptrayItem->notifyIcon) ) {
- if (pnid->uFlags & NIF_ICON)
- SYSTRAY_ItemSetIcon(ptrayItem, pnid->hIcon);
- if (pnid->uFlags & NIF_MESSAGE)
- SYSTRAY_ItemSetMessage(ptrayItem, pnid->uCallbackMessage);
- if (pnid->uFlags & NIF_TIP)
- SYSTRAY_ItemSetTip(ptrayItem, pnid->szTip, TRUE);
-
- TRACE("%p: %p %s\n", ptrayItem, ptrayItem->notifyIcon.hWnd, ptrayItem->notifyIcon.szTip);
- return TRUE;
- }
- ptrayItem = ptrayItem->nextTrayItem;
- }
- return FALSE; /* not found */
-}
+ HWND hwnd;
+ COPYDATASTRUCT data;
+ const static WCHAR wszShellTrayClassName[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d','\0'};
+ BOOL ret = FALSE;
+ int len = sizeof(TrayNotifyCDS_Dummy)-sizeof(DWORD)+nid_size;
-static BOOL SYSTRAY_Delete(PNOTIFYICONDATAA pnid)
-{
- SystrayItem **ptrayItem = &systray;
+ TrayNotifyCDS_Dummy* pnotify_data = (TrayNotifyCDS_Dummy*) HeapAlloc(GetProcessHeap(), 0, len);
- while (*ptrayItem) {
- if (SYSTRAY_ItemIsEqual(pnid, &(*ptrayItem)->notifyIcon)) {
- SystrayItem *next = (*ptrayItem)->nextTrayItem;
- TRACE("%p: %p %s\n", *ptrayItem, (*ptrayItem)->notifyIcon.hWnd, (*ptrayItem)->notifyIcon.szTip);
- SYSTRAY_ItemTerm(*ptrayItem);
+ pnotify_data->cookie = 1;
+ pnotify_data->notify_code = dwMessage;
+ memcpy(&pnotify_data->nicon_data, pnid, nid_size);
- free(*ptrayItem);
- *ptrayItem = next;
+ data.dwData = 1;
+ data.cbData = len;
+ data.lpData = pnotify_data;
- return TRUE;
- }
- ptrayItem = &((*ptrayItem)->nextTrayItem);
- }
+ for(hwnd=0; (hwnd=FindWindowExW(0, hwnd, wszShellTrayClassName, NULL)); )
+ if ((unicode?SendMessageW:SendMessageA)(hwnd, WM_COPYDATA, (WPARAM)nid_hwnd, (LPARAM)&data))
+ ret = TRUE;
- return FALSE; /* not found */
-}
+ HeapFree(GetProcessHeap(), 0, pnotify_data);
-/*************************************************************************
- *
- */
-BOOL SYSTRAY_Init(void)
-{
- return TRUE;
+ return ret;
}
/*************************************************************************
* Shell_NotifyIcon [SHELL32.296]
* Shell_NotifyIconA [SHELL32.297]
*/
-BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid )
+BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid)
{
- BOOL flag=FALSE;
- TRACE("enter %p %d %ld\n", pnid->hWnd, pnid->uID, dwMessage);
- switch(dwMessage) {
- case NIM_ADD:
- flag = SYSTRAY_Add(pnid);
- break;
- case NIM_MODIFY:
- flag = SYSTRAY_Modify(pnid);
- break;
- case NIM_DELETE:
- flag = SYSTRAY_Delete(pnid);
- break;
- }
- TRACE("leave %p %d %ld=%d\n", pnid->hWnd, pnid->uID, dwMessage, flag);
- return flag;
+ return SHELL_NotifyIconAW(dwMessage, pnid, pnid->hWnd, pnid->cbSize, FALSE);
}
/*************************************************************************
* Shell_NotifyIconW [SHELL32.298]
*/
-BOOL WINAPI Shell_NotifyIconW (DWORD dwMessage, PNOTIFYICONDATAW pnid )
+BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW pnid)
{
- BOOL ret;
-
- PNOTIFYICONDATAA p = HeapAlloc(GetProcessHeap(),0,sizeof(NOTIFYICONDATAA));
- memcpy(p, pnid, sizeof(NOTIFYICONDATAA));
- WideCharToMultiByte( CP_ACP, 0, pnid->szTip, -1, p->szTip, sizeof(p->szTip), NULL, NULL );
- p->szTip[sizeof(p->szTip)-1] = 0;
-
- ret = Shell_NotifyIconA(dwMessage, p );
-
- HeapFree(GetProcessHeap(),0,p);
- return ret;
+ return SHELL_NotifyIconAW(dwMessage, pnid, pnid->hWnd, pnid->cbSize, TRUE);
}
More information about the wine-patches
mailing list