From 0fdbdc36c05fb2811a8b7bc5a69e4d104287cff7 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sat, 26 Aug 2023 19:25:34 +0300 Subject: [PATCH] xdg-surface: fix init state flow Fixes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3677 --- include/wlr/types/wlr_xdg_shell.h | 4 +++- types/xdg_shell/wlr_xdg_popup.c | 7 +++---- types/xdg_shell/wlr_xdg_surface.c | 11 +++++++++++ types/xdg_shell/wlr_xdg_toplevel.c | 7 ++----- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 1b15bfe4..8c1bda05 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -166,7 +166,6 @@ struct wlr_xdg_toplevel_requested { struct wlr_xdg_toplevel { struct wl_resource *resource; struct wlr_xdg_surface *base; - bool sent_initial_configure; struct wlr_xdg_toplevel *parent; struct wl_listener parent_unmap; @@ -257,6 +256,9 @@ struct wlr_xdg_surface { struct wlr_xdg_surface_state current, pending; + bool initialized; + bool initial_commit; + struct { struct wl_signal destroy; struct wl_signal ping_timeout; diff --git a/types/xdg_shell/wlr_xdg_popup.c b/types/xdg_shell/wlr_xdg_popup.c index 1bb73ddc..49db2913 100644 --- a/types/xdg_shell/wlr_xdg_popup.c +++ b/types/xdg_shell/wlr_xdg_popup.c @@ -245,13 +245,12 @@ void handle_xdg_popup_committed(struct wlr_xdg_popup *popup) { return; } - if (!popup->sent_initial_configure) { + popup->current = popup->pending; + + if (popup->base->initial_commit && !popup->sent_initial_configure) { wlr_xdg_surface_schedule_configure(popup->base); popup->sent_initial_configure = true; - return; } - - popup->current = popup->pending; } static const struct xdg_popup_interface xdg_popup_implementation; diff --git a/types/xdg_shell/wlr_xdg_surface.c b/types/xdg_shell/wlr_xdg_surface.c index 80373fbf..2cade81d 100644 --- a/types/xdg_shell/wlr_xdg_surface.c +++ b/types/xdg_shell/wlr_xdg_surface.c @@ -25,6 +25,7 @@ static void xdg_surface_configure_destroy( static void reset_xdg_surface(struct wlr_xdg_surface *surface) { surface->client_mapped = false; + surface->initialized = false; surface->configured = false; struct wlr_xdg_popup *popup, *popup_tmp; @@ -166,6 +167,11 @@ uint32_t wlr_xdg_surface_schedule_configure(struct wlr_xdg_surface *surface) { struct wl_display *display = wl_client_get_display(surface->client->client); struct wl_event_loop *loop = wl_display_get_event_loop(display); + if (!surface->initialized) { + wlr_log(WLR_ERROR, "A configure is scheduled for an uninitialized xdg_surface %p", + surface); + } + if (surface->configure_idle == NULL) { surface->scheduled_serial = wl_display_next_serial(display); surface->configure_idle = wl_event_loop_add_idle(loop, @@ -270,10 +276,15 @@ static void xdg_surface_role_commit(struct wlr_surface *wlr_surface) { return; } + surface->initial_commit = !surface->initialized; + if (surface->client_mapped && !wlr_surface_has_buffer(wlr_surface)) { + assert(!surface->initial_commit); // This commit has unmapped the surface reset_xdg_surface_role_object(surface); reset_xdg_surface(surface); + } else { + surface->initialized = true; } surface->current = surface->pending; diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index 08d316d9..30e46630 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -138,11 +138,10 @@ void handle_xdg_toplevel_committed(struct wlr_xdg_toplevel *toplevel) { toplevel->current = toplevel->pending; - if (!toplevel->sent_initial_configure) { - // on the first commit, send a configure request to tell the client it + if (toplevel->base->initial_commit) { + // On the initial commit, send a configure request to tell the client it // is added wlr_xdg_surface_schedule_configure(toplevel->base); - toplevel->sent_initial_configure = true; if (toplevel->base->client->shell->version >= XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) { @@ -525,8 +524,6 @@ void reset_xdg_toplevel(struct wlr_xdg_toplevel *toplevel) { toplevel->requested.fullscreen = false; toplevel->requested.maximized = false; toplevel->requested.minimized = false; - - toplevel->sent_initial_configure = false; } void destroy_xdg_toplevel(struct wlr_xdg_toplevel *toplevel) {