From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index c6ef4ab7d9d..246e2e2b002 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1194,8 +1194,16 @@ static void update_net_wm_fullscreen_monitors( struct x11drv_win_data *data ) } }
+static BOOL window_needs_config_change_delay( struct x11drv_win_data *data ) +{ + static const UINT fullscreen_mask = (1 << NET_WM_STATE_MAXIMIZED) | (1 << NET_WM_STATE_FULLSCREEN); + if (data->pending_state.wm_state != NormalState || !data->net_wm_state_serial) return FALSE; + return (data->pending_state.net_wm_state ^ data->current_state.net_wm_state) & fullscreen_mask; +} + static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_state ) { + static const UINT fullscreen_mask = (1 << NET_WM_STATE_MAXIMIZED) | (1 << NET_WM_STATE_FULLSCREEN); UINT i, count, old_state = data->pending_state.net_wm_state;
new_state &= x11drv_thread_data()->net_wm_state_mask; @@ -1205,6 +1213,13 @@ static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_stat /* we ignore and override previous _NET_WM_STATE update requests */ if (old_state == new_state) return; /* states are the same, nothing to update */
+ if (window_needs_config_change_delay( data )) + { + /* another maximized/fullscreen NET_WM_STATE update is pending, wait for it to complete as we might have delayed our config request */ + WARN( "window %p/%lx is entering/exiting maximize/fullscreen, delaying request\n", data->hwnd, data->whole_window ); + return; + } + if (data->pending_state.wm_state == IconicState) return; /* window is iconic, don't update its state now */ if (data->pending_state.wm_state == WithdrawnState) /* set the _NET_WM_STATE atom directly */ { @@ -1242,13 +1257,14 @@ static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_stat for (i = 0; i < NB_NET_WM_STATES; i++) { if (!((old_state ^ new_state) & (1 << i))) continue; + if (data->configure_serial && ((1 << i) & fullscreen_mask)) continue; /* another config request is pending, wait for it to complete */
xev.xclient.data.l[0] = (new_state & (1 << i)) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; xev.xclient.data.l[1] = X11DRV_Atoms[net_wm_state_atoms[i] - FIRST_XATOM]; xev.xclient.data.l[2] = ((net_wm_state_atoms[i] == XATOM__NET_WM_STATE_MAXIMIZED_VERT) ? x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ) : 0);
- data->pending_state.net_wm_state = new_state; + data->pending_state.net_wm_state ^= (1 << i); data->net_wm_state_serial = NextRequest( data->display ); TRACE( "window %p/%lx, requesting _NET_WM_STATE %#x serial %lu\n", data->hwnd, data->whole_window, data->pending_state.net_wm_state, data->net_wm_state_serial ); @@ -1262,7 +1278,6 @@ static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_stat
static void window_set_config( struct x11drv_win_data *data, const RECT *new_rect, BOOL above ) { - static const UINT fullscreen_mask = (1 << NET_WM_STATE_MAXIMIZED) | (1 << NET_WM_STATE_FULLSCREEN); UINT style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ), mask = 0; const RECT *old_rect = &data->pending_state.rect; XWindowChanges changes; @@ -1271,15 +1286,13 @@ static void window_set_config( struct x11drv_win_data *data, const RECT *new_rec if (!data->whole_window) return; /* no window, nothing to update */ if (EqualRect( old_rect, new_rect ) && !above) return; /* rects are the same, no need to be raised, nothing to update */
- if (data->pending_state.wm_state == NormalState && data->net_wm_state_serial && - !(data->pending_state.net_wm_state & fullscreen_mask) && - (data->current_state.net_wm_state & fullscreen_mask)) + if (window_needs_config_change_delay( data )) { /* Some window managers are sending a ConfigureNotify event with the fullscreen size when - * exiting a fullscreen window, with a serial that we cannot predict. Handling that event - * will override the Win32 window size and make the window fullscreen again. + * entering/exiting a maximized/fullscreen window, with a serial that we cannot predict. + * Handling that event will override the Win32 window size and make the window fullscreen again. */ - WARN( "window %p/%lx is exiting maximize/fullscreen, delaying request\n", data->hwnd, data->whole_window ); + WARN( "window %p/%lx is entering/exiting maximize/fullscreen, delaying request\n", data->hwnd, data->whole_window ); return; }