This MR should be no-op and doesn't change much, but makes some small refactoring in preparation for an improved window state tracker as designed in https://gitlab.winehq.org/wine/wine/-/merge_requests/6569.
Overall with that full MR not much would be changed either, and instead some existing fields are replaced with a cleaner design, until the end of the MR where state requests are made asynchronous and where the new information is used to decide whether to apply or delay client state updates.
I believe that the whole MR would fix the currently often failing d3d/ddraw tests, and more generally fix race conditions that happen with window state updates. I believe that it should also ultimately make it easier/safer to change the current design, to delay the client state updates a bit more and apply them outside of the driver ProcessEvent calls: tracking the pending and host states accurately and independently of the win32 state will let us decide what change needs to be requested to make them match, at any moment.
The latter would fix some existing bug where applications stop responding as they start a new message loop in response to SC_RESTORE commands, and as we do not process X11 events recursively.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 893c73df62f..e06b515025b 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2989,7 +2989,8 @@ LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) if (old_pos.x != pos.x) mask |= CWX; if (old_pos.y != pos.y) mask |= CWY;
- if (mask) XReconfigureWMWindow( data->display, data->whole_window, data->vis.screen, mask, &changes ); + data->configure_serial = NextRequest( data->display ); + XReconfigureWMWindow( data->display, data->whole_window, data->vis.screen, mask, &changes ); }
release_win_data( data );
From: Rémi Bernon rbernon@codeweavers.com
And return the property value instead of updating the window data. --- dlls/winex11.drv/event.c | 4 ++-- dlls/winex11.drv/window.c | 12 +++++------- dlls/winex11.drv/x11drv.h | 3 +-- 3 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 9e380141e18..8a60e817802 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -1125,7 +1125,7 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ); if ((style & WS_CAPTION) == WS_CAPTION || !data->is_fullscreen) { - read_net_wm_states( event->display, data ); + data->net_wm_state = get_window_net_wm_state( event->display, data->whole_window ); if ((data->net_wm_state & (1 << NET_WM_STATE_MAXIMIZED))) { if (!(style & WS_MAXIMIZE)) @@ -1226,7 +1226,7 @@ static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL updat if (data->iconic && data->wm_state == NormalState) /* restore window */ { data->iconic = FALSE; - read_net_wm_states( event->display, data ); + data->net_wm_state = get_window_net_wm_state( event->display, data->whole_window ); if ((style & WS_CAPTION) == WS_CAPTION && (data->net_wm_state & (1 << NET_WM_STATE_MAXIMIZED))) { if ((style & WS_MAXIMIZEBOX) && !(style & WS_DISABLED)) diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index e06b515025b..76bf99af032 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1213,7 +1213,7 @@ static void update_net_wm_fullscreen_monitors( struct x11drv_win_data *data ) /*********************************************************************** * update_net_wm_states */ -void update_net_wm_states( struct x11drv_win_data *data ) +static void update_net_wm_states( struct x11drv_win_data *data ) { UINT i, style, ex_style, new_state = 0;
@@ -1301,17 +1301,15 @@ void update_net_wm_states( struct x11drv_win_data *data ) /*********************************************************************** * read_net_wm_states */ -void read_net_wm_states( Display* display, struct x11drv_win_data *data ) +UINT get_window_net_wm_state( Display *display, Window window ) { Atom type, *state; int format; unsigned long i, j, count, remaining; - DWORD new_state = 0; + UINT new_state = 0; BOOL maximized_horz = FALSE;
- if (!data->whole_window) return; - - if (!XGetWindowProperty( display, data->whole_window, x11drv_atom(_NET_WM_STATE), 0, + if (!XGetWindowProperty( display, window, x11drv_atom(_NET_WM_STATE), 0, 65536/sizeof(CARD32), False, XA_ATOM, &type, &format, &count, &remaining, (unsigned char **)&state )) { @@ -1336,7 +1334,7 @@ void read_net_wm_states( Display* display, struct x11drv_win_data *data ) if (!maximized_horz) new_state &= ~(1 << NET_WM_STATE_MAXIMIZED);
- data->net_wm_state = new_state; + return new_state; }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 64380c1322f..83a423b8996 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -650,8 +650,7 @@ extern void destroy_vk_surface( HWND hwnd ); extern void wait_for_withdrawn_state( HWND hwnd, BOOL set ); extern Window init_clip_window(void); extern void update_user_time( Time time ); -extern void read_net_wm_states( Display *display, struct x11drv_win_data *data ); -extern void update_net_wm_states( struct x11drv_win_data *data ); +extern UINT get_window_net_wm_state( Display *display, Window window ); extern void make_window_embedded( struct x11drv_win_data *data ); extern Window create_client_window( HWND hwnd, const XVisualInfo *visual, Colormap colormap ); extern void detach_client_window( struct x11drv_win_data *data, Window client_window );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 8a60e817802..1ae7afd2fa4 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -1075,6 +1075,13 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) host_window_configure_child( data->parent, data->whole_window, rect, event->send_event ); }
+ /* synthetic events are already in absolute coordinates */ + if (!event->send_event) pos = host_window_map_point( data->parent, event->x, event->y ); + else if (is_virtual_desktop()) FIXME( "synthetic event mapping not implemented\n" ); + + pos = root_to_virtual_screen( pos.x, pos.y ); + SetRect( &rect, pos.x, pos.y, pos.x + event->width, pos.y + event->height ); + if (!data->mapped || data->iconic) goto done; if (!data->whole_window || !data->managed) goto done; if (data->configure_serial && (long)(data->configure_serial - event->serial) > 0) @@ -1085,12 +1092,6 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) goto done; }
- /* synthetic events are already in absolute coordinates */ - if (!event->send_event) pos = host_window_map_point( data->parent, event->x, event->y ); - else if (is_virtual_desktop()) FIXME( "synthetic event mapping not implemented\n" ); - - pos = root_to_virtual_screen( pos.x, pos.y ); - SetRect( &rect, pos.x, pos.y, pos.x + event->width, pos.y + event->height ); rect = window_rect_from_visible( &data->rects, rect );
TRACE( "win %p/%lx new X rect %d,%d,%dx%d (event %d,%d,%dx%d)\n",
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 76bf99af032..e8c5f4fbb6d 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -488,7 +488,7 @@ static int get_window_attributes( struct x11drv_win_data *data, XSetWindowAttrib */ static void sync_window_style( struct x11drv_win_data *data ) { - if (data->whole_window != root_window) + if (data->whole_window != root_window && !data->embedded) { XSetWindowAttributes attr; int mask = get_window_attributes( data, &attr ); @@ -1217,7 +1217,7 @@ static void update_net_wm_states( struct x11drv_win_data *data ) { UINT i, style, ex_style, new_state = 0;
- if (!data->managed) return; + if (!data->managed || data->embedded) return; if (data->whole_window == root_window) { update_desktop_fullscreen(data->display); @@ -1372,15 +1372,12 @@ static void map_window( HWND hwnd, DWORD new_style )
remove_startup_notification( data->display, data->whole_window ); set_wm_hints( data ); + update_net_wm_states( data ); + sync_window_style( data );
- if (!data->embedded) - { - update_net_wm_states( data ); - sync_window_style( data ); - XMapWindow( data->display, data->whole_window ); - XFlush( data->display ); - } - else set_xembed_flags( data, XEMBED_MAPPED ); + if (data->embedded) set_xembed_flags( data, XEMBED_MAPPED ); + else XMapWindow( data->display, data->whole_window ); + XFlush( data->display );
data->mapped = TRUE; data->iconic = (new_style & WS_MINIMIZE) != 0;
From: Rémi Bernon rbernon@codeweavers.com
The events will be ignored later but this helps making the window state tracking more consistent. --- dlls/winex11.drv/window.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index e8c5f4fbb6d..c778d1099c9 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -473,8 +473,7 @@ static int get_window_attributes( struct x11drv_win_data *data, XSetWindowAttrib attr->event_mask = (ExposureMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | KeyPressMask | KeyReleaseMask | FocusChangeMask | - KeymapStateMask | StructureNotifyMask); - if (data->managed) attr->event_mask |= PropertyChangeMask; + KeymapStateMask | StructureNotifyMask | PropertyChangeMask);
return (CWOverrideRedirect | CWSaveUnder | CWColormap | CWBorderPixel | CWEventMask | CWBitGravity | CWBackingStore);