diff --git a/src/backend/wayland/wl_client.c b/src/backend/wayland/wl_client.c index e0e4638..a553b7b 100644 --- a/src/backend/wayland/wl_client.c +++ b/src/backend/wayland/wl_client.c @@ -220,6 +220,7 @@ wl_client_reparent(WNativeWindow client, WNativeWindow new_parent, int x, int y) } } + fb->canary = 0xDEADBEEF; wl_list_insert(&wl_state.frame_list, &fb->link); /* Connect the WINGs view's backing store to this frame_buf's image */ @@ -327,6 +328,7 @@ void wl_view_commit_backing_impl(unsigned long id) wlr_scene_node_set_enabled(&fb->scene_buf->node, false); } } + fb->canary = 0xDEADBEEF; wl_list_insert(&wl_state.frame_list, &fb->link); } else { wfree(fb); diff --git a/src/backend/wayland/wl_fakeleader.c b/src/backend/wayland/wl_fakeleader.c index 78d7b88..adf4caa 100644 --- a/src/backend/wayland/wl_fakeleader.c +++ b/src/backend/wayland/wl_fakeleader.c @@ -47,6 +47,7 @@ WNativeWindow wl_fake_leader_create(WScreen *scr) } } + fb->canary = 0xDEADBEEF; wl_list_insert(&wl_state.frame_list, &fb->link); return fb->id; } diff --git a/src/backend/wayland/wl_framebuf.c b/src/backend/wayland/wl_framebuf.c index 22a7edf..c3323c8 100644 --- a/src/backend/wayland/wl_framebuf.c +++ b/src/backend/wayland/wl_framebuf.c @@ -3,6 +3,7 @@ #endif #include #include +#include #include #include #include @@ -403,6 +404,7 @@ wl_frame_create_toplevel(WScreen *scr, } } + fb->canary = 0xDEADBEEF; wl_list_insert(&wl_state.frame_list, &fb->link); /* Register this frame_buf image in the WINGs backing table so * WMDrawString() can resolve the window ID to a pixman_image_t @@ -460,6 +462,7 @@ wl_frame_create_child(WNativeWindow parent_win, WScreen *scr, } } + fb->canary = 0xDEADBEEF; wl_list_insert(&wl_state.frame_list, &fb->link); W_RegisterBacking(fb->id, fb->image); return fb->id; @@ -573,9 +576,37 @@ void wl_frame_paint_button(WCoreWindow *button, WTexture *texture, * pixman for bevel lines, and the WINGs font backend for title text. * Returns 1 (handled) so wFrameWindowPaint skips the Xlib code path. */ +static void +frame_buf_check_canaries(void) +{ + struct wl_frame_buf *fb; + wl_list_for_each(fb, &wl_state.frame_list, link) { + if (fb->canary != 0xDEADBEEF) { + { + FILE *f = fopen("/tmp/wm-canary.log", "w"); + if (f) { + fprintf(f, "CANARY TRASHED: fb id=0x%lx size=%dx%d parent=0x%lx canary=0x%08x\n", + (unsigned long)fb->id, fb->width, fb->height, + (unsigned long)fb->parent_id, fb->canary); + struct wl_frame_buf *f2; + wl_list_for_each(f2, &wl_state.frame_list, link) { + fprintf(f, " fb %p id=0x%lx %dx%d parent=0x%lx canary=%s\n", + (void*)f2, (unsigned long)f2->id, f2->width, f2->height, + (unsigned long)f2->parent_id, + f2->canary == 0xDEADBEEF ? "OK" : "BAD"); + } + fclose(f); + } + } + abort(); + } + } +} + int wl_frame_paint(struct WFrameWindow *fwin) { + frame_buf_check_canaries(); /* During live resize, skip expensive repaint — decorations content * doesn't change, only geometry. Paint once on grab release. */ if (wl_state.grab_type == 2) diff --git a/src/backend/wayland/wl_screen.c b/src/backend/wayland/wl_screen.c index c936e0f..517b905 100644 --- a/src/backend/wayland/wl_screen.c +++ b/src/backend/wayland/wl_screen.c @@ -513,6 +513,7 @@ wl_screen_create_internals(WScreen *scr) wlr_scene_node_set_enabled(&dsfb->tree->node, false); wlr_scene_node_lower_to_bottom(&dsfb->tree->node); } + dsfb->canary = 0xDEADBEEF; wl_list_insert(&wl_state.frame_list, &dsfb->link); scr->dock_shadow = dsfb->id; } else { @@ -562,6 +563,7 @@ wl_screen_create_internals(WScreen *scr) } wlr_scene_node_set_enabled(&fb->tree->node, false); } + fb->canary = 0xDEADBEEF; wl_list_insert(&wl_state.frame_list, &fb->link); W_RegisterBacking(fb->id, fb->image); scr->workspace_name = fb->id; diff --git a/src/backend/wayland/wl_types.h b/src/backend/wayland/wl_types.h index 280f9e1..e423257 100644 --- a/src/backend/wayland/wl_types.h +++ b/src/backend/wayland/wl_types.h @@ -109,6 +109,7 @@ struct wl_frame_buf { int rel_x, rel_y; /* position relative to parent */ int width, height; pixman_image_t *bg_pixmap; /* background pixmap for window_clear */ + uint32_t canary; /* overflow detection: must be 0xDEADBEEF */ struct wl_list link; /* wl_state.frame_list */ }; diff --git a/src/backend/wayland/wl_window.c b/src/backend/wayland/wl_window.c index aa83ceb..e6e6294 100644 --- a/src/backend/wayland/wl_window.c +++ b/src/backend/wayland/wl_window.c @@ -618,6 +618,7 @@ void wl_balloon_init(WScreen *scr) wlr_scene_node_set_enabled(&fb->tree->node, false); } + fb->canary = 0xDEADBEEF; wl_list_insert(&wl_state.frame_list, &fb->link); W_RegisterBacking(fb->id, fb->image); scr->balloon->window = (WNativeWindow)fb->id;