From 23cbd72571b7bcfa6d93740bbd47a7bccb2fd268 Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Mon, 6 Jul 2020 00:24:06 -0400 Subject: [PATCH] config/output: reconfigure on commit failure If the wlr_output_commit fails and the output was previously enabled, we re-enable the output. If the output was previously enabled, then it was also configured. Without reenabling or reconfiguring the output, the output is left in an invalid state. This adds the missing reconfiguring step. This also adds safe guards in output_disable to prevent removing an output index that is not in the list. --- sway/config/output.c | 23 ++++++++++++++++++----- sway/tree/output.c | 32 ++++++++++++++++++++------------ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index 68aafbe1c..ee584127c 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -397,13 +397,21 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { struct wlr_output *wlr_output = output->wlr_output; + // Store some information so we can restore in case the commit fails. bool was_enabled = output->enabled; + bool was_configured = output->configured; + double old_x = 0, old_y = 0; + 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); + if (was_configured) { + wlr_output_layout_output_coords( + root->output_layout, wlr_output, &old_x, &old_y); + wlr_output_layout_remove(root->output_layout, wlr_output); + } } } else { output->enabled = true; @@ -417,11 +425,16 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { sway_log(SWAY_DEBUG, "Committing output %s", wlr_output->name); if (!wlr_output_commit(wlr_output)) { - // Failed to commit output changes, maybe the output is missing a CRTC. - // 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); + // Failed to commit output changes. Restore the output. If this was an + // attempt to enable and was caused by a lack of a CRTC, it will be + // retried when the output mode we asked for gets set. + sway_log(SWAY_ERROR, "Failed to commit output %s. Restoring output.", + wlr_output->name); output->enabled = was_enabled; + if (was_configured) { + wlr_output_layout_add(root->output_layout, wlr_output, old_x, old_y); + output_configure(output); + } return false; } diff --git a/sway/tree/output.c b/sway/tree/output.c index 9a10c6a89..77e510d57 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -254,23 +254,31 @@ void output_disable(struct sway_output *output) { sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name); wl_signal_emit(&output->events.destroy, output); - output_evacuate(output); + if (output->configured) { + output_evacuate(output); - root_for_each_container(untrack_output, output); + root_for_each_container(untrack_output, output); - int index = list_find(root->outputs, output); - list_del(root->outputs, index); + int index = list_find(root->outputs, output); + if (index >= 0) { + list_del(root->outputs, index); + } else { + sway_log(SWAY_ERROR, "Output %s was configured, but unlisted", + output->wlr_output->name); + } + + output->configured = false; + + arrange_root(); + + // Reconfigure all devices, since devices with map_to_output directives for + // an output that goes offline should stop sending events as long as the + // output remains offline. + input_manager_configure_all_inputs(); + } output->enabled = false; - output->configured = false; output->current_mode = NULL; - - arrange_root(); - - // Reconfigure all devices, since devices with map_to_output directives for - // an output that goes offline should stop sending events as long as the - // output remains offline. - input_manager_configure_all_inputs(); } void output_begin_destroy(struct sway_output *output) {