]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Handle layers under the scene-graph API
authorJohan Malm <jgm323@gmail.com>
Sun, 20 Feb 2022 13:15:58 +0000 (13:15 +0000)
committerJohan Malm <jgm323@gmail.com>
Wed, 23 Feb 2022 21:47:01 +0000 (21:47 +0000)
This excludes popups.

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

index 6586fc5553a65bfbf5505fd172358d6bb5c46257..d0555290d78b400c1ae70504bccf7b326b5a5eb7 100644 (file)
@@ -185,6 +185,7 @@ struct output {
        struct wlr_output *wlr_output;
        struct wlr_scene_output *scene_output;
        struct wl_list layers[4];
+       struct wlr_scene_tree *layer_tree[4];
        struct wlr_box usable_area;
 
        struct lab_data_buffer *osd_buffer;
index 1613020b35fa451e39327d3cadaff0e0f8b64869..0eaccbb092e654040af430a791295e7db59185e7 100644 (file)
@@ -12,8 +12,8 @@ enum layer_parent {
 };
 
 struct lab_layer_surface {
-       struct wlr_layer_surface_v1 *layer_surface;
-       struct wl_list link;
+       struct wl_list link; /* output::layers[] */
+       struct wlr_scene_layer_surface_v1 *scene_layer_surface;
 
        struct wl_listener destroy;
        struct wl_listener map;
index fda5d1315cfc1f5b209f6b4aae882df5c8fa480f..46ff372334d6881c55f072e718acfdd7a2f48afb 100644 (file)
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
+#include <wlr/types/wlr_layer_shell_v1.h>
 #include <wlr/types/wlr_scene.h>
 #include "buffer.h"
 #include "labwc.h"
@@ -40,6 +41,23 @@ dump_tree(struct wlr_scene_node *node, int pos, int x, int y)
        }
 }
 
+static char *
+get_layer_name(uint32_t layer)
+{
+       switch (layer) {
+       case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND:
+               return "background";
+       case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM:
+               return "bottom";
+       case ZWLR_LAYER_SHELL_V1_LAYER_TOP:
+               return "top";
+       case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY:
+               return "overlay";
+       default:
+               abort();
+       }
+}
+
 void
 debug_dump_scene(struct server *server)
 {
@@ -49,7 +67,13 @@ debug_dump_scene(struct server *server)
        node = &server->view_tree->node;
        dump_tree(node, 0, node->state.x, node->state.y);
 
-       printf(":: osd_tree ::\n");
-       node = &server->osd_tree->node;
-       dump_tree(node, 0, node->state.x, node->state.y);
+       printf(":: layer_tree ::\n");
+       struct output *output;
+       wl_list_for_each(output, &server->outputs, link) {
+               for (int i = 0; i < 4; i++) {
+                       node = &output->layer_tree[i]->node;
+                       printf("layer-%s\n", get_layer_name(i));
+                       dump_tree(node, 0, node->state.x, node->state.y);
+               }
+       }
 }
index 1200c95ac2d47ac4cf7ffeea944817c4686194dd..59e365b2c67961c3f112ff91b82447cd8108a1d0 100644 (file)
 #include "layers.h"
 #include "labwc.h"
 
-static void
-apply_exclusive(struct wlr_box *usable_area, uint32_t anchor, int32_t exclusive,
-               int32_t margin_top, int32_t margin_right, int32_t margin_bottom,
-               int32_t margin_left)
+void
+arrange_layers(struct output *output)
 {
-       if (exclusive <= 0) {
-               return;
-       }
-       struct {
-               uint32_t anchors;
-               int *positive_axis;
-               int *negative_axis;
-               int margin;
-       } edges[] = {
-               {
-                       .anchors =
-                               ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
-                               ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
-                               ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
-                       .positive_axis = &usable_area->y,
-                       .negative_axis = &usable_area->height,
-                       .margin = margin_top,
-               },
-               {
-                       .anchors =
-                               ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
-                               ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
-                               ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
-                       .positive_axis = NULL,
-                       .negative_axis = &usable_area->height,
-                       .margin = margin_bottom,
-               },
-               {
-                       .anchors =
-                               ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
-                               ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
-                               ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
-                       .positive_axis = &usable_area->x,
-                       .negative_axis = &usable_area->width,
-                       .margin = margin_left,
-               },
-               {
-                       .anchors =
-                               ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
-                               ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
-                               ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
-                       .positive_axis = NULL,
-                       .negative_axis = &usable_area->width,
-                       .margin = margin_right,
-               },
-       };
-       for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) {
-               if ((anchor & edges[i].anchors) == edges[i].anchors) {
-                       if (edges[i].positive_axis) {
-                               *edges[i].positive_axis +=
-                                       exclusive + edges[i].margin;
-                       }
-                       if (edges[i].negative_axis) {
-                               *edges[i].negative_axis -=
-                                       exclusive + edges[i].margin;
-                       }
-               }
-       }
-}
+       struct server *server = output->server;
+       struct wlr_scene_output *scene_output =
+               wlr_scene_get_scene_output(server->scene, output->wlr_output);
 
-/**
- * @list: struct lab_layer_surface
- */
-static void
-arrange_layer(struct wlr_output *output, struct wl_list *list,
-               struct wlr_box *usable_area, bool exclusive)
-{
-       struct lab_layer_surface *surface;
        struct wlr_box full_area = { 0 };
-       wlr_output_effective_resolution(output, &full_area.width,
-               &full_area.height);
-       wl_list_for_each_reverse(surface, list, link) {
-               struct wlr_layer_surface_v1 *layer = surface->layer_surface;
-               struct wlr_layer_surface_v1_state *state = &layer->current;
-               if (exclusive != (state->exclusive_zone > 0)) {
-                       continue;
-               }
-               struct wlr_box bounds;
-               if (state->exclusive_zone == -1) {
-                       bounds = full_area;
-               } else {
-                       bounds = *usable_area;
-               }
-               struct wlr_box box = {
-                       .width = state->desired_width,
-                       .height = state->desired_height
-               };
-               /* Horizontal axis */
-               const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
-                       | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
-               if ((state->anchor & both_horiz) && box.width == 0) {
-                       box.x = bounds.x;
-                       box.width = bounds.width;
-               } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
-                       box.x = bounds.x;
-               } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
-                       box.x = bounds.x + (bounds.width - box.width);
-               } else {
-                       box.x = bounds.x + ((bounds.width / 2) - (box.width / 2));
-               }
-               /* Vertical axis */
-               const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
-                       | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
-               if ((state->anchor & both_vert) && box.height == 0) {
-                       box.y = bounds.y;
-                       box.height = bounds.height;
-               } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
-                       box.y = bounds.y;
-               } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
-                       box.y = bounds.y + (bounds.height - box.height);
-               } else {
-                       box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
-               }
-               /* Margin */
-               if ((state->anchor & both_horiz) == both_horiz) {
-                       box.x += state->margin.left;
-                       box.width -= state->margin.left + state->margin.right;
-               } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
-                       box.x += state->margin.left;
-               } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
-                       box.x -= state->margin.right;
-               }
-               if ((state->anchor & both_vert) == both_vert) {
-                       box.y += state->margin.top;
-                       box.height -= state->margin.top + state->margin.bottom;
-               } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
-                       box.y += state->margin.top;
-               } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
-                       box.y -= state->margin.bottom;
-               }
-               if (box.width < 0 || box.height < 0) {
-                       wlr_log(WLR_ERROR, "surface has no positive size");
-                       continue;
+       wlr_output_effective_resolution(output->wlr_output,
+                       &full_area.width, &full_area.height);
+       struct wlr_box usable_area = full_area;
+
+       for (int i = 0; i < 4; i++) {
+               struct lab_layer_surface *lab_layer_surface;
+               wl_list_for_each(lab_layer_surface, &output->layers[i], link) {
+                       struct wlr_scene_layer_surface_v1 *scene_layer_surface =
+                               lab_layer_surface->scene_layer_surface;
+                       wlr_scene_layer_surface_v1_configure(
+                               scene_layer_surface, &full_area, &usable_area);
                }
+       }
 
-               /* Apply */
-               surface->geo = box;
-               apply_exclusive(usable_area, state->anchor,
-                       state->exclusive_zone, state->margin.top,
-                       state->margin.right, state->margin.bottom,
-                       state->margin.left);
-               wlr_layer_surface_v1_configure(layer, box.width, box.height);
+       for (int i = 0; i < 4; i++) {
+               struct wlr_scene_node *node = &output->layer_tree[i]->node;
+               wlr_scene_node_set_position(node,
+                       scene_output->x + usable_area.x,
+                       scene_output->y + usable_area.y);
        }
-}
 
-void
-arrange_layers(struct output *output)
-{
-       assert(output);
 
-       struct wlr_box usable_area = { 0 };
-       wlr_output_effective_resolution(output->wlr_output,
-               &usable_area.width, &usable_area.height);
-
-       /* Exclusive surfaces */
-       arrange_layer(output->wlr_output,
-                       &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
-                       &usable_area, true);
-       arrange_layer(output->wlr_output,
-                       &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
-                       &usable_area, true);
-       arrange_layer(output->wlr_output,
-                       &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
-                       &usable_area, true);
-       arrange_layer(output->wlr_output,
-                       &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
-                       &usable_area, true);
-       memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box));
-
-       /* TODO: re-arrange all views taking into account updated usable_area */
-
-       /* Non-exclusive surfaces */
-       arrange_layer(output->wlr_output,
-                       &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
-                       &usable_area, false);
-       arrange_layer(output->wlr_output,
-                       &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
-                       &usable_area, false);
-       arrange_layer(output->wlr_output,
-                       &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
-                       &usable_area, false);
-       arrange_layer(output->wlr_output,
-                       &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
-                       &usable_area, false);
+       /* TODO: workout how we set this */
+//     memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box));
 
        /* Find topmost keyboard interactive layer, if such a layer exists */
        uint32_t layers_above_shell[] = {
@@ -217,7 +60,7 @@ arrange_layers(struct output *output)
        for (size_t i = 0; i < nlayers; ++i) {
                wl_list_for_each_reverse (layer,
                                &output->layers[layers_above_shell[i]], link) {
-                       if (layer->layer_surface->current.keyboard_interactive) {
+                       if (layer->scene_layer_surface->layer_surface->current.keyboard_interactive) {
                                topmost = layer;
                                break;
                        }
@@ -228,7 +71,8 @@ arrange_layers(struct output *output)
        }
        struct seat *seat = &output->server->seat;
        if (topmost) {
-               seat_set_focus_layer(seat, topmost->layer_surface);
+               seat_set_focus_layer(seat,
+                       topmost->scene_layer_surface->layer_surface);
        } else if (seat->focused_layer &&
                        !seat->focused_layer->current.keyboard_interactive) {
                seat_set_focus_layer(seat, NULL);
@@ -240,9 +84,8 @@ output_destroy_notify(struct wl_listener *listener, void *data)
 {
        struct lab_layer_surface *layer =
                wl_container_of(listener, layer, output_destroy);
-       layer->layer_surface->output = NULL;
        wl_list_remove(&layer->output_destroy.link);
-       wlr_layer_surface_v1_destroy(layer->layer_surface);
+       wlr_layer_surface_v1_destroy(layer->scene_layer_surface->layer_surface);
 }
 
 static void
@@ -250,8 +93,10 @@ surface_commit_notify(struct wl_listener *listener, void *data)
 {
        struct lab_layer_surface *layer =
                wl_container_of(listener, layer, surface_commit);
-       struct wlr_layer_surface_v1 *layer_surface = layer->layer_surface;
-       struct wlr_output *wlr_output = layer->layer_surface->output;
+       struct wlr_layer_surface_v1 *layer_surface =
+               layer->scene_layer_surface->layer_surface;
+       struct wlr_output *wlr_output =
+               layer->scene_layer_surface->layer_surface->output;
 
        if (!wlr_output) {
                return;
@@ -264,14 +109,13 @@ surface_commit_notify(struct wl_listener *listener, void *data)
                        output_from_wlr_output(layer->server, wlr_output);
                arrange_layers(output);
        }
-       damage_all_outputs(layer->server);
 }
 
 static void
 unmap(struct lab_layer_surface *layer)
 {
        struct seat *seat = &layer->server->seat;
-       if (seat->focused_layer == layer->layer_surface) {
+       if (seat->focused_layer == layer->scene_layer_surface->layer_surface) {
                seat_set_focus_layer(seat, NULL);
        }
        damage_all_outputs(layer->server);
@@ -282,17 +126,19 @@ destroy_notify(struct wl_listener *listener, void *data)
 {
        struct lab_layer_surface *layer = wl_container_of(
                listener, layer, destroy);
-       if (layer->layer_surface->mapped) {
+       if (layer->scene_layer_surface->layer_surface->mapped) {
                unmap(layer);
        }
+
+       /* TODO: sort this out properly */
        wl_list_remove(&layer->link);
        wl_list_remove(&layer->destroy.link);
        wl_list_remove(&layer->map.link);
        wl_list_remove(&layer->surface_commit.link);
-       if (layer->layer_surface->output) {
+       if (layer->scene_layer_surface->layer_surface->output) {
                wl_list_remove(&layer->output_destroy.link);
                struct output *output = output_from_wlr_output(
-                       layer->server, layer->layer_surface->output);
+                       layer->server, layer->scene_layer_surface->layer_surface->output);
                arrange_layers(output);
        }
        free(layer);
@@ -312,224 +158,149 @@ map_notify(struct wl_listener *listener, void *data)
        wlr_surface_send_enter(l->surface, l->output);
 }
 
-static void
-subsurface_damage(struct lab_layer_subsurface *subsurface, bool whole)
-{
-       struct lab_layer_surface *layer = subsurface->layer_surface;
-       struct wlr_output *wlr_output = layer->layer_surface->output;
-       if (!wlr_output) {
-               return;
-       }
-//     struct output *output = wlr_output->data;
-//     int ox = subsurface->wlr_subsurface->current.x + layer->geo.x;
-//     int oy = subsurface->wlr_subsurface->current.y + layer->geo.y;
-       damage_all_outputs(layer->server);
-}
-
-static void
-subsurface_handle_unmap(struct wl_listener *listener, void *data)
-{
-       struct lab_layer_subsurface *subsurface =
-                       wl_container_of(listener, subsurface, unmap);
-       subsurface_damage(subsurface, true);
-}
-
-static void
-subsurface_handle_map(struct wl_listener *listener, void *data)
-{
-       struct lab_layer_subsurface *subsurface =
-                       wl_container_of(listener, subsurface, map);
-       subsurface_damage(subsurface, true);
-}
-
-static void
-subsurface_handle_commit(struct wl_listener *listener, void *data)
-{
-       struct lab_layer_subsurface *subsurface =
-                       wl_container_of(listener, subsurface, commit);
-       subsurface_damage(subsurface, false);
-}
-
-static void
-subsurface_handle_destroy(struct wl_listener *listener, void *data)
-{
-       struct lab_layer_subsurface *subsurface =
-                       wl_container_of(listener, subsurface, destroy);
-
-       wl_list_remove(&subsurface->map.link);
-       wl_list_remove(&subsurface->unmap.link);
-       wl_list_remove(&subsurface->destroy.link);
-       wl_list_remove(&subsurface->commit.link);
-       free(subsurface);
-}
-
-static struct
-lab_layer_subsurface *create_subsurface(struct wlr_subsurface *wlr_subsurface,
-               struct lab_layer_surface *layer_surface)
-{
-       struct lab_layer_subsurface *subsurface =
-                       calloc(1, sizeof(struct lab_layer_subsurface));
-       if (!subsurface) {
-               return NULL;
-       }
-
-       subsurface->wlr_subsurface = wlr_subsurface;
-       subsurface->layer_surface = layer_surface;
-
-       subsurface->map.notify = subsurface_handle_map;
-       wl_signal_add(&wlr_subsurface->events.map, &subsurface->map);
-       subsurface->unmap.notify = subsurface_handle_unmap;
-       wl_signal_add(&wlr_subsurface->events.unmap, &subsurface->unmap);
-       subsurface->destroy.notify = subsurface_handle_destroy;
-       wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy);
-       subsurface->commit.notify = subsurface_handle_commit;
-       wl_signal_add(&wlr_subsurface->surface->events.commit,
-               &subsurface->commit);
-
-       return subsurface;
-}
-
-static void
-new_subsurface_notify(struct wl_listener *listener, void *data)
-{
-       struct lab_layer_surface *lab_layer_surface =
-               wl_container_of(listener, lab_layer_surface, new_subsurface);
-       struct wlr_subsurface *wlr_subsurface = data;
-       create_subsurface(wlr_subsurface, lab_layer_surface);
-}
-
-
-static struct
-lab_layer_surface *popup_get_layer(struct lab_layer_popup *popup)
-{
-       while (popup->parent_type == LAYER_PARENT_POPUP) {
-               popup = popup->parent_popup;
-       }
-       return popup->parent_layer;
-}
-
-static void
-popup_damage(struct lab_layer_popup *layer_popup, bool whole)
-{
-       struct lab_layer_surface *layer;
-       while (true) {
-               if (layer_popup->parent_type == LAYER_PARENT_POPUP) {
-                       layer_popup = layer_popup->parent_popup;
-               } else {
-                       layer = layer_popup->parent_layer;
-                       break;
-               }
-       }
-       damage_all_outputs(layer->server);
-}
-
-static void
-popup_handle_map(struct wl_listener *listener, void *data)
-{
-       struct lab_layer_popup *popup = wl_container_of(listener, popup, map);
-       struct lab_layer_surface *layer = popup_get_layer(popup);
-       struct wlr_output *wlr_output = layer->layer_surface->output;
-       wlr_surface_send_enter(popup->wlr_popup->base->surface, wlr_output);
-       popup_damage(popup, true);
-}
-
-static void
-popup_handle_unmap(struct wl_listener *listener, void *data)
-{
-       struct lab_layer_popup *popup = wl_container_of(listener, popup, unmap);
-       popup_damage(popup, true);
-}
-
-static void
-popup_handle_commit(struct wl_listener *listener, void *data)
-{
-       struct lab_layer_popup *popup = wl_container_of(listener, popup, commit);
-       popup_damage(popup, false);
-}
-
-static void
-popup_handle_destroy(struct wl_listener *listener, void *data)
-{
-       struct lab_layer_popup *popup =
-               wl_container_of(listener, popup, destroy);
-
-       wl_list_remove(&popup->map.link);
-       wl_list_remove(&popup->unmap.link);
-       wl_list_remove(&popup->destroy.link);
-       wl_list_remove(&popup->commit.link);
-       free(popup);
-}
-
-static void
-popup_unconstrain(struct lab_layer_popup *popup)
-{
-       struct lab_layer_surface *layer = popup_get_layer(popup);
-       struct wlr_xdg_popup *wlr_popup = popup->wlr_popup;
-       struct output *output = layer->layer_surface->output->data;
-
-       struct wlr_box output_box = { 0 };
-       wlr_output_effective_resolution(output->wlr_output, &output_box.width,
-               &output_box.height);
-
-       struct wlr_box output_toplevel_sx_box = {
-               .x = -layer->geo.x,
-               .y = -layer->geo.y,
-               .width = output_box.width,
-               .height = output_box.height,
-       };
-
-       wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
-}
-
-static void popup_handle_new_popup(struct wl_listener *listener, void *data);
-
-static struct lab_layer_popup *
-create_popup(struct wlr_xdg_popup *wlr_popup,
-               enum layer_parent parent_type, void *parent)
-{
-       struct lab_layer_popup *popup =
-               calloc(1, sizeof(struct lab_layer_popup));
-       if (!popup) {
-               return NULL;
-       }
-
-       popup->wlr_popup = wlr_popup;
-       popup->parent_type = parent_type;
-       popup->parent_layer = parent;
-
-       popup->map.notify = popup_handle_map;
-       wl_signal_add(&wlr_popup->base->events.map, &popup->map);
-       popup->unmap.notify = popup_handle_unmap;
-       wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
-       popup->destroy.notify = popup_handle_destroy;
-       wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
-       popup->commit.notify = popup_handle_commit;
-       wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
-       popup->new_popup.notify = popup_handle_new_popup;
-       wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
-
-       popup_unconstrain(popup);
-
-       return popup;
-}
-
-static void
-popup_handle_new_popup(struct wl_listener *listener, void *data)
-{
-       struct lab_layer_popup *lab_layer_popup =
-               wl_container_of(listener, lab_layer_popup, new_popup);
-       struct wlr_xdg_popup *wlr_popup = data;
-       create_popup(wlr_popup, LAYER_PARENT_POPUP, lab_layer_popup);
-}
-
-static void
-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, LAYER_PARENT_LAYER, lab_layer_surface);
-}
+//static struct
+//lab_layer_surface *popup_get_layer(struct lab_layer_popup *popup)
+//{
+//     while (popup->parent_type == LAYER_PARENT_POPUP) {
+//             popup = popup->parent_popup;
+//     }
+//     return popup->parent_layer;
+//}
+//
+//static void
+//popup_damage(struct lab_layer_popup *layer_popup, bool whole)
+//{
+//     struct lab_layer_surface *layer;
+//     while (true) {
+//             if (layer_popup->parent_type == LAYER_PARENT_POPUP) {
+//                     layer_popup = layer_popup->parent_popup;
+//             } else {
+//                     layer = layer_popup->parent_layer;
+//                     break;
+//             }
+//     }
+//     damage_all_outputs(layer->server);
+//}
+//
+//static void
+//popup_handle_map(struct wl_listener *listener, void *data)
+//{
+//     struct lab_layer_popup *popup = wl_container_of(listener, popup, map);
+//     struct lab_layer_surface *layer = popup_get_layer(popup);
+//     struct wlr_output *wlr_output = layer->scene_layer_surface->layer_surface->output;
+//     wlr_surface_send_enter(popup->wlr_popup->base->surface, wlr_output);
+//     popup_damage(popup, true);
+//}
+//
+//static void
+//popup_handle_unmap(struct wl_listener *listener, void *data)
+//{
+//     struct lab_layer_popup *popup = wl_container_of(listener, popup, unmap);
+//     popup_damage(popup, true);
+//}
+//
+//static void
+//popup_handle_commit(struct wl_listener *listener, void *data)
+//{
+//     struct lab_layer_popup *popup = wl_container_of(listener, popup, commit);
+//     popup_damage(popup, false);
+//}
+//
+//static void
+//popup_handle_destroy(struct wl_listener *listener, void *data)
+//{
+//     struct lab_layer_popup *popup =
+//             wl_container_of(listener, popup, destroy);
+//     wl_list_remove(&popup->destroy.link);
+//     free(popup);
+//}
+//
+//static void
+//popup_unconstrain(struct lab_layer_popup *popup)
+//{
+//     struct lab_layer_surface *layer = popup_get_layer(popup);
+//     struct wlr_xdg_popup *wlr_popup = popup->wlr_popup;
+//     struct output *output = layer->scene_layer_surface->layer_surface->output->data;
+//
+//     struct wlr_box output_box = { 0 };
+//     wlr_output_effective_resolution(output->wlr_output, &output_box.width,
+//             &output_box.height);
+//
+//     struct wlr_box output_toplevel_sx_box = {
+//             .x = -layer->geo.x,
+//             .y = -layer->geo.y,
+//             .width = output_box.width,
+//             .height = output_box.height,
+//     };
+//
+//     wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
+//}
+//
+//static void popup_handle_new_popup(struct wl_listener *listener, void *data);
+//
+//static struct lab_layer_popup *
+//create_popup(struct wlr_xdg_popup *wlr_popup,
+//             enum layer_parent parent_type, void *parent)
+//{
+//     struct lab_layer_popup *popup =
+//             calloc(1, sizeof(struct lab_layer_popup));
+//     if (!popup) {
+//             return NULL;
+//     }
+//
+//     struct lab_layer_surface *layer = parent_type == LAYER_PARENT_LAYER
+//                     ? (struct lab_layer_surface *)parent
+//                     : (struct lab_layer_popup *)parent;
+//     struct server *server = layer->server;
+//
+//     popup->wlr_popup = wlr_popup;
+//     popup->parent_type = parent_type;
+//     popup->parent_layer = parent;
+//
+//     popup->destroy.notify = popup_handle_destroy;
+//     wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
+//     popup->new_popup.notify = popup_handle_new_popup;
+//     wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
+//
+//     if (!wlr_surface_is_layer_surface(wlr_popup->base->surface)) {
+//             wlr_log(WLR_ERROR, "xdg_surface is not layer surface");
+//             return;
+//     }
+//
+//     struct wlr_output *wlr_output =
+//             layer->scene_layer_surface->layer_surface->data;
+//     struct output *output = output_from_wlr_output(server, wlr_output);
+//
+//     struct wlr_scene_tree *selected_layer =
+//             output->layer_tree[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY];
+//     struct wlr_scene_node *node =
+//             wlr_scene_layer_surface_v1_create(&server->view_tree->node,
+//                     wlr_popup->base->surface->data);
+//     wlr_popup->base->surface->data =
+//             wlr_scene_xdg_surface_create(&selected_layer->node, wlr_popup->base);
+//
+//     popup_unconstrain(popup);
+//
+//     return popup;
+//}
+//
+//static void
+//popup_handle_new_popup(struct wl_listener *listener, void *data)
+//{
+//     struct lab_layer_popup *lab_layer_popup =
+//             wl_container_of(listener, lab_layer_popup, new_popup);
+//     struct wlr_xdg_popup *wlr_popup = data;
+//     create_popup(wlr_popup, LAYER_PARENT_POPUP, lab_layer_popup);
+//}
+//
+//static void
+//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, LAYER_PARENT_LAYER, lab_layer_surface);
+//}
 
 static void
 new_layer_surface_notify(struct wl_listener *listener, void *data)
@@ -564,18 +335,28 @@ new_layer_surface_notify(struct wl_listener *listener, void *data)
        surface->unmap.notify = unmap_notify;
        wl_signal_add(&layer_surface->events.unmap, &surface->unmap);
 
-       surface->new_popup.notify = new_popup_notify;
-       wl_signal_add(&layer_surface->events.new_popup, &surface->new_popup);
+       /* TODO: support popups */
+//     surface->new_popup.notify = new_popup_notify;
+//     wl_signal_add(&layer_surface->events.new_popup, &surface->new_popup);
+//
+//     surface->new_subsurface.notify = new_subsurface_notify;
+//     wl_signal_add(&layer_surface->surface->events.new_subsurface,
+//             &surface->new_subsurface);
+
+       struct output *output = layer_surface->output->data;
 
-       surface->new_subsurface.notify = new_subsurface_notify;
-       wl_signal_add(&layer_surface->surface->events.new_subsurface,
-               &surface->new_subsurface);
+       struct wlr_scene_tree *selected_layer =
+               output->layer_tree[layer_surface->current.layer];
+
+       surface->scene_layer_surface = wlr_scene_layer_surface_v1_create(
+               &selected_layer->node, layer_surface);
 
-       surface->layer_surface = layer_surface;
-       layer_surface->data = surface;
        surface->server = server;
+       surface->scene_layer_surface->layer_surface = layer_surface;
+
+       /* wlr_surface->data needed to find parent in xdg_surface_new() */
+       layer_surface->surface->data = surface->scene_layer_surface->node;
 
-       struct output *output = layer_surface->output->data;
        surface->output_destroy.notify = output_destroy_notify;
        wl_signal_add(&layer_surface->output->events.destroy,
                &surface->output_destroy);
index 297e4260ef23260ab48e752cca43e028ed09f1c7..1b29183da1290d7a5aa5132de37c3f88bd595d19 100644 (file)
@@ -12,6 +12,7 @@
 #include <wlr/types/wlr_buffer.h>
 #include <wlr/types/wlr_xdg_output_v1.h>
 #include <wlr/types/wlr_output_damage.h>
+#include <wlr/types/wlr_scene.h>
 #include <wlr/util/region.h>
 #include <wlr/util/log.h>
 #include "buffer.h"
@@ -110,14 +111,16 @@ new_output_notify(struct wl_listener *listener, void *data)
        output->frame.notify = output_frame_notify;
        wl_signal_add(&wlr_output->events.frame, &output->frame);
 
-       wl_list_init(&output->layers[0]);
-       wl_list_init(&output->layers[1]);
-       wl_list_init(&output->layers[2]);
-       wl_list_init(&output->layers[3]);
-       /*
-        * Arrange outputs from left-to-right in the order they appear.
-        * TODO: support configuration in run-time
-        */
+       for (int i = 0; i < 4; i++) {
+               wl_list_init(&output->layers[i]);
+               output->layer_tree[i] =
+                       wlr_scene_tree_create(&server->scene->node);
+               output->layer_tree[i]->node.data = output->wlr_output;
+       }
+       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);
 
        if (rc.adaptive_sync) {
                wlr_log(WLR_INFO, "enable adaptive sync on %s",
@@ -318,11 +321,13 @@ handle_output_layout_change(struct wl_listener *listener, void *data)
                                "wlr_output_manager_v1_set_configuration()");
                }
                struct output *output;
-               wl_list_for_each(output, &server->outputs, link) {
-                       if (output) {
-                               arrange_layers(output);
-                       }
-               }
+
+               /* FIXME: Sort this out */
+//             wl_list_for_each(output, &server->outputs, link) {
+//                     if (output) {
+//                             arrange_layers(output);
+//                     }
+//             }
                output_update_for_layout_change(server);
        }
 }