]> git.mdlowis.com Git - proto/labwc.git/commitdiff
layers: put popups in separate node-tree
authorJohan Malm <jgm323@gmail.com>
Thu, 3 Mar 2022 17:56:38 +0000 (17:56 +0000)
committerJohan Malm <jgm323@gmail.com>
Thu, 3 Mar 2022 17:56:38 +0000 (17:56 +0000)
This allows popups to be rendered above views and other layers. Without
this, the popups of a layer-shell application in the bottom layer would
render below views, which does not seem right. For example, consider the
case of a panel with right-click popups.

include/labwc.h
src/layers.c
src/output.c

index 8f5aa9894c01522d0620abdc887c7b8ea23d981d..ee5d72d0014175d8c432b5a23aa184200ddeab2b 100644 (file)
@@ -196,6 +196,7 @@ struct output {
        struct wlr_scene_output *scene_output;
        struct wl_list layers[LAB_NR_LAYERS];
        struct wlr_scene_tree *layer_tree[LAB_NR_LAYERS];
+       struct wlr_scene_tree *layer_popup_tree;
        struct wlr_box usable_area;
 
        struct lab_data_buffer *osd_buffer;
index 6f1d5292b2c7c9f462c9d9243f5a9ce8b38555b4..060d5cca984dd4d5c795a399896438a9f7cfaf76 100644 (file)
@@ -247,12 +247,6 @@ create_popup(struct wlr_xdg_popup *wlr_popup, struct wlr_scene_node *parent)
        popup->new_popup.notify = popup_handle_new_popup;
        wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
 
-       /*
-        * FIXME: should we put popups in ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY
-        * or a dedicated output->layer_popup_tree - so that for example
-        * a panel in the bottom layer displays any popup above views.
-        */
-
        popup_unconstrain(popup);
        return popup;
 }
@@ -272,7 +266,24 @@ new_popup_notify(struct wl_listener *listener, void *data)
        struct lab_layer_surface *lab_layer_surface =
                wl_container_of(listener, lab_layer_surface, new_popup);
        struct wlr_xdg_popup *wlr_popup = data;
-       create_popup(wlr_popup, lab_layer_surface->scene_layer_surface->node);
+
+       /*
+        * We always put popups in a special popup_tree so that for example a
+        * panel in the bottom layer displays popups above views.
+        */
+       struct server *server = lab_layer_surface->server;
+       struct wlr_output *wlr_output =
+               lab_layer_surface->scene_layer_surface->layer_surface->output;
+       struct output *output = output_from_wlr_output(server, wlr_output);
+       struct wlr_scene_node *node = &output->layer_popup_tree->node;
+
+       create_popup(wlr_popup, node);
+
+       struct wlr_box box = { 0 };
+       wlr_output_layout_get_box(server->output_layout, wlr_output, &box);
+       box.x += lab_layer_surface->scene_layer_surface->node->state.x;
+       box.y += lab_layer_surface->scene_layer_surface->node->state.y;
+       wlr_scene_node_set_position(node, box.x, box.y);
 }
 
 static void
index c9981af3d30ca130e0fc835e449a36fa91ca7922..fbd629a1e17d5ed0456e9dc0574348edf878e3e1 100644 (file)
@@ -111,6 +111,10 @@ new_output_notify(struct wl_listener *listener, void *data)
        output->frame.notify = output_frame_notify;
        wl_signal_add(&wlr_output->events.frame, &output->frame);
 
+       /*
+        * Create layer-trees (background, bottom, top and overlay) and
+        * a layer-popup-tree.
+        */
        int nr_layers = sizeof(output->layers) / sizeof(output->layers[0]);
        for (int i = 0; i < nr_layers; i++) {
                wl_list_init(&output->layers[i]);
@@ -118,10 +122,23 @@ new_output_notify(struct wl_listener *listener, void *data)
                        wlr_scene_tree_create(&server->scene->node);
                output->layer_tree[i]->node.data = output->wlr_output;
        }
+       output->layer_popup_tree = wlr_scene_tree_create(&server->scene->node);
+
+       /*
+        * Set the z-positions to achieve the following order (from top to
+        * bottom):
+        *      - layer-shell popups
+        *      - overlay layer
+        *      - top layer
+        *      - views
+        *      - bottom layer
+        *      - background layer
+        */
        wlr_scene_node_lower_to_bottom(&output->layer_tree[1]->node);
        wlr_scene_node_lower_to_bottom(&output->layer_tree[0]->node);
        wlr_scene_node_raise_to_top(&output->layer_tree[2]->node);
        wlr_scene_node_raise_to_top(&output->layer_tree[3]->node);
+       wlr_scene_node_raise_to_top(&output->layer_popup_tree->node);
 
        if (rc.adaptive_sync) {
                wlr_log(WLR_INFO, "enable adaptive sync on %s",