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.
This commit is contained in:
Brian Ashworth 2020-07-06 00:24:06 -04:00
parent 1d149230ea
commit 23cbd72571
2 changed files with 38 additions and 17 deletions

View file

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

View file

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