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.
This commit is contained in:
Kirill Primak 2024-02-11 10:50:14 +03:00
parent d80c46250d
commit 629a5171f2
2 changed files with 35 additions and 4 deletions

View File

@ -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);

View File

@ -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 {