We don't track the corresponding property changes, because it seems like they sometimes are different from what was requested [^1], and that would defeat the purpose of this MR. This shouldn't matter and there's actually no reason for the properties to change as these are direct property change requests.
[^1]: At least for me on XWayland, the differences seem mostly about x/y position hints, and they might come from XWayland quirks.
-- v2: winex11: Track requested _NET_WM_ICON to avoid unnecessary requests. winex11: Track requested _NET_WM_WINDOW_STATE to avoid unnecessary requests. winex11: Track requested WM_HINTS to avoid unnecessary requests. winex11: Track requested WM_NORMAL_HINTS to avoid unnecessary requests.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 18 ++++++++++++ dlls/winex11.drv/window.c | 52 +++++++++++++++++++++++++++++++--- dlls/winex11.drv/x11drv.h | 4 +++ dlls/winex11.drv/x11drv_main.c | 1 + 4 files changed, 71 insertions(+), 4 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index f33db32839f..94e178fd9f0 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -1296,6 +1296,23 @@ static void handle_mwm_hints_notify( HWND hwnd, XPropertyEvent *event ) release_win_data( data ); }
+static void handle_wm_normal_hints_notify( HWND hwnd, XPropertyEvent *event ) +{ + struct x11drv_win_data *data; + XSizeHints *hints; + long len = 0; + + if (!(data = get_win_data( hwnd ))) return; + if ((hints = XAllocSizeHints())) + { + if (event->state == PropertyNewValue) XGetWMNormalHints( event->display, event->window, hints, &len ); + if (len < sizeof(*hints)) memset( (char *)hints + len, 0, sizeof(*hints) - len ); + window_wm_normal_hints_notify( data, event->serial, hints ); + XFree( hints ); + } + release_win_data( data ); +} + static void handle_net_supported_notify( XPropertyEvent *event ) { struct x11drv_thread_data *data = x11drv_thread_data(); @@ -1331,6 +1348,7 @@ static BOOL X11DRV_PropertyNotify( HWND hwnd, XEvent *xev ) if (event->atom == x11drv_atom(_XEMBED_INFO)) handle_xembed_info_notify( hwnd, event ); if (event->atom == x11drv_atom(_NET_WM_STATE)) handle_net_wm_state_notify( hwnd, event ); if (event->atom == x11drv_atom(_MOTIF_WM_HINTS)) handle_mwm_hints_notify( hwnd, event ); + if (event->atom == x11drv_atom(WM_NORMAL_HINTS)) handle_wm_normal_hints_notify( hwnd, event ); if (event->atom == x11drv_atom(_NET_SUPPORTED)) handle_net_supported_notify( event ); if (event->atom == x11drv_atom(_NET_ACTIVE_WINDOW)) handle_net_active_window( event );
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 0eddc40da0c..78e95b55808 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -111,6 +111,22 @@ static const char *debugstr_mwm_hints( const MwmHints *hints ) return wine_dbg_sprintf( "%lx,%lx", hints->functions, hints->decorations ); }
+static const char *debugstr_size_hints( const XSizeHints *hints ) +{ + char buffer[1024], *buf = buffer; + buf += sprintf( buf, "{" ); + if (hints->flags & PPosition) buf += sprintf( buf, " pos %d,%d", hints->x, hints->y ); + if (hints->flags & PSize) buf += sprintf( buf, " size %d,%d", hints->width, hints->height ); + if (hints->flags & PMinSize) buf += sprintf( buf, " min %d,%d", hints->min_width, hints->min_height ); + if (hints->flags & PMaxSize) buf += sprintf( buf, " max %d,%d", hints->max_width, hints->max_height ); + if (hints->flags & PResizeInc) buf += sprintf( buf, " inc %d,%d", hints->width_inc, hints->height_inc ); + if (hints->flags & PAspect) buf += sprintf( buf, " a/r min %d:%d max %d:%d", hints->min_aspect.x, hints->min_aspect.y, hints->max_aspect.x, hints->max_aspect.y ); + if (hints->flags & PBaseSize) buf += sprintf( buf, " base %d,%d", hints->base_width, hints->base_height ); + if (hints->flags & PWinGravity) buf += sprintf( buf, " grav %d", hints->win_gravity ); + buf += sprintf( buf, " }" ); + return __wine_dbg_strdup( buffer ); +} + static const char *debugstr_monitor_indices( const struct monitor_indices *monitors ) { return wine_dbg_sprintf( "%ld,%ld,%ld,%ld", monitors->indices[0], monitors->indices[1], monitors->indices[2], monitors->indices[3] ); @@ -862,6 +878,21 @@ static void set_window_icon_data( struct x11drv_win_data *data, HICON icon, cons data->icon_size = size; }
+static void window_set_wm_normal_hints( struct x11drv_win_data *data, XSizeHints *new_hints ) +{ + const XSizeHints *old_hints = &data->pending_state.wm_normal_hints; + + data->desired_state.wm_normal_hints = *new_hints; + if (!data->whole_window) return; /* no window or not managed, nothing to update */ + if (!memcmp( old_hints, new_hints, sizeof(*new_hints) )) return; /* hints are the same, nothing to update */ + + data->pending_state.wm_normal_hints = *new_hints; + data->wm_normal_hints_serial = NextRequest( data->display ); + TRACE( "window %p/%lx, requesting WM_NORMAL_HINTS %s serial %lu\n", data->hwnd, data->whole_window, + debugstr_size_hints(&data->pending_state.wm_normal_hints), data->wm_normal_hints_serial ); + XSetWMNormalHints( data->display, data->whole_window, new_hints ); +} +
/*********************************************************************** * set_size_hints @@ -870,7 +901,7 @@ static void set_window_icon_data( struct x11drv_win_data *data, HICON icon, cons */ static void set_size_hints( struct x11drv_win_data *data, DWORD style ) { - XSizeHints* size_hints; + XSizeHints *size_hints;
if (!(size_hints = XAllocSizeHints())) return;
@@ -901,9 +932,7 @@ static void set_size_hints( struct x11drv_win_data *data, DWORD style ) } }
- TRACE( "window %p/%lx requesting WM_NORMAL_HINTS flags %#lx, serial %lu\n", data->hwnd, - data->whole_window, size_hints->flags, NextRequest( data->display ) ); - XSetWMNormalHints( data->display, data->whole_window, size_hints ); + window_set_wm_normal_hints( data, size_hints ); XFree( size_hints ); }
@@ -1844,6 +1873,20 @@ void window_mwm_hints_notify( struct x11drv_win_data *data, unsigned long serial window_set_config( data, data->desired_state.rect, FALSE ); }
+void window_wm_normal_hints_notify( struct x11drv_win_data *data, unsigned long serial, const XSizeHints *value ) +{ + XSizeHints *desired = &data->desired_state.wm_normal_hints, *pending = &data->pending_state.wm_normal_hints, *current = &data->current_state.wm_normal_hints; + unsigned long *expect_serial = &data->wm_normal_hints_serial; + const char *expected, *received, *prefix; + + prefix = wine_dbg_sprintf( "window %p/%lx ", data->hwnd, data->whole_window ); + received = wine_dbg_sprintf( "WM_NORMAL_HINTS %s/%lu", debugstr_size_hints(value), serial ); + expected = *expect_serial ? wine_dbg_sprintf( ", expected %s/%lu", debugstr_size_hints(pending), *expect_serial ) : ""; + + handle_state_change( serial, expect_serial, sizeof(*value), value, desired, pending, + current, expected, prefix, received, NULL ); +} + void window_configure_notify( struct x11drv_win_data *data, unsigned long serial, const RECT *value ) { RECT *desired = &data->desired_state.rect, *pending = &data->pending_state.rect, *current = &data->current_state.rect; @@ -2426,6 +2469,7 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des data->wm_state_serial = 0; data->net_wm_state_serial = 0; data->mwm_hints_serial = 0; + data->wm_normal_hints_serial = 0; data->configure_serial = 0; data->reparenting = 0;
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index e597b956e67..39be211c018 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -500,6 +500,7 @@ enum x11drv_atoms XATOM_RAW_CAP_HEIGHT, XATOM_WM_PROTOCOLS, XATOM_WM_DELETE_WINDOW, + XATOM_WM_NORMAL_HINTS, XATOM_WM_STATE, XATOM_WM_TAKE_FOCUS, XATOM_DndProtocol, @@ -642,6 +643,7 @@ struct window_state BOOL activate; UINT net_wm_state; MwmHints mwm_hints; + XSizeHints wm_normal_hints; struct monitor_indices monitors; RECT rect; BOOL above; @@ -684,6 +686,7 @@ struct x11drv_win_data unsigned long wm_state_serial; /* serial of last pending WM_STATE request */ unsigned long net_wm_state_serial; /* serial of last pending _NET_WM_STATE request */ unsigned long mwm_hints_serial; /* serial of last pending _MOTIF_WM_HINTS request */ + unsigned long wm_normal_hints_serial;/* serial of last pending WM_NORMAL_HINTS request */ unsigned long configure_serial; /* serial of last pending configure request */ };
@@ -699,6 +702,7 @@ extern BOOL window_has_pending_wm_state( HWND hwnd, UINT state ); extern void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value, Time time ); extern void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value ); extern void window_mwm_hints_notify( struct x11drv_win_data *data, unsigned long serial, const MwmHints *hints ); +extern void window_wm_normal_hints_notify( struct x11drv_win_data *data, unsigned long serial, const XSizeHints *hints ); extern void window_configure_notify( struct x11drv_win_data *data, unsigned long serial, const RECT *rect );
extern void set_net_active_window( HWND hwnd, HWND previous ); diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 6616f9fb7d0..9dfb8347cf4 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -120,6 +120,7 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] = "RAW_CAP_HEIGHT", "WM_PROTOCOLS", "WM_DELETE_WINDOW", + "WM_NORMAL_HINTS", "WM_STATE", "WM_TAKE_FOCUS", "DndProtocol",
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 13 +++++++++ dlls/winex11.drv/window.c | 50 +++++++++++++++++++++++++++++++--- dlls/winex11.drv/x11drv.h | 4 +++ dlls/winex11.drv/x11drv_main.c | 1 + 4 files changed, 64 insertions(+), 4 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 94e178fd9f0..acf0c3dccfb 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -1285,6 +1285,18 @@ static void handle_net_wm_state_notify( HWND hwnd, XPropertyEvent *event ) NtUserPostMessage( hwnd, WM_WINE_WINDOW_STATE_CHANGED, 0, 0 ); }
+static void handle_wm_hints_notify( HWND hwnd, XPropertyEvent *event ) +{ + struct x11drv_win_data *data; + XWMHints empty = {0}, *hints; + + if (!(data = get_win_data( hwnd ))) return; + hints = event->state == PropertyNewValue ? XGetWMHints( event->display, event->window ) : ∅ + window_wm_hints_notify( data, event->serial, hints ); + if (hints != &empty) XFree( hints ); + release_win_data( data ); +} + static void handle_mwm_hints_notify( HWND hwnd, XPropertyEvent *event ) { struct x11drv_win_data *data; @@ -1347,6 +1359,7 @@ static BOOL X11DRV_PropertyNotify( HWND hwnd, XEvent *xev ) if (event->atom == x11drv_atom(WM_STATE)) handle_wm_state_notify( hwnd, event ); if (event->atom == x11drv_atom(_XEMBED_INFO)) handle_xembed_info_notify( hwnd, event ); if (event->atom == x11drv_atom(_NET_WM_STATE)) handle_net_wm_state_notify( hwnd, event ); + if (event->atom == x11drv_atom(WM_HINTS)) handle_wm_hints_notify( hwnd, event ); if (event->atom == x11drv_atom(_MOTIF_WM_HINTS)) handle_mwm_hints_notify( hwnd, event ); if (event->atom == x11drv_atom(WM_NORMAL_HINTS)) handle_wm_normal_hints_notify( hwnd, event ); if (event->atom == x11drv_atom(_NET_SUPPORTED)) handle_net_supported_notify( event ); diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 78e95b55808..96062faa505 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -127,6 +127,22 @@ static const char *debugstr_size_hints( const XSizeHints *hints ) return __wine_dbg_strdup( buffer ); }
+static const char *debugstr_wm_hints( const XWMHints *hints ) +{ + char buffer[1024], *buf = buffer; + buf += sprintf( buf, "{" ); + if (hints->flags & InputHint) buf += sprintf( buf, " input %u", hints->input ); + if (hints->flags & StateHint) buf += sprintf( buf, " state %u", hints->initial_state ); + if (hints->flags & IconPixmapHint) buf += sprintf( buf, " icon pix %lx", hints->icon_pixmap ); + if (hints->flags & IconWindowHint) buf += sprintf( buf, " icon win %lx", hints->icon_window ); + if (hints->flags & IconPositionHint) buf += sprintf( buf, " icon pos %d,%d", hints->icon_x, hints->icon_y ); + if (hints->flags & IconMaskHint) buf += sprintf( buf, " icon mask %lx", hints->icon_mask ); + if (hints->flags & WindowGroupHint) buf += sprintf( buf, " group %lx", hints->window_group ); + if (hints->flags & XUrgencyHint) buf += sprintf( buf, " urgent" ); + buf += sprintf( buf, " }" ); + return __wine_dbg_strdup( buffer ); +} + static const char *debugstr_monitor_indices( const struct monitor_indices *monitors ) { return wine_dbg_sprintf( "%ld,%ld,%ld,%ld", monitors->indices[0], monitors->indices[1], monitors->indices[2], monitors->indices[3] ); @@ -1039,6 +1055,21 @@ static void set_mwm_hints( struct x11drv_win_data *data, UINT style, UINT ex_sty }
+static void window_set_wm_hints( struct x11drv_win_data *data, XWMHints *new_hints ) +{ + const XWMHints *old_hints = &data->pending_state.wm_hints; + + data->desired_state.wm_hints = *new_hints; + if (!data->whole_window) return; /* no window or not managed, nothing to update */ + if (!memcmp( old_hints, new_hints, sizeof(*new_hints) )) return; /* hints are the same, nothing to update */ + + data->pending_state.wm_hints = *new_hints; + data->wm_hints_serial = NextRequest( data->display ); + TRACE( "window %p/%lx, requesting WM_HINTS %s serial %lu\n", data->hwnd, data->whole_window, + debugstr_wm_hints(&data->pending_state.wm_hints), data->wm_hints_serial ); + XSetWMHints( data->display, data->whole_window, new_hints ); +} + /*********************************************************************** * set_style_hints */ @@ -1088,10 +1119,7 @@ static void set_style_hints( struct x11drv_win_data *data, DWORD style, DWORD ex wm_hints->icon_mask = data->icon_mask; wm_hints->flags |= IconPixmapHint | IconMaskHint; } - - TRACE( "window %p/%lx requesting WM_HINTS flags %#lx, serial %lu\n", data->hwnd, - data->whole_window, wm_hints->flags, NextRequest( data->display ) ); - XSetWMHints( data->display, data->whole_window, wm_hints ); + window_set_wm_hints( data, wm_hints ); XFree( wm_hints ); }
@@ -1852,6 +1880,20 @@ void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long ser window_set_config( data, data->desired_state.rect, FALSE ); }
+void window_wm_hints_notify( struct x11drv_win_data *data, unsigned long serial, const XWMHints *value ) +{ + XWMHints *desired = &data->desired_state.wm_hints, *pending = &data->pending_state.wm_hints, *current = &data->current_state.wm_hints; + unsigned long *expect_serial = &data->wm_hints_serial; + const char *expected, *received, *prefix; + + prefix = wine_dbg_sprintf( "window %p/%lx ", data->hwnd, data->whole_window ); + received = wine_dbg_sprintf( "WM_HINTS %s/%lu", debugstr_wm_hints(value), serial ); + expected = *expect_serial ? wine_dbg_sprintf( ", expected %s/%lu", debugstr_wm_hints(pending), *expect_serial ) : ""; + + handle_state_change( serial, expect_serial, sizeof(*value), value, desired, pending, + current, expected, prefix, received, NULL ); +} + void window_mwm_hints_notify( struct x11drv_win_data *data, unsigned long serial, const MwmHints *value ) { MwmHints *desired = &data->desired_state.mwm_hints, *pending = &data->pending_state.mwm_hints, *current = &data->current_state.mwm_hints; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 39be211c018..4d0ce851e8e 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -500,6 +500,7 @@ enum x11drv_atoms XATOM_RAW_CAP_HEIGHT, XATOM_WM_PROTOCOLS, XATOM_WM_DELETE_WINDOW, + XATOM_WM_HINTS, XATOM_WM_NORMAL_HINTS, XATOM_WM_STATE, XATOM_WM_TAKE_FOCUS, @@ -642,6 +643,7 @@ struct window_state UINT wm_state; BOOL activate; UINT net_wm_state; + XWMHints wm_hints; MwmHints mwm_hints; XSizeHints wm_normal_hints; struct monitor_indices monitors; @@ -685,6 +687,7 @@ struct x11drv_win_data struct window_state current_state; /* window state tracking the current X11 state */ unsigned long wm_state_serial; /* serial of last pending WM_STATE request */ unsigned long net_wm_state_serial; /* serial of last pending _NET_WM_STATE request */ + unsigned long wm_hints_serial; /* serial of last pending WM_HINTS request */ unsigned long mwm_hints_serial; /* serial of last pending _MOTIF_WM_HINTS request */ unsigned long wm_normal_hints_serial;/* serial of last pending WM_NORMAL_HINTS request */ unsigned long configure_serial; /* serial of last pending configure request */ @@ -701,6 +704,7 @@ extern BOOL window_should_take_focus( HWND hwnd, Time time ); extern BOOL window_has_pending_wm_state( HWND hwnd, UINT state ); extern void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value, Time time ); extern void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value ); +extern void window_wm_hints_notify( struct x11drv_win_data *data, unsigned long serial, const XWMHints *hints ); extern void window_mwm_hints_notify( struct x11drv_win_data *data, unsigned long serial, const MwmHints *hints ); extern void window_wm_normal_hints_notify( struct x11drv_win_data *data, unsigned long serial, const XSizeHints *hints ); extern void window_configure_notify( struct x11drv_win_data *data, unsigned long serial, const RECT *rect ); diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 9dfb8347cf4..e02c4cfdd9a 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -120,6 +120,7 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] = "RAW_CAP_HEIGHT", "WM_PROTOCOLS", "WM_DELETE_WINDOW", + "WM_HINTS", "WM_NORMAL_HINTS", "WM_STATE", "WM_TAKE_FOCUS",
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 25 +++++++++++++++++-------- dlls/winex11.drv/x11drv.h | 2 ++ dlls/winex11.drv/x11drv_main.c | 4 ++-- 3 files changed, 21 insertions(+), 10 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 96062faa505..3dc271cf767 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1055,6 +1055,21 @@ static void set_mwm_hints( struct x11drv_win_data *data, UINT style, UINT ex_sty }
+static void window_set_net_wm_window_type( struct x11drv_win_data *data, enum x11drv_atoms atom ) +{ + Atom old_type = data->pending_state.net_wm_window_type, new_type = X11DRV_Atoms[atom - FIRST_XATOM]; + + data->desired_state.net_wm_window_type = new_type; + if (!data->whole_window) return; /* no window or not managed, nothing to update */ + if (old_type == new_type) return; /* hints are the same, nothing to update */ + + data->pending_state.net_wm_window_type = new_type; + TRACE( "window %p/%lx, requesting _NET_WM_WINDOW_TYPE %lx (%s) serial %lu\n", data->hwnd, data->whole_window, + new_type, X11DRV_atom_names[atom - FIRST_XATOM], NextRequest( data->display ) ); + XChangeProperty( data->display, data->whole_window, x11drv_atom(_NET_WM_WINDOW_TYPE), XA_ATOM, + 32, PropModeReplace, (unsigned char *)&new_type, 1 ); +} + static void window_set_wm_hints( struct x11drv_win_data *data, XWMHints *new_hints ) { const XWMHints *old_hints = &data->pending_state.wm_hints; @@ -1079,7 +1094,6 @@ static void set_style_hints( struct x11drv_win_data *data, DWORD style, DWORD ex HWND owner = NtUserGetWindowRelative( data->hwnd, GW_OWNER ); Window owner_win = 0; XWMHints *wm_hints; - Atom window_type;
if (owner) { @@ -1098,14 +1112,9 @@ static void set_style_hints( struct x11drv_win_data *data, DWORD style, DWORD ex * dialogs owned by fullscreen windows. */ if (((style & WS_POPUP) || (ex_style & WS_EX_DLGMODALFRAME)) && owner) - window_type = x11drv_atom(_NET_WM_WINDOW_TYPE_DIALOG); + window_set_net_wm_window_type( data, XATOM__NET_WM_WINDOW_TYPE_DIALOG ); else - window_type = x11drv_atom(_NET_WM_WINDOW_TYPE_NORMAL); - - TRACE( "window %p/%lx requesting _NET_WM_WINDOW_TYPE %#lx, serial %lu\n", data->hwnd, - data->whole_window, window_type, NextRequest( data->display ) ); - XChangeProperty(data->display, data->whole_window, x11drv_atom(_NET_WM_WINDOW_TYPE), - XA_ATOM, 32, PropModeReplace, (unsigned char*)&window_type, 1); + window_set_net_wm_window_type( data, XATOM__NET_WM_WINDOW_TYPE_NORMAL );
if ((wm_hints = XAllocWMHints())) { diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 4d0ce851e8e..5841384ad77 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -577,6 +577,7 @@ enum x11drv_atoms };
extern Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM]; +extern const char * const X11DRV_atom_names[]; extern Atom systray_atom; extern HWND systray_hwnd;
@@ -643,6 +644,7 @@ struct window_state UINT wm_state; BOOL activate; UINT net_wm_state; + Atom net_wm_window_type; XWMHints wm_hints; MwmHints mwm_hints; XSizeHints wm_normal_hints; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index e02c4cfdd9a..0b8eedadd98 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -102,7 +102,7 @@ static pthread_mutex_t error_mutex = PTHREAD_MUTEX_INITIALIZER;
Atom X11DRV_Atoms[NB_XATOMS - FIRST_XATOM];
-static const char * const atom_names[NB_XATOMS - FIRST_XATOM] = +const char * const X11DRV_atom_names[NB_XATOMS - FIRST_XATOM] = { "CLIPBOARD", "COMPOUND_TEXT", @@ -654,7 +654,7 @@ static NTSTATUS x11drv_init( void *arg ) init_visuals( display, DefaultScreen( display )); screen_bpp = pixmap_formats[default_visual.depth]->bits_per_pixel;
- XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms ); + XInternAtoms( display, (char **)X11DRV_atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms );
init_win_context();
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 32 +++++++++++++++++--------------- dlls/winex11.drv/x11drv.h | 1 + 2 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 3dc271cf767..c07885e72b5 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -888,6 +888,7 @@ static void set_window_icon_data( struct x11drv_win_data *data, HICON icon, cons if (data->icon_pixmap) XFreePixmap( gdi_display, data->icon_pixmap ); if (data->icon_mask) XFreePixmap( gdi_display, data->icon_mask ); free( data->icon_bits ); + data->net_wm_icon_serial = 0; /* allow requesting it again */ data->icon_pixmap = icon_pixmap; data->icon_mask = mask_pixmap; data->icon_bits = bits; @@ -1085,6 +1086,20 @@ static void window_set_wm_hints( struct x11drv_win_data *data, XWMHints *new_hin XSetWMHints( data->display, data->whole_window, new_hints ); }
+static void window_set_net_wm_icon( struct x11drv_win_data *data, const void *icon_data, UINT icon_size ) +{ + /* we don't keep track of requested icon data exactly, and use net_wm_icon_serial instead */ + if (!data->whole_window) return; /* no window or not managed, nothing to update */ + if (data->net_wm_icon_serial) return; /* icon has already been requested */ + + data->net_wm_icon_serial = NextRequest( data->display ); + TRACE( "window %p/%lx, requesting _NET_WM_ICON %p/%u serial %lu\n", data->hwnd, data->whole_window, + icon_data, icon_size, data->net_wm_icon_serial ); + if (!icon_data) XChangeProperty( data->display, data->whole_window, x11drv_atom(_NET_WM_ICON), XA_CARDINAL, + 32, PropModeReplace, icon_data, icon_size ); + else XDeleteProperty( data->display, data->whole_window, x11drv_atom(_NET_WM_ICON) ); +} + /*********************************************************************** * set_style_hints */ @@ -1132,21 +1147,7 @@ static void set_style_hints( struct x11drv_win_data *data, DWORD style, DWORD ex XFree( wm_hints ); }
- if (data->icon_bits) - { - TRACE( "window %p/%lx requesting _NET_WM_ICON, serial %lu\n", data->hwnd, - data->whole_window, NextRequest( data->display ) ); - XChangeProperty( data->display, data->whole_window, x11drv_atom(_NET_WM_ICON), - XA_CARDINAL, 32, PropModeReplace, - (unsigned char *)data->icon_bits, data->icon_size ); - } - else - { - TRACE( "window %p/%lx deleting _NET_WM_ICON, serial %lu\n", data->hwnd, - data->whole_window, NextRequest( data->display ) ); - XDeleteProperty( data->display, data->whole_window, x11drv_atom(_NET_WM_ICON) ); - } - + window_set_net_wm_icon( data, data->icon_bits, data->icon_size ); }
@@ -2522,6 +2523,7 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des data->mwm_hints_serial = 0; data->wm_normal_hints_serial = 0; data->configure_serial = 0; + data->net_wm_icon_serial = 0; data->reparenting = 0;
if (data->xic) diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 5841384ad77..e08a7a85652 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -693,6 +693,7 @@ struct x11drv_win_data unsigned long mwm_hints_serial; /* serial of last pending _MOTIF_WM_HINTS request */ unsigned long wm_normal_hints_serial;/* serial of last pending WM_NORMAL_HINTS request */ unsigned long configure_serial; /* serial of last pending configure request */ + unsigned long net_wm_icon_serial; /* serial of last pending _NET_WM_ICON request */ };
extern struct x11drv_win_data *get_win_data( HWND hwnd );
v2: Use the Xlib functions to set/get WM_HINTS / WM_NORMAL_HINTS and track their property changes. The issues I was seeing was caused by direct property changes where these are not actually matching their structures, but rather fixed up as needed by Xlib... The properties data doesn't have the same layout on 32bit vs 64bit clients for instance.
Tracking the property changes isn't strictly required, but it might help debugging if something goes wrong. Also, this should also probably fix the tests.