Moving most systray code out of winex11, and removing the need for a custom export in winemac. Maybe winemac could perhaps later use that new interface as well but I didn't want to mess with it too much.
-- v2: explorer: Remove now unnecessary wine_notify_icon support. winex11: Use the new SystrayDock driver interface. explorer: Use layered windows for the docked systray icons. win32u: Introduce new SystrayDock driver entry points. winemac: Use the new NotifyIcon user driver interface. win32u: Introduce a new NtUserSystemTrayCall message call. explorer: Hide the standalone systray window on close. explorer: Always set the systray icon tooltip text.
From: Rémi Bernon rbernon@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) {
From: Rémi Bernon rbernon@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:
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;
From: Rémi Bernon rbernon@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 a1cdcc76ebc..e1dd1c61b3f 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); extern BOOL macdrv_SetDeviceGammaRamp(PHYSDEV dev, LPVOID ramp); extern BOOL macdrv_ClipCursor(const RECT *clip, BOOL reset); +extern LRESULT macdrv_NotifyIcon(HWND hwnd, UINT msg, NOTIFYICONDATAW *data); +extern void macdrv_CleanupIcons(HWND hwnd); extern LRESULT macdrv_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); extern void macdrv_DestroyWindow(HWND hwnd); extern void macdrv_SetDesktopWindow(HWND hwnd); @@ -281,7 +283,6 @@ extern NTSTATUS macdrv_dnd_get_formats(void *arg); extern NTSTATUS macdrv_dnd_have_format(void *arg); extern NTSTATUS macdrv_dnd_release(void *arg); extern NTSTATUS macdrv_dnd_retain(void *arg); -extern NTSTATUS macdrv_notify_icon(void *arg);
extern NTSTATUS macdrv_client_func(enum macdrv_client_funcs func, const void *params, ULONG size); 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)
From: Rémi Bernon rbernon@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)
From: Rémi Bernon rbernon@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" );
From: Rémi Bernon rbernon@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 2917579927c..baa903e5099 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 ); extern BOOL X11DRV_SetCursorPos( INT x, INT y ); extern BOOL X11DRV_GetCursorPos( LPPOINT pos ); extern BOOL X11DRV_ClipCursor( const RECT *clip, BOOL reset ); +extern void X11DRV_SystrayDockInit( HWND systray ); +extern BOOL X11DRV_SystrayDockInsert( HWND owner, UINT cx, UINT cy, void *icon ); +extern void X11DRV_SystrayDockClear( HWND hwnd ); +extern BOOL X11DRV_SystrayDockRemove( HWND hwnd ); extern LONG X11DRV_ChangeDisplaySettings( LPDEVMODEW displays, LPCWSTR primary_name, HWND hwnd, DWORD flags, LPVOID lpvoid ); extern BOOL X11DRV_GetCurrentDisplaySettings( LPCWSTR name, BOOL is_primary, LPDEVMODEW devmode ); extern INT X11DRV_GetDisplayDepth( LPCWSTR name, BOOL is_primary ); @@ -442,7 +446,6 @@ extern BOOL usexvidmode; extern BOOL use_take_focus; extern BOOL use_primary_selection; extern BOOL use_system_cursors; -extern BOOL show_systray; extern BOOL grab_fullscreen; extern BOOL usexcomposite; extern BOOL managed_mode; @@ -554,6 +557,7 @@ enum x11drv_atoms
extern Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM]; extern Atom systray_atom; +extern HWND systray_hwnd;
#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 ); -extern NTSTATUS x11drv_systray_dock( void *arg ); -extern NTSTATUS x11drv_systray_hide( void *arg ); -extern NTSTATUS x11drv_systray_init( void *arg ); extern NTSTATUS x11drv_tablet_attach_queue( void *arg ); extern NTSTATUS x11drv_tablet_get_packet( void *arg ); extern NTSTATUS x11drv_tablet_load_info( void *arg ); diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index f43b3e72810..89b8d50057e 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 ); extern NTSTATUS WINAPI x11drv_dnd_position_event( void *params, ULONG size ); extern NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ); -extern NTSTATUS WINAPI x11drv_systray_change_owner( void *params, ULONG size );
extern NTSTATUS x11drv_dnd_drop_event( UINT arg ); extern NTSTATUS x11drv_dnd_leave_event( UINT arg ); @@ -38,7 +37,6 @@ extern NTSTATUS x11drv_dnd_leave_event( UINT arg ); extern LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam );
-extern BOOL show_systray; extern HMODULE x11drv_module;
#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 ); }
From: Rémi Bernon rbernon@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;
v2: Rebased and dropped DECLSPEC_HIDDEN.