diff --git a/include/labwc.h b/include/labwc.h index 4016da3b..cbd61424 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -254,7 +254,14 @@ struct server { /* Tree for all non-layer xdg/xwayland-shell surfaces */ struct wlr_scene_tree *view_tree; - /* Tree for all non-layer xdg/xwayland-shell surfaces with always-on-top */ + + /* + * Popups need to be rendered above always-on-top views, so we reparent + * them to this dedicated tree + */ + struct wlr_scene_tree *xdg_popup_tree; + + /* Tree for all non-layer xdg/xwayland-shell surfaces with always-on-top/below */ struct wlr_scene_tree *view_tree_always_on_top; #if HAVE_XWAYLAND /* Tree for unmanaged xsurfaces without initialized view (usually popups) */ diff --git a/src/server.c b/src/server.c index b0c09c44..9e9ad428 100644 --- a/src/server.c +++ b/src/server.c @@ -285,8 +285,31 @@ server_init(struct server *server) wlr_log(WLR_ERROR, "unable to create scene"); exit(EXIT_FAILURE); } + + /* + * The order in which the scene-trees below are created determines the + * z-order for nodes which cover the whole work-area. For per-output + * scene-trees, see new_output_notify() in src/output.c + * + * | Type | Scene Tree | Per Output | Example + * | ----------------- | ---------------- | ---------- | ------- + * | ext-session | lock-screen | Yes | swaylock + * | layer-shell | layer-popups | Yes | + * | layer-shell | overlay-layer | Yes | + * | layer-shell | top-layer | Yes | waybar + * | server | labwc-menus | No | + * | xwayland-OR | unmanaged | No | dmenu + * | xdg-popups | xdg-popups | No | + * | toplevels windows | always-on-top | No | + * | toplevels windows | normal | No | firefox + * | toplevels windows | always-on-bottom | No | pcmanfm-qt --desktop + * | layer-shell | bottom-layer | Yes | waybar + * | layer-shell | background-layer | Yes | swaybg + */ + server->view_tree = wlr_scene_tree_create(&server->scene->tree); server->view_tree_always_on_top = wlr_scene_tree_create(&server->scene->tree); + server->xdg_popup_tree = wlr_scene_tree_create(&server->scene->tree); #if HAVE_XWAYLAND server->unmanaged_tree = wlr_scene_tree_create(&server->scene->tree); #endif diff --git a/src/xdg-popup.c b/src/xdg-popup.c index 350d76de..14cdf560 100644 --- a/src/xdg-popup.c +++ b/src/xdg-popup.c @@ -85,8 +85,18 @@ xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup) * provide the proper parent scene node of the xdg popup. To enable * this, we always set the user data field of xdg_surfaces to the * corresponding scene node. + * + * xdg-popups live in server->xdg_popup_tree so that they can be + * rendered above always-on-top windows */ - struct wlr_scene_tree *parent_tree = parent->surface->data; + struct wlr_scene_tree *parent_tree = NULL; + if (parent->role == WLR_XDG_SURFACE_ROLE_POPUP) { + parent_tree = parent->surface->data; + } else { + parent_tree = view->server->xdg_popup_tree; + wlr_scene_node_set_position(&view->server->xdg_popup_tree->node, + view->current.x, view->current.y); + } wlr_popup->base->surface->data = wlr_scene_xdg_surface_create(parent_tree, wlr_popup->base); node_descriptor_create(wlr_popup->base->surface->data,