From 629a5171f25df03817bff7db26500ad1b8cabddd Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sun, 11 Feb 2024 10:50:14 +0300 Subject: [PATCH] backend/wayland: don't ack outdated configures This commit fixes the following interaction: 1) The host compositor sends a configure sequence for an output. 2) Before handling it, the guest compositor disables and immediately re-enables the output. 3) The guest compositor tries to ack the configure event from step 1 which isn't relevant anymore after unmapping and re-initialization. Instead, ignore all configure events after unmapping until we're sure the host compositor has processed the unmapping. Also see https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/108. --- backend/wayland/output.c | 35 +++++++++++++++++++++++++++++++---- include/backend/wayland.h | 4 ++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/backend/wayland/output.c b/backend/wayland/output.c index c051a764..d370e200 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -539,6 +539,17 @@ static bool commit_layers(struct wlr_wl_output *output, return true; } +static void unmap_callback_handle_done(void *data, struct wl_callback *callback, + uint32_t cb_data) { + struct wlr_wl_output *output = data; + output->unmap_callback = NULL; + wl_callback_destroy(callback); +} + +static const struct wl_callback_listener unmap_callback_listener = { + .done = unmap_callback_handle_done, +}; + static bool output_commit(struct wlr_output *wlr_output, const struct wlr_output_state *state) { struct wlr_wl_output *output = @@ -551,6 +562,14 @@ static bool output_commit(struct wlr_output *wlr_output, bool pending_enabled = output_pending_enabled(wlr_output, state); if (wlr_output->enabled && !pending_enabled) { + if (output->own_surface) { + output->unmap_callback = wl_display_sync(output->backend->remote_display); + if (output->unmap_callback == NULL) { + return false; + } + wl_callback_add_listener(output->unmap_callback, &unmap_callback_listener, output); + } + wl_surface_attach(output->surface, NULL, 0, 0); wl_surface_commit(output->surface); @@ -710,6 +729,10 @@ static void output_destroy(struct wlr_output *wlr_output) { presentation_feedback_destroy(feedback); } + if (output->unmap_callback) { + wl_callback_destroy(output->unmap_callback); + } + if (output->zxdg_toplevel_decoration_v1) { zxdg_toplevel_decoration_v1_destroy(output->zxdg_toplevel_decoration_v1); } @@ -766,10 +789,6 @@ static void xdg_surface_handle_configure(void *data, struct wlr_wl_output *output = data; assert(output && output->xdg_surface == xdg_surface); - output->configured = true; - output->has_configure_serial = true; - output->configure_serial = serial; - int32_t req_width = output->wlr_output.width; int32_t req_height = output->wlr_output.height; if (output->requested_width > 0) { @@ -781,6 +800,14 @@ static void xdg_surface_handle_configure(void *data, output->requested_height = 0; } + if (output->unmap_callback != NULL) { + return; + } + + output->configured = true; + output->has_configure_serial = true; + output->configure_serial = serial; + struct wlr_output_state state; wlr_output_state_init(&state); wlr_output_state_set_custom_mode(&state, req_width, req_height, 0); diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 9a5f7b2c..fdc83091 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -101,6 +101,10 @@ struct wlr_wl_output { bool initialized; + // If not NULL, the host compositor hasn't acknowledged the unmapping yet; + // ignore all configure events + struct wl_callback *unmap_callback; + uint32_t enter_serial; struct {