From 66e26cd28a44b3830cc2b03bde3a25cda8df2e34 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Sun, 31 Aug 2025 04:41:08 +0900 Subject: [PATCH] overlay: refactor - 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 | 25 ++------ src/debug.c | 25 ++------ src/interactive.c | 2 +- src/output.c | 2 +- src/overlay.c | 145 +++++++++++----------------------------------- src/regions.c | 2 +- src/seat.c | 2 +- src/workspaces.c | 2 +- 8 files changed, 51 insertions(+), 154 deletions(-) diff --git a/include/overlay.h b/include/overlay.h index 111532a1..a7911f3a 100644 --- a/include/overlay.h +++ b/include/overlay.h @@ -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 diff --git a/src/debug.c b/src/debug.c index 41537103..97c011f2 100644 --- a/src/debug.c +++ b/src/debug.c @@ -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 == ®ion_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, ' ', ""); return; } diff --git a/src/interactive.c b/src/interactive.c index 517b898e..f0c30e75 100644 --- a/src/interactive.c +++ b/src/interactive.c @@ -303,7 +303,7 @@ interactive_cancel(struct view *view) return; } - overlay_hide(&view->server->seat); + overlay_finish(&view->server->seat); resize_indicator_hide(view); diff --git a/src/output.c b/src/output.c index f683c2de..7715b899 100644 --- a/src/output.c +++ b/src/output.c @@ -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); diff --git a/src/overlay.c b/src/overlay.c index 2a5cc845..4cf6c4fd 100644 --- a/src/overlay.c +++ b/src/overlay.c @@ -11,97 +11,40 @@ #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}; } diff --git a/src/regions.c b/src/regions.c index 5243b95a..c06698b9 100644 --- a/src/regions.c +++ b/src/regions.c @@ -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(®ion->link); if (seat && seat->overlay.active.region == region) { - overlay_hide(seat); + overlay_finish(seat); } zfree(region->name); zfree(region); diff --git a/src/seat.c b/src/seat.c index 9817e78b..25d8fc57 100644 --- a/src/seat.c +++ b/src/seat.c @@ -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) { diff --git a/src/workspaces.c b/src/workspaces.c index 04856a47..5345f69d 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -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);