fix: exit dialog not visible on Wayland — preserve frame_buf parent on backing resize
This commit is contained in:
parent
86f7510a13
commit
d95d2c007c
|
|
@ -7908,11 +7908,19 @@ wl_client_reparent(WNativeWindow client, WNativeWindow new_parent, int x, int y)
|
|||
void wl_view_commit_backing_impl(unsigned long id)
|
||||
{
|
||||
struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)id);
|
||||
WNativeWindow saved_parent_id = 0;
|
||||
int saved_rel_x = 0, saved_rel_y = 0;
|
||||
/* If the view was resized, the old frame_buf's image is stale. */
|
||||
if (fb) {
|
||||
extern void *W_GetViewBacking(unsigned long id);
|
||||
void *current = W_GetViewBacking((unsigned long)id);
|
||||
if (current != (void *)fb->image) {
|
||||
/* Save parent relation before destroying — the new frame_buf
|
||||
* must be positioned within the same parent tree so dialog
|
||||
* content reparented via wl_client_reparent stays visible. */
|
||||
saved_parent_id = fb->parent_id;
|
||||
saved_rel_x = fb->rel_x;
|
||||
saved_rel_y = fb->rel_y;
|
||||
wlr_scene_node_destroy(&fb->scene_buf->node);
|
||||
wl_list_remove(&fb->link);
|
||||
wlr_buffer_drop(&fb->base);
|
||||
|
|
@ -7921,37 +7929,51 @@ void wl_view_commit_backing_impl(unsigned long id)
|
|||
}
|
||||
}
|
||||
if (!fb) {
|
||||
/* Auto-create a frame_buf for WINGs toplevel views that were
|
||||
* not explicitly reparented (e.g. switch panel, menus).
|
||||
* Without a frame_buf/scene_buffer the view content is painted
|
||||
* into its pixman backing but never appears on screen. */
|
||||
extern W_View *W_GetViewForWindow(unsigned long id);
|
||||
extern void *W_GetViewBacking(unsigned long id);
|
||||
W_View *view = W_GetViewForWindow((unsigned long)id);
|
||||
if (view && view->flags.topLevel) {
|
||||
fb = wmalloc(sizeof(*fb));
|
||||
memset(fb, 0, sizeof(*fb));
|
||||
fb->id = id;
|
||||
fb->x = view->pos.x;
|
||||
fb->y = view->pos.y;
|
||||
fb->width = view->size.width;
|
||||
fb->height = view->size.height;
|
||||
fb->image = (pixman_image_t *)W_GetViewBacking(id);
|
||||
fb->id = id;
|
||||
fb->parent_id = saved_parent_id;
|
||||
fb->rel_x = saved_rel_x;
|
||||
fb->rel_y = saved_rel_y;
|
||||
fb->x = view->pos.x;
|
||||
fb->y = view->pos.y;
|
||||
fb->width = view->size.width;
|
||||
fb->height = view->size.height;
|
||||
fb->image = (pixman_image_t *)W_GetViewBacking(id);
|
||||
if (fb->image) {
|
||||
pixman_image_ref(fb->image);
|
||||
wlr_buffer_init(&fb->base, &frame_buf_impl,
|
||||
pixman_image_get_width(fb->image),
|
||||
pixman_image_get_height(fb->image));
|
||||
if (wl_state.scene) {
|
||||
struct wlr_scene_tree *parent =
|
||||
wl_state.level_trees[WL_LAYER_FLOATING]
|
||||
struct wlr_scene_tree *parent = NULL;
|
||||
/* Re-parent under the saved parent's tree so
|
||||
* dialogs reparented via wl_client_reparent stay
|
||||
* correctly positioned within their frame. */
|
||||
if (saved_parent_id) {
|
||||
struct wl_frame_buf *pfb =
|
||||
frame_buf_find(saved_parent_id);
|
||||
if (pfb && pfb->tree)
|
||||
parent = pfb->tree;
|
||||
}
|
||||
if (!parent)
|
||||
parent = wl_state.level_trees[WL_LAYER_FLOATING]
|
||||
? wl_state.level_trees[WL_LAYER_FLOATING]
|
||||
: &wl_state.scene->tree;
|
||||
fb->scene_buf = wlr_scene_buffer_create(parent, &fb->base);
|
||||
if (fb->scene_buf) {
|
||||
fb_attach_scene_buf_listener(fb);
|
||||
wlr_scene_node_set_position(&fb->scene_buf->node,
|
||||
fb->x, fb->y);
|
||||
/* Position relative to parent's tree or absolute */
|
||||
if (parent != &wl_state.scene->tree && saved_parent_id)
|
||||
wlr_scene_node_set_position(&fb->scene_buf->node,
|
||||
saved_rel_x, saved_rel_y);
|
||||
else
|
||||
wlr_scene_node_set_position(&fb->scene_buf->node,
|
||||
fb->x, fb->y);
|
||||
wlr_scene_node_set_enabled(&fb->scene_buf->node, false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue