From 50fd65416f7463708b3be3ad4268bdf8bb379109 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Sun, 14 Apr 2024 02:24:36 +0900 Subject: [PATCH] overlay: add theme setting `snapping.preview.[region|edge].fill` This settings allows user to choose whether to draw a filled rectangle or an outlined rectangle as the preview for window snapping. --- docs/labwc-theme.5.scd | 10 +++++ docs/themerc | 3 ++ include/overlay.h | 14 +++++-- include/theme.h | 3 ++ src/debug.c | 20 ++++++++-- src/overlay.c | 89 ++++++++++++++++++++++++++++-------------- src/seat.c | 1 + src/theme.c | 10 +++++ 8 files changed, 114 insertions(+), 36 deletions(-) diff --git a/docs/labwc-theme.5.scd b/docs/labwc-theme.5.scd index deda8abe..73359e20 100644 --- a/docs/labwc-theme.5.scd +++ b/docs/labwc-theme.5.scd @@ -198,6 +198,16 @@ elements are not listed here, but are supported. Height of boxes in workspace switcher in pixels. Setting to 0 disables boxes. Default is 20. +*snapping.preview.region.fill* [yes|no] + Show a filled rectangle as the preview when a window is snapped to a region. + Otherwise, an outlined rectangle is shown instead. + If software rendering is used, an outlined rectangle is always shown. + +*snapping.preview.edge.fill* [yes|no] + Show a filled rectangle as the preview when a window is snapped to an edge. + Otherwise, an outlined rectangle is shown instead. + If software rendering is used, an outlined rectangle is always shown. + *border.color* Set both *window.active.border.color* and *window.inactive.border.color*. This is obsolete, but supported for backward compatibility as some themes diff --git a/docs/themerc b/docs/themerc index 83e0f73e..05791d8b 100644 --- a/docs/themerc +++ b/docs/themerc @@ -71,3 +71,6 @@ osd.window-switcher.item.active.border.width: 2 osd.workspace-switcher.boxes.width: 20 osd.workspace-switcher.boxes.height: 20 + +snapping.preview.region.fill: yes +snapping.preview.edge.fill: yes diff --git a/include/overlay.h b/include/overlay.h index 3d56f8d7..5b6a5800 100644 --- a/include/overlay.h +++ b/include/overlay.h @@ -7,12 +7,19 @@ #include "regions.h" #include "view.h" -struct overlay { - struct wlr_scene_tree *tree; +struct overlay_rect { + struct wlr_scene_node *node; + bool fill; union { - struct wlr_scene_rect *rect; + /* if fill is true */ + struct wlr_scene_rect *scene_rect; + /* if fill is false */ struct multi_rect *pixman_rect; }; +}; + +struct overlay { + struct overlay_rect region_rect, edge_rect; /* Represents currently shown or delayed overlay */ struct { @@ -28,6 +35,7 @@ struct overlay { struct wl_event_source *timer; }; +void overlay_reconfigure(struct seat *seat); /* Calls overlay_hide() internally if there's no overlay to show */ void overlay_update(struct seat *seat); /* This function must be called when server->grabbed_view is destroyed */ diff --git a/include/theme.h b/include/theme.h index 5b584d59..d35ccc15 100644 --- a/include/theme.h +++ b/include/theme.h @@ -80,6 +80,9 @@ struct theme { int osd_workspace_switcher_boxes_width; int osd_workspace_switcher_boxes_height; + bool snapping_preview_region_fill; + bool snapping_preview_edge_fill; + /* textures */ struct lab_data_buffer *button_close_active_unpressed; struct lab_data_buffer *button_maximize_active_unpressed; diff --git a/src/debug.c b/src/debug.c index 3b79f7ac..3a1a1761 100644 --- a/src/debug.c +++ b/src/debug.c @@ -18,6 +18,7 @@ #define IGNORE_SSD true #define IGNORE_MENU true #define IGNORE_OSD_PREVIEW_OUTLINE true +#define IGNORE_SNAPPING_PREVIEW_OUTLINE true static struct view *last_view; @@ -136,10 +137,15 @@ 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.tree - && node == &server->seat.overlay.tree->node) { + if (server->seat.overlay.region_rect.node + && node == server->seat.overlay.region_rect.node) { /* Created on-demand */ - return "seat->overlay"; + return "seat->overlay.region_rect"; + } + if (server->seat.overlay.edge_rect.node + && node == server->seat.overlay.edge_rect.node) { + /* Created on-demand */ + return "seat->overlay.edge_rect"; } if (server->seat.input_method_relay->popup_tree && node == &server->seat.input_method_relay->popup_tree->node) { @@ -216,7 +222,13 @@ dump_tree(struct server *server, struct wlr_scene_node *node, || (IGNORE_SSD && last_view && ssd_debug_is_root_node(last_view->ssd, node)) || (IGNORE_OSD_PREVIEW_OUTLINE && server->osd_state.preview_outline - && node == &server->osd_state.preview_outline->tree->node)) { + && node == &server->osd_state.preview_outline->tree->node) + || (IGNORE_SNAPPING_PREVIEW_OUTLINE && server->seat.overlay.region_rect.node + && !server->seat.overlay.region_rect.fill + && node == server->seat.overlay.region_rect.node) + || (IGNORE_SNAPPING_PREVIEW_OUTLINE && server->seat.overlay.edge_rect.node + && !server->seat.overlay.edge_rect.fill + && node == server->seat.overlay.edge_rect.node)) { printf("%*c%s\n", pos + 4 + INDENT_SIZE, ' ', ""); return; } diff --git a/src/overlay.c b/src/overlay.c index 7d3166e7..7958bf24 100644 --- a/src/overlay.c +++ b/src/overlay.c @@ -6,52 +6,74 @@ #include "view.h" static void -create_overlay(struct seat *seat) +create_overlay_rect(struct seat *seat, struct overlay_rect *rect, int fill) { - assert(!seat->overlay.tree); - struct server *server = seat->server; - struct wlr_scene_tree *parent = wlr_scene_tree_create(&server->scene->tree); - seat->overlay.tree = parent; - wlr_scene_node_set_enabled(&parent->node, false); - if (!wlr_renderer_is_pixman(server->renderer)) { - /* Hardware assisted rendering: Half transparent overlay, pre-multiplied */ + rect->fill = fill; + /* For pixman renderer, always render outlines to save CPU resource */ + if (wlr_renderer_is_pixman(server->renderer)) { + rect->fill = false; + } + + if (rect->fill) { + /* Create a filled rectangle */ float color[4] = { 0.25, 0.25, 0.35, 0.5 }; - seat->overlay.rect = wlr_scene_rect_create(parent, 0, 0, color); + rect->scene_rect = wlr_scene_rect_create(&server->scene->tree, + 0, 0, color); + rect->node = &rect->scene_rect->node; } else { - /* Software rendering: Outlines */ + /* Create outlines */ int line_width = server->theme->osd_border_width; float *colors[3] = { server->theme->osd_bg_color, server->theme->osd_label_text_color, server->theme->osd_bg_color }; - seat->overlay.pixman_rect = multi_rect_create(parent, colors, line_width); + rect->pixman_rect = multi_rect_create(&server->scene->tree, + colors, line_width); + rect->node = &rect->pixman_rect->tree->node; + } + + wlr_scene_node_set_enabled(rect->node, false); +} + +void overlay_reconfigure(struct seat *seat) +{ + if (seat->overlay.region_rect.node) { + wlr_scene_node_destroy(seat->overlay.region_rect.node); + } + if (seat->overlay.edge_rect.node) { + wlr_scene_node_destroy(seat->overlay.edge_rect.node); } + + struct theme *theme = seat->server->theme; + create_overlay_rect(seat, &seat->overlay.region_rect, + theme->snapping_preview_region_fill); + create_overlay_rect(seat, &seat->overlay.edge_rect, + theme->snapping_preview_edge_fill); } static void -show_overlay(struct seat *seat, struct wlr_box *box) +show_overlay(struct seat *seat, struct overlay_rect *rect, struct wlr_box *box) { struct server *server = seat->server; struct view *view = server->grabbed_view; assert(view); + struct wlr_scene_node *node = rect->node; - if (!seat->overlay.tree) { - create_overlay(seat); + if (!node) { + overlay_reconfigure(seat); + node = rect->node; + assert(node); } - struct wlr_scene_node *node = &seat->overlay.tree->node; - if (!wlr_renderer_is_pixman(server->renderer)) { - /* Hardware assisted rendering: Half transparent overlay */ - wlr_scene_rect_set_size(seat->overlay.rect, - box->width, box->height); + if (rect->fill) { + wlr_scene_rect_set_size(rect->scene_rect, box->width, box->height); } else { - /* Software rendering: Outlines */ - multi_rect_set_size(seat->overlay.pixman_rect, - box->width, box->height); + multi_rect_set_size(rect->pixman_rect, box->width, box->height); } + wlr_scene_node_reparent(node, view->scene_tree->node.parent); wlr_scene_node_place_below(node, &view->scene_tree->node); wlr_scene_node_set_position(node, box->x, box->y); @@ -61,8 +83,13 @@ show_overlay(struct seat *seat, struct wlr_box *box) static void inactivate_overlay(struct overlay *overlay) { - if (overlay->tree) { - wlr_scene_node_set_enabled(&overlay->tree->node, false); + if (overlay->region_rect.node) { + wlr_scene_node_set_enabled( + overlay->region_rect.node, false); + } + if (overlay->edge_rect.node) { + wlr_scene_node_set_enabled( + overlay->edge_rect.node, false); } overlay->active.region = NULL; overlay->active.edge = VIEW_EDGE_INVALID; @@ -81,7 +108,7 @@ show_region_overlay(struct seat *seat, struct region *region) inactivate_overlay(&seat->overlay); seat->overlay.active.region = region; - show_overlay(seat, ®ion->geo); + show_overlay(seat, &seat->overlay.region_rect, ®ion->geo); } /* TODO: share logic with view_get_edge_snap_box() */ @@ -119,7 +146,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, &box); + show_overlay(seat, &seat->overlay.edge_rect, &box); return 0; } @@ -186,7 +213,7 @@ show_edge_overlay(struct seat *seat, enum view_edge edge, /* Show overlay now */ struct wlr_box box = get_edge_snap_box(seat->overlay.active.edge, seat->overlay.active.output); - show_overlay(seat, &box); + show_overlay(seat, &seat->overlay.edge_rect, &box); } } @@ -227,8 +254,12 @@ overlay_hide(struct seat *seat) * Reparent the rectangle nodes to server's scene-tree so they don't * get destroyed on view destruction */ - if (seat->overlay.tree) { - wlr_scene_node_reparent(&overlay->tree->node, + if (overlay->region_rect.node) { + wlr_scene_node_reparent(overlay->region_rect.node, + &server->scene->tree); + } + if (overlay->edge_rect.node) { + wlr_scene_node_reparent(overlay->edge_rect.node, &server->scene->tree); } } diff --git a/src/seat.c b/src/seat.c index db9b6775..e504c6d7 100644 --- a/src/seat.c +++ b/src/seat.c @@ -587,6 +587,7 @@ seat_reconfigure(struct server *server) struct seat *seat = &server->seat; struct input *input; cursor_load(seat); + overlay_reconfigure(seat); wl_list_for_each(input, &seat->inputs, link) { switch (input->wlr_input_device->type) { case WLR_INPUT_DEVICE_KEYBOARD: diff --git a/src/theme.c b/src/theme.c index 4a3efeac..615c2aef 100644 --- a/src/theme.c +++ b/src/theme.c @@ -24,6 +24,7 @@ #include "common/graphic-helpers.h" #include "common/match.h" #include "common/mem.h" +#include "common/parse-bool.h" #include "common/string-helpers.h" #include "config/rcxml.h" #include "button/button-png.h" @@ -520,6 +521,9 @@ theme_builtin(struct theme *theme) theme->osd_border_width = INT_MIN; theme->osd_border_color[0] = FLT_MIN; theme->osd_label_text_color[0] = FLT_MIN; + + theme->snapping_preview_region_fill = true; + theme->snapping_preview_edge_fill = true; } static void @@ -715,6 +719,12 @@ entry(struct theme *theme, const char *key, const char *value) if (match_glob(key, "osd.label.text.color")) { parse_hexstr(value, theme->osd_label_text_color); } + if (match_glob(key, "snapping.preview.region.fill")) { + theme->snapping_preview_region_fill = parse_bool(value, true); + } + if (match_glob(key, "snapping.preview.edge.fill")) { + theme->snapping_preview_edge_fill = parse_bool(value, true); + } } static void -- 2.52.0