aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFurkan Sahin <furkan-dev@proton.me>2025-05-06 01:35:05 +0200
committerFurkan Sahin <furkan-dev@proton.me>2025-05-06 01:35:05 +0200
commitb5b1d77158704691bce44e8d1a416da7b4d4efd5 (patch)
tree1b746633f7a59fd271c50e6eacefc27b230ae8cb
parente4076aaf30c6eb0c6680a5a467514abb5047da6f (diff)
output: Minimize interaction with output after destroy
When an output is destroyed, we go through the process of disabling it. This includes evacuating all content away from the output, which can lead to various modifications to the scene. With the scene_output still present, this can lead to things like output_enter events being emitted for the output currently being destroyed. Ensure that the scene output is destroyed first and that the output is immediately considered disabled. References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3974
-rw-r--r--sway/desktop/output.c16
-rw-r--r--sway/tree/output.c13
2 files changed, 15 insertions, 14 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index aec1d0a6..e6fe2ee4 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -422,13 +422,6 @@ void force_modeset(void) {
}
static void begin_destroy(struct sway_output *output) {
- if (output->enabled) {
- output_disable(output);
- }
-
- output_begin_destroy(output);
-
- wl_list_remove(&output->link);
wl_list_remove(&output->layout_destroy.link);
wl_list_remove(&output->destroy.link);
@@ -436,8 +429,17 @@ static void begin_destroy(struct sway_output *output) {
wl_list_remove(&output->frame.link);
wl_list_remove(&output->request_state.link);
+ // Remove the scene_output first to ensure that the scene does not emit
+ // events for this output.
wlr_scene_output_destroy(output->scene_output);
output->scene_output = NULL;
+
+ if (output->enabled) {
+ output_disable(output);
+ }
+ output_begin_destroy(output);
+ wl_list_remove(&output->link);
+
output->wlr_output->data = NULL;
output->wlr_output = NULL;
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 65d9e3e7..bc380629 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -205,11 +205,8 @@ static void output_evacuate(struct sway_output *output) {
return;
}
struct sway_output *fallback_output = NULL;
- if (root->outputs->length > 1) {
+ if (root->outputs->length > 0) {
fallback_output = root->outputs->items[0];
- if (fallback_output == output) {
- fallback_output = root->outputs->items[1];
- }
}
while (output->workspaces->length) {
@@ -289,11 +286,13 @@ void output_disable(struct sway_output *output) {
sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name);
wl_signal_emit_mutable(&output->events.disable, output);
- output_evacuate(output);
-
+ // Remove the output now to avoid interacting with it during e.g.,
+ // transactions, as the output might be physically removed with the scene
+ // output destroyed.
list_del(root->outputs, index);
-
output->enabled = false;
+
+ output_evacuate(output);
}
void output_begin_destroy(struct sway_output *output) {