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.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 66 +++++++++++++++++++++++----------- dlls/winex11.drv/x11drv.h | 5 ++- dlls/winex11.drv/x11drv_main.c | 4 ++- 3 files changed, 53 insertions(+), 22 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 0eddc40da0c..8f52313e20b 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, "%p {", hints ); + 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, const 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; + 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), NextRequest( data->display ) ); + XChangeProperty( data->display, data->whole_window, x11drv_atom(WM_NORMAL_HINTS), x11drv_atom(WM_SIZE_HINTS), + 32, PropModeReplace, (unsigned char *)new_hints, sizeof(*new_hints) / sizeof(long) ); +} +
/*********************************************************************** * set_size_hints @@ -870,12 +901,10 @@ 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; - - if (!(size_hints = XAllocSizeHints())) return; + XSizeHints size_hints = {0};
- size_hints->win_gravity = StaticGravity; - size_hints->flags |= PWinGravity; + size_hints.win_gravity = StaticGravity; + size_hints.flags |= PWinGravity;
/* don't update size hints if window is not in normal state */ if (!(style & (WS_MINIMIZE | WS_MAXIMIZE))) @@ -883,28 +912,25 @@ static void set_size_hints( struct x11drv_win_data *data, DWORD style ) if (data->hwnd != NtUserGetDesktopWindow()) /* don't force position of desktop */ { POINT pt = virtual_screen_to_root( data->rects.visible.left, data->rects.visible.top ); - size_hints->x = pt.x; - size_hints->y = pt.y; - size_hints->flags |= PPosition; + size_hints.x = pt.x; + size_hints.y = pt.y; + size_hints.flags |= PPosition; } - else size_hints->win_gravity = NorthWestGravity; + else size_hints.win_gravity = NorthWestGravity;
if (!is_window_resizable( data, style )) { - size_hints->max_width = data->rects.visible.right - data->rects.visible.left; - size_hints->max_height = data->rects.visible.bottom - data->rects.visible.top; - if (size_hints->max_width <= 0 ||size_hints->max_height <= 0) - size_hints->max_width = size_hints->max_height = 1; - size_hints->min_width = size_hints->max_width; - size_hints->min_height = size_hints->max_height; - size_hints->flags |= PMinSize | PMaxSize; + size_hints.max_width = data->rects.visible.right - data->rects.visible.left; + size_hints.max_height = data->rects.visible.bottom - data->rects.visible.top; + if (size_hints.max_width <= 0 ||size_hints.max_height <= 0) + size_hints.max_width = size_hints.max_height = 1; + size_hints.min_width = size_hints.max_width; + size_hints.min_height = size_hints.max_height; + size_hints.flags |= PMinSize | PMaxSize; } }
- 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 ); - XFree( size_hints ); + window_set_wm_normal_hints( data, &size_hints ); }
/* bits that can trigger spurious ConfigureNotify events */ diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index e597b956e67..792526d02bd 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -498,8 +498,10 @@ enum x11drv_atoms XATOM_RAW_ASCENT, XATOM_RAW_DESCENT, XATOM_RAW_CAP_HEIGHT, - XATOM_WM_PROTOCOLS, XATOM_WM_DELETE_WINDOW, + XATOM_WM_NORMAL_HINTS, + XATOM_WM_PROTOCOLS, + XATOM_WM_SIZE_HINTS, XATOM_WM_STATE, XATOM_WM_TAKE_FOCUS, XATOM_DndProtocol, @@ -642,6 +644,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; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 6616f9fb7d0..14b75443656 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -118,8 +118,10 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] = "RAW_ASCENT", "RAW_DESCENT", "RAW_CAP_HEIGHT", - "WM_PROTOCOLS", "WM_DELETE_WINDOW", + "WM_NORMAL_HINTS", + "WM_PROTOCOLS", + "WM_SIZE_HINTS", "WM_STATE", "WM_TAKE_FOCUS", "DndProtocol",
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 58 ++++++++++++++++++++++++---------- dlls/winex11.drv/x11drv.h | 2 ++ dlls/winex11.drv/x11drv_main.c | 1 + 3 files changed, 44 insertions(+), 17 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 8f52313e20b..99580d47623 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, "%p {", hints ); + 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] ); @@ -1036,6 +1052,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, const 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; + TRACE( "window %p/%lx, requesting WM_HINTS %s serial %lu\n", data->hwnd, data->whole_window, + debugstr_wm_hints(&data->pending_state.wm_hints), NextRequest( data->display ) ); + XChangeProperty( data->display, data->whole_window, x11drv_atom(WM_HINTS), x11drv_atom(WM_HINTS), + 32, PropModeReplace, (unsigned char *)new_hints, sizeof(*new_hints) / sizeof(long) ); +} + /*********************************************************************** * set_style_hints */ @@ -1044,7 +1075,7 @@ static void set_style_hints( struct x11drv_win_data *data, DWORD style, DWORD ex Window group_leader = data->whole_window; HWND owner = NtUserGetWindowRelative( data->hwnd, GW_OWNER ); Window owner_win = 0; - XWMHints *wm_hints; + XWMHints wm_hints = {0}; Atom window_type;
if (owner) @@ -1073,24 +1104,17 @@ static void set_style_hints( struct x11drv_win_data *data, DWORD style, DWORD ex XChangeProperty(data->display, data->whole_window, x11drv_atom(_NET_WM_WINDOW_TYPE), XA_ATOM, 32, PropModeReplace, (unsigned char*)&window_type, 1);
- if ((wm_hints = XAllocWMHints())) + wm_hints.flags = InputHint | StateHint | WindowGroupHint; + wm_hints.input = !use_take_focus && !(style & WS_DISABLED); + wm_hints.initial_state = (style & WS_MINIMIZE) ? IconicState : NormalState; + wm_hints.window_group = group_leader; + if (data->icon_pixmap) { - wm_hints->flags = InputHint | StateHint | WindowGroupHint; - wm_hints->input = !use_take_focus && !(style & WS_DISABLED); - wm_hints->initial_state = (style & WS_MINIMIZE) ? IconicState : NormalState; - wm_hints->window_group = group_leader; - if (data->icon_pixmap) - { - wm_hints->icon_pixmap = data->icon_pixmap; - 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 ); - XFree( wm_hints ); + wm_hints.icon_pixmap = data->icon_pixmap; + wm_hints.icon_mask = data->icon_mask; + wm_hints.flags |= IconPixmapHint | IconMaskHint; } + window_set_wm_hints( data, &wm_hints );
if (data->icon_bits) { diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 792526d02bd..1a68a17119c 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_DELETE_WINDOW, XATOM_WM_NORMAL_HINTS, + XATOM_WM_HINTS, XATOM_WM_PROTOCOLS, XATOM_WM_SIZE_HINTS, XATOM_WM_STATE, @@ -643,6 +644,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; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 14b75443656..1cbf7451c4d 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -119,6 +119,7 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] = "RAW_DESCENT", "RAW_CAP_HEIGHT", "WM_DELETE_WINDOW", + "WM_HINTS", "WM_NORMAL_HINTS", "WM_PROTOCOLS", "WM_SIZE_HINTS",
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 99580d47623..0694611d806 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1052,6 +1052,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, const XWMHints *new_hints ) { const XWMHints *old_hints = &data->pending_state.wm_hints; @@ -1076,7 +1091,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 = {0}; - Atom window_type;
if (owner) { @@ -1095,14 +1109,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 );
wm_hints.flags = InputHint | StateHint | WindowGroupHint; wm_hints.input = !use_take_focus && !(style & WS_DISABLED); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 1a68a17119c..e7a2f679b1e 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -578,6 +578,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;
@@ -644,6 +645,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 1cbf7451c4d..33440382f45 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", @@ -655,7 +655,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 0694611d806..bb72fc74c3b 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; @@ -1082,6 +1083,20 @@ static void window_set_wm_hints( struct x11drv_win_data *data, const XWMHints *n 32, PropModeReplace, (unsigned char *)new_hints, sizeof(*new_hints) / sizeof(long) ); }
+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 */ @@ -1125,21 +1140,7 @@ static void set_style_hints( struct x11drv_win_data *data, DWORD style, DWORD ex } window_set_wm_hints( data, &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 ); }
@@ -2486,6 +2487,7 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des data->net_wm_state_serial = 0; data->mwm_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 e7a2f679b1e..90d022c2976 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -692,6 +692,7 @@ struct x11drv_win_data 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 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 );