From: tokyo4j Date: Sat, 20 Apr 2024 17:30:31 +0000 (+0900) Subject: overlay: allow to draw both/either of filled/outlined rectangle X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=b0ba585ff860e3f0e21967c8f90467744c2fc571;p=proto%2Flabwc.git overlay: allow to draw both/either of filled/outlined rectangle Filled/outlined rectangles shown as snapping overlay are now enabled/disabled independently with `snapping.overlay.[region|edge].bg.enabled` and `snapping.overlay.[region|edge].border.enabled`. To keep the default behavior, `*.bg.enabled` is yes and `*.border.enabled` is no for hardware-based renderers, while `*.bg.enabled` is no and `*.border.enabled` is yes for software-based (pixman) renderer. Users can now use a filled rectangle as an overlay even with pixman renderer. However, this may severely impact performance when used with translucent `snapping.overlay.[region|edge].bg.color`. This commit includes a refactor to use substruct `theme_snapping_overlay` inside `theme` in order to pass it to `create_overlay_rect()` in a cleaner way. Breaking changes is: - `snapping.overlay.[region|edge].fill` is now removed. --- diff --git a/docs/labwc-theme.5.scd b/docs/labwc-theme.5.scd index 4506e125..5913dfa5 100644 --- a/docs/labwc-theme.5.scd +++ b/docs/labwc-theme.5.scd @@ -210,15 +210,25 @@ 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.overlay.region.fill* [yes|no] +*snapping.overlay.region.bg.enabled* [yes|no] Show a filled rectangle as an overlay 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. + Default is yes for hardware-based renderers and no for software-based + renderers. -*snapping.overlay.edge.fill* [yes|no] +*snapping.overlay.edge.bg.enabled* [yes|no] Show a filled rectangle as an overlay 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. + Default is yes for hardware-based renderer and no for software-based + renderers. + +*snapping.overlay.region.border.enabled* [yes|no] + Show an outlined rectangle as an overlay when a window is snapped to a + region. Default is no for hardware-based renderers and yes for software-based + renderers. + +*snapping.overlay.edge.border.enabled* [yes|no] + Show an outlined rectangle as an overlay when a window is snapped to an edge. + Default is no for hardware-based renderer and yes for software-based + renderers. *snapping.overlay.region.bg.color* Color of a filled rectangle shown as an overlay when a window is snapped to diff --git a/docs/themerc b/docs/themerc index e4b6733f..cb3c254a 100644 --- a/docs/themerc +++ b/docs/themerc @@ -74,8 +74,18 @@ osd.window-switcher.preview.border.color: #dddda6,#000000,#dddda6 osd.workspace-switcher.boxes.width: 20 osd.workspace-switcher.boxes.height: 20 -snapping.overlay.region.fill: yes -snapping.overlay.edge.fill: yes +# Default values for following options change depending on the rendering +# backend. For software-based renderers, *.bg.enabled is "no" and +# *.border.enabled is "yes" if not set. For hardware-based renderers, +# *.bg.enabled is "yes" and *.border.enabled is "no" if not set. +# Setting *.bg.enabled to "yes" for software-based renderer with translucent +# background color may severely impact performance. +# +# snapping.overlay.region.bg.enabled: +# snapping.overlay.edge.bg.enabled: +# snapping.overlay.region.border.enabled: +# snapping.overlay.edge.border.enabled: + snapping.overlay.region.bg.color: #8080b380 snapping.overlay.edge.bg.color: #8080b380 snapping.overlay.region.border.width: 1 diff --git a/include/overlay.h b/include/overlay.h index 5b6a5800..bb280f8c 100644 --- a/include/overlay.h +++ b/include/overlay.h @@ -8,14 +8,13 @@ #include "view.h" struct overlay_rect { - struct wlr_scene_node *node; - bool fill; - union { - /* if fill is true */ - struct wlr_scene_rect *scene_rect; - /* if fill is false */ - struct multi_rect *pixman_rect; - }; + struct wlr_scene_tree *tree; + + bool bg_enabled; + struct wlr_scene_rect *bg_rect; + + bool border_enabled; + struct multi_rect *border_rect; }; struct overlay { diff --git a/include/theme.h b/include/theme.h index 54bb4ceb..b0bb0c87 100644 --- a/include/theme.h +++ b/include/theme.h @@ -17,6 +17,14 @@ enum lab_justification { LAB_JUSTIFY_RIGHT, }; +struct theme_snapping_overlay { + bool bg_enabled; + bool border_enabled; + float bg_color[4]; + int border_width; + float border_color[3][4]; +}; + struct theme { int border_width; int padding_height; @@ -82,16 +90,8 @@ struct theme { int osd_workspace_switcher_boxes_width; int osd_workspace_switcher_boxes_height; - bool snapping_overlay_region_fill; - bool snapping_overlay_edge_fill; - - float snapping_overlay_region_bg_color[4]; - float snapping_overlay_edge_bg_color[4]; - - int snapping_overlay_region_border_width; - int snapping_overlay_edge_border_width; - float snapping_overlay_region_border_color[3][4]; - float snapping_overlay_edge_border_color[3][4]; + struct theme_snapping_overlay + snapping_overlay_region, snapping_overlay_edge; /* textures */ struct lab_data_buffer *button_close_active_unpressed; @@ -128,13 +128,16 @@ struct theme { int osd_window_switcher_item_height; }; +struct server; + /** * theme_init - read openbox theme and generate button textures * @theme: theme data + * @server: server * @theme_name: theme-name in //openbox-3/themerc * Note is obtained in theme-dir.c */ -void theme_init(struct theme *theme, const char *theme_name); +void theme_init(struct theme *theme, struct server *server, const char *theme_name); /** * theme_finish - free button textures diff --git a/src/debug.c b/src/debug.c index 75f2f794..d5750fea 100644 --- a/src/debug.c +++ b/src/debug.c @@ -138,13 +138,13 @@ 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.node - && node == server->seat.overlay.region_rect.node) { + if (server->seat.overlay.region_rect.tree + && node == &server->seat.overlay.region_rect.tree->node) { /* Created on-demand */ return "seat->overlay.region_rect"; } - if (server->seat.overlay.edge_rect.node - && node == server->seat.overlay.edge_rect.node) { + if (server->seat.overlay.edge_rect.tree + && node == &server->seat.overlay.edge_rect.tree->node) { /* Created on-demand */ return "seat->overlay.edge_rect"; } @@ -219,17 +219,23 @@ dump_tree(struct server *server, struct wlr_scene_node *node, } printf("%.*s %*c %4d %4d [%p]\n", max_width - 1, type, padding, ' ', x, y, node); + struct multi_rect *osd_preview_outline = + server->osd_state.preview_outline; + struct multi_rect *region_snapping_overlay_outline = + server->seat.overlay.region_rect.border_rect; + struct multi_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 && server->osd_state.preview_outline - && 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)) { + || (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)) { printf("%*c%s\n", pos + 4 + INDENT_SIZE, ' ', ""); return; } diff --git a/src/main.c b/src/main.c index 1860efa5..1fdfcd3a 100644 --- a/src/main.c +++ b/src/main.c @@ -171,7 +171,7 @@ main(int argc, char *argv[]) server_start(&server); struct theme theme = { 0 }; - theme_init(&theme, rc.theme_name); + theme_init(&theme, &server, rc.theme_name); rc.theme = &theme; server.theme = &theme; diff --git a/src/overlay.c b/src/overlay.c index 7f23ec4b..ed9446bf 100644 --- a/src/overlay.c +++ b/src/overlay.c @@ -1,62 +1,54 @@ // SPDX-License-Identifier: GPL-2.0-only #include -#include #include "labwc.h" #include "overlay.h" #include "view.h" +#include "theme.h" static void -create_overlay_rect(struct seat *seat, struct overlay_rect *rect, int fill, - float bg_color[4], int border_width, float border_colors[3][4]) +create_overlay_rect(struct seat *seat, struct overlay_rect *rect, + struct theme_snapping_overlay *theme) { struct server *server = seat->server; - rect->fill = fill; - /* For pixman renderer, always render outlines to save CPU resource */ - if (wlr_renderer_is_pixman(server->renderer)) { - rect->fill = false; - } + rect->bg_enabled = theme->bg_enabled; + rect->border_enabled = theme->border_enabled; + rect->tree = wlr_scene_tree_create(&server->scene->tree); - if (rect->fill) { + if (rect->bg_enabled) { /* Create a filled rectangle */ - rect->scene_rect = wlr_scene_rect_create(&server->scene->tree, - 0, 0, bg_color); - rect->node = &rect->scene_rect->node; - } else { + rect->bg_rect = wlr_scene_rect_create( + rect->tree, 0, 0, theme->bg_color); + } + + if (rect->border_enabled) { /* Create outlines */ float *colors[3] = { - border_colors[0], - border_colors[1], - border_colors[2], + theme->border_color[0], + theme->border_color[1], + theme->border_color[2], }; - rect->pixman_rect = multi_rect_create(&server->scene->tree, - colors, border_width); - rect->node = &rect->pixman_rect->tree->node; + rect->border_rect = multi_rect_create( + rect->tree, colors, theme->border_width); } - wlr_scene_node_set_enabled(rect->node, false); + wlr_scene_node_set_enabled(&rect->tree->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.region_rect.tree) { + wlr_scene_node_destroy(&seat->overlay.region_rect.tree->node); } - if (seat->overlay.edge_rect.node) { - wlr_scene_node_destroy(seat->overlay.edge_rect.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_fill, - theme->snapping_overlay_region_bg_color, - theme->snapping_overlay_region_border_width, - theme->snapping_overlay_region_border_color); + &theme->snapping_overlay_region); create_overlay_rect(seat, &seat->overlay.edge_rect, - theme->snapping_overlay_edge_fill, - theme->snapping_overlay_edge_bg_color, - theme->snapping_overlay_edge_border_width, - theme->snapping_overlay_edge_border_color); + &theme->snapping_overlay_edge); } static void @@ -65,20 +57,20 @@ 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 (!node) { + if (!rect->tree) { overlay_reconfigure(seat); - node = rect->node; - assert(node); + assert(rect->tree); } - if (rect->fill) { - wlr_scene_rect_set_size(rect->scene_rect, box->width, box->height); - } else { - multi_rect_set_size(rect->pixman_rect, box->width, box->height); + if (rect->bg_enabled) { + wlr_scene_rect_set_size(rect->bg_rect, box->width, box->height); + } + if (rect->border_enabled) { + multi_rect_set_size(rect->border_rect, box->width, box->height); } + struct wlr_scene_node *node = &rect->tree->node; 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); @@ -88,13 +80,13 @@ show_overlay(struct seat *seat, struct overlay_rect *rect, struct wlr_box *box) static void inactivate_overlay(struct overlay *overlay) { - if (overlay->region_rect.node) { + if (overlay->region_rect.tree) { wlr_scene_node_set_enabled( - overlay->region_rect.node, false); + &overlay->region_rect.tree->node, false); } - if (overlay->edge_rect.node) { + if (overlay->edge_rect.tree) { wlr_scene_node_set_enabled( - overlay->edge_rect.node, false); + &overlay->edge_rect.tree->node, false); } overlay->active.region = NULL; overlay->active.edge = VIEW_EDGE_INVALID; @@ -259,12 +251,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 (overlay->region_rect.node) { - wlr_scene_node_reparent(overlay->region_rect.node, + if (overlay->region_rect.tree) { + wlr_scene_node_reparent(&overlay->region_rect.tree->node, &server->scene->tree); } - if (overlay->edge_rect.node) { - wlr_scene_node_reparent(overlay->edge_rect.node, + if (overlay->edge_rect.tree) { + wlr_scene_node_reparent(&overlay->edge_rect.tree->node, &server->scene->tree); } } diff --git a/src/server.c b/src/server.c index 58b95e55..48304019 100644 --- a/src/server.c +++ b/src/server.c @@ -51,7 +51,7 @@ reload_config_and_theme(struct server *server) rcxml_finish(); rcxml_read(rc.config_file); theme_finish(server->theme); - theme_init(server->theme, rc.theme_name); + theme_init(server->theme, server, rc.theme_name); struct view *view; wl_list_for_each(view, &server->views, link) { diff --git a/src/theme.c b/src/theme.c index 44290c37..bc2fde4d 100644 --- a/src/theme.c +++ b/src/theme.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "common/macros.h" #include "common/dir.h" @@ -28,6 +29,7 @@ #include "common/string-helpers.h" #include "config/rcxml.h" #include "button/button-png.h" +#include "labwc.h" #if HAVE_RSVG #include "button/button-svg.h" @@ -463,7 +465,7 @@ parse_justification(const char *str) * theme_builtin() applies a theme that is similar to vanilla GTK */ static void -theme_builtin(struct theme *theme) +theme_builtin(struct theme *theme, struct server *server) { theme->border_width = 1; theme->padding_height = 3; @@ -538,21 +540,31 @@ theme_builtin(struct theme *theme) theme->osd_border_color[0] = FLT_MIN; theme->osd_label_text_color[0] = FLT_MIN; - theme->snapping_overlay_region_fill = true; - theme->snapping_overlay_edge_fill = true; + if (wlr_renderer_is_pixman(server->renderer)) { + /* Draw only outlined overlay by default to save CPU resource */ + theme->snapping_overlay_region.bg_enabled = false; + theme->snapping_overlay_edge.bg_enabled = false; + theme->snapping_overlay_region.border_enabled = true; + theme->snapping_overlay_edge.border_enabled = true; + } else { + theme->snapping_overlay_region.bg_enabled = true; + theme->snapping_overlay_edge.bg_enabled = true; + theme->snapping_overlay_region.border_enabled = false; + theme->snapping_overlay_edge.border_enabled = false; + } - parse_hexstr("#8080b380", theme->snapping_overlay_region_bg_color); - parse_hexstr("#8080b380", theme->snapping_overlay_edge_bg_color); + parse_hexstr("#8080b380", theme->snapping_overlay_region.bg_color); + parse_hexstr("#8080b380", theme->snapping_overlay_edge.bg_color); /* inherit settings in post_processing() if not set elsewhere */ - theme->snapping_overlay_region_border_width = INT_MIN; - theme->snapping_overlay_edge_border_width = INT_MIN; - memset(theme->snapping_overlay_region_border_color, 0, - sizeof(theme->snapping_overlay_region_border_color)); - theme->snapping_overlay_region_border_color[0][0] = FLT_MIN; - memset(theme->snapping_overlay_edge_border_color, 0, - sizeof(theme->snapping_overlay_edge_border_color)); - theme->snapping_overlay_edge_border_color[0][0] = FLT_MIN; + theme->snapping_overlay_region.border_width = INT_MIN; + theme->snapping_overlay_edge.border_width = INT_MIN; + memset(theme->snapping_overlay_region.border_color, 0, + sizeof(theme->snapping_overlay_region.border_color)); + theme->snapping_overlay_region.border_color[0][0] = FLT_MIN; + memset(theme->snapping_overlay_edge.border_color, 0, + sizeof(theme->snapping_overlay_edge.border_color)); + theme->snapping_overlay_edge.border_color[0][0] = FLT_MIN; } static void @@ -754,29 +766,35 @@ 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.overlay.region.fill")) { - theme->snapping_overlay_region_fill = parse_bool(value, true); + if (match_glob(key, "snapping.overlay.region.bg.enabled")) { + set_bool(value, &theme->snapping_overlay_region.bg_enabled); + } + if (match_glob(key, "snapping.overlay.edge.bg.enabled")) { + set_bool(value, &theme->snapping_overlay_edge.bg_enabled); + } + if (match_glob(key, "snapping.overlay.region.border.enabled")) { + set_bool(value, &theme->snapping_overlay_region.border_enabled); } - if (match_glob(key, "snapping.overlay.edge.fill")) { - theme->snapping_overlay_edge_fill = parse_bool(value, true); + if (match_glob(key, "snapping.overlay.edge.border.enabled")) { + set_bool(value, &theme->snapping_overlay_edge.border_enabled); } if (match_glob(key, "snapping.overlay.region.bg.color")) { - parse_hexstr(value, theme->snapping_overlay_region_bg_color); + parse_hexstr(value, theme->snapping_overlay_region.bg_color); } if (match_glob(key, "snapping.overlay.edge.bg.color")) { - parse_hexstr(value, theme->snapping_overlay_edge_bg_color); + parse_hexstr(value, theme->snapping_overlay_edge.bg_color); } if (match_glob(key, "snapping.overlay.region.border.width")) { - theme->snapping_overlay_region_border_width = atoi(value); + theme->snapping_overlay_region.border_width = atoi(value); } if (match_glob(key, "snapping.overlay.edge.border.width")) { - theme->snapping_overlay_edge_border_width = atoi(value); + theme->snapping_overlay_edge.border_width = atoi(value); } if (match_glob(key, "snapping.overlay.region.border.color")) { - parse_hexstrs(value, theme->snapping_overlay_region_border_color); + parse_hexstrs(value, theme->snapping_overlay_region.border_color); } if (match_glob(key, "snapping.overlay.edge.border.color")) { - parse_hexstrs(value, theme->snapping_overlay_edge_border_color); + parse_hexstrs(value, theme->snapping_overlay_edge.border_color); } } @@ -1113,32 +1131,32 @@ post_processing(struct theme *theme) theme->osd_window_switcher_preview_border_color); } - if (theme->snapping_overlay_region_border_width == INT_MIN) { - theme->snapping_overlay_region_border_width = + if (theme->snapping_overlay_region.border_width == INT_MIN) { + theme->snapping_overlay_region.border_width = theme->osd_border_width; } - if (theme->snapping_overlay_edge_border_width == INT_MIN) { - theme->snapping_overlay_edge_border_width = + if (theme->snapping_overlay_edge.border_width == INT_MIN) { + theme->snapping_overlay_edge.border_width = theme->osd_border_width; } - if (theme->snapping_overlay_region_border_color[0][0] == FLT_MIN) { + if (theme->snapping_overlay_region.border_color[0][0] == FLT_MIN) { fill_colors_with_osd_theme(theme, - theme->snapping_overlay_region_border_color); + theme->snapping_overlay_region.border_color); } - if (theme->snapping_overlay_edge_border_color[0][0] == FLT_MIN) { + if (theme->snapping_overlay_edge.border_color[0][0] == FLT_MIN) { fill_colors_with_osd_theme(theme, - theme->snapping_overlay_edge_border_color); + theme->snapping_overlay_edge.border_color); } } void -theme_init(struct theme *theme, const char *theme_name) +theme_init(struct theme *theme, struct server *server, const char *theme_name) { /* * Set some default values. This is particularly important on * reconfigure as not all themes set all options */ - theme_builtin(theme); + theme_builtin(theme, server); /* Read /share/themes/$theme_name/openbox-3/themerc */ struct wl_list paths;