diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index b1c78f7..0935393 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -282,7 +282,9 @@ struct wl_frame_buf { pixman_image_t *image; /* ARGB32 pixel data */ struct wlr_scene_buffer *scene_buf; /* scene graph node */ WNativeWindow id; /* synthetic ID (>= 0x10000000) */ + WNativeWindow parent_id; /* parent frame_buf ID (0 = root) */ int x, y; /* position in output coords */ + int rel_x, rel_y; /* position relative to parent */ int width, height; struct wl_list link; /* wl_state.frame_list */ }; @@ -3596,12 +3598,51 @@ static WNativeWindow wl_frame_create_child(WNativeWindow parent_win, WScreen *scr, int x, int y, int width, int height) { - (void)parent_win; (void)scr; - (void)x; (void)y; (void)width; (void)height; - /* Child windows (titlebar, buttons, resizebar) are sub-regions of the - * parent frame buffer. Return a synthetic ID so context_save works, - * but no separate buffer is needed — frame_paint renders everything. */ - return wl_state.next_synthetic_id++; + (void)scr; + + if (width <= 0) width = 1; + if (height <= 0) height = 1; + + /* Compute absolute position from parent */ + int abs_x = x, abs_y = y; + struct wl_frame_buf *parent = frame_buf_find(parent_win); + if (parent) { + abs_x = parent->x + x; + abs_y = parent->y + y; + } + + struct wl_frame_buf *fb = wmalloc(sizeof(*fb)); + memset(fb, 0, sizeof(*fb)); + + fb->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, + width, height, NULL, 0); + if (!fb->image) { + wfree(fb); + return WNATIVE_NONE; + } + + wlr_buffer_init(&fb->base, &frame_buf_impl, width, height); + + fb->id = wl_state.next_synthetic_id++; + fb->parent_id = parent_win; + fb->rel_x = x; + fb->rel_y = y; + fb->x = abs_x; + fb->y = abs_y; + fb->width = width; + fb->height = height; + + if (wl_state.scene) { + fb->scene_buf = wlr_scene_buffer_create(&wl_state.scene->tree, + &fb->base); + if (fb->scene_buf) { + wlr_scene_node_set_position(&fb->scene_buf->node, abs_x, abs_y); + wlr_scene_node_set_enabled(&fb->scene_buf->node, false); + } + } + + wl_list_insert(&wl_state.frame_list, &fb->link); + return fb->id; } static void @@ -5294,10 +5335,16 @@ wl_window_map(WNativeWindow win) wlr_scene_node_set_enabled(&v->scene_node->node, true); return; } - /* Frame buffer: enable its scene node. */ + /* Frame buffer: enable its scene node and children. */ struct wl_frame_buf *fb = frame_buf_find(win); if (fb && fb->scene_buf) { wlr_scene_node_set_enabled(&fb->scene_buf->node, true); + /* Also enable children */ + struct wl_frame_buf *child; + wl_list_for_each(child, &wl_state.frame_list, link) { + if (child->parent_id == win && child->scene_buf) + wlr_scene_node_set_enabled(&child->scene_buf->node, true); + } return; } } @@ -5355,6 +5402,17 @@ static void wl_window_move(WNativeWindow win, int x, int y) fb->x = x; fb->y = y; if (fb->scene_buf) wlr_scene_node_set_position(&fb->scene_buf->node, x, y); + /* Move children that track this parent */ + struct wl_frame_buf *child; + wl_list_for_each(child, &wl_state.frame_list, link) { + if (child->parent_id == win) { + child->x = x + child->rel_x; + child->y = y + child->rel_y; + if (child->scene_buf) + wlr_scene_node_set_position(&child->scene_buf->node, + child->x, child->y); + } + } return; } }