[PATCH 0/8] MR4540: explorer: Support dockable systray icons through a new NtUser interface.
Moving most systray code out of winex11, and removing the need for a custom export in winemac. Maybe winemac could use that new interface as well but I didn't want to mess with it too much. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/4540
From: Rémi Bernon <rbernon(a)codeweavers.com> --- programs/explorer/systray.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c index eb844a45003..2af028c0ef9 100644 --- a/programs/explorer/systray.c +++ b/programs/explorer/systray.c @@ -563,7 +563,7 @@ static BOOL modify_icon( struct icon *icon, NOTIFYICONDATAW *nid ) if (nid->uFlags & NIF_TIP) { lstrcpynW( icon->tiptext, nid->szTip, ARRAY_SIZE( icon->tiptext )); - if (icon->display != ICON_DISPLAY_HIDDEN) update_tooltip_text(icon); + update_tooltip_text( icon ); } if (nid->uFlags & NIF_INFO && nid->cbSize >= NOTIFYICONDATAA_V2_SIZE) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4540
From: Rémi Bernon <rbernon(a)codeweavers.com> --- programs/explorer/systray.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c index 2af028c0ef9..e3ec17a7708 100644 --- a/programs/explorer/systray.c +++ b/programs/explorer/systray.c @@ -938,6 +938,8 @@ static LRESULT WINAPI shell_traywnd_proc( HWND hwnd, UINT msg, WPARAM wparam, LP case WM_CLOSE: /* don't destroy the tray window, just hide it */ ShowWindow( hwnd, SW_HIDE ); + hide_balloon( balloon_icon ); + show_systray = FALSE; return 0; case WM_DRAWITEM: -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4540
From: Rémi Bernon <rbernon(a)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 943384efc30..855c3ae0f30 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 ) DECLSPEC_HIDDEN; +/* systray.c */ +extern LRESULT system_tray_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, void *data ) DECLSPEC_HIDDEN; + /* 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; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4540
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/winemac.drv/dllmain.c | 6 ---- dlls/winemac.drv/gdi.c | 2 ++ dlls/winemac.drv/macdrv.h | 3 +- dlls/winemac.drv/macdrv_main.c | 57 ------------------------------- dlls/winemac.drv/systray.c | 24 +++++-------- dlls/winemac.drv/unixlib.h | 8 ----- dlls/winemac.drv/winemac.drv.spec | 2 -- 7 files changed, 12 insertions(+), 90 deletions(-) diff --git a/dlls/winemac.drv/dllmain.c b/dlls/winemac.drv/dllmain.c index 8812426cc44..5917ed0906f 100644 --- a/dlls/winemac.drv/dllmain.c +++ b/dlls/winemac.drv/dllmain.c @@ -424,9 +424,3 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) macdrv_module = instance; return process_attach(); } - -int CDECL wine_notify_icon(DWORD msg, NOTIFYICONDATAW *data) -{ - struct notify_icon_params params = { .msg = msg, .data = data }; - return MACDRV_CALL(notify_icon, ¶ms); -} diff --git a/dlls/winemac.drv/gdi.c b/dlls/winemac.drv/gdi.c index 60ee9339467..6c2241514a9 100644 --- a/dlls/winemac.drv/gdi.c +++ b/dlls/winemac.drv/gdi.c @@ -269,6 +269,8 @@ static const struct user_driver_funcs macdrv_funcs = .pBeep = macdrv_Beep, .pChangeDisplaySettings = macdrv_ChangeDisplaySettings, .pClipCursor = macdrv_ClipCursor, + .pNotifyIcon = macdrv_NotifyIcon, + .pCleanupIcons = macdrv_CleanupIcons, .pClipboardWindowProc = macdrv_ClipboardWindowProc, .pDesktopWindowProc = macdrv_DesktopWindowProc, .pDestroyCursorIcon = macdrv_DestroyCursorIcon, diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index bcb048707ca..6e4a0d04f64 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -134,6 +134,8 @@ extern BOOL macdrv_UpdateDisplayDevices( const struct gdi_device_manager *device extern BOOL macdrv_GetDeviceGammaRamp(PHYSDEV dev, LPVOID ramp) DECLSPEC_HIDDEN; extern BOOL macdrv_SetDeviceGammaRamp(PHYSDEV dev, LPVOID ramp) DECLSPEC_HIDDEN; extern BOOL macdrv_ClipCursor(const RECT *clip, BOOL reset) DECLSPEC_HIDDEN; +extern LRESULT macdrv_NotifyIcon(HWND hwnd, UINT msg, NOTIFYICONDATAW *data) DECLSPEC_HIDDEN; +extern void macdrv_CleanupIcons(HWND hwnd) DECLSPEC_HIDDEN; extern LRESULT macdrv_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) DECLSPEC_HIDDEN; extern void macdrv_DestroyWindow(HWND hwnd) DECLSPEC_HIDDEN; extern void macdrv_SetDesktopWindow(HWND hwnd) DECLSPEC_HIDDEN; @@ -281,7 +283,6 @@ extern NTSTATUS macdrv_dnd_get_formats(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_dnd_have_format(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_dnd_release(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_dnd_retain(void *arg) DECLSPEC_HIDDEN; -extern NTSTATUS macdrv_notify_icon(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_client_func(enum macdrv_client_funcs func, const void *params, ULONG size) DECLSPEC_HIDDEN; diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c index b40bf02f267..21b148ff558 100644 --- a/dlls/winemac.drv/macdrv_main.c +++ b/dlls/winemac.drv/macdrv_main.c @@ -623,7 +623,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] = macdrv_dnd_release, macdrv_dnd_retain, macdrv_init, - macdrv_notify_icon, macdrv_quit_result, }; @@ -661,61 +660,6 @@ static NTSTATUS wow64_init(void *arg) return macdrv_init(¶ms); } -static NTSTATUS wow64_notify_icon(void *arg) -{ - struct - { - DWORD msg; - ULONG data; - } *params32 = arg; - 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; - } *data32 = UlongToPtr(params32->data); - - struct notify_icon_params params; - NOTIFYICONDATAW data; - - params.msg = params32->msg; - params.data = &data; - - data.cbSize = sizeof(data); - data.hWnd = UlongToHandle(data32->hWnd); - data.uID = data32->uID; - data.uFlags = data32->uFlags; - data.uCallbackMessage = data32->uCallbackMessage; - data.hIcon = UlongToHandle(data32->hIcon); - if (data.uFlags & NIF_TIP) - wcscpy(data.szTip, data32->szTip); - data.dwState = data32->dwState; - data.dwStateMask = data32->dwStateMask; - if (data.uFlags & NIF_INFO) - { - wcscpy(data.szInfoTitle, data32->szInfoTitle); - wcscpy(data.szInfo, data32->szInfo); - data.uTimeout = data32->uTimeout; - data.dwInfoFlags = data32->dwInfoFlags; - } - data.guidItem = data32->guidItem; - data.hBalloonIcon = UlongToHandle(data32->hBalloonIcon); - - return macdrv_notify_icon(¶ms); -} - const unixlib_entry_t __wine_unix_call_wow64_funcs[] = { wow64_dnd_get_data, @@ -724,7 +668,6 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = macdrv_dnd_release, macdrv_dnd_retain, wow64_init, - wow64_notify_icon, macdrv_quit_result, }; diff --git a/dlls/winemac.drv/systray.c b/dlls/winemac.drv/systray.c index 42ffe49f563..0231e08e82b 100644 --- a/dlls/winemac.drv/systray.c +++ b/dlls/winemac.drv/systray.c @@ -59,12 +59,11 @@ static struct list icon_list = LIST_INIT(icon_list); static BOOL delete_icon(struct tray_icon *icon); + /*********************************************************************** - * cleanup_icons - * - * Delete all systray icons owned by a given window. + * CleanupIcons (MACDRV.@) */ -static void cleanup_icons(HWND hwnd) +void macdrv_CleanupIcons(HWND hwnd) { struct tray_icon *icon, *next; @@ -245,18 +244,14 @@ static BOOL delete_icon(struct tray_icon *icon) /*********************************************************************** - * wine_notify_icon (MACDRV.@) - * - * Driver-side implementation of Shell_NotifyIcon. + * NotifyIcon (MACDRV.@) */ -NTSTATUS macdrv_notify_icon(void *arg) +LRESULT macdrv_NotifyIcon(HWND hwnd, UINT msg, NOTIFYICONDATAW *data) { - struct notify_icon_params *params = arg; - NOTIFYICONDATAW *data = params->data; BOOL ret = FALSE; struct tray_icon *icon; - switch (params->msg) + switch (msg) { case NIM_ADD: ret = add_icon(data); @@ -267,9 +262,6 @@ NTSTATUS macdrv_notify_icon(void *arg) case NIM_MODIFY: if ((icon = get_icon(data->hWnd, data->uID))) ret = modify_icon(icon, data); break; - case 0xdead: /* Wine extension: owner window has died */ - cleanup_icons(data->hWnd); - break; case NIM_SETVERSION: if ((icon = get_icon(data->hWnd, data->uID))) { @@ -278,8 +270,8 @@ NTSTATUS macdrv_notify_icon(void *arg) } break; default: - FIXME("unhandled tray message: %u\n", params->msg); - break; + ERR("Unexpected NotifyIconProc call\n"); + return -1; } return ret; } diff --git a/dlls/winemac.drv/unixlib.h b/dlls/winemac.drv/unixlib.h index 7f14517a8ee..e77a31a86c1 100644 --- a/dlls/winemac.drv/unixlib.h +++ b/dlls/winemac.drv/unixlib.h @@ -27,7 +27,6 @@ enum macdrv_funcs unix_dnd_release, unix_dnd_retain, unix_init, - unix_notify_icon, unix_quit_result, unix_funcs_count }; @@ -70,13 +69,6 @@ struct init_params struct localized_string *strings; }; -/* macdrv_notify_icon params */ -struct notify_icon_params -{ - unsigned int msg; - struct _NOTIFYICONDATAW *data; -}; - /* macdrv_quit_result params */ struct quit_result_params { diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec index 5f086f5c4e5..e69de29bb2d 100644 --- a/dlls/winemac.drv/winemac.drv.spec +++ b/dlls/winemac.drv/winemac.drv.spec @@ -1,2 +0,0 @@ -# System tray -@ cdecl wine_notify_icon(long ptr) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4540
From: Rémi Bernon <rbernon(a)codeweavers.com> explorer: Add WS_CHILD style to systray icon windows. --- dlls/win32u/driver.c | 46 +++++++++++++++++++++++++++++++++++++ dlls/win32u/systray.c | 12 ++++++++++ include/ntuser.h | 4 ++++ include/wine/gdi_driver.h | 4 ++++ programs/explorer/systray.c | 23 ++++++++++++++++--- 5 files changed, 86 insertions(+), 3 deletions(-) diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 14488419b14..6676a946514 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -766,6 +766,24 @@ static void nulldrv_CleanupIcons( HWND hwnd ) { } +static void nulldrv_SystrayDockInit( HWND hwnd ) +{ +} + +static BOOL nulldrv_SystrayDockInsert( HWND hwnd, UINT cx, UINT cy, void *icon ) +{ + return FALSE; +} + +static void nulldrv_SystrayDockClear( HWND hwnd ) +{ +} + +static BOOL nulldrv_SystrayDockRemove( HWND hwnd ) +{ + return FALSE; +} + static void nulldrv_UpdateClipboard(void) { } @@ -1157,6 +1175,26 @@ static void loaderdrv_CleanupIcons( HWND hwnd ) load_driver()->pCleanupIcons( hwnd ); } +static void loaderdrv_SystrayDockInit( HWND hwnd ) +{ + load_driver()->pSystrayDockInit( hwnd ); +} + +static BOOL loaderdrv_SystrayDockInsert( HWND hwnd, UINT cx, UINT cy, void *icon ) +{ + return load_driver()->pSystrayDockInsert( hwnd, cx, cy, icon ); +} + +static void loaderdrv_SystrayDockClear( HWND hwnd ) +{ + load_driver()->pSystrayDockClear( hwnd ); +} + +static BOOL loaderdrv_SystrayDockRemove( HWND hwnd ) +{ + return load_driver()->pSystrayDockRemove( hwnd ); +} + static LRESULT nulldrv_ClipboardWindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { return 0; @@ -1244,6 +1282,10 @@ static const struct user_driver_funcs lazy_load_driver = /* systray functions */ loaderdrv_NotifyIcon, loaderdrv_CleanupIcons, + loaderdrv_SystrayDockInit, + loaderdrv_SystrayDockInsert, + loaderdrv_SystrayDockClear, + loaderdrv_SystrayDockRemove, /* clipboard functions */ nulldrv_ClipboardWindowProc, loaderdrv_UpdateClipboard, @@ -1328,6 +1370,10 @@ void __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version SET_USER_FUNC(ClipCursor); SET_USER_FUNC(NotifyIcon); SET_USER_FUNC(CleanupIcons); + SET_USER_FUNC(SystrayDockInit); + SET_USER_FUNC(SystrayDockInsert); + SET_USER_FUNC(SystrayDockClear); + SET_USER_FUNC(SystrayDockRemove); SET_USER_FUNC(ClipboardWindowProc); SET_USER_FUNC(UpdateClipboard); SET_USER_FUNC(ChangeDisplaySettings); diff --git a/dlls/win32u/systray.c b/dlls/win32u/systray.c index 2e4e2b757e5..67217dad634 100644 --- a/dlls/win32u/systray.c +++ b/dlls/win32u/systray.c @@ -40,6 +40,18 @@ LRESULT system_tray_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, voi case WINE_SYSTRAY_CLEANUP_ICONS: user_driver->pCleanupIcons( hwnd ); return 0; + + case WINE_SYSTRAY_DOCK_INIT: + user_driver->pSystrayDockInit( hwnd ); + return 0; + case WINE_SYSTRAY_DOCK_INSERT: + return user_driver->pSystrayDockInsert( hwnd, wparam, lparam, data ); + case WINE_SYSTRAY_DOCK_CLEAR: + user_driver->pSystrayDockClear( hwnd ); + return 0; + case WINE_SYSTRAY_DOCK_REMOVE: + return user_driver->pSystrayDockRemove( hwnd ); + default: FIXME( "Unknown NtUserSystemTrayCall msg %#x\n", msg ); break; diff --git a/include/ntuser.h b/include/ntuser.h index 1ba55210e46..dd19c57221e 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -526,6 +526,10 @@ enum wine_systray_call { WINE_SYSTRAY_NOTIFY_ICON, WINE_SYSTRAY_CLEANUP_ICONS, + WINE_SYSTRAY_DOCK_INIT, + WINE_SYSTRAY_DOCK_INSERT, + WINE_SYSTRAY_DOCK_CLEAR, + WINE_SYSTRAY_DOCK_REMOVE, }; #define WM_SYSTIMER 0x0118 diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 8e42df3df96..e27bd708eaa 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -306,6 +306,10 @@ struct user_driver_funcs /* notify icon functions */ LRESULT (*pNotifyIcon)(HWND,UINT,NOTIFYICONDATAW *); void (*pCleanupIcons)(HWND); + void (*pSystrayDockInit)(HWND); + BOOL (*pSystrayDockInsert)(HWND,UINT,UINT,void *); + void (*pSystrayDockClear)(HWND); + BOOL (*pSystrayDockRemove)(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 ac0015e4ebf..1cf0e9a7b8d 100644 --- a/programs/explorer/systray.c +++ b/programs/explorer/systray.c @@ -60,6 +60,7 @@ struct notify_data /* platform-independent format for NOTIFYICONDATA */ static int (CDECL *wine_notify_icon)(DWORD,NOTIFYICONDATAW *); #define ICON_DISPLAY_HIDDEN -1 +#define ICON_DISPLAY_DOCKED -2 /* an individual systray icon, unpacked from the NOTIFYICONDATA and always in unicode */ struct icon @@ -472,6 +473,8 @@ static void systray_add_icon( struct icon *icon ) if (icon->display != ICON_DISPLAY_HIDDEN) return; /* already added */ icon->display = nb_displayed++; + SetWindowLongW( icon->window, GWL_STYLE, GetWindowLongW( icon->window, GWL_STYLE ) | WS_CHILD ); + SetParent( icon->window, tray_window ); pos = get_icon_pos( icon ); SetWindowPos( icon->window, 0, pos.x, pos.y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW ); @@ -502,6 +505,8 @@ static void systray_remove_icon( struct icon *icon ) TRACE( "removed %u now %d icons\n", icon->id, nb_displayed ); icon->display = ICON_DISPLAY_HIDDEN; + SetParent( icon->window, GetDesktopWindow() ); + SetWindowLongW( icon->window, GWL_STYLE, GetWindowLongW( icon->window, GWL_STYLE ) & ~WS_CHILD ); } /* make an icon visible */ @@ -511,6 +516,9 @@ static BOOL show_icon(struct icon *icon) if (icon->display != ICON_DISPLAY_HIDDEN) return TRUE; /* already displayed */ + if (!enable_taskbar && NtUserMessageCall( icon->window, WINE_SYSTRAY_DOCK_INSERT, icon_cx, + icon_cy, icon, NtUserSystemTrayCall, FALSE )) + icon->display = ICON_DISPLAY_DOCKED; systray_add_icon( icon ); update_tooltip_position( icon ); @@ -525,6 +533,9 @@ static BOOL hide_icon(struct icon *icon) if (icon->display == ICON_DISPLAY_HIDDEN) return TRUE; /* already hidden */ + if (!enable_taskbar && NtUserMessageCall( icon->window, WINE_SYSTRAY_DOCK_REMOVE, 0, 0, + NULL, NtUserSystemTrayCall, FALSE )) + icon->display = ICON_DISPLAY_HIDDEN; ShowWindow( icon->window, SW_HIDE ); systray_remove_icon( icon ); @@ -554,7 +565,12 @@ static BOOL modify_icon( struct icon *icon, NOTIFYICONDATAW *nid ) { if (icon->image) DestroyIcon(icon->image); icon->image = CopyIcon(nid->hIcon); - if (icon->display >= 0) InvalidateRect( icon->window, NULL, TRUE ); + + if (icon->display >= 0) + InvalidateRect( icon->window, NULL, TRUE ); + else if (!enable_taskbar) + NtUserMessageCall( icon->window, WINE_SYSTRAY_DOCK_CLEAR, 0, 0, + NULL, NtUserSystemTrayCall, FALSE ); } if (nid->uFlags & NIF_MESSAGE) @@ -604,8 +620,8 @@ static BOOL add_icon(NOTIFYICONDATAW *nid) icon->owner = nid->hWnd; icon->display = ICON_DISPLAY_HIDDEN; - CreateWindowW( tray_icon_class.lpszClassName, NULL, WS_CHILD, - 0, 0, icon_cx, icon_cy, tray_window, NULL, NULL, icon ); + CreateWindowExW( 0, tray_icon_class.lpszClassName, NULL, WS_CLIPSIBLINGS | WS_POPUP, + 0, 0, icon_cx, icon_cy, 0, NULL, NULL, icon ); if (!icon->window) ERR( "Failed to create systray icon window\n" ); list_add_tail(&icon_list, &icon->entry); @@ -1027,6 +1043,7 @@ void initialize_systray( HMODULE graphics_driver, BOOL using_root, BOOL arg_enab SIZE size = get_window_size(); tray_window = CreateWindowExW( 0, shell_traywnd_class.lpszClassName, L"", WS_CAPTION | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, size.cx, size.cy, 0, 0, 0, 0 ); + NtUserMessageCall( tray_window, WINE_SYSTRAY_DOCK_INIT, 0, 0, NULL, NtUserSystemTrayCall, FALSE ); } if (!tray_window) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4540
From: Rémi Bernon <rbernon(a)codeweavers.com> --- programs/explorer/systray.c | 102 ++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 5 deletions(-) diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c index 1cf0e9a7b8d..94b2a856ba0 100644 --- a/programs/explorer/systray.c +++ b/programs/explorer/systray.c @@ -69,6 +69,7 @@ struct icon HICON image; /* the image to render */ HWND owner; /* the HWND passed in to the Shell_NotifyIcon call */ HWND window; /* the adaptor window */ + BOOL layered; /* whether we are using a layered window */ HWND tooltip; /* Icon tooltip */ UINT state; /* state flags */ UINT id; /* the unique id given by the app */ @@ -363,6 +364,80 @@ static void update_tooltip_position( struct icon *icon ) if (balloon_icon == icon) set_balloon_position( icon ); } +static void paint_layered_icon( struct icon *icon ) +{ + BLENDFUNCTION blend = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; + int width = GetSystemMetrics( SM_CXSMICON ); + int height = GetSystemMetrics( SM_CYSMICON ); + BITMAPINFO *info; + HBITMAP dib, mask; + HDC hdc; + RECT rc; + SIZE size; + POINT pos; + int i, x, y; + void *color_bits, *mask_bits; + DWORD *ptr; + BOOL has_alpha = FALSE; + + GetWindowRect( icon->window, &rc ); + size.cx = rc.right - rc.left; + size.cy = rc.bottom - rc.top; + pos.x = (size.cx - width) / 2; + pos.y = (size.cy - height) / 2; + + if (!(info = calloc( 1, FIELD_OFFSET( BITMAPINFO, bmiColors[2] ) ))) return; + info->bmiHeader.biSize = sizeof(info->bmiHeader); + info->bmiHeader.biWidth = size.cx; + info->bmiHeader.biHeight = size.cy; + info->bmiHeader.biBitCount = 32; + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biCompression = BI_RGB; + + hdc = CreateCompatibleDC( 0 ); + if (!(dib = CreateDIBSection( 0, info, DIB_RGB_COLORS, &color_bits, NULL, 0 ))) goto done; + SelectObject( hdc, dib ); + DrawIconEx( hdc, pos.x, pos.y, icon->image, width, height, 0, 0, DI_DEFAULTSIZE | DI_NORMAL ); + + /* check if the icon was drawn with an alpha channel */ + for (i = 0, ptr = color_bits; i < size.cx * size.cy; i++) + if ((has_alpha = (ptr[i] & 0xff000000) != 0)) break; + + if (!has_alpha) + { + unsigned int width_bytes = (size.cx + 31) / 32 * 4; + + info->bmiHeader.biBitCount = 1; + info->bmiColors[0].rgbRed = 0; + info->bmiColors[0].rgbGreen = 0; + info->bmiColors[0].rgbBlue = 0; + info->bmiColors[0].rgbReserved = 0; + info->bmiColors[1].rgbRed = 0xff; + info->bmiColors[1].rgbGreen = 0xff; + info->bmiColors[1].rgbBlue = 0xff; + info->bmiColors[1].rgbReserved = 0; + + if (!(mask = CreateDIBSection( 0, info, DIB_RGB_COLORS, &mask_bits, NULL, 0 ))) goto done; + memset( mask_bits, 0xff, width_bytes * size.cy ); + SelectObject( hdc, mask ); + DrawIconEx( hdc, pos.x, pos.y, icon->image, width, height, 0, 0, DI_DEFAULTSIZE | DI_MASK ); + + for (y = 0, ptr = color_bits; y < size.cy; y++) + for (x = 0; x < size.cx; x++, ptr++) + if (!((((BYTE *)mask_bits)[y * width_bytes + x / 8] << (x % 8)) & 0x80)) + *ptr |= 0xff000000; + + SelectObject( hdc, dib ); + DeleteObject( mask ); + } + + UpdateLayeredWindow( icon->window, 0, NULL, NULL, hdc, NULL, 0, &blend, ULW_ALPHA ); +done: + free( info ); + if (hdc) DeleteDC( hdc ); + if (dib) DeleteObject( dib ); +} + static BOOL notify_owner( struct icon *icon, UINT msg, LPARAM lparam ) { WPARAM wp = icon->id; @@ -410,14 +485,22 @@ static LRESULT WINAPI tray_icon_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPA create_tooltip( icon ); break; + case WM_SIZE: + case WM_MOVE: + if (icon->layered) paint_layered_icon( icon ); + break; + case WM_PAINT: { PAINTSTRUCT ps; RECT rc; HDC hdc; - int cx = GetSystemMetrics( SM_CXSMICON ); - int cy = GetSystemMetrics( SM_CYSMICON ); + int cx, cy; + + if (icon->layered) break; + cx = GetSystemMetrics( SM_CXSMICON ); + cy = GetSystemMetrics( SM_CYSMICON ); hdc = BeginPaint( hwnd, &ps ); GetClientRect( hwnd, &rc ); TRACE( "painting rect %s\n", wine_dbgstr_rect( &rc ) ); @@ -516,9 +599,13 @@ static BOOL show_icon(struct icon *icon) if (icon->display != ICON_DISPLAY_HIDDEN) return TRUE; /* already displayed */ - if (!enable_taskbar && NtUserMessageCall( icon->window, WINE_SYSTRAY_DOCK_INSERT, icon_cx, - icon_cy, icon, NtUserSystemTrayCall, FALSE )) + if (!enable_taskbar && NtUserMessageCall( icon->window, WINE_SYSTRAY_DOCK_INSERT, icon_cx, icon_cy, + icon, NtUserSystemTrayCall, FALSE )) + { icon->display = ICON_DISPLAY_DOCKED; + icon->layered = TRUE; + SendMessageW( icon->window, WM_SIZE, SIZE_RESTORED, MAKELONG( icon_cx, icon_cy ) ); + } systray_add_icon( icon ); update_tooltip_position( icon ); @@ -535,7 +622,10 @@ static BOOL hide_icon(struct icon *icon) if (!enable_taskbar && NtUserMessageCall( icon->window, WINE_SYSTRAY_DOCK_REMOVE, 0, 0, NULL, NtUserSystemTrayCall, FALSE )) + { icon->display = ICON_DISPLAY_HIDDEN; + icon->layered = FALSE; + } ShowWindow( icon->window, SW_HIDE ); systray_remove_icon( icon ); @@ -568,6 +658,8 @@ static BOOL modify_icon( struct icon *icon, NOTIFYICONDATAW *nid ) if (icon->display >= 0) InvalidateRect( icon->window, NULL, TRUE ); + else if (icon->layered) + paint_layered_icon( icon ); else if (!enable_taskbar) NtUserMessageCall( icon->window, WINE_SYSTRAY_DOCK_CLEAR, 0, 0, NULL, NtUserSystemTrayCall, FALSE ); @@ -620,7 +712,7 @@ static BOOL add_icon(NOTIFYICONDATAW *nid) icon->owner = nid->hWnd; icon->display = ICON_DISPLAY_HIDDEN; - CreateWindowExW( 0, tray_icon_class.lpszClassName, NULL, WS_CLIPSIBLINGS | WS_POPUP, + CreateWindowExW( WS_EX_LAYERED, tray_icon_class.lpszClassName, NULL, WS_CLIPSIBLINGS | WS_POPUP, 0, 0, icon_cx, icon_cy, 0, NULL, NULL, icon ); if (!icon->window) ERR( "Failed to create systray icon window\n" ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4540
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/winex11.drv/dllmain.c | 2 - dlls/winex11.drv/event.c | 6 +- dlls/winex11.drv/init.c | 4 + dlls/winex11.drv/systray.c | 748 +----------------------------- dlls/winex11.drv/unixlib.h | 20 - dlls/winex11.drv/window.c | 82 ++-- dlls/winex11.drv/winex11.drv.spec | 3 - dlls/winex11.drv/x11drv.h | 10 +- dlls/winex11.drv/x11drv_dll.h | 2 - dlls/winex11.drv/x11drv_main.c | 48 +- programs/explorer/systray.c | 18 + 11 files changed, 60 insertions(+), 883 deletions(-) diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 99e2d47c508..b0a579e4ee2 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -47,7 +47,6 @@ static const kernel_callback kernel_callbacks[] = x11drv_dnd_enter_event, x11drv_dnd_position_event, x11drv_dnd_post_drop, - x11drv_systray_change_owner, }; C_ASSERT( NtUserDriverCallbackFirst + ARRAYSIZE(kernel_callbacks) == client_func_last ); @@ -59,7 +58,6 @@ BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved ) struct init_params params = { foreign_window_proc, - &show_systray, }; if (reason != DLL_PROCESS_ATTACH) return TRUE; diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 97bec34b0ea..97ebf4ae0d6 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -603,12 +603,8 @@ static void handle_manager_message( HWND hwnd, XClientMessageEvent *event ) if (systray_atom && event->data.l[1] == systray_atom) { - struct systray_change_owner_params params; - TRACE( "new owner %lx\n", event->data.l[2] ); - - params.event_handle = (UINT_PTR)event; - x11drv_client_func( client_func_systray_change_owner, ¶ms, sizeof(params) ); + NtUserPostMessage( systray_hwnd, WM_USER + 1, 0, 0 ); } } diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index c3d54da1d4d..2cef05d2140 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -404,6 +404,10 @@ static const struct user_driver_funcs x11drv_funcs = .pGetCursorPos = X11DRV_GetCursorPos, .pSetCursorPos = X11DRV_SetCursorPos, .pClipCursor = X11DRV_ClipCursor, + .pSystrayDockInit = X11DRV_SystrayDockInit, + .pSystrayDockInsert = X11DRV_SystrayDockInsert, + .pSystrayDockClear = X11DRV_SystrayDockClear, + .pSystrayDockRemove = X11DRV_SystrayDockRemove, .pChangeDisplaySettings = X11DRV_ChangeDisplaySettings, .pGetCurrentDisplaySettings = X11DRV_GetCurrentDisplaySettings, .pGetDisplayDepth = X11DRV_GetDisplayDepth, diff --git a/dlls/winex11.drv/systray.c b/dlls/winex11.drv/systray.c index db6c7bc88fe..e21ce481f9b 100644 --- a/dlls/winex11.drv/systray.c +++ b/dlls/winex11.drv/systray.c @@ -29,757 +29,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(systray); -BOOL show_systray = TRUE; - -/* an individual systray icon */ -struct tray_icon -{ - struct list entry; - HICON image; /* the image to render */ - HWND owner; /* the HWND passed in to the Shell_NotifyIcon call */ - HWND window; /* the adaptor window */ - BOOL layered; /* whether we are using a layered window */ - HWND tooltip; /* Icon tooltip */ - UINT state; /* state flags */ - UINT id; /* the unique id given by the app */ - UINT callback_message; - int display; /* display index, or -1 if hidden */ - WCHAR tiptext[128]; /* tooltip text */ - WCHAR info_text[256]; /* info balloon text */ - WCHAR info_title[64]; /* info balloon title */ - 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 ); - -static const WCHAR icon_classname[] = {'_','_','w','i','n','e','x','1','1','_','t','r','a','y','_','i','c','o','n',0}; -static const WCHAR tray_classname[] = {'_','_','w','i','n','e','x','1','1','_','s','t','a','n','d','a','l','o','n','e','_','t','r','a','y',0}; - -static BOOL show_icon( struct tray_icon *icon ); -static BOOL hide_icon( struct tray_icon *icon ); -static BOOL delete_icon( struct tray_icon *icon ); - -#define MIN_DISPLAYED 8 -#define ICON_BORDER 2 - -#define BALLOON_CREATE_TIMER 1 -#define BALLOON_SHOW_TIMER 2 - -#define BALLOON_CREATE_TIMEOUT 2000 -#define BALLOON_SHOW_MIN_TIMEOUT 10000 -#define BALLOON_SHOW_MAX_TIMEOUT 30000 - -static struct tray_icon *balloon_icon; -static HWND balloon_window; -static POINT balloon_pos; - -/* stand-alone tray window */ -static HWND standalone_tray; -static int icon_cx, icon_cy; -static unsigned int nb_displayed; - -/* retrieves icon record by owner window and ID */ -static struct tray_icon *get_icon(HWND owner, UINT id) -{ - struct tray_icon *this; - - LIST_FOR_EACH_ENTRY( this, &icon_list, struct tray_icon, entry ) - if ((this->id == id) && (this->owner == owner)) return this; - return NULL; -} - -static void init_common_controls(void) -{ - static BOOL initialized = FALSE; - - if (!initialized) - { - INITCOMMONCONTROLSEX init_tooltip; - - init_tooltip.dwSize = sizeof(INITCOMMONCONTROLSEX); - init_tooltip.dwICC = ICC_TAB_CLASSES; - - InitCommonControlsEx(&init_tooltip); - initialized = TRUE; - } -} - -/* create tooltip window for icon */ -static void create_tooltip(struct tray_icon *icon) -{ - init_common_controls(); - icon->tooltip = CreateWindowExW( WS_EX_TOPMOST, TOOLTIPS_CLASSW, NULL, - WS_POPUP | TTS_ALWAYSTIP, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - icon->window, NULL, NULL, NULL); - if (icon->tooltip) - { - TTTOOLINFOW ti; - ZeroMemory(&ti, sizeof(ti)); - ti.cbSize = sizeof(TTTOOLINFOW); - ti.uFlags = TTF_SUBCLASS | TTF_IDISHWND; - ti.hwnd = icon->window; - ti.uId = (UINT_PTR)icon->window; - ti.lpszText = icon->tiptext; - SendMessageW(icon->tooltip, TTM_ADDTOOLW, 0, (LPARAM)&ti); - } -} - -static void update_systray_balloon_position(void) -{ - RECT rect; - POINT pos; - - if (!balloon_icon) return; - GetWindowRect( balloon_icon->window, &rect ); - pos.x = (rect.left + rect.right) / 2; - pos.y = (rect.top + rect.bottom) / 2; - if (pos.x == balloon_pos.x && pos.y == balloon_pos.y) return; /* nothing changed */ - balloon_pos = pos; - SendMessageW( balloon_window, TTM_TRACKPOSITION, 0, MAKELONG( pos.x, pos.y )); -} - -static void balloon_create_timer( struct tray_icon *icon ) -{ - TTTOOLINFOW ti; - - init_common_controls(); - balloon_window = CreateWindowExW( WS_EX_TOPMOST, TOOLTIPS_CLASSW, NULL, - WS_POPUP | TTS_ALWAYSTIP | TTS_NOPREFIX | TTS_BALLOON | TTS_CLOSE, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - icon->window, NULL, NULL, NULL); - - memset( &ti, 0, sizeof(ti) ); - ti.cbSize = sizeof(TTTOOLINFOW); - ti.hwnd = icon->window; - ti.uId = (UINT_PTR)icon->window; - ti.uFlags = TTF_TRACK | TTF_IDISHWND; - ti.lpszText = icon->info_text; - SendMessageW( balloon_window, TTM_ADDTOOLW, 0, (LPARAM)&ti ); - if ((icon->info_flags & NIIF_ICONMASK) == NIIF_USER) - SendMessageW( balloon_window, TTM_SETTITLEW, (WPARAM)icon->info_icon, (LPARAM)icon->info_title ); - else - SendMessageW( balloon_window, TTM_SETTITLEW, icon->info_flags, (LPARAM)icon->info_title ); - balloon_icon = icon; - balloon_pos.x = balloon_pos.y = MAXLONG; - update_systray_balloon_position(); - SendMessageW( balloon_window, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti ); - KillTimer( icon->window, BALLOON_CREATE_TIMER ); - SetTimer( icon->window, BALLOON_SHOW_TIMER, icon->info_timeout, NULL ); -} - -static BOOL show_balloon( struct tray_icon *icon ) -{ - if (standalone_tray && !show_systray) return FALSE; /* no systray window */ - if (!icon->window) return FALSE; /* not displayed */ - if (!icon->info_text[0]) return FALSE; /* no balloon */ - balloon_icon = icon; - SetTimer( icon->window, BALLOON_CREATE_TIMER, BALLOON_CREATE_TIMEOUT, NULL ); - return TRUE; -} - -static void hide_balloon(void) -{ - if (!balloon_icon) return; - if (balloon_window) - { - KillTimer( balloon_icon->window, BALLOON_SHOW_TIMER ); - DestroyWindow( balloon_window ); - balloon_window = 0; - } - else KillTimer( balloon_icon->window, BALLOON_CREATE_TIMER ); - balloon_icon = NULL; -} - -static void show_next_balloon(void) -{ - struct tray_icon *icon; - - LIST_FOR_EACH_ENTRY( icon, &icon_list, struct tray_icon, entry ) - if (show_balloon( icon )) break; -} - -static void update_balloon( struct tray_icon *icon ) -{ - if (balloon_icon == icon) - { - hide_balloon(); - show_balloon( icon ); - } - else if (!balloon_icon) - { - if (!show_balloon( icon )) return; - } - if (!balloon_icon) show_next_balloon(); -} - -static void balloon_timer(void) -{ - if (balloon_icon) balloon_icon->info_text[0] = 0; /* clear text now that balloon has been shown */ - hide_balloon(); - show_next_balloon(); -} - -/* synchronize tooltip text with tooltip window */ -static void update_tooltip_text(struct tray_icon *icon) -{ - TTTOOLINFOW ti; - - ZeroMemory(&ti, sizeof(ti)); - ti.cbSize = sizeof(TTTOOLINFOW); - ti.uFlags = TTF_SUBCLASS | TTF_IDISHWND; - ti.hwnd = icon->window; - ti.uId = (UINT_PTR)icon->window; - ti.lpszText = icon->tiptext; - - SendMessageW(icon->tooltip, TTM_UPDATETIPTEXTW, 0, (LPARAM)&ti); -} - -/* get the size of the stand-alone tray window */ -static SIZE get_window_size(void) -{ - SIZE size; - RECT rect; - - rect.left = 0; - rect.top = 0; - rect.right = icon_cx * max( nb_displayed, MIN_DISPLAYED ); - rect.bottom = icon_cy; - AdjustWindowRect( &rect, WS_CAPTION, FALSE ); - size.cx = rect.right - rect.left; - size.cy = rect.bottom - rect.top; - return size; -} - -/* get the position of an icon in the stand-alone tray */ -static POINT get_icon_pos( struct tray_icon *icon ) -{ - POINT pos; - - pos.x = icon_cx * icon->display; - pos.y = 0; - return pos; -} - -/* window procedure for the standalone tray window */ -static LRESULT WINAPI standalone_tray_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) -{ - switch (msg) - { - case WM_MOVE: - update_systray_balloon_position(); - break; - case WM_CLOSE: - ShowWindow( hwnd, SW_HIDE ); - hide_balloon(); - show_systray = FALSE; - return 0; - case WM_DESTROY: - standalone_tray = 0; - break; - } - return DefWindowProcW( hwnd, msg, wparam, lparam ); -} - -/* add an icon to the standalone tray window */ -static void add_to_standalone_tray( struct tray_icon *icon ) -{ - SIZE size; - POINT pos; - - if (!standalone_tray) - { - static const WCHAR winname[] = {'W','i','n','e',' ','S','y','s','t','e','m',' ','T','r','a','y',0}; - - size = get_window_size(); - standalone_tray = CreateWindowExW( 0, tray_classname, winname, WS_CAPTION | WS_SYSMENU, - CW_USEDEFAULT, CW_USEDEFAULT, size.cx, size.cy, 0, 0, 0, 0 ); - if (!standalone_tray) return; - } - - icon->display = nb_displayed; - pos = get_icon_pos( icon ); - CreateWindowW( icon_classname, NULL, WS_CHILD | WS_VISIBLE, - pos.x, pos.y, icon_cx, icon_cy, standalone_tray, NULL, NULL, icon ); - if (!icon->window) - { - icon->display = -1; - return; - } - - nb_displayed++; - size = get_window_size(); - SetWindowPos( standalone_tray, 0, 0, 0, size.cx, size.cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER ); - if (nb_displayed == 1 && show_systray) ShowWindow( standalone_tray, SW_SHOWNA ); - TRACE( "added %u now %d icons\n", icon->id, nb_displayed ); -} - -/* remove an icon from the stand-alone tray */ -static void remove_from_standalone_tray( struct tray_icon *icon ) -{ - struct tray_icon *ptr; - POINT pos; - - if (icon->display == -1) return; - - LIST_FOR_EACH_ENTRY( ptr, &icon_list, struct tray_icon, entry ) - { - if (ptr == icon) continue; - if (ptr->display < icon->display) continue; - ptr->display--; - pos = get_icon_pos( ptr ); - SetWindowPos( ptr->window, 0, pos.x, pos.y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER ); - } - icon->display = -1; - if (!--nb_displayed) ShowWindow( standalone_tray, SW_HIDE ); - TRACE( "removed %u now %d icons\n", icon->id, nb_displayed ); -} - -static void repaint_tray_icon( struct tray_icon *icon ) -{ - BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; - int width = GetSystemMetrics( SM_CXSMICON ); - int height = GetSystemMetrics( SM_CYSMICON ); - BITMAPINFO *info; - HBITMAP dib, mask; - HDC hdc; - RECT rc; - SIZE size; - POINT pos; - int i, x, y; - void *color_bits, *mask_bits; - DWORD *ptr; - BOOL has_alpha = FALSE; - - GetWindowRect( icon->window, &rc ); - size.cx = rc.right - rc.left; - size.cy = rc.bottom - rc.top; - pos.x = (size.cx - width) / 2; - pos.y = (size.cy - height) / 2; - - info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET( BITMAPINFO, bmiColors[2] )); - if (!info) return; - info->bmiHeader.biSize = sizeof(info->bmiHeader); - info->bmiHeader.biWidth = size.cx; - info->bmiHeader.biHeight = size.cy; - info->bmiHeader.biBitCount = 32; - info->bmiHeader.biPlanes = 1; - info->bmiHeader.biCompression = BI_RGB; - - hdc = CreateCompatibleDC( 0 ); - if (!(dib = CreateDIBSection( 0, info, DIB_RGB_COLORS, &color_bits, NULL, 0 ))) goto done; - SelectObject( hdc, dib ); - DrawIconEx( hdc, pos.x, pos.y, icon->image, width, height, 0, 0, DI_DEFAULTSIZE | DI_NORMAL ); - - /* check if the icon was drawn with an alpha channel */ - for (i = 0, ptr = color_bits; i < size.cx * size.cy; i++) - if ((has_alpha = (ptr[i] & 0xff000000) != 0)) break; - - if (!has_alpha) - { - unsigned int width_bytes = (size.cx + 31) / 32 * 4; - - info->bmiHeader.biBitCount = 1; - info->bmiColors[0].rgbRed = 0; - info->bmiColors[0].rgbGreen = 0; - info->bmiColors[0].rgbBlue = 0; - info->bmiColors[0].rgbReserved = 0; - info->bmiColors[1].rgbRed = 0xff; - info->bmiColors[1].rgbGreen = 0xff; - info->bmiColors[1].rgbBlue = 0xff; - info->bmiColors[1].rgbReserved = 0; - - if (!(mask = CreateDIBSection( 0, info, DIB_RGB_COLORS, &mask_bits, NULL, 0 ))) goto done; - memset( mask_bits, 0xff, width_bytes * size.cy ); - SelectObject( hdc, mask ); - DrawIconEx( hdc, pos.x, pos.y, icon->image, width, height, 0, 0, DI_DEFAULTSIZE | DI_MASK ); - - for (y = 0, ptr = color_bits; y < size.cy; y++) - for (x = 0; x < size.cx; x++, ptr++) - if (!((((BYTE *)mask_bits)[y * width_bytes + x / 8] << (x % 8)) & 0x80)) - *ptr |= 0xff000000; - - SelectObject( hdc, dib ); - DeleteObject( mask ); - } - - UpdateLayeredWindow( icon->window, 0, NULL, NULL, hdc, NULL, 0, &blend, ULW_ALPHA ); -done: - HeapFree (GetProcessHeap(), 0, info); - if (hdc) DeleteDC( hdc ); - if (dib) DeleteObject( dib ); -} - -static BOOL notify_owner( struct tray_icon *icon, UINT msg, LPARAM lparam ) -{ - WPARAM wp = icon->id; - LPARAM lp = msg; - - if (icon->version >= NOTIFYICON_VERSION_4) - { - POINT pt = { (short)LOWORD(lparam), (short)HIWORD(lparam) }; - - ClientToScreen( icon->window, &pt ); - wp = MAKEWPARAM( pt.x, pt.y ); - lp = MAKELPARAM( msg, icon->id ); - } - - TRACE( "relaying 0x%x\n", msg ); - if (!SendNotifyMessageW( icon->owner, icon->callback_message, wp, lp ) && - (GetLastError() == ERROR_INVALID_WINDOW_HANDLE)) - { - WARN( "application window was destroyed, removing icon %u\n", icon->id ); - delete_icon( icon ); - return FALSE; - } - return TRUE; -} - -/* window procedure for the individual tray icon window */ -static LRESULT WINAPI tray_icon_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - struct tray_icon *icon = NULL; - - TRACE("hwnd=%p, msg=0x%x\n", hwnd, msg); - - /* set the icon data for the window from the data passed into CreateWindow */ - if (msg == WM_NCCREATE) - SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LPARAM)((const CREATESTRUCTW *)lparam)->lpCreateParams); - - icon = (struct tray_icon *) GetWindowLongPtrW(hwnd, GWLP_USERDATA); - - switch (msg) - { - case WM_CREATE: - icon->window = hwnd; - create_tooltip( icon ); - break; - - case WM_SIZE: - if (icon->window && icon->layered) repaint_tray_icon( icon ); - break; - - case WM_PAINT: - if (!icon->layered) - { - PAINTSTRUCT ps; - RECT rc; - HDC hdc; - int cx = GetSystemMetrics( SM_CXSMICON ); - int cy = GetSystemMetrics( SM_CYSMICON ); - - hdc = BeginPaint(hwnd, &ps); - GetClientRect(hwnd, &rc); - TRACE("painting rect %s\n", wine_dbgstr_rect(&rc)); - DrawIconEx( hdc, (rc.left + rc.right - cx) / 2, (rc.top + rc.bottom - cy) / 2, - icon->image, cx, cy, 0, 0, DI_DEFAULTSIZE|DI_NORMAL ); - EndPaint(hwnd, &ps); - return 0; - } - break; - - case WM_MOUSEMOVE: - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_LBUTTONDBLCLK: - case WM_RBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - notify_owner( icon, msg, lparam ); - break; - - case WM_LBUTTONUP: - if (!notify_owner( icon, msg, lparam )) break; - if (icon->version > 0) notify_owner( icon, NIN_SELECT, lparam ); - break; - - case WM_RBUTTONUP: - if (!notify_owner( icon, msg, lparam )) break; - if (icon->version > 0) notify_owner( icon, WM_CONTEXTMENU, lparam ); - break; - - case WM_WINDOWPOSCHANGED: - update_systray_balloon_position(); - break; - - case WM_TIMER: - switch (wparam) - { - case BALLOON_CREATE_TIMER: - balloon_create_timer( icon ); - break; - case BALLOON_SHOW_TIMER: - balloon_timer(); - break; - } - return 0; - - case WM_CLOSE: - if (icon->display == -1) - { - TRACE( "icon %u no longer embedded\n", icon->id ); - hide_icon( icon ); - add_to_standalone_tray( icon ); - } - return 0; - } - return DefWindowProcW( hwnd, msg, wparam, lparam ); -} - -static BOOL init_systray(void) -{ - static BOOL init_done; - WNDCLASSEXW class; - - if (init_done) return TRUE; - if (!X11DRV_CALL( systray_init, NULL )) - { - init_done = TRUE; - return FALSE; - } - - icon_cx = GetSystemMetrics( SM_CXSMICON ) + 2 * ICON_BORDER; - icon_cy = GetSystemMetrics( SM_CYSMICON ) + 2 * ICON_BORDER; - - memset( &class, 0, sizeof(class) ); - class.cbSize = sizeof(class); - class.lpfnWndProc = tray_icon_wndproc; - class.hIcon = LoadIconW(0, (LPCWSTR)IDI_WINLOGO); - class.hCursor = LoadCursorW( 0, (LPCWSTR)IDC_ARROW ); - class.lpszClassName = icon_classname; - class.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; - - if (!RegisterClassExW( &class ) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) - { - ERR( "Could not register icon tray window class\n" ); - return FALSE; - } - - class.lpfnWndProc = standalone_tray_wndproc; - class.hbrBackground = (HBRUSH)COLOR_WINDOW; - class.lpszClassName = tray_classname; - class.style = CS_DBLCLKS; - - if (!RegisterClassExW( &class ) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) - { - ERR( "Could not register standalone tray window class\n" ); - return FALSE; - } - - init_done = TRUE; - return TRUE; -} - -/* dock systray windows again with the new owner */ -NTSTATUS WINAPI x11drv_systray_change_owner( void *arg, ULONG size ) -{ - struct systray_change_owner_params *params = arg; - struct systray_dock_params dock_params; - struct tray_icon *icon; - - LIST_FOR_EACH_ENTRY( icon, &icon_list, struct tray_icon, entry ) - { - if (icon->display == -1) continue; - hide_icon( icon ); - - dock_params.event_handle = params->event_handle; - dock_params.icon = icon; - dock_params.cx = icon_cx; - dock_params.cy = icon_cy; - dock_params.layered = &icon->layered; - X11DRV_CALL( systray_dock, &dock_params ); - } - - return 0; -} - -/* hide a tray icon */ -static BOOL hide_icon( struct tray_icon *icon ) -{ - TRACE( "id=0x%x, hwnd=%p\n", icon->id, icon->owner ); - - if (!icon->window) return TRUE; /* already hidden */ - - X11DRV_CALL( systray_hide, &icon->window ); - DestroyWindow(icon->window); - DestroyWindow(icon->tooltip); - icon->window = 0; - icon->layered = FALSE; - icon->tooltip = 0; - remove_from_standalone_tray( icon ); - update_balloon( icon ); - return TRUE; -} - -/* make the icon visible */ -static BOOL show_icon( struct tray_icon *icon ) -{ - struct systray_dock_params params; - - if (icon->window) return TRUE; /* already shown */ - - TRACE( "id=0x%x, hwnd=%p\n", icon->id, icon->owner ); - - params.event_handle = 0; - params.icon = icon; - params.cx = icon_cx; - params.cy = icon_cy; - params.layered = &icon->layered; - - if (X11DRV_CALL( systray_dock, ¶ms )) - add_to_standalone_tray( icon ); - - update_balloon( icon ); - return TRUE; -} - -/* Modifies an existing icon record */ -static BOOL modify_icon( struct tray_icon *icon, NOTIFYICONDATAW *nid ) -{ - TRACE( "id=0x%x hwnd=%p flags=%x\n", nid->uID, nid->hWnd, nid->uFlags ); - - if (nid->uFlags & NIF_STATE) - { - icon->state = (icon->state & ~nid->dwStateMask) | (nid->dwState & nid->dwStateMask); - } - - if (nid->uFlags & NIF_ICON) - { - if (icon->image) DestroyIcon(icon->image); - icon->image = CopyIcon(nid->hIcon); - if (icon->window) - { - if (icon->display != -1) InvalidateRect( icon->window, NULL, TRUE ); - else if (icon->layered) repaint_tray_icon( icon ); - else X11DRV_CALL( systray_clear, &icon->window ); - } - } - - if (nid->uFlags & NIF_MESSAGE) - { - icon->callback_message = nid->uCallbackMessage; - } - if (nid->uFlags & NIF_TIP) - { - lstrcpynW(icon->tiptext, nid->szTip, ARRAY_SIZE( icon->tiptext )); - if (icon->tooltip) update_tooltip_text(icon); - } - if (nid->uFlags & NIF_INFO && nid->cbSize >= NOTIFYICONDATAA_V2_SIZE) - { - lstrcpynW( icon->info_text, nid->szInfo, ARRAY_SIZE( icon->info_text )); - lstrcpynW( icon->info_title, nid->szInfoTitle, ARRAY_SIZE( icon->info_title )); - icon->info_flags = nid->dwInfoFlags; - icon->info_timeout = max(min(nid->uTimeout, BALLOON_SHOW_MAX_TIMEOUT), BALLOON_SHOW_MIN_TIMEOUT); - icon->info_icon = nid->hBalloonIcon; - update_balloon( icon ); - } - if (icon->state & NIS_HIDDEN) hide_icon( icon ); - else show_icon( icon ); - return TRUE; -} - -/* Adds a new icon record to the list */ -static BOOL add_icon(NOTIFYICONDATAW *nid) -{ - struct tray_icon *icon; - - TRACE("id=0x%x, hwnd=%p\n", nid->uID, nid->hWnd); - - if ((icon = get_icon(nid->hWnd, nid->uID))) - { - WARN("duplicate tray icon add, buggy app?\n"); - return FALSE; - } - - if (!(icon = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*icon)))) - { - ERR("out of memory\n"); - return FALSE; - } - - ZeroMemory(icon, sizeof(struct tray_icon)); - icon->id = nid->uID; - icon->owner = nid->hWnd; - icon->display = -1; - - list_add_tail(&icon_list, &icon->entry); - - return modify_icon( icon, nid ); -} - -/* delete tray icon window and icon structure */ -static BOOL delete_icon( struct tray_icon *icon ) -{ - hide_icon( icon ); - list_remove( &icon->entry ); - DestroyIcon( icon->image ); - HeapFree( GetProcessHeap(), 0, icon ); - return TRUE; -} - -/* cleanup all icons for a given window */ -static void cleanup_icons( HWND owner ) -{ - struct tray_icon *this, *next; - - LIST_FOR_EACH_ENTRY_SAFE( this, next, &icon_list, struct tray_icon, entry ) - if (this->owner == owner) delete_icon( this ); -} - - -/*********************************************************************** - * wine_notify_icon (X11DRV.@) - * - * Driver-side implementation of Shell_NotifyIcon. - */ -int CDECL wine_notify_icon( DWORD msg, NOTIFYICONDATAW *data ) -{ - BOOL ret = FALSE; - struct tray_icon *icon; - - switch (msg) - { - case NIM_ADD: - if (!init_systray()) return -1; /* fall back to default handling */ - ret = add_icon( data ); - break; - case NIM_DELETE: - if ((icon = get_icon( data->hWnd, data->uID ))) ret = delete_icon( icon ); - break; - case NIM_MODIFY: - if ((icon = get_icon( data->hWnd, data->uID ))) ret = modify_icon( icon, data ); - break; - case NIM_SETVERSION: - if ((icon = get_icon( data->hWnd, data->uID ))) - { - icon->version = data->uVersion; - ret = TRUE; - } - break; - case 0xdead: /* Wine extension: owner window has died */ - cleanup_icons( data->hWnd ); - break; - default: - FIXME( "unhandled tray message: %lu\n", msg ); - break; - } - return ret; -} - - /* window procedure for foreign windows */ LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { switch(msg) { case WM_WINDOWPOSCHANGED: - update_systray_balloon_position(); + { + HWND hwnd = FindWindowW( L"Shell_TrayWnd", NULL ); + PostMessageW( hwnd, WM_USER + 0, 0, 0 ); break; + } case WM_PARENTNOTIFY: if (LOWORD(wparam) == WM_DESTROY) { diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index cc9f0184afd..9f3f7ec2926 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -22,10 +22,6 @@ enum x11drv_funcs { unix_init, - unix_systray_clear, - unix_systray_dock, - unix_systray_hide, - unix_systray_init, unix_tablet_attach_queue, unix_tablet_get_packet, unix_tablet_info, @@ -39,16 +35,6 @@ enum x11drv_funcs struct init_params { WNDPROC foreign_window_proc; - BOOL *show_systray; -}; - -struct systray_dock_params -{ - UINT64 event_handle; - void *icon; - int cx; - int cy; - BOOL *layered; }; /* x11drv_tablet_info params */ @@ -73,7 +59,6 @@ enum x11drv_client_funcs client_func_dnd_enter_event, client_func_dnd_position_event, client_func_dnd_post_drop, - client_func_systray_change_owner, client_func_last }; @@ -109,8 +94,3 @@ struct dnd_position_event_params POINT point; DWORD effect; }; - -struct systray_change_owner_params -{ - UINT64 event_handle; -}; diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 53982bb8c3b..51125065958 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2189,12 +2189,16 @@ HWND create_foreign_window( Display *display, Window xwin ) } -NTSTATUS x11drv_systray_init( void *arg ) +/*********************************************************************** + * SystrayDockInit (X11DRV.@) + */ +void X11DRV_SystrayDockInit( HWND hwnd ) { Display *display; - if (is_virtual_desktop()) return FALSE; + if (is_virtual_desktop()) return; + systray_hwnd = hwnd; display = thread_init_display(); if (DefaultScreen( display ) == 0) systray_atom = x11drv_atom(_NET_SYSTEM_TRAY_S0); @@ -2205,33 +2209,36 @@ NTSTATUS x11drv_systray_init( void *arg ) systray_atom = XInternAtom( display, systray_buffer, False ); } XSelectInput( display, root_window, StructureNotifyMask ); - - return TRUE; } -NTSTATUS x11drv_systray_clear( void *arg ) +/*********************************************************************** + * SystrayDockClear (X11DRV.@) + */ +void X11DRV_SystrayDockClear( HWND hwnd ) { - HWND hwnd = *(HWND*)arg; Window win = X11DRV_get_whole_window( hwnd ); if (win) XClearArea( gdi_display, win, 0, 0, 0, 0, True ); - return 0; } -NTSTATUS x11drv_systray_hide( void *arg ) +/*********************************************************************** + * SystrayDockRemove (X11DRV.@) + */ +BOOL X11DRV_SystrayDockRemove( HWND hwnd ) { - HWND hwnd = *(HWND*)arg; struct x11drv_win_data *data; + BOOL ret; /* make sure we don't try to unmap it, it confuses some systray docks */ if ((data = get_win_data( hwnd ))) { - if (data->embedded) data->mapped = FALSE; + if ((ret = data->embedded)) data->mapped = FALSE; release_win_data( data ); + return ret; } - return 0; + return FALSE; } @@ -2270,46 +2277,23 @@ static void get_systray_visual_info( Display *display, Window systray_window, XV } -NTSTATUS x11drv_systray_dock( void *arg ) +/*********************************************************************** + * SystrayDockInsert (X11DRV.@) + */ +BOOL X11DRV_SystrayDockInsert( HWND hwnd, UINT cx, UINT cy, void *icon ) { - struct systray_dock_params *params = arg; + Display *display = thread_init_display(); Window systray_window, window; - Display *display; XEvent ev; - XSetWindowAttributes attr; XVisualInfo visual; struct x11drv_win_data *data; - UNICODE_STRING class_name; - BOOL layered; - HWND hwnd; - static const WCHAR icon_classname[] = - {'_','_','w','i','n','e','x','1','1','_','t','r','a','y','_','i','c','o','n',0}; - - if (params->event_handle) - { - XClientMessageEvent *event = (XClientMessageEvent *)(UINT_PTR)params->event_handle; - display = event->display; - systray_window = event->data.l[2]; - } - else - { - display = thread_init_display(); - if (!(systray_window = get_systray_selection_owner( display ))) return STATUS_UNSUCCESSFUL; - } + if (!(systray_window = get_systray_selection_owner( display ))) return FALSE; get_systray_visual_info( display, systray_window, &visual ); - *params->layered = layered = (visual.depth == 32); - - RtlInitUnicodeString( &class_name, icon_classname ); - hwnd = NtUserCreateWindowEx( layered ? WS_EX_LAYERED : 0, &class_name, &class_name, NULL, - WS_CLIPSIBLINGS | WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, - params->cx, params->cy, NULL, 0, NULL, params->icon, 0, - NULL, 0, FALSE ); - - if (!(data = get_win_data( hwnd ))) return STATUS_UNSUCCESSFUL; - if (layered) set_window_visual( data, &visual, TRUE ); + if (!(data = get_win_data( hwnd ))) return FALSE; + set_window_visual( data, &visual, TRUE ); make_window_embedded( data ); window = data->whole_window; release_win_data( data ); @@ -2330,19 +2314,7 @@ NTSTATUS x11drv_systray_dock( void *arg ) ev.xclient.data.l[4] = 0; XSendEvent( display, systray_window, False, NoEventMask, &ev ); - if (!layered) - { - attr.background_pixmap = ParentRelative; - attr.bit_gravity = ForgetGravity; - XChangeWindowAttributes( display, window, CWBackPixmap | CWBitGravity, &attr ); - } - else - { - /* force repainig */ - send_message( hwnd, WM_SIZE, SIZE_RESTORED, MAKELONG( params->cx, params->cy )); - } - - return STATUS_SUCCESS; + return TRUE; } diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec index 6dedae550e8..43d9ae6ba71 100644 --- a/dlls/winex11.drv/winex11.drv.spec +++ b/dlls/winex11.drv/winex11.drv.spec @@ -3,6 +3,3 @@ @ cdecl GetCurrentPacket(ptr) X11DRV_GetCurrentPacket @ cdecl LoadTabletInfo(long) X11DRV_LoadTabletInfo @ cdecl WTInfoW(long long ptr) X11DRV_WTInfoW - -# System tray -@ cdecl wine_notify_icon(long ptr) diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 2c15a95dfab..67a7cf1117f 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -217,6 +217,10 @@ extern void X11DRV_SetCursor( HWND hwnd, HCURSOR handle ) DECLSPEC_HIDDEN; extern BOOL X11DRV_SetCursorPos( INT x, INT y ) DECLSPEC_HIDDEN; extern BOOL X11DRV_GetCursorPos( LPPOINT pos ) DECLSPEC_HIDDEN; extern BOOL X11DRV_ClipCursor( const RECT *clip, BOOL reset ) DECLSPEC_HIDDEN; +extern void X11DRV_SystrayDockInit( HWND systray ) DECLSPEC_HIDDEN; +extern BOOL X11DRV_SystrayDockInsert( HWND owner, UINT cx, UINT cy, void *icon ) DECLSPEC_HIDDEN; +extern void X11DRV_SystrayDockClear( HWND hwnd ) DECLSPEC_HIDDEN; +extern BOOL X11DRV_SystrayDockRemove( HWND hwnd ) DECLSPEC_HIDDEN; extern LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, LPCWSTR primary_name, HWND hwnd, DWORD flags, LPVOID lpvoid ) DECLSPEC_HIDDEN; extern BOOL X11DRV_GetCurrentDisplaySettings( LPCWSTR name, BOOL is_primary, LPDEVMODEW devmode ) DECLSPEC_HIDDEN; extern INT X11DRV_GetDisplayDepth( LPCWSTR name, BOOL is_primary ) DECLSPEC_HIDDEN; @@ -442,7 +446,6 @@ extern BOOL usexvidmode DECLSPEC_HIDDEN; extern BOOL use_take_focus DECLSPEC_HIDDEN; extern BOOL use_primary_selection DECLSPEC_HIDDEN; extern BOOL use_system_cursors DECLSPEC_HIDDEN; -extern BOOL show_systray DECLSPEC_HIDDEN; extern BOOL grab_fullscreen DECLSPEC_HIDDEN; extern BOOL usexcomposite DECLSPEC_HIDDEN; extern BOOL managed_mode DECLSPEC_HIDDEN; @@ -554,6 +557,7 @@ enum x11drv_atoms extern Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM] DECLSPEC_HIDDEN; extern Atom systray_atom DECLSPEC_HIDDEN; +extern HWND systray_hwnd DECLSPEC_HIDDEN; #define x11drv_atom(name) (X11DRV_Atoms[XATOM_##name - FIRST_XATOM]) @@ -835,10 +839,6 @@ static inline BOOL is_window_rect_mapped( const RECT *rect ) /* unixlib interface */ -extern NTSTATUS x11drv_systray_clear( void *arg ) DECLSPEC_HIDDEN; -extern NTSTATUS x11drv_systray_dock( void *arg ) DECLSPEC_HIDDEN; -extern NTSTATUS x11drv_systray_hide( void *arg ) DECLSPEC_HIDDEN; -extern NTSTATUS x11drv_systray_init( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_tablet_attach_queue( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_tablet_get_packet( void *arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_tablet_load_info( void *arg ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index bab27afce14..b3403c9c599 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -30,7 +30,6 @@ extern NTSTATUS WINAPI x11drv_dnd_enter_event( void *params, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_dnd_position_event( void *params, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ) DECLSPEC_HIDDEN; -extern NTSTATUS WINAPI x11drv_systray_change_owner( void *params, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; @@ -38,7 +37,6 @@ extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; extern LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN; -extern BOOL show_systray DECLSPEC_HIDDEN; extern HMODULE x11drv_module DECLSPEC_HIDDEN; #endif /* __WINE_X11DRV_DLL_H */ diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 32a20e0e4f2..d1f31081b09 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -65,6 +65,7 @@ XVisualInfo argb_visual = { 0 }; Colormap default_colormap = None; XPixmapFormatValues **pixmap_formats; Atom systray_atom = 0; +HWND systray_hwnd = 0; unsigned int screen_bpp; Window root_window; BOOL usexvidmode = TRUE; @@ -73,7 +74,6 @@ BOOL usexcomposite = TRUE; BOOL use_take_focus = TRUE; BOOL use_primary_selection = FALSE; BOOL use_system_cursors = TRUE; -BOOL show_systray = TRUE; BOOL grab_fullscreen = FALSE; BOOL managed_mode = TRUE; BOOL decorated_mode = TRUE; @@ -494,9 +494,6 @@ static void setup_options(void) if (!get_config_key( hkey, appkey, "UseSystemCursors", buffer, sizeof(buffer) )) use_system_cursors = IS_OPTION_TRUE( buffer[0] ); - if (!get_config_key( hkey, appkey, "ShowSystray", buffer, sizeof(buffer) )) - show_systray = IS_OPTION_TRUE( buffer[0] ); - if (!get_config_key( hkey, appkey, "GrabFullscreen", buffer, sizeof(buffer) )) grab_fullscreen = IS_OPTION_TRUE( buffer[0] ); @@ -708,7 +705,6 @@ static NTSTATUS x11drv_init( void *arg ) init_user_driver(); X11DRV_DisplayDevices_Init(FALSE); - *params->show_systray = show_systray; return STATUS_SUCCESS; } @@ -1319,10 +1315,6 @@ NTSTATUS x11drv_client_call( enum client_callback func, UINT arg ) const unixlib_entry_t __wine_unix_call_funcs[] = { x11drv_init, - x11drv_systray_clear, - x11drv_systray_dock, - x11drv_systray_hide, - x11drv_systray_init, x11drv_tablet_attach_queue, x11drv_tablet_get_packet, x11drv_tablet_info, @@ -1340,47 +1332,13 @@ static NTSTATUS x11drv_wow64_init( void *arg ) struct { ULONG foreign_window_proc; - ULONG show_systray; } *params32 = arg; struct init_params params; params.foreign_window_proc = UlongToPtr( params32->foreign_window_proc ); - params.show_systray = UlongToPtr( params32->show_systray ); return x11drv_init( ¶ms ); } -static NTSTATUS x11drv_wow64_systray_clear( void *arg ) -{ - HWND hwnd = UlongToPtr( *(ULONG *)arg ); - return x11drv_systray_clear( &hwnd ); -} - -static NTSTATUS x11drv_wow64_systray_dock( void *arg ) -{ - struct - { - UINT64 event_handle; - ULONG icon; - int cx; - int cy; - ULONG layered; - } *params32 = arg; - struct systray_dock_params params; - - params.event_handle = params32->event_handle; - params.icon = UlongToPtr( params32->icon ); - params.cx = params32->cx; - params.cy = params32->cy; - params.layered = UlongToPtr( params32->layered ); - return x11drv_systray_dock( ¶ms ); -} - -static NTSTATUS x11drv_wow64_systray_hide( void *arg ) -{ - HWND hwnd = UlongToPtr( *(ULONG *)arg ); - return x11drv_systray_hide( &hwnd ); -} - static NTSTATUS x11drv_wow64_tablet_get_packet( void *arg ) { FIXME( "%p\n", arg ); @@ -1406,10 +1364,6 @@ static NTSTATUS x11drv_wow64_tablet_info( void *arg ) const unixlib_entry_t __wine_unix_call_wow64_funcs[] = { x11drv_wow64_init, - x11drv_wow64_systray_clear, - x11drv_wow64_systray_dock, - x11drv_wow64_systray_hide, - x11drv_systray_init, x11drv_tablet_attach_queue, x11drv_wow64_tablet_get_packet, x11drv_wow64_tablet_info, diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c index 94b2a856ba0..670493be086 100644 --- a/programs/explorer/systray.c +++ b/programs/explorer/systray.c @@ -1069,6 +1069,24 @@ static LRESULT WINAPI shell_traywnd_proc( HWND hwnd, UINT msg, WPARAM wparam, LP case WM_MENUCOMMAND: return menu_wndproc(hwnd, msg, wparam, lparam); + case WM_USER + 0: + update_systray_balloon_position(); + return 0; + + case WM_USER + 1: + { + struct icon *icon; + + LIST_FOR_EACH_ENTRY( icon, &icon_list, struct icon, entry ) + { + if (!icon->window) continue; + hide_icon( icon ); + show_icon( icon ); + } + + return 0; + } + default: return DefWindowProcW( hwnd, msg, wparam, lparam ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4540
From: Rémi Bernon <rbernon(a)codeweavers.com> --- programs/explorer/desktop.c | 9 +++------ programs/explorer/explorer_private.h | 2 +- programs/explorer/systray.c | 11 ++--------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c index 0af8d4c8e3c..9a58f13d887 100644 --- a/programs/explorer/desktop.c +++ b/programs/explorer/desktop.c @@ -841,7 +841,7 @@ static BOOL get_default_enable_shell( const WCHAR *name ) return result; } -static HMODULE load_graphics_driver( const WCHAR *driver, GUID *guid ) +static void load_graphics_driver( const WCHAR *driver, GUID *guid ) { static const WCHAR device_keyW[] = L"System\\CurrentControlSet\\Control\\Video\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\0000"; @@ -914,8 +914,6 @@ static HMODULE load_graphics_driver( const WCHAR *driver, GUID *guid ) RegSetValueExA( hkey, "DriverError", 0, REG_SZ, (BYTE *)error, strlen(error) + 1 ); RegCloseKey( hkey ); } - - return module; } static const char *debugstr_devmodew( const DEVMODEW *devmode ) @@ -1018,7 +1016,6 @@ void manage_desktop( WCHAR *arg ) GUID guid; MSG msg; HWND hwnd; - HMODULE graphics_driver; unsigned int width, height; WCHAR *cmdline = NULL, *driver = NULL; WCHAR *p = arg; @@ -1062,7 +1059,7 @@ void manage_desktop( WCHAR *arg ) UuidCreate( &guid ); TRACE( "display guid %s\n", debugstr_guid(&guid) ); - graphics_driver = load_graphics_driver( driver, &guid ); + load_graphics_driver( driver, &guid ); if (name && width && height) { @@ -1104,7 +1101,7 @@ void manage_desktop( WCHAR *arg ) if (using_root) enable_shell = FALSE; - initialize_systray( graphics_driver, using_root, enable_shell ); + initialize_systray( using_root, enable_shell ); if (!using_root) initialize_launchers( hwnd ); if ((shell32 = LoadLibraryW( L"shell32.dll" )) && diff --git a/programs/explorer/explorer_private.h b/programs/explorer/explorer_private.h index df598187fc1..34aa1cf046b 100644 --- a/programs/explorer/explorer_private.h +++ b/programs/explorer/explorer_private.h @@ -22,7 +22,7 @@ #define __WINE_EXPLORER_PRIVATE_H extern void manage_desktop( WCHAR *arg ); -extern void initialize_systray( HMODULE graphics_driver, BOOL using_root, BOOL enable_shell ); +extern void initialize_systray( BOOL using_root, BOOL enable_shell ); extern void initialize_appbar(void); extern void handle_parent_notify( HWND hwnd, WPARAM wp ); extern void do_startmenu( HWND owner ); diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c index 670493be086..1af8a72de46 100644 --- a/programs/explorer/systray.c +++ b/programs/explorer/systray.c @@ -57,8 +57,6 @@ struct notify_data /* platform-independent format for NOTIFYICONDATA */ UINT bpp; }; -static int (CDECL *wine_notify_icon)(DWORD,NOTIFYICONDATAW *); - #define ICON_DISPLAY_HIDDEN -1 #define ICON_DISPLAY_DOCKED -2 @@ -743,7 +741,6 @@ static void cleanup_systray_window( HWND hwnd ) if (icon->owner == hwnd) delete_icon( icon ); 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 */ @@ -842,8 +839,6 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds) 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)) - goto done; ret = FALSE; } @@ -1110,12 +1105,10 @@ void handle_parent_notify( HWND hwnd, WPARAM wp ) } /* this function creates the listener window */ -void initialize_systray( HMODULE graphics_driver, BOOL using_root, BOOL arg_enable_shell ) +void initialize_systray( BOOL using_root, BOOL arg_enable_shell ) { RECT work_rect, primary_rect, taskbar_rect; - if (using_root && graphics_driver) wine_notify_icon = (void *)GetProcAddress( graphics_driver, "wine_notify_icon" ); - shell_traywnd_class.hIcon = LoadIconW( 0, (const WCHAR *)IDI_WINLOGO ); shell_traywnd_class.hCursor = LoadCursorW( 0, (const WCHAR *)IDC_ARROW ); tray_icon_class.hIcon = shell_traywnd_class.hIcon; @@ -1132,7 +1125,7 @@ void initialize_systray( HMODULE graphics_driver, BOOL using_root, BOOL arg_enab ERR( "Could not register SysTray window class\n" ); return; } - if (!wine_notify_icon && !RegisterClassExW( &tray_icon_class )) + if (!RegisterClassExW( &tray_icon_class )) { ERR( "Could not register Wine SysTray window classes\n" ); return; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/4540
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=140497 Your paranoid android. === debian11 (build log) === error: patch failed: programs/explorer/systray.c:563 error: patch failed: programs/explorer/systray.c:60 error: patch failed: programs/explorer/systray.c:69 error: patch failed: programs/explorer/systray.c:57 Task: Patch failed to apply === debian11b (build log) === error: patch failed: programs/explorer/systray.c:563 error: patch failed: programs/explorer/systray.c:60 error: patch failed: programs/explorer/systray.c:69 error: patch failed: programs/explorer/systray.c:57 Task: Patch failed to apply
participants (2)
-
Marvin -
Rémi Bernon