From: Alexandros Frantzis alexandros.frantzis@collabora.com
Track the xdg state we have requested from the compositor and take it into account when sending xdg state update requests.
This fixes a race which would cause us to miss a state update if we haven't yet processed the compositor's configure reply to a previous state request. For example:
0. Initial state: win32 fullscreen, xdg fullscreen 1. Window becomes windowed, we send xdg unset_fullscreen request 2. Window becomes fullscreen, before compositor's xdg "not fullscreen" reply arrives, so we still consider the current xdg state to be fullscreen and thus do not request an xdg fullscreen state 3. Compositor xdg configure "not fullscreen" arrives --- dlls/winewayland.drv/wayland_surface.c | 2 ++ dlls/winewayland.drv/waylanddrv.h | 4 +++- dlls/winewayland.drv/window.c | 16 ++++++++++++---- 3 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 2178f5431cb..4a0e33a35db 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -610,6 +610,7 @@ static BOOL wayland_surface_reconfigure_xdg(struct wayland_surface *surface, { surface->current = surface->processing; memset(&surface->processing, 0, sizeof(surface->processing)); + surface->client_request_state = surface->current.state; xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial); } /* If this is the initial configure, and we have a compatible requested @@ -622,6 +623,7 @@ static BOOL wayland_surface_reconfigure_xdg(struct wayland_surface *surface, { surface->current = surface->requested; memset(&surface->requested, 0, sizeof(surface->requested)); + surface->client_request_state = surface->current.state; xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial); } else if (!surface->current.serial || diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index ead2269b72c..cafc7b704b5 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -72,7 +72,8 @@ enum wayland_surface_config_state WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED = (1 << 0), WAYLAND_SURFACE_CONFIG_STATE_RESIZING = (1 << 1), WAYLAND_SURFACE_CONFIG_STATE_TILED = (1 << 2), - WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN = (1 << 3) + WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN = (1 << 3), + WAYLAND_SURFACE_CONFIG_STATE_UNCERTAIN = (1u << 31), };
enum wayland_surface_role @@ -246,6 +247,7 @@ struct wayland_surface };
struct wayland_surface_config pending, requested, processing, current; + enum wayland_surface_config_state client_request_state; BOOL resizing; struct wayland_window_config window; int content_width, content_height; diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index e80bebdc042..d2557e50373 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -256,25 +256,33 @@ static void wayland_surface_update_state_toplevel(struct wayland_surface *surfac /* First do all state unsettings, before setting new state. Some * Wayland compositors misbehave if the order is reversed. */ if (!(surface->window.state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) && - (surface->current.state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED)) + ((surface->current.state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) || + (surface->client_request_state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED))) { xdg_toplevel_unset_maximized(surface->xdg_toplevel); + surface->client_request_state &= ~WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED; } if (!(surface->window.state & WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN) && - (surface->current.state & WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN)) + ((surface->current.state & WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN) || + (surface->client_request_state & WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN))) { xdg_toplevel_unset_fullscreen(surface->xdg_toplevel); + surface->client_request_state &= ~WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN; }
if ((surface->window.state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) && - !(surface->current.state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED)) + (!(surface->current.state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) || + !(surface->client_request_state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED))) { xdg_toplevel_set_maximized(surface->xdg_toplevel); + surface->client_request_state |= WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED; } if ((surface->window.state & WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN) && - !(surface->current.state & WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN)) + (!(surface->current.state & WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN) || + !(surface->client_request_state & WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN))) { xdg_toplevel_set_fullscreen(surface->xdg_toplevel, NULL); + surface->client_request_state |= WAYLAND_SURFACE_CONFIG_STATE_FULLSCREEN; } } else