From c1c5e2ca690aec8ab2087c1df4915218d44021a8 Mon Sep 17 00:00:00 2001 From: save196 Date: Tue, 24 Feb 2026 17:43:22 +0200 Subject: [PATCH 1/5] Fix crash when overlay surface is destroyed before its role --- src/overlay.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/overlay.c b/src/overlay.c index 0b2b2b2..803cbaf 100644 --- a/src/overlay.c +++ b/src/overlay.c @@ -60,6 +60,9 @@ static PangoLayout *create_text_layout(struct wd_head *head, } static void resize(struct wd_output *output) { + if (output->overlay_window == NULL || output->overlay_layer_surface == NULL) + return; + struct wd_head *head = wd_find_head(output->state, output); uint32_t screen_width = head->custom_mode.width; @@ -138,11 +141,6 @@ void window_map(GtkWidget *widget, gpointer data) { resize(output); } -void window_unmap(GtkWidget *widget, gpointer data) { - struct wd_output *output = data; - zwlr_layer_surface_v1_destroy(output->overlay_layer_surface); -} - gboolean window_draw(GtkWidget *widget, cairo_t *cr, gpointer data) { struct wd_output *output = data; struct wd_head *head = wd_find_head(output->state, output); @@ -177,8 +175,6 @@ void wd_create_overlay(struct wd_output *output) { G_CALLBACK(window_realize), output); g_signal_connect(output->overlay_window, "map", G_CALLBACK(window_map), output); - g_signal_connect(output->overlay_window, "unmap", - G_CALLBACK(window_unmap), output); g_signal_connect(output->overlay_window, "draw", G_CALLBACK(window_draw), output); @@ -190,6 +186,10 @@ void wd_create_overlay(struct wd_output *output) { void wd_destroy_overlay(struct wd_output *output) { if (output->overlay_window != NULL) { + if (output->overlay_layer_surface != NULL) { + zwlr_layer_surface_v1_destroy(output->overlay_layer_surface); + output->overlay_layer_surface = NULL; + } gtk_widget_destroy(output->overlay_window); output->overlay_window = NULL; } From 4c7342b5c5456c51ba77293c56129b672256431a Mon Sep 17 00:00:00 2001 From: save196 Date: Wed, 25 Feb 2026 11:58:56 +0200 Subject: [PATCH 2/5] Handle NULL head in overlay resize/draw --- src/overlay.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/overlay.c b/src/overlay.c index 803cbaf..5be9b27 100644 --- a/src/overlay.c +++ b/src/overlay.c @@ -64,6 +64,8 @@ static void resize(struct wd_output *output) { return; struct wd_head *head = wd_find_head(output->state, output); + if (head == NULL) + return; uint32_t screen_width = head->custom_mode.width; uint32_t screen_height = head->custom_mode.height; @@ -144,6 +146,8 @@ void window_map(GtkWidget *widget, gpointer data) { gboolean window_draw(GtkWidget *widget, cairo_t *cr, gpointer data) { struct wd_output *output = data; struct wd_head *head = wd_find_head(output->state, output); + if (head == NULL) + return TRUE; GtkStyleContext *style_ctx = gtk_widget_get_style_context(widget); GdkRGBA fg; From 4ef6948efc7c5155bb63f041d2c10039ccb121bf Mon Sep 17 00:00:00 2001 From: Mars-Wave <57585293+Mars-Wave@users.noreply.github.com> Date: Fri, 3 Apr 2026 19:19:29 +0200 Subject: [PATCH 3/5] Clear head output when the output is destroyed --- src/outputs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/outputs.c b/src/outputs.c index 024a686..7886d72 100644 --- a/src/outputs.c +++ b/src/outputs.c @@ -310,6 +310,12 @@ static void wd_output_destroy(struct wd_output *output) { if (output->state->layer_shell != NULL) { wd_destroy_overlay(output); } + struct wd_head *head; + wl_list_for_each(head, &output->state->heads, link) { + if (head->output == output) { + head->output = NULL; + } + } zxdg_output_v1_destroy(output->xdg_output); free(output->name); free(output); From d657f9236e6b1c1bec2f24a8e140526426ad78cd Mon Sep 17 00:00:00 2001 From: Mars-Wave <57585293+Mars-Wave@users.noreply.github.com> Date: Sun, 12 Apr 2026 17:37:16 +0200 Subject: [PATCH 4/5] Destroy outputs before heads on shutdown --- src/outputs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/outputs.c b/src/outputs.c index 7886d72..c98160c 100644 --- a/src/outputs.c +++ b/src/outputs.c @@ -684,14 +684,14 @@ void wd_capture_wait(struct wd_state *state, struct wl_display *display) { } void wd_state_destroy(struct wd_state *state) { - struct wd_head *head, *head_tmp; - wl_list_for_each_safe(head, head_tmp, &state->heads, link) { - wd_head_destroy(head); - } struct wd_output *output, *output_tmp; wl_list_for_each_safe(output, output_tmp, &state->outputs, link) { wd_output_destroy(output); } + struct wd_head *head, *head_tmp; + wl_list_for_each_safe(head, head_tmp, &state->heads, link) { + wd_head_destroy(head); + } if (state->layer_shell != NULL) { zwlr_layer_shell_v1_destroy(state->layer_shell); } From a3a7493c5604dc8726d6635839aea03d61585b83 Mon Sep 17 00:00:00 2001 From: Mars-Wave <57585293+Mars-Wave@users.noreply.github.com> Date: Mon, 13 Apr 2026 23:04:44 +0200 Subject: [PATCH 5/5] Only round-trip when an overlay is first mapped --- src/overlay.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/overlay.c b/src/overlay.c index 5be9b27..3887a57 100644 --- a/src/overlay.c +++ b/src/overlay.c @@ -102,9 +102,6 @@ static void resize(struct wd_output *output) { struct wl_surface *surface = gdk_wayland_window_get_wl_surface(window); wl_surface_commit(surface); - - GdkDisplay *display = gdk_window_get_display(window); - wl_display_roundtrip(gdk_wayland_display_get_wl_display(display)); } void wd_redraw_overlay(struct wd_output *output) { @@ -141,6 +138,9 @@ void window_map(GtkWidget *widget, gpointer data) { ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); resize(output); + + GdkDisplay *display = gdk_window_get_display(window); + wl_display_roundtrip(gdk_wayland_display_get_wl_display(display)); } gboolean window_draw(GtkWidget *widget, cairo_t *cr, gpointer data) {