]> git.mdlowis.com Git - proto/labwc.git/commitdiff
overlay: refactor
authortokyo4j <hrak1529@gmail.com>
Sat, 30 Aug 2025 19:41:08 +0000 (04:41 +0900)
committerJohan Malm <johanmalm@users.noreply.github.com>
Sun, 31 Aug 2025 12:24:51 +0000 (13:24 +0100)
- Use a single `lab_scene_rect` for both overlay background and outlines,
  like I described in the TODO comment in ffd4005.
- Simplify the resource management by destroying the overlay tree when
  it's hidden. I think its overhead is pretty minimal.
- Share a single `lab_scene_rect` for both region/edge overlays.

include/overlay.h
src/debug.c
src/interactive.c
src/output.c
src/overlay.c
src/regions.c
src/seat.c
src/workspaces.c

index 111532a1df4db7cbbf396285658594f1ae6828e5..a7911f3aeb274ea0d6920e89a99dc0b1b9c13648 100644 (file)
@@ -6,19 +6,8 @@
 
 struct seat;
 
-/* TODO: replace this with single lab_scene_rect */
-struct overlay_rect {
-       struct wlr_scene_tree *tree;
-
-       bool bg_enabled;
-       struct wlr_scene_rect *bg_rect;
-
-       bool border_enabled;
-       struct lab_scene_rect *border_rect;
-};
-
 struct overlay {
-       struct overlay_rect region_rect, edge_rect;
+       struct lab_scene_rect *rect;
 
        /* Represents currently shown or delayed overlay */
        struct {
@@ -34,15 +23,13 @@ struct overlay {
        struct wl_event_source *timer;
 };
 
-void overlay_reconfigure(struct seat *seat);
-
-/* Calls overlay_hide() internally if there's no overlay to show */
+/*
+ * Shows or updates an overlay when the grabbed window can be snapped to
+ * a region or an output edge. Calls overlay_finish() otherwise.
+ */
 void overlay_update(struct seat *seat);
 
-/* This function must be called when server->grabbed_view is destroyed */
-void overlay_hide(struct seat *seat);
-
-/* This function is called to clean up the timer on exit */
+/* Destroys the overlay if it exists */
 void overlay_finish(struct seat *seat);
 
 #endif
index 415371030c4b4f25e9bf0ce8ab26a72da0ffc5aa..97c011f2ecc79ffa438f9a8dbe0f60cb8f0d7996 100644 (file)
@@ -22,7 +22,7 @@
 #define IGNORE_SSD true
 #define IGNORE_MENU true
 #define IGNORE_OSD_PREVIEW_OUTLINE true
-#define IGNORE_SNAPPING_PREVIEW_OUTLINE true
+#define IGNORE_SNAPPING_OVERLAY true
 
 static struct view *last_view;
 
@@ -141,15 +141,10 @@ get_special(struct server *server, struct wlr_scene_node *node)
        if (node == &server->seat.drag.icons->node) {
                return "seat->drag.icons";
        }
-       if (server->seat.overlay.region_rect.tree
-                       && node == &server->seat.overlay.region_rect.tree->node) {
+       if (server->seat.overlay.rect
+                       && node == &server->seat.overlay.rect->tree->node) {
                /* Created on-demand */
-               return "seat->overlay.region_rect";
-       }
-       if (server->seat.overlay.edge_rect.tree
-                       && node == &server->seat.overlay.edge_rect.tree->node) {
-               /* Created on-demand */
-               return "seat->overlay.edge_rect";
+               return "seat->overlay.rect";
        }
        if (server->seat.input_method_relay->popup_tree
                        && node == &server->seat.input_method_relay->popup_tree->node) {
@@ -224,21 +219,13 @@ dump_tree(struct server *server, struct wlr_scene_node *node,
 
        struct lab_scene_rect *osd_preview_outline =
                server->osd_state.preview_outline;
-       struct lab_scene_rect *region_snapping_overlay_outline =
-               server->seat.overlay.region_rect.border_rect;
-       struct lab_scene_rect *edge_snapping_overlay_outline =
-               server->seat.overlay.edge_rect.border_rect;
        if ((IGNORE_MENU && node == &server->menu_tree->node)
                        || (IGNORE_SSD && last_view
                                && ssd_debug_is_root_node(last_view->ssd, node))
                        || (IGNORE_OSD_PREVIEW_OUTLINE && osd_preview_outline
                                && node == &osd_preview_outline->tree->node)
-                       || (IGNORE_SNAPPING_PREVIEW_OUTLINE
-                               && region_snapping_overlay_outline
-                               && node == &region_snapping_overlay_outline->tree->node)
-                       || (IGNORE_SNAPPING_PREVIEW_OUTLINE
-                               && edge_snapping_overlay_outline
-                               && node == &edge_snapping_overlay_outline->tree->node)) {
+                       || (IGNORE_SNAPPING_OVERLAY && server->seat.overlay.rect
+                               && node == &server->seat.overlay.rect->tree->node)) {
                printf("%*c%s\n", pos + 4 + INDENT_SIZE, ' ', "<skipping children>");
                return;
        }
index 517b898e6a669a172faf66fdf895c7085f77eb38..f0c30e759b3771989f72ec7fe9cf29051266a9c5 100644 (file)
@@ -303,7 +303,7 @@ interactive_cancel(struct view *view)
                return;
        }
 
-       overlay_hide(&view->server->seat);
+       overlay_finish(&view->server->seat);
 
        resize_indicator_hide(view);
 
index f683c2dec6a40c1191f665136d5647549a31f51b..7715b8994050580ee920662cbef4751321fa13d5 100644 (file)
@@ -171,7 +171,7 @@ handle_output_destroy(struct wl_listener *listener, void *data)
        regions_evacuate_output(output);
        regions_destroy(seat, &output->regions);
        if (seat->overlay.active.output == output) {
-               overlay_hide(seat);
+               overlay_finish(seat);
        }
        wl_list_remove(&output->link);
        wl_list_remove(&output->frame.link);
index 2a5cc845018a68b57a3dae4e0a308aee28292058..4cf6c4fd6630b3263262646a3028f918b42f1e41 100644 (file)
 #include "view.h"
 
 static void
-create_overlay_rect(struct seat *seat, struct overlay_rect *rect,
-               struct theme_snapping_overlay *theme)
-{
-       struct server *server = seat->server;
-
-       rect->bg_enabled = theme->bg_enabled;
-       rect->border_enabled = theme->border_enabled;
-       rect->tree = wlr_scene_tree_create(&server->scene->tree);
-
-       if (rect->bg_enabled) {
-               /* Create a filled rectangle */
-               rect->bg_rect = wlr_scene_rect_create(
-                       rect->tree, 0, 0, theme->bg_color);
-       }
-
-       if (rect->border_enabled) {
-               /* Create outlines */
-               struct lab_scene_rect_options opts = {
-                       .border_colors = (float *[3]) {
-                               theme->border_color[0],
-                               theme->border_color[1],
-                               theme->border_color[2],
-                       },
-                       .nr_borders = 3,
-                       .border_width = theme->border_width,
-               };
-               rect->border_rect = lab_scene_rect_create(rect->tree, &opts);
-       }
-
-       wlr_scene_node_set_enabled(&rect->tree->node, false);
-}
-
-void overlay_reconfigure(struct seat *seat)
-{
-       if (seat->overlay.region_rect.tree) {
-               wlr_scene_node_destroy(&seat->overlay.region_rect.tree->node);
-       }
-       if (seat->overlay.edge_rect.tree) {
-               wlr_scene_node_destroy(&seat->overlay.edge_rect.tree->node);
-       }
-
-       struct theme *theme = seat->server->theme;
-       create_overlay_rect(seat, &seat->overlay.region_rect,
-               &theme->snapping_overlay_region);
-       create_overlay_rect(seat, &seat->overlay.edge_rect,
-               &theme->snapping_overlay_edge);
-}
-
-static void
-show_overlay(struct seat *seat, struct overlay_rect *rect, struct wlr_box *box)
+show_overlay(struct seat *seat, struct theme_snapping_overlay *overlay_theme,
+               struct wlr_box *box)
 {
        struct server *server = seat->server;
        struct view *view = server->grabbed_view;
        assert(view);
+       assert(!seat->overlay.rect);
 
-       if (!rect->tree) {
-               overlay_reconfigure(seat);
-               assert(rect->tree);
+       struct lab_scene_rect_options opts = {
+               .width = box->width,
+               .height = box->height,
+       };
+       if (overlay_theme->bg_enabled) {
+               /* Create a filled rectangle */
+               opts.bg_color = overlay_theme->bg_color;
+       }
+       float *border_colors[3] = {
+               overlay_theme->border_color[0],
+               overlay_theme->border_color[1],
+               overlay_theme->border_color[2],
+       };
+       if (overlay_theme->border_enabled) {
+               /* Create outlines */
+               opts.border_colors = border_colors;
+               opts.nr_borders = 3;
+               opts.border_width = overlay_theme->border_width;
        }
 
-       if (rect->bg_enabled) {
-               wlr_scene_rect_set_size(rect->bg_rect, box->width, box->height);
-       }
-       if (rect->border_enabled) {
-               lab_scene_rect_set_size(rect->border_rect, box->width, box->height);
-       }
+       seat->overlay.rect =
+               lab_scene_rect_create(view->scene_tree->node.parent, &opts);
 
-       struct wlr_scene_node *node = &rect->tree->node;
-       wlr_scene_node_reparent(node, view->scene_tree->node.parent);
+       struct wlr_scene_node *node = &seat->overlay.rect->tree->node;
        wlr_scene_node_place_below(node, &view->scene_tree->node);
        wlr_scene_node_set_position(node, box->x, box->y);
-       wlr_scene_node_set_enabled(node, true);
-}
-
-static void
-inactivate_overlay(struct overlay *overlay)
-{
-       if (overlay->region_rect.tree) {
-               wlr_scene_node_set_enabled(
-                       &overlay->region_rect.tree->node, false);
-       }
-       if (overlay->edge_rect.tree) {
-               wlr_scene_node_set_enabled(
-                       &overlay->edge_rect.tree->node, false);
-       }
-       overlay->active.region = NULL;
-       overlay->active.edge = LAB_EDGE_NONE;
-       overlay->active.output = NULL;
-       if (overlay->timer) {
-               wl_event_source_timer_update(overlay->timer, 0);
-       }
 }
 
 static void
@@ -110,11 +53,11 @@ show_region_overlay(struct seat *seat, struct region *region)
        if (region == seat->overlay.active.region) {
                return;
        }
-       inactivate_overlay(&seat->overlay);
+       overlay_finish(seat);
        seat->overlay.active.region = region;
 
        struct wlr_box geo = view_get_region_snap_box(NULL, region);
-       show_overlay(seat, &seat->overlay.region_rect, &geo);
+       show_overlay(seat, &rc.theme->snapping_overlay_region, &geo);
 }
 
 static struct wlr_box
@@ -135,7 +78,7 @@ handle_edge_overlay_timeout(void *data)
                && seat->overlay.active.output);
        struct wlr_box box = get_edge_snap_box(seat->overlay.active.edge,
                seat->overlay.active.output);
-       show_overlay(seat, &seat->overlay.edge_rect, &box);
+       show_overlay(seat, &rc.theme->snapping_overlay_edge, &box);
        return 0;
 }
 
@@ -165,7 +108,7 @@ show_edge_overlay(struct seat *seat, enum lab_edge edge1, enum lab_edge edge2,
                        && seat->overlay.active.output == output) {
                return;
        }
-       inactivate_overlay(&seat->overlay);
+       overlay_finish(seat);
        seat->overlay.active.edge = edge;
        seat->overlay.active.output = output;
 
@@ -186,8 +129,7 @@ show_edge_overlay(struct seat *seat, enum lab_edge edge1, enum lab_edge edge2,
                wl_event_source_timer_update(seat->overlay.timer, delay);
        } else {
                /* Show overlay now */
-               struct wlr_box box = get_edge_snap_box(edge, output);
-               show_overlay(seat, &seat->overlay.edge_rect, &box);
+               handle_edge_overlay_timeout(seat);
        }
 }
 
@@ -213,36 +155,17 @@ overlay_update(struct seat *seat)
                return;
        }
 
-       overlay_hide(seat);
-}
-
-void
-overlay_hide(struct seat *seat)
-{
-       struct overlay *overlay = &seat->overlay;
-       struct server *server = seat->server;
-
-       inactivate_overlay(overlay);
-
-       /*
-        * Reparent the rectangle nodes to server's scene-tree so they don't
-        * get destroyed on view destruction
-        */
-       if (overlay->region_rect.tree) {
-               wlr_scene_node_reparent(&overlay->region_rect.tree->node,
-                       &server->scene->tree);
-       }
-       if (overlay->edge_rect.tree) {
-               wlr_scene_node_reparent(&overlay->edge_rect.tree->node,
-                       &server->scene->tree);
-       }
+       overlay_finish(seat);
 }
 
 void
 overlay_finish(struct seat *seat)
 {
+       if (seat->overlay.rect) {
+               wlr_scene_node_destroy(&seat->overlay.rect->tree->node);
+       }
        if (seat->overlay.timer) {
                wl_event_source_remove(seat->overlay.timer);
-               seat->overlay.timer = NULL;
        }
+       seat->overlay = (struct overlay){0};
 }
index 5243b95abfe633984c7217740fb858c419721078..c06698b99448bb5bddae8e9c9efc4513a8e86261 100644 (file)
@@ -166,7 +166,7 @@ regions_destroy(struct seat *seat, struct wl_list *regions)
        wl_list_for_each_safe(region, region_tmp, regions, link) {
                wl_list_remove(&region->link);
                if (seat && seat->overlay.active.region == region) {
-                       overlay_hide(seat);
+                       overlay_finish(seat);
                }
                zfree(region->name);
                zfree(region);
index 9817e78b3fea6c8a4f2d1ed0394cfd339c0bc5a8..25d8fc577ebf05cf4e663cb59b22b058f364f7b3 100644 (file)
@@ -731,7 +731,7 @@ seat_reconfigure(struct server *server)
        struct seat *seat = &server->seat;
        struct input *input;
        cursor_reload(seat);
-       overlay_reconfigure(seat);
+       overlay_finish(seat);
        keyboard_reset_current_keybind();
        wl_list_for_each(input, &seat->inputs, link) {
                switch (input->wlr_input_device->type) {
index 04856a4748fd0ad1ee47581901a12fca630f0149..5345f69d8e0c8ad86164603013faddee9d169c6a 100644 (file)
@@ -602,7 +602,7 @@ workspaces_reconfigure(struct server *server)
        }
 
        /* # of configured workspaces decreased */
-       overlay_hide(&server->seat);
+       overlay_finish(&server->seat);
        struct workspace *first_workspace =
                wl_container_of(server->workspaces.all.next, first_workspace, link);