diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 4f8030f..31a5067 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -5431,11 +5431,18 @@ wl_window_map(WNativeWindow win) return; /* parent not visible yet */ } wlr_scene_node_set_enabled(&fb->scene_buf->node, true); - /* Also enable children */ + /* Also enable children (and grandchildren) */ struct wl_frame_buf *child; wl_list_for_each(child, &wl_state.frame_list, link) { - if (child->parent_id == win && child->scene_buf) + if (child->parent_id == win && child->scene_buf) { wlr_scene_node_set_enabled(&child->scene_buf->node, true); + /* Enable grandchildren */ + struct wl_frame_buf *gc; + wl_list_for_each(gc, &wl_state.frame_list, link) { + if (gc->parent_id == child->id && gc->scene_buf) + wlr_scene_node_set_enabled(&gc->scene_buf->node, true); + } + } } return; } @@ -5500,7 +5507,7 @@ 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 */ + /* Move children and grandchildren */ struct wl_frame_buf *child; wl_list_for_each(child, &wl_state.frame_list, link) { if (child->parent_id == win) { @@ -5509,6 +5516,17 @@ static void wl_window_move(WNativeWindow win, int x, int y) if (child->scene_buf) wlr_scene_node_set_position(&child->scene_buf->node, child->x, child->y); + /* Grandchildren */ + struct wl_frame_buf *gc; + wl_list_for_each(gc, &wl_state.frame_list, link) { + if (gc->parent_id == child->id) { + gc->x = child->x + gc->rel_x; + gc->y = child->y + gc->rel_y; + if (gc->scene_buf) + wlr_scene_node_set_position(&gc->scene_buf->node, + gc->x, gc->y); + } + } } } return; @@ -5714,6 +5732,7 @@ wl_client_adopt_attributes(WNativeWindow win, unsigned long event_mask) static void wl_client_reparent(WNativeWindow client, WNativeWindow new_parent, int x, int y) { + /* For WINGs internal windows: create a child frame_buf so the dialog * content is visible in the scene graph. */ if (client >= 0x20000000 && new_parent >= 0x10000000) { @@ -5737,9 +5756,11 @@ wl_client_reparent(WNativeWindow client, WNativeWindow new_parent, int x, int y) } /* Create a new frame_buf for this WINGs view. - * We don't know the size yet — use parent's content area. */ - int w = parent_fb->width; - int h = parent_fb->height - y; + * Get size from the view itself. */ + extern W_View *W_GetViewForWindow(unsigned long id); + W_View *view = W_GetViewForWindow((unsigned long)client); + int w = view ? view->size.width : parent_fb->width; + int h = view ? view->size.height : (parent_fb->height - y); if (w <= 0) w = 1; if (h <= 0) h = 1; @@ -5775,6 +5796,20 @@ wl_client_reparent(WNativeWindow client, WNativeWindow new_parent, int x, int y) extern void W_SetViewBacking(unsigned long id, void *img); W_SetViewBacking((unsigned long)client, fb->image); } + /* Reparent an existing frame_buf into a new parent */ + else if (client >= 0x10000000 && new_parent >= 0x10000000) { + struct wl_frame_buf *fb = frame_buf_find(client); + struct wl_frame_buf *parent_fb = frame_buf_find(new_parent); + if (fb && parent_fb) { + fb->parent_id = new_parent; + fb->rel_x = x; + fb->rel_y = y; + fb->x = parent_fb->x + x; + fb->y = parent_fb->y + y; + if (fb->scene_buf) + wlr_scene_node_set_position(&fb->scene_buf->node, fb->x, fb->y); + } + } } /* Called by WINGs after a view repaints — commit its frame_buf to scene graph */ @@ -5923,7 +5958,29 @@ wl_icccm_free_command(char **argv) /* Fake leader */ /* ------------------------------------------------------------------ */ -static WNativeWindow wl_fake_leader_create(WScreen *scr) { (void)scr; return WNATIVE_NONE; } +static WNativeWindow wl_fake_leader_create(WScreen *scr) +{ + (void)scr; + /* Create a frame_buf to act as the dialog's content container */ + struct wl_frame_buf *fb = wmalloc(sizeof(*fb)); + memset(fb, 0, sizeof(*fb)); + + fb->id = wl_state.next_synthetic_id++; + fb->parent_id = 0; + fb->width = 1; + fb->height = 1; + fb->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, 1, 1, NULL, 0); + wlr_buffer_init(&fb->base, &frame_buf_impl, 1, 1); + + 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_enabled(&fb->scene_buf->node, false); + } + + wl_list_insert(&wl_state.frame_list, &fb->link); + return fb->id; +} static void wl_fake_leader_destroy(WNativeWindow win) { (void)win; } /* ------------------------------------------------------------------ */