From d5f5885c941d9f74f131734b253133108c759e20 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 10 Jul 2020 18:04:45 +0200 Subject: config/output: don't change output state before commit Previously, we called output_disable prior to wlr_output_commit. This mutates Sway's output state before the output commit actually succeeds. This results in Sway's state getting out-of-sync with wlroots'. An alternative fix [1] was to revert the changes made by output_disable in case of failure. This is a little complicated. Instead, this patch makes it so Sway's internal state is never changed before a successful wlr_output commit. We had two output flags: enabled and configured. However enabled was set prior to the output becoming enabled, and was used to prevent the output event handlers (specifically, the mode handler) from calling apply_output_config again (infinite loop). Rename enabled to enabling and use it exclusively for this purpose. Rename configure to enabled, because that's what it really means. [1]: https://github.com/swaywm/sway/pull/5521 Closes: https://github.com/swaywm/sway/issues/5483 (cherry picked from commit 5432f00adfdd8375fb422ad9033253d17f04efc7) --- include/sway/output.h | 4 ++-- sway/config/output.c | 26 ++++++++++++-------------- sway/desktop/output.c | 8 ++++---- sway/input/cursor.c | 4 ++-- sway/tree/output.c | 7 +++---- 5 files changed, 23 insertions(+), 26 deletions(-) diff --git a/include/sway/output.h b/include/sway/output.h index cabb4b55..f27f6344 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -36,7 +36,7 @@ struct sway_output { // last applied mode when the output is DPMS'ed struct wlr_output_mode *current_mode; - bool enabled, configured; + bool enabling, enabled; list_t *workspaces; struct sway_output_state current; @@ -98,7 +98,7 @@ struct sway_output *all_output_by_name_or_id(const char *name_or_id); void output_sort_workspaces(struct sway_output *output); -void output_configure(struct sway_output *output); +void output_enable(struct sway_output *output); void output_disable(struct sway_output *output); diff --git a/sway/config/output.c b/sway/config/output.c index 68aafbe1..b59cabd4 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -397,17 +397,8 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { struct wlr_output *wlr_output = output->wlr_output; - bool was_enabled = output->enabled; - if (oc && !oc->enabled) { - // Output is configured to be disabled - sway_log(SWAY_DEBUG, "Disabling output %s", oc->name); - if (output->enabled) { - output_disable(output); - wlr_output_layout_remove(root->output_layout, wlr_output); - } - } else { - output->enabled = true; - } + // Flag to prevent the output mode event handler from calling us + output->enabling = (!oc || oc->enabled); queue_output_config(oc, output); @@ -421,11 +412,18 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { // Leave the output disabled for now and try again when the output gets // the mode we asked for. sway_log(SWAY_ERROR, "Failed to commit output %s", wlr_output->name); - output->enabled = was_enabled; + output->enabling = false; return false; } + output->enabling = false; + if (oc && !oc->enabled) { + sway_log(SWAY_DEBUG, "Disabling output %s", oc->name); + if (output->enabled) { + output_disable(output); + wlr_output_layout_remove(root->output_layout, wlr_output); + } return true; } @@ -468,8 +466,8 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { output->width = output_box->width; output->height = output_box->height; - if (!output->configured) { - output_configure(output); + if (!output->enabled) { + output_enable(output); } if (oc && oc->max_render_time >= 0) { diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 4a51b5cc..5fdaba68 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -844,7 +844,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { static void handle_mode(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, mode); - if (!output->configured && !output->enabled) { + if (!output->enabled && !output->enabling) { struct output_config *oc = find_output_config(output); if (output->wlr_output->current_mode != NULL && (!oc || oc->enabled)) { @@ -857,7 +857,7 @@ static void handle_mode(struct wl_listener *listener, void *data) { } return; } - if (!output->enabled || !output->configured) { + if (!output->enabled) { return; } arrange_layers(output); @@ -869,7 +869,7 @@ static void handle_mode(struct wl_listener *listener, void *data) { static void handle_transform(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, transform); - if (!output->enabled || !output->configured) { + if (!output->enabled) { return; } arrange_layers(output); @@ -886,7 +886,7 @@ static void update_textures(struct sway_container *con, void *data) { static void handle_scale(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, scale); - if (!output->enabled || !output->configured) { + if (!output->enabled) { return; } arrange_layers(output); diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d10ba444..0d5b076b 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -99,8 +99,8 @@ struct sway_node *node_at_coords( return NULL; } struct sway_output *output = wlr_output->data; - if (!output || !output->configured) { - // output is being destroyed or is being configured + if (!output || !output->enabled) { + // output is being destroyed or is being enabled return NULL; } double ox = lx, oy = ly; diff --git a/sway/tree/output.c b/sway/tree/output.c index 9a10c6a8..ae3c3abf 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -110,12 +110,12 @@ struct sway_output *output_create(struct wlr_output *wlr_output) { return output; } -void output_configure(struct sway_output *output) { - if (!sway_assert(!output->configured, "output is already configured")) { +void output_enable(struct sway_output *output) { + if (!sway_assert(!output->enabled, "output is already enabled")) { return; } struct wlr_output *wlr_output = output->wlr_output; - output->configured = true; + output->enabled = true; list_add(root->outputs, output); restore_workspaces(output); @@ -262,7 +262,6 @@ void output_disable(struct sway_output *output) { list_del(root->outputs, index); output->enabled = false; - output->configured = false; output->current_mode = NULL; arrange_root(); -- cgit v1.2.3