[PATCH v2 4/9] winex11: Use unixlib interface for systray docking.
Jacek Caban
wine at gitlab.winehq.org
Thu May 5 08:42:39 CDT 2022
From: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
dlls/winex11.drv/dllmain.c | 1 +
dlls/winex11.drv/event.c | 10 ++-
dlls/winex11.drv/systray.c | 117 ++++++---------------------------
dlls/winex11.drv/unixlib.h | 16 +++++
dlls/winex11.drv/window.c | 114 ++++++++++++++++++++++++++++++++
dlls/winex11.drv/x11drv.h | 2 +
dlls/winex11.drv/x11drv_main.c | 2 +
7 files changed, 165 insertions(+), 97 deletions(-)
diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c
index bbfcefe05e3..7ea07647dc9 100644
--- a/dlls/winex11.drv/dllmain.c
+++ b/dlls/winex11.drv/dllmain.c
@@ -157,6 +157,7 @@ static const kernel_callback kernel_callbacks[] =
x11drv_dnd_post_drop,
x11drv_ime_set_composition_string,
x11drv_ime_set_result,
+ x11drv_systray_change_owner,
};
C_ASSERT( NtUserDriverCallbackFirst + ARRAYSIZE(kernel_callbacks) == client_func_last );
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index cefc86d0902..12b0884a250 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -621,8 +621,16 @@ static void set_focus( Display *display, HWND hwnd, Time time )
static void handle_manager_message( HWND hwnd, XClientMessageEvent *event )
{
if (hwnd != NtUserGetDesktopWindow()) return;
+
if (systray_atom && event->data.l[1] == systray_atom)
- change_systray_owner( event->display, event->data.l[2] );
+ {
+ 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) );
+ }
}
diff --git a/dlls/winex11.drv/systray.c b/dlls/winex11.drv/systray.c
index bb2e5d563dd..ae1c5738f8e 100644
--- a/dlls/winex11.drv/systray.c
+++ b/dlls/winex11.drv/systray.c
@@ -75,12 +75,6 @@ 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 SYSTEM_TRAY_REQUEST_DOCK 0
-#define SYSTEM_TRAY_BEGIN_MESSAGE 1
-#define SYSTEM_TRAY_CANCEL_MESSAGE 2
-
-Atom systray_atom = 0;
-
#define MIN_DISPLAYED 8
#define ICON_BORDER 2
@@ -550,39 +544,6 @@ static LRESULT WINAPI tray_icon_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPAR
return DefWindowProcW( hwnd, msg, wparam, lparam );
}
-/* find the X11 window owner the system tray selection */
-static Window get_systray_selection_owner( Display *display )
-{
- return XGetSelectionOwner( display, systray_atom );
-}
-
-static void get_systray_visual_info( Display *display, Window systray_window, XVisualInfo *info )
-{
- XVisualInfo *list, template;
- VisualID *visual_id;
- Atom type;
- int format, num;
- unsigned long count, remaining;
-
- *info = default_visual;
- if (XGetWindowProperty( display, systray_window, x11drv_atom(_NET_SYSTEM_TRAY_VISUAL), 0,
- 65536/sizeof(CARD32), False, XA_VISUALID, &type, &format, &count,
- &remaining, (unsigned char **)&visual_id ))
- return;
-
- if (type == XA_VISUALID && format == 32)
- {
- template.visualid = visual_id[0];
- if ((list = XGetVisualInfo( display, VisualIDMask, &template, &num )))
- {
- *info = list[0];
- TRACE( "systray window %lx got visual %lx\n", systray_window, info->visualid );
- XFree( list );
- }
- }
- XFree( visual_id );
-}
-
static BOOL init_systray(void)
{
static BOOL init_done;
@@ -627,66 +588,27 @@ static BOOL init_systray(void)
return TRUE;
}
-/* dock the given icon with the NETWM system tray */
-static void dock_systray_icon( Display *display, struct tray_icon *icon, Window systray_window )
-{
- Window window;
- XEvent ev;
- XSetWindowAttributes attr;
- XVisualInfo visual;
- struct x11drv_win_data *data;
-
- get_systray_visual_info( display, systray_window, &visual );
-
- icon->layered = (visual.depth == 32);
- CreateWindowExW( icon->layered ? WS_EX_LAYERED : 0,
- icon_classname, NULL, WS_CLIPSIBLINGS | WS_POPUP,
- CW_USEDEFAULT, CW_USEDEFAULT, icon_cx, icon_cy,
- NULL, NULL, NULL, icon );
-
- if (!(data = get_win_data( icon->window ))) return;
- if (icon->layered) set_window_visual( data, &visual, TRUE );
- make_window_embedded( data );
- window = data->whole_window;
- release_win_data( data );
-
- ShowWindow( icon->window, SW_SHOWNA );
-
- TRACE( "icon window %p/%lx\n", icon->window, window );
-
- /* send the docking request message */
- ev.xclient.type = ClientMessage;
- ev.xclient.window = systray_window;
- ev.xclient.message_type = x11drv_atom( _NET_SYSTEM_TRAY_OPCODE );
- ev.xclient.format = 32;
- ev.xclient.data.l[0] = CurrentTime;
- ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
- ev.xclient.data.l[2] = window;
- ev.xclient.data.l[3] = 0;
- ev.xclient.data.l[4] = 0;
- XSendEvent( display, systray_window, False, NoEventMask, &ev );
-
- if (!icon->layered)
- {
- attr.background_pixmap = ParentRelative;
- attr.bit_gravity = ForgetGravity;
- XChangeWindowAttributes( display, window, CWBackPixmap | CWBitGravity, &attr );
- }
- else repaint_tray_icon( icon );
-}
-
/* dock systray windows again with the new owner */
-void change_systray_owner( Display *display, Window systray_window )
+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;
- TRACE( "new owner %lx\n", systray_window );
LIST_FOR_EACH_ENTRY( icon, &icon_list, struct tray_icon, entry )
{
if (icon->display == -1) continue;
hide_icon( icon );
- dock_systray_icon( display, icon, systray_window );
+
+ 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 */
@@ -710,16 +632,19 @@ static BOOL hide_icon( struct tray_icon *icon )
/* make the icon visible */
static BOOL show_icon( struct tray_icon *icon )
{
- Window systray_window;
- Display *display = thread_init_display();
+ struct systray_dock_params params;
+
+ if (icon->window) return TRUE; /* already shown */
TRACE( "id=0x%x, hwnd=%p\n", icon->id, icon->owner );
- if (icon->window) return TRUE; /* already shown */
+ params.event_handle = 0;
+ params.icon = icon;
+ params.cx = icon_cx;
+ params.cy = icon_cy;
+ params.layered = &icon->layered;
- if ((systray_window = get_systray_selection_owner( display )))
- dock_systray_icon( display, icon, systray_window );
- else
+ if (X11DRV_CALL( systray_dock, ¶ms ))
add_to_standalone_tray( icon );
update_balloon( icon );
diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h
index ce89f7d4d39..dc3c74979ca 100644
--- a/dlls/winex11.drv/unixlib.h
+++ b/dlls/winex11.drv/unixlib.h
@@ -25,6 +25,7 @@ enum x11drv_funcs
unix_create_desktop,
unix_init,
unix_systray_clear,
+ unix_systray_dock,
unix_systray_hide,
unix_systray_init,
unix_tablet_attach_queue,
@@ -56,6 +57,15 @@ struct create_desktop_params
UINT height;
};
+struct systray_dock_params
+{
+ UINT64 event_handle;
+ void *icon;
+ int cx;
+ int cy;
+ BOOL *layered;
+};
+
/* x11drv_tablet_info params */
struct tablet_info_params
{
@@ -80,6 +90,7 @@ enum x11drv_client_funcs
client_func_dnd_post_drop,
client_func_ime_set_composition_string,
client_func_ime_set_result,
+ client_func_systray_change_owner,
client_func_last
};
@@ -121,3 +132,8 @@ 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 4ae1d3f11a3..f006150fb7c 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -53,6 +53,7 @@
#include "mwm.h"
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
+WINE_DECLARE_DEBUG_CHANNEL(systray);
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
#define _NET_WM_MOVERESIZE_SIZE_TOP 1
@@ -70,6 +71,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
#define _NET_WM_STATE_ADD 1
#define _NET_WM_STATE_TOGGLE 2
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+#define SYSTEM_TRAY_BEGIN_MESSAGE 1
+#define SYSTEM_TRAY_CANCEL_MESSAGE 2
+
static const unsigned int net_wm_state_atoms[NB_NET_WM_STATES] =
{
XATOM__NET_WM_STATE_FULLSCREEN,
@@ -2138,6 +2143,115 @@ NTSTATUS x11drv_systray_hide( void *arg )
}
+/* find the X11 window owner the system tray selection */
+static Window get_systray_selection_owner( Display *display )
+{
+ return XGetSelectionOwner( display, systray_atom );
+}
+
+
+static void get_systray_visual_info( Display *display, Window systray_window, XVisualInfo *info )
+{
+ XVisualInfo *list, template;
+ VisualID *visual_id;
+ Atom type;
+ int format, num;
+ unsigned long count, remaining;
+
+ *info = default_visual;
+ if (XGetWindowProperty( display, systray_window, x11drv_atom(_NET_SYSTEM_TRAY_VISUAL), 0,
+ 65536/sizeof(CARD32), False, XA_VISUALID, &type, &format, &count,
+ &remaining, (unsigned char **)&visual_id ))
+ return;
+
+ if (type == XA_VISUALID && format == 32)
+ {
+ template.visualid = visual_id[0];
+ if ((list = XGetVisualInfo( display, VisualIDMask, &template, &num )))
+ {
+ *info = list[0];
+ TRACE_(systray)( "systray window %lx got visual %lx\n", systray_window, info->visualid );
+ XFree( list );
+ }
+ }
+ XFree( visual_id );
+}
+
+
+NTSTATUS x11drv_systray_dock( void *arg )
+{
+ struct systray_dock_params *params = arg;
+ Window systray_window, window;
+ Display *display;
+ XEvent ev;
+ XSetWindowAttributes attr;
+ XVisualInfo visual;
+ struct x11drv_win_data *data;
+ 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;
+ }
+
+ get_systray_visual_info( display, systray_window, &visual );
+
+ *params->layered = layered = (visual.depth == 32);
+
+ hwnd = CreateWindowExW( layered ? WS_EX_LAYERED : 0,
+ icon_classname, NULL, WS_CLIPSIBLINGS | WS_POPUP,
+ CW_USEDEFAULT, CW_USEDEFAULT, params->cx, params->cy,
+ NULL, NULL, NULL, params->icon );
+
+ if (!(data = get_win_data( hwnd ))) return STATUS_UNSUCCESSFUL;
+ if (layered) set_window_visual( data, &visual, TRUE );
+ make_window_embedded( data );
+ window = data->whole_window;
+ release_win_data( data );
+
+ NtUserShowWindow( hwnd, SW_SHOWNA );
+
+ TRACE_(systray)( "icon window %p/%lx\n", hwnd, window );
+
+ /* send the docking request message */
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = systray_window;
+ ev.xclient.message_type = x11drv_atom( _NET_SYSTEM_TRAY_OPCODE );
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = CurrentTime;
+ ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
+ ev.xclient.data.l[2] = window;
+ ev.xclient.data.l[3] = 0;
+ 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;
+}
+
+
/***********************************************************************
* X11DRV_get_whole_window
*
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index ec72d8a550e..d3db49b86b6 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -828,6 +828,7 @@ static inline BOOL is_window_rect_mapped( const RECT *rect )
extern NTSTATUS x11drv_clipboard_message( void *arg ) DECLSPEC_HIDDEN;
extern NTSTATUS x11drv_create_desktop( void *arg ) DECLSPEC_HIDDEN;
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;
@@ -842,6 +843,7 @@ extern NTSTATUS WINAPI x11drv_dnd_position_event( void *params, ULONG size ) DEC
extern NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ) DECLSPEC_HIDDEN;
extern NTSTATUS WINAPI x11drv_ime_set_composition_string( void *params, ULONG size ) DECLSPEC_HIDDEN;
extern NTSTATUS WINAPI x11drv_ime_set_result( void *params, 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;
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index 2d65f2a03d6..cbcfc659a67 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -60,6 +60,7 @@ XVisualInfo default_visual = { 0 };
XVisualInfo argb_visual = { 0 };
Colormap default_colormap = None;
XPixmapFormatValues **pixmap_formats;
+Atom systray_atom = 0;
unsigned int screen_bpp;
Window root_window;
BOOL usexvidmode = TRUE;
@@ -978,6 +979,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
x11drv_create_desktop,
x11drv_init,
x11drv_systray_clear,
+ x11drv_systray_dock,
x11drv_systray_hide,
x11drv_systray_init,
x11drv_tablet_attach_queue,
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/39
More information about the wine-devel
mailing list