From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/Makefile.in | 1 + dlls/win32u/driver.c | 24 ++++++++++++++++ dlls/win32u/message.c | 3 ++ dlls/win32u/ntuser_private.h | 4 +++ dlls/win32u/systray.c | 49 +++++++++++++++++++++++++++++++++ dlls/wow64win/user.c | 53 ++++++++++++++++++++++++++++++++++++ include/ntuser.h | 9 ++++++ include/wine/gdi_driver.h | 4 +++ programs/explorer/systray.c | 18 ++++++------ 9 files changed, 156 insertions(+), 9 deletions(-) create mode 100644 dlls/win32u/systray.c
diff --git a/dlls/win32u/Makefile.in b/dlls/win32u/Makefile.in index e3ba0db82be..878baeaffbe 100644 --- a/dlls/win32u/Makefile.in +++ b/dlls/win32u/Makefile.in @@ -50,6 +50,7 @@ SOURCES = \ spy.c \ syscall.c \ sysparams.c \ + systray.c \ vertical.c \ vulkan.c \ window.c \ diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index e6a24d1a46c..14488419b14 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -757,6 +757,15 @@ static BOOL nulldrv_ClipCursor( const RECT *clip, BOOL reset ) return TRUE; }
+static LRESULT nulldrv_NotifyIcon( HWND hwnd, UINT msg, NOTIFYICONDATAW *data ) +{ + return -1; +} + +static void nulldrv_CleanupIcons( HWND hwnd ) +{ +} + static void nulldrv_UpdateClipboard(void) { } @@ -1138,6 +1147,16 @@ static BOOL loaderdrv_ClipCursor( const RECT *clip, BOOL reset ) return load_driver()->pClipCursor( clip, reset ); }
+static LRESULT loaderdrv_NotifyIcon( HWND hwnd, UINT msg, NOTIFYICONDATAW *data ) +{ + return load_driver()->pNotifyIcon( hwnd, msg, data ); +} + +static void loaderdrv_CleanupIcons( HWND hwnd ) +{ + load_driver()->pCleanupIcons( hwnd ); +} + static LRESULT nulldrv_ClipboardWindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { return 0; @@ -1222,6 +1241,9 @@ static const struct user_driver_funcs lazy_load_driver = loaderdrv_GetCursorPos, loaderdrv_SetCursorPos, loaderdrv_ClipCursor, + /* systray functions */ + loaderdrv_NotifyIcon, + loaderdrv_CleanupIcons, /* clipboard functions */ nulldrv_ClipboardWindowProc, loaderdrv_UpdateClipboard, @@ -1304,6 +1326,8 @@ void __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version SET_USER_FUNC(GetCursorPos); SET_USER_FUNC(SetCursorPos); SET_USER_FUNC(ClipCursor); + SET_USER_FUNC(NotifyIcon); + SET_USER_FUNC(CleanupIcons); SET_USER_FUNC(ClipboardWindowProc); SET_USER_FUNC(UpdateClipboard); SET_USER_FUNC(ChangeDisplaySettings); diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 3c59eb8ee1d..56391977eae 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -4362,6 +4362,9 @@ LRESULT WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpa case NtUserImeDriverCall: return ime_driver_call( hwnd, msg, wparam, lparam, result_info );
+ case NtUserSystemTrayCall: + return system_tray_call( hwnd, msg, wparam, lparam, result_info ); + default: FIXME( "%p %x %lx %lx %p %x %x\n", hwnd, msg, (long)wparam, lparam, result_info, (int)type, ansi ); } diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 496d6bab9fe..11bb7f4baf6 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -23,6 +23,7 @@ #define __WINE_NTUSER_PRIVATE_H
#include "ntuser.h" +#include "shellapi.h" #include "wine/list.h"
@@ -249,6 +250,9 @@ extern void invalidate_dce( WND *win, const RECT *extra_rect ); /* message.c */ extern BOOL set_keyboard_auto_repeat( BOOL enable );
+/* systray.c */ +extern LRESULT system_tray_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, void *data ); + /* window.c */ HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ); void *free_user_handle( HANDLE handle, unsigned int type ); diff --git a/dlls/win32u/systray.c b/dlls/win32u/systray.c new file mode 100644 index 00000000000..2e4e2b757e5 --- /dev/null +++ b/dlls/win32u/systray.c @@ -0,0 +1,49 @@ +/* + * Copyright 2023 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "win32u_private.h" +#include "ntuser_private.h" +#include "shellapi.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(systray); + +LRESULT system_tray_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, void *data ) +{ + switch (msg) + { + case WINE_SYSTRAY_NOTIFY_ICON: + return user_driver->pNotifyIcon( hwnd, wparam, data ); + case WINE_SYSTRAY_CLEANUP_ICONS: + user_driver->pCleanupIcons( hwnd ); + return 0; + default: + FIXME( "Unknown NtUserSystemTrayCall msg %#x\n", msg ); + break; + } + + return -1; +} diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 43d83470a64..44b422ef62c 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -25,6 +25,7 @@ #include "windef.h" #include "winbase.h" #include "ntuser.h" +#include "shellapi.h" #include "wow64win_private.h" #include "wine/debug.h"
@@ -3600,6 +3601,58 @@ NTSTATUS WINAPI wow64_NtUserMessageCall( UINT *args ) params.compstr = UlongToPtr( params32->compstr ); return NtUserMessageCall( hwnd, msg, wparam, lparam, ¶ms, type, ansi ); } + + case NtUserSystemTrayCall: + switch (msg) + { + case WINE_SYSTRAY_NOTIFY_ICON: + { + struct + { + DWORD cbSize; + ULONG hWnd; + UINT uID; + UINT uFlags; + UINT uCallbackMessage; + ULONG hIcon; + WCHAR szTip[128]; + DWORD dwState; + DWORD dwStateMask; + WCHAR szInfo[256]; + UINT uTimeout; + WCHAR szInfoTitle[64]; + DWORD dwInfoFlags; + GUID guidItem; + ULONG hBalloonIcon; + } *params32 = result_info; + + NOTIFYICONDATAW params = {.cbSize = sizeof(params)}; + params.hWnd = UlongToHandle( params32->hWnd ); + params.uID = params32->uID; + params.uFlags = params32->uFlags; + params.uCallbackMessage = params32->uCallbackMessage; + params.hIcon = UlongToHandle( params32->hIcon ); + if (params.uFlags & NIF_TIP) wcscpy( params.szTip, params32->szTip ); + params.dwState = params32->dwState; + params.dwStateMask = params32->dwStateMask; + + if (params.uFlags & NIF_INFO) + { + wcscpy( params.szInfoTitle, params32->szInfoTitle ); + wcscpy( params.szInfo, params32->szInfo ); + params.uTimeout = params32->uTimeout; + params.dwInfoFlags = params32->dwInfoFlags; + } + + params.guidItem = params32->guidItem; + params.hBalloonIcon = UlongToHandle( params32->hBalloonIcon ); + + return NtUserMessageCall( hwnd, msg, wparam, lparam, ¶ms, type, ansi ); + } + + default: + return NtUserMessageCall( hwnd, msg, wparam, lparam, result_info, type, ansi ); + } }
return message_call_32to64( hwnd, msg, wparam, lparam, result_info, type, ansi ); diff --git a/include/ntuser.h b/include/ntuser.h index b62c2e60538..1ba55210e46 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -23,6 +23,7 @@ #include <wingdi.h> #include <imm.h> #include <immdev.h> +#include <shellapi.h> #include <winternl.h>
#ifndef W32KAPI @@ -314,6 +315,7 @@ enum NtUserSpyEnter = 0x0303, NtUserSpyExit = 0x0304, NtUserImeDriverCall = 0x0305, + NtUserSystemTrayCall = 0x0306, };
/* NtUserThunkedMenuItemInfo codes */ @@ -519,6 +521,13 @@ struct ime_driver_call_params COMPOSITIONSTRING *compstr; };
+/* NtUserSystemTrayCall calls */ +enum wine_systray_call +{ + WINE_SYSTRAY_NOTIFY_ICON, + WINE_SYSTRAY_CLEANUP_ICONS, +}; + #define WM_SYSTIMER 0x0118
diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index aa59a256482..8e42df3df96 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -28,6 +28,7 @@ #include "winternl.h" #include "ntuser.h" #include "immdev.h" +#include "shellapi.h" #include "ddk/d3dkmthk.h" #include "wine/list.h"
@@ -302,6 +303,9 @@ struct user_driver_funcs BOOL (*pGetCursorPos)(LPPOINT); BOOL (*pSetCursorPos)(INT,INT); BOOL (*pClipCursor)(const RECT*,BOOL); + /* notify icon functions */ + LRESULT (*pNotifyIcon)(HWND,UINT,NOTIFYICONDATAW *); + void (*pCleanupIcons)(HWND); /* clipboard functions */ LRESULT (*pClipboardWindowProc)(HWND,UINT,WPARAM,LPARAM); void (*pUpdateClipboard)(void); diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c index e3ec17a7708..ac0015e4ebf 100644 --- a/programs/explorer/systray.c +++ b/programs/explorer/systray.c @@ -21,6 +21,7 @@ #include <assert.h>
#include <windows.h> +#include <ntuser.h> #include <commctrl.h> #include <shellapi.h>
@@ -627,16 +628,14 @@ static BOOL delete_icon( struct icon *icon ) /* cleanup icons belonging to a window that has been destroyed */ static void cleanup_systray_window( HWND hwnd ) { + NOTIFYICONDATAW nid = {.cbSize = sizeof(nid), .hWnd = hwnd}; struct icon *icon, *next;
LIST_FOR_EACH_ENTRY_SAFE( icon, next, &icon_list, struct icon, entry ) if (icon->owner == hwnd) delete_icon( icon );
- if (wine_notify_icon) - { - NOTIFYICONDATAW nid = { sizeof(nid), hwnd }; - wine_notify_icon( 0xdead, &nid ); - } + NtUserMessageCall( hwnd, WINE_SYSTRAY_CLEANUP_ICONS, 0, 0, NULL, NtUserSystemTrayCall, FALSE ); + if (wine_notify_icon) wine_notify_icon( 0xdead, &nid ); }
/* update the taskbar buttons when something changed */ @@ -732,11 +731,11 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds) /* try forwarding to the display driver first */ if (cds->dwData == NIM_ADD || !(icon = get_icon( nid.hWnd, nid.uID ))) { + if ((ret = NtUserMessageCall( hwndSource, WINE_SYSTRAY_NOTIFY_ICON, cds->dwData, 0, + &nid, NtUserSystemTrayCall, FALSE )) != -1) + goto done; if (wine_notify_icon && ((ret = wine_notify_icon( cds->dwData, &nid )) != -1)) - { - if (nid.hIcon) DestroyIcon( nid.hIcon ); - return ret; - } + goto done; ret = FALSE; }
@@ -763,6 +762,7 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds) break; }
+done: if (nid.hIcon) DestroyIcon( nid.hIcon ); sync_taskbar_buttons(); return ret;