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