]> git.mdlowis.com Git - proto/labwc.git/commitdiff
overlay: allow to draw both/either of filled/outlined rectangle
authortokyo4j <hrak1529@gmail.com>
Sat, 20 Apr 2024 17:30:31 +0000 (02:30 +0900)
committerJohan Malm <johanmalm@users.noreply.github.com>
Mon, 22 Apr 2024 18:22:23 +0000 (19:22 +0100)
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.

docs/labwc-theme.5.scd
docs/themerc
include/overlay.h
include/theme.h
src/debug.c
src/main.c
src/overlay.c
src/server.c
src/theme.c

index 4506e125e0c4d4df5c7bb397a42d5283fca71e4e..5913dfa5bc81877b8a39940a46ac68c6b62f92c6 100644 (file)
@@ -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
index e4b6733f64257da09dadf24940b71d201feaa8a3..cb3c254a5aaf52ae1ec2e7ef58fcb0d88ffd1954 100644 (file)
@@ -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
index 5b6a58001ceb07dc16a55badf391e5ff21c66f8b..bb280f8c19ef5177a592d1fd175994c29aeb49ac 100644 (file)
@@ -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 {
index 54bb4ceb5db7b1cb12ef9eb77e7692f68286b2a0..b0bb0c875b3546c25a53b4f1b2f5c80e7f1e0da6 100644 (file)
@@ -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 <theme-dir>/<theme-name>/openbox-3/themerc
  * Note <theme-dir> 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
index 75f2f794671e0b604238136c19bc4b04ac45dadd..d5750feaab5b0c5533c39518ad6fbb6cc36754ac 100644 (file)
@@ -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 == &region_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, ' ', "<skipping children>");
                return;
        }
index 1860efa5c6fb10488c40f3a6aafcb655ed1d5472..1fdfcd3add55162b292f06ee3e584ae74e93b2c6 100644 (file)
@@ -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;
 
index 7f23ec4bf7fbbd8ba26f147b257820e492066f96..ed9446bf44a2f558618343128341c622ef738008 100644 (file)
@@ -1,62 +1,54 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #include <assert.h>
-#include <wlr/render/pixman.h>
 #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);
        }
 }
index 58b95e55adb5a79c37712a2b80927d27e1406e0c..483040191da7ec1718b09274b3034b4249410705 100644 (file)
@@ -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) {
index 44290c3722aa9ac14ca36b359413d2b96b1298a6..bc2fde4d30f7c4450e4ebb1396d26b7ff75af650 100644 (file)
@@ -17,6 +17,7 @@
 #include <string.h>
 #include <wlr/util/box.h>
 #include <wlr/util/log.h>
+#include <wlr/render/pixman.h>
 #include <strings.h>
 #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 <data-dir>/share/themes/$theme_name/openbox-3/themerc */
        struct wl_list paths;