Kirill K. Smirnov : systray: Correctly handle icon addition/deletion.
Alexandre Julliard
julliard at winehq.org
Fri Feb 15 05:36:04 CST 2008
Module: wine
Branch: master
Commit: be2911a180236344abc6ad112c91972d7e6a300e
URL: http://source.winehq.org/git/wine.git/?a=commit;h=be2911a180236344abc6ad112c91972d7e6a300e
Author: Kirill K. Smirnov <lich at math.spbu.ru>
Date: Thu Feb 7 15:23:54 2008 +0000
systray: Correctly handle icon addition/deletion.
---
programs/explorer/systray.c | 202 +++++++++++++++++++++++--------------------
1 files changed, 108 insertions(+), 94 deletions(-)
diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c
index 8fa7447..28a440f 100644
--- a/programs/explorer/systray.c
+++ b/programs/explorer/systray.c
@@ -77,80 +77,6 @@ static BOOL hide_systray;
/* space around icon (forces icon to center of KDE systray area) */
#define ICON_BORDER 4
-static LRESULT WINAPI adaptor_wndproc(HWND window, UINT msg,
- WPARAM wparam, LPARAM lparam)
-{
- struct icon *icon = NULL;
- BOOL ret;
-
- WINE_TRACE("hwnd=%p, msg=0x%x\n", window, msg);
-
- /* set the icon data for the window from the data passed into CreateWindow */
- if (msg == WM_NCCREATE)
- SetWindowLongPtrW(window, GWLP_USERDATA, (LPARAM)((const CREATESTRUCT *)lparam)->lpCreateParams);
-
- icon = (struct icon *) GetWindowLongPtr(window, GWLP_USERDATA);
-
- switch (msg)
- {
- case WM_PAINT:
- {
- RECT rc;
- int top;
- PAINTSTRUCT ps;
- HDC hdc;
-
- WINE_TRACE("painting\n");
-
- hdc = BeginPaint(window, &ps);
- GetClientRect(window, &rc);
-
- /* calculate top so we can deal with arbitrary sized trays */
- top = ((rc.bottom-rc.top)/2) - ((ICON_SIZE)/2);
-
- DrawIconEx(hdc, (ICON_BORDER/2), top, icon->image,
- ICON_SIZE, ICON_SIZE, 0, 0, DI_DEFAULTSIZE|DI_NORMAL);
-
- EndPaint(window, &ps);
- break;
- }
-
- case WM_MOUSEMOVE:
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONUP:
- case WM_MBUTTONDOWN:
- case WM_MBUTTONUP:
- case WM_LBUTTONDBLCLK:
- case WM_RBUTTONDBLCLK:
- case WM_MBUTTONDBLCLK:
- /* notify the owner hwnd of the message */
- WINE_TRACE("relaying 0x%x\n", msg);
- ret = PostMessage(icon->owner, icon->callback_message, (WPARAM) icon->id, (LPARAM) msg);
- if (!ret && (GetLastError() == ERROR_INVALID_HANDLE))
- {
- WINE_WARN("application window was destroyed without removing "
- "notification icon, removing automatically\n");
- DestroyWindow(window);
- }
- break;
-
- case WM_NCDESTROY:
- SetWindowLongPtr(window, GWLP_USERDATA, 0);
-
- list_remove(&icon->entry);
- DestroyIcon(icon->image);
- HeapFree(GetProcessHeap(), 0, icon);
- break;
-
- default:
- return DefWindowProc(window, msg, wparam, lparam);
- }
-
- return 0;
-}
-
/* Retrieves icon record by owner window and ID */
static struct icon *get_icon(HWND owner, UINT id)
@@ -226,12 +152,19 @@ static BOOL display_icon(struct icon *icon, BOOL hide)
WINE_TRACE("id=0x%x, hwnd=%p, hide=%d\n", icon->id, icon->owner, hide);
- if (icon->hidden == hide || (!icon->hidden) == (!hide)) return TRUE;
+ /* not a startup case and nothing to do */
+ if (icon->window && !icon->hidden == !hide)
+ return TRUE;
+
icon->hidden = hide;
if (hide)
{
- DestroyWindow(icon->window);
- DestroyWindow(icon->tooltip);
+ /* At startup icon->hidden == FALSE and icon->window == NULL */
+ if (icon->window)
+ {
+ DestroyWindow(icon->window);
+ DestroyWindow(icon->tooltip);
+ }
return TRUE;
}
@@ -264,7 +197,7 @@ static BOOL display_icon(struct icon *icon, BOOL hide)
}
/* Modifies an existing icon record */
-static BOOL modify_icon(NOTIFYICONDATAW *nid, BOOL modify_tooltip)
+static BOOL modify_icon(NOTIFYICONDATAW *nid)
{
struct icon *icon;
@@ -278,14 +211,11 @@ static BOOL modify_icon(NOTIFYICONDATAW *nid, BOOL modify_tooltip)
return FALSE;
}
- if (nid->uFlags & NIF_STATE)
- {
- if (nid->dwStateMask & NIS_HIDDEN)
- display_icon(icon, !!(nid->dwState & NIS_HIDDEN));
- else
- display_icon(icon, FALSE);
- }
- else
+ if ((nid->uFlags & NIF_STATE) && (nid->dwStateMask & NIS_HIDDEN))
+ display_icon(icon, !!(nid->dwState & NIS_HIDDEN));
+
+ /* startup case*/
+ if ((!icon->window) && (!icon->hidden))
display_icon(icon, FALSE);
if (nid->uFlags & NIF_ICON)
@@ -333,31 +263,45 @@ static BOOL add_icon(NOTIFYICONDATAW *nid)
return FALSE;
}
+ ZeroMemory(icon, sizeof(struct icon));
icon->id = nid->uID;
icon->owner = nid->hWnd;
- icon->image = NULL;
- icon->window = NULL;
- icon->hidden = TRUE;
list_add_tail(&tray.icons, &icon->entry);
- return modify_icon(nid, FALSE);
+ /*
+ * Both icon->window and icon->hidden are zero. modify_icon function
+ * will treat this case as a startup, i.e. icon window will be created if
+ * NIS_HIDDEN flag is not set.
+ */
+
+ return modify_icon(nid);
}
+/* Deletes tray icon window and icon record */
+static BOOL delete_icon_directly(struct icon *icon)
+{
+ display_icon(icon, TRUE);
+ list_remove(&icon->entry);
+ DestroyIcon(icon->image);
+ HeapFree(GetProcessHeap(), 0, icon);
+ return TRUE;
+}
+
+/* Deletes tray icon window and icon structure */
static BOOL delete_icon(const NOTIFYICONDATAW *nid)
{
struct icon *icon = get_icon(nid->hWnd, nid->uID);
WINE_TRACE("id=0x%x, hwnd=%p\n", nid->uID, nid->hWnd);
-
+
if (!icon)
{
WINE_WARN("invalid tray icon ID specified: %u\n", nid->uID);
return FALSE;
}
- display_icon(icon, TRUE);
- return TRUE;
+ return delete_icon_directly(icon);
}
static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
@@ -420,7 +364,7 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
ret = delete_icon(&nid);
break;
case NIM_MODIFY:
- ret = modify_icon(&nid, TRUE);
+ ret = modify_icon(&nid);
break;
default:
WINE_FIXME("unhandled tray message: %ld\n", cds->dwData);
@@ -444,6 +388,76 @@ static LRESULT WINAPI listener_wndproc(HWND window, UINT msg,
return DefWindowProc(window, msg, wparam, lparam);
}
+static LRESULT WINAPI adaptor_wndproc(HWND window, UINT msg,
+ WPARAM wparam, LPARAM lparam)
+{
+ struct icon *icon = NULL;
+ BOOL ret;
+
+ WINE_TRACE("hwnd=%p, msg=0x%x\n", window, msg);
+
+ /* set the icon data for the window from the data passed into CreateWindow */
+ if (msg == WM_NCCREATE)
+ SetWindowLongPtrW(window, GWLP_USERDATA, (LPARAM)((const CREATESTRUCT *)lparam)->lpCreateParams);
+
+ icon = (struct icon *) GetWindowLongPtr(window, GWLP_USERDATA);
+
+ switch (msg)
+ {
+ case WM_PAINT:
+ {
+ RECT rc;
+ int top;
+ PAINTSTRUCT ps;
+ HDC hdc;
+
+ WINE_TRACE("painting\n");
+
+ hdc = BeginPaint(window, &ps);
+ GetClientRect(window, &rc);
+
+ /* calculate top so we can deal with arbitrary sized trays */
+ top = ((rc.bottom-rc.top)/2) - ((ICON_SIZE)/2);
+
+ DrawIconEx(hdc, (ICON_BORDER/2), top, icon->image,
+ ICON_SIZE, ICON_SIZE, 0, 0, DI_DEFAULTSIZE|DI_NORMAL);
+
+ EndPaint(window, &ps);
+ break;
+ }
+
+ case WM_MOUSEMOVE:
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONUP:
+ case WM_MBUTTONDOWN:
+ case WM_MBUTTONUP:
+ case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONDBLCLK:
+ case WM_MBUTTONDBLCLK:
+ /* notify the owner hwnd of the message */
+ WINE_TRACE("relaying 0x%x\n", msg);
+ ret = PostMessage(icon->owner, icon->callback_message, (WPARAM) icon->id, (LPARAM) msg);
+ if (!ret && (GetLastError() == ERROR_INVALID_HANDLE))
+ {
+ WINE_WARN("application window was destroyed without removing "
+ "notification icon, removing automatically\n");
+ delete_icon_directly(icon);
+ }
+ break;
+
+ case WM_NCDESTROY:
+ SetWindowLongPtr(window, GWLP_USERDATA, 0);
+ break;
+
+ default:
+ return DefWindowProc(window, msg, wparam, lparam);
+ }
+
+ return 0;
+}
+
static BOOL is_systray_hidden(void)
{
More information about the wine-cvs
mailing list