[PATCH] shell32: Implement NIM_SETVERSION in Shell_NotifyIcon()
Roman Pisl
rpisl at seznam.cz
Tue Mar 1 09:26:50 CST 2016
Fixes https://bugs.winehq.org/show_bug.cgi?id=29412
The patch adds support for different versions of Shell_NotifyIcon() API
function by implementing NIM_SETVERSION and fixes Qt programs that use
tray icon in wine.
Tested on Gentoo Linux and Qt 4.8/5.5.
Signed-off-by: Roman Pisl <rpisl at seznam.cz>
---
dlls/shell32/systray.c | 2 ++
dlls/winex11.drv/systray.c | 64 ++++++++++++++++++++++++++++++++++++++++-----
programs/explorer/systray.c | 51 ++++++++++++++++++++++++++++++++++--
3 files changed, 108 insertions(+), 9 deletions(-)
diff --git a/dlls/shell32/systray.c b/dlls/shell32/systray.c
index dfa30ff..a043912 100644
--- a/dlls/shell32/systray.c
+++ b/dlls/shell32/systray.c
@@ -234,6 +234,8 @@ noicon:
}
if (data->uFlags & NIF_GUID)
data->guidItem = nid->guidItem;
+ if (dwMessage == NIM_SETVERSION)
+ data->u.uVersion = nid->u.uVersion;
/* FIXME: balloon icon */
cds.lpData = data;
diff --git a/dlls/winex11.drv/systray.c b/dlls/winex11.drv/systray.c
index c7e7013..78cba87 100644
--- a/dlls/winex11.drv/systray.c
+++ b/dlls/winex11.drv/systray.c
@@ -65,6 +65,7 @@ struct tray_icon
UINT info_flags; /* flags for info balloon */
UINT info_timeout; /* timeout for info balloon */
HICON info_icon; /* info balloon icon */
+ UINT version; /* notify icon api version */
};
static struct list icon_list = LIST_INIT( icon_list );
@@ -484,15 +485,56 @@ static LRESULT WINAPI tray_icon_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPAR
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
- /* notify the owner hwnd of the message */
- TRACE("relaying 0x%x\n", msg);
- ret = PostMessageW(icon->owner, icon->callback_message, icon->id, msg);
- if (!ret && (GetLastError() == ERROR_INVALID_WINDOW_HANDLE))
{
- WARN( "application window was destroyed, removing icon %u\n", icon->id );
- delete_icon( icon );
+ WPARAM wpar;
+ BOOL oldver;
+
+ oldver = icon->version <= NOTIFY_VERSION;
+ if (oldver) {
+ /* 0 up to NOTIFYICON_VERSION (=3) */
+ wpar = icon->id;
+ } else {
+ /* NOTIFYICON_VERSION_4 */
+ RECT rect;
+ WORD x, y;
+
+ GetWindowRect( icon->window, &rect );
+ x = rect.left + LOWORD(lparam);
+ y = rect.top + HIWORD(lparam);
+ wpar = MAKEWPARAM(x, y);
+ }
+
+ /* notify the owner hwnd of the message */
+ TRACE("relaying 0x%x\n", msg);
+ ret = PostMessageW(icon->owner, icon->callback_message, wpar,
+ oldver ? msg : MAKELPARAM(msg, icon->id));
+
+ if (ret && icon->version > 0) {
+ switch (msg) {
+ case WM_RBUTTONUP:
+ /* notify the owner hwnd of the message */
+ TRACE("relaying 0x%x\n", WM_CONTEXTMENU);
+ ret = PostMessageW(icon->owner, icon->callback_message, wpar,
+ oldver ? WM_CONTEXTMENU : MAKELPARAM(WM_CONTEXTMENU, icon->id));
+ break;
+ case WM_LBUTTONUP:
+ /* notify the owner hwnd of the message */
+ TRACE("relaying 0x%x\n", NIN_SELECT);
+ ret = PostMessageW(icon->owner, icon->callback_message, wpar,
+ oldver ? NIN_SELECT : MAKELPARAM(NIN_SELECT, icon->id));
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!ret && (GetLastError() == ERROR_INVALID_WINDOW_HANDLE))
+ {
+ WARN( "application window was destroyed, removing icon %u\n", icon->id );
+ delete_icon( icon );
+ }
+ return 0;
}
- return 0;
case WM_WINDOWPOSCHANGED:
update_systray_balloon_position();
@@ -834,6 +876,14 @@ int CDECL wine_notify_icon( DWORD msg, NOTIFYICONDATAW *data )
case NIM_MODIFY:
if ((icon = get_icon( data->hWnd, data->uID ))) ret = modify_icon( icon, data );
break;
+ case NIM_SETVERSION:
+ if (data->u.uVersion <= NOTIFY_VERSION_4) {
+ if ((icon = get_icon( data->hWnd, data->uID ))) {
+ icon->version = data->u.uVersion;
+ ret = TRUE;
+ }
+ }
+ break;
case 0xdead: /* Wine extension: owner window has died */
cleanup_icons( data->hWnd );
break;
diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c
index beb0a88..8806e34 100644
--- a/programs/explorer/systray.c
+++ b/programs/explorer/systray.c
@@ -77,6 +77,7 @@ struct icon
UINT info_flags; /* flags for info balloon */
UINT info_timeout; /* timeout for info balloon */
HICON info_icon; /* info balloon icon */
+ UINT version; /* notify icon api version */
};
static struct list icon_list = LIST_INIT( icon_list );
@@ -526,6 +527,12 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
case NIM_MODIFY:
if (icon) ret = modify_icon( icon, &nid );
break;
+ case NIM_SETVERSION:
+ if (nid.u.uVersion <= NOTIFY_VERSION_4) {
+ icon->version = nid.u.uVersion;
+ ret = TRUE;
+ }
+ break;
default:
WINE_FIXME("unhandled tray message: %ld\n", cds->dwData);
break;
@@ -598,6 +605,9 @@ static LRESULT WINAPI tray_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM l
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
{
+ WPARAM wpar;
+ BOOL oldver;
+ BOOL ret;
MSG message;
struct icon *icon = icon_from_point( (short)LOWORD(lparam), (short)HIWORD(lparam) );
if (!icon) break;
@@ -611,8 +621,45 @@ static LRESULT WINAPI tray_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM l
message.lParam = lparam;
SendMessageW( icon->tooltip, TTM_RELAYEVENT, 0, (LPARAM)&message );
- if (!PostMessageW( icon->owner, icon->callback_message, (WPARAM) icon->id, (LPARAM) msg ) &&
- GetLastError() == ERROR_INVALID_WINDOW_HANDLE)
+ oldver = icon->version <= NOTIFY_VERSION;
+ if (oldver) {
+ /* 0 up to NOTIFYICON_VERSION (=3) */
+ wpar = icon->id;
+ } else {
+ /* NOTIFYICON_VERSION_4 */
+ RECT rect;
+ WORD x, y;
+
+ rect = get_icon_rect( icon );
+ MapWindowPoints( tray_window, 0, (POINT *)&rect, 2 );
+ x = rect.left + LOWORD(lparam);
+ y = rect.top + HIWORD(lparam);
+ wpar = MAKEWPARAM(x, y);
+ }
+
+ ret = PostMessageW(icon->owner, icon->callback_message, wpar,
+ oldver ? msg : MAKELPARAM(msg, icon->id));
+
+ if (ret && icon->version > 0) {
+ switch (msg) {
+ case WM_RBUTTONUP:
+ /* notify the owner hwnd of the message */
+ WINE_TRACE("relaying 0x%x\n", WM_CONTEXTMENU);
+ ret = PostMessageW(icon->owner, icon->callback_message, wpar,
+ oldver ? WM_CONTEXTMENU : MAKELPARAM(WM_CONTEXTMENU, icon->id));
+ break;
+ case WM_LBUTTONUP:
+ /* notify the owner hwnd of the message */
+ WINE_TRACE("relaying 0x%x\n", NIN_SELECT);
+ ret = PostMessageW(icon->owner, icon->callback_message, wpar,
+ oldver ? NIN_SELECT : MAKELPARAM(NIN_SELECT, icon->id));
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!ret && (GetLastError() == ERROR_INVALID_WINDOW_HANDLE))
{
WINE_WARN("application window was destroyed without removing "
"notification icon, removing automatically\n");
--
2.4.10
More information about the wine-patches
mailing list