]> git.mdlowis.com Git - proto/labwc.git/commitdiff
SnapToRegion: Add dynamic overlay
authorConsolatis <35009135+Consolatis@users.noreply.github.com>
Tue, 13 Sep 2022 06:15:33 +0000 (08:15 +0200)
committerConsolatis <35009135+Consolatis@users.noreply.github.com>
Wed, 11 Jan 2023 17:52:24 +0000 (18:52 +0100)
Either uses a half transparent single rect if running
hardware accelerated or uses a solid struct multirect
outline if not.

include/labwc.h
include/regions.h
src/config/rcxml.c
src/cursor.c
src/interactive.c
src/keyboard.c
src/output.c
src/regions.c
src/server.c
src/view.c

index 230a640114ffe13abd9603102bed04984369e916..596bb0d71f261304aea649518fa5df5dd004d459 100644 (file)
@@ -47,6 +47,7 @@
 #include "cursor.h"
 #include "config/keybind.h"
 #include "config/rcxml.h"
+#include "regions.h"
 #if HAVE_NLS
 #include <libintl.h>
 #include <locale.h>
@@ -156,7 +157,9 @@ struct seat {
                struct wlr_scene_tree *icons;
        } drag;
 
-       struct wlr_scene_rect *region_overlay;
+       /* Private use by regions.c */
+       struct region *region_active;
+       struct region_overlay region_overlay;
 
        struct wl_client *active_client_while_inhibited;
        struct wl_list inputs;
@@ -312,6 +315,7 @@ struct output {
        struct wlr_box usable_area;
 
        struct wl_list regions;  /* struct region.link */
+       struct wlr_box regions_usable_area;
 
        struct lab_data_buffer *osd_buffer;
 
index f583a31072437e5fbbf61031474a698268b041db..87806123831769c6f333bc7fc619bebd076c1232 100644 (file)
@@ -2,14 +2,13 @@
 #ifndef __LABWC_REGIONS_H
 #define __LABWC_REGIONS_H
 
-//FIXME: ignore that there could be more than a single seat
-
 struct seat;
 struct view;
 struct server;
 struct output;
 struct wl_list;
 struct wlr_box;
+struct multi_rect;
 
 /* Double use: rcxml.c for config and output.c for usage */
 struct region {
@@ -23,17 +22,24 @@ struct region {
        } center;
 };
 
+struct region_overlay {
+       struct wlr_scene_tree *tree;
+       union {
+               struct wlr_scene_rect *overlay;
+               struct multi_rect *pixman_overlay;
+       };
+};
+
 /* Can be used as a cheap check to detect if there are any regions configured */
 bool regions_available(void);
 
-void regions_init(struct server *server, struct seat *seat);
 void regions_update(struct output *output);
 void regions_evacuate_output(struct output *output);
-void regions_destroy(struct wl_list *regions);
+void regions_destroy(struct seat *seat, struct wl_list *regions);
 
 struct region *regions_from_cursor(struct server *server);
 struct region *regions_from_name(const char *region_name, struct output *output);
 void regions_show_overlay(struct view *view, struct seat *seat, struct region *region);
-void regions_hide_overlay(struct server *server, struct seat *seat);
+void regions_hide_overlay(struct seat *seat);
 
 #endif /* __LABWC_REGIONS_H */
index 4341bf5c01c08bf5babc2c20728d7b13ae7940c7..068e6d3c1d6dc0e8b9bf39e9329b845a31cecaa6 100644 (file)
@@ -868,7 +868,7 @@ rcxml_finish(void)
                zfree(w);
        }
 
-       regions_destroy(&rc.regions);
+       regions_destroy(NULL, &rc.regions);
 
        /* Reset state vars for starting fresh when Reload is triggered */
        current_keybind = NULL;
index 9b534e23c92c106fd0dea18205057abd6a6f69d0..9be1e4748eb1bbac07ed3ad42ae50bfbbeec955e 100644 (file)
@@ -198,7 +198,7 @@ process_cursor_move(struct server *server, uint32_t time)
                if (region) {
                        regions_show_overlay(view, &server->seat, region);
                } else {
-                       regions_hide_overlay(server, &server->seat);
+                       regions_hide_overlay(&server->seat);
                }
        }
 }
index 3b3746f81292d8d78826fe90c019b1ecef738269..f1007441f00d9d473195dd467fe587b17cecf38b 100644 (file)
@@ -163,7 +163,7 @@ interactive_finish(struct view *view)
 {
        if (view->server->grabbed_view == view) {
                enum input_mode mode = view->server->input_mode;
-               regions_hide_overlay(view->server, &view->server->seat);
+               regions_hide_overlay(&view->server->seat);
                view->server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
                view->server->grabbed_view = NULL;
                if (mode == LAB_INPUT_STATE_MOVE) {
index edac5ed89b6139970435db732cafa1d779aae853..39414cd802f7d0a9a878011921f1a27f61a48d4f 100644 (file)
@@ -71,7 +71,7 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data)
                                workspaces_osd_hide(seat);
                        }
                        if (server->grabbed_view) {
-                               regions_hide_overlay(server, seat);
+                               regions_hide_overlay(seat);
                        }
                }
        }
index c28186aca69c67690f8c14957a502340b82b4527..fa258ba9f05bc5dc1b2aaaf138fa6bdedacc4fc8 100644 (file)
@@ -42,7 +42,7 @@ output_destroy_notify(struct wl_listener *listener, void *data)
 {
        struct output *output = wl_container_of(listener, output, destroy);
        regions_evacuate_output(output);
-       regions_destroy(&output->regions);
+       regions_destroy(&output->server->seat, &output->regions);
        wl_list_remove(&output->link);
        wl_list_remove(&output->frame.link);
        wl_list_remove(&output->destroy.link);
index 35937a2e5ebfeb80eac1213218bf65e6aef9d946..727a78c30a216c69c8c5b3268e5002b26c713b02 100644 (file)
@@ -22,22 +22,30 @@ regions_available(void)
        return !wl_list_empty(&rc.regions);
 }
 
-void
-regions_init(struct server *server, struct seat *seat)
+static void
+overlay_create(struct seat *seat)
 {
-       assert(server);
-       assert(seat);
+       assert(!seat->region_overlay.tree);
+
+       struct server *server = seat->server;
+       struct wlr_scene_tree *parent = wlr_scene_tree_create(&server->scene->tree);
 
-       float *color;
-       float solid[4] = { 0.5, 0.5, 0.7, 1 };
-       float trans[4] = { 0.25, 0.25, 0.35, 0.5 };
-       if (wlr_renderer_is_pixman(server->renderer)) {
-               color = solid;
+       seat->region_overlay.tree = parent;
+       wlr_scene_node_set_enabled(&parent->node, false);
+       if (!wlr_renderer_is_pixman(server->renderer)) {
+               /* Hardware assisted rendering: Half transparent overlay */
+               float color[4] = { 0.25, 0.25, 0.35, 0.5 };
+               seat->region_overlay.overlay = wlr_scene_rect_create(parent, 0, 0, color);
        } else {
-               color = trans;
+               /* Software rendering: 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->region_overlay.pixman_overlay = multi_rect_create(parent, colors, line_width);
        }
-       seat->region_overlay = wlr_scene_rect_create(&server->scene->tree, 0, 0, color);
-       wlr_scene_node_set_enabled(&seat->region_overlay->node, false);
 }
 
 struct region *
@@ -91,36 +99,53 @@ regions_show_overlay(struct view *view, struct seat *seat, struct region *region
        assert(view);
        assert(seat);
        assert(region);
-       static struct region *old_region;
 
-       struct wlr_scene_rect *overlay = seat->region_overlay;
-       if (old_region != region) {
-               wlr_scene_rect_set_size(overlay, region->geo.width, region->geo.height);
-               wlr_scene_node_set_position(&overlay->node, region->geo.x, region->geo.y);
-               old_region = region;
+       /* Don't show active region */
+       if (seat->region_active == region) {
+               return;
        }
-       if (overlay->node.parent != view->scene_tree->node.parent) {
-               wlr_scene_node_reparent(&overlay->node, view->scene_tree->node.parent);
-               wlr_scene_node_place_below(&overlay->node, &view->scene_tree->node);
+
+       if (!seat->region_overlay.tree) {
+               overlay_create(seat);
+       }
+
+       /* Update overlay */
+       struct server *server = seat->server;
+       struct wlr_scene_node *node = &seat->region_overlay.tree->node;
+       if (!wlr_renderer_is_pixman(server->renderer)) {
+               /* Hardware assisted rendering: Half transparent overlay */
+               wlr_scene_rect_set_size(seat->region_overlay.overlay,
+                       region->geo.width, region->geo.height);
+       } else {
+               /* Software rendering: Outlines */
+               multi_rect_set_size(seat->region_overlay.pixman_overlay,
+                       region->geo.width, region->geo.height);
        }
-       if (!overlay->node.enabled) {
-               wlr_scene_node_set_enabled(&overlay->node, true);
+       if (node->parent != view->scene_tree->node.parent) {
+               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, region->geo.x, region->geo.y);
+       wlr_scene_node_set_enabled(node, true);
+       seat->region_active = region;
 }
 
 void
-regions_hide_overlay(struct server *server, struct seat *seat)
+regions_hide_overlay(struct seat *seat)
 {
-       assert(server);
        assert(seat);
-
-       struct wlr_scene_rect *overlay = seat->region_overlay;
-       if (overlay->node.enabled) {
-               wlr_scene_node_set_enabled(&overlay->node, false);
+       if (!seat->region_active) {
+               return;
        }
-       if (overlay->node.parent != &server->scene->tree) {
-               wlr_scene_node_reparent(&overlay->node, &server->scene->tree);
+
+       struct server *server = seat->server;
+       struct wlr_scene_node *node = &seat->region_overlay.tree->node;
+
+       wlr_scene_node_set_enabled(node, false);
+       if (node->parent != &server->scene->tree) {
+               wlr_scene_node_reparent(node, &server->scene->tree);
        }
+       seat->region_active = NULL;
 }
 
 void
@@ -142,6 +167,12 @@ regions_update(struct output *output)
                }
        }
 
+       if (wlr_box_equal(&output->regions_usable_area, &usable)) {
+               /* Nothing changed */
+               return;
+       }
+       output->regions_usable_area = usable;
+
        /* Update regions */
        struct wlr_box *perc, *geo;
        wl_list_for_each(region, &output->regions, link) {
@@ -177,13 +208,16 @@ regions_evacuate_output(struct output *output)
 }
 
 void
-regions_destroy(struct wl_list *regions)
+regions_destroy(struct seat *seat, struct wl_list *regions)
 {
        assert(regions);
        struct region *region, *region_tmp;
        wl_list_for_each_safe(region, region_tmp, regions, link) {
                wl_list_remove(&region->link);
                zfree(region->name);
+               if (seat && seat->region_active == region) {
+                       seat->region_active = NULL;
+               }
                zfree(region);
        }
 }
index e4c41e0977c6e0b66a6bee315b71f5ec349c1302..e36c2880a8e735d1bdc05320a3d75d10bb1ec397 100644 (file)
@@ -20,7 +20,6 @@
 #include "labwc.h"
 #include "layers.h"
 #include "menu/menu.h"
-#include "regions.h"
 #include "theme.h"
 #include "view.h"
 #include "workspaces.h"
@@ -389,7 +388,6 @@ server_init(struct server *server)
                &server->output_power_manager_set_mode);
 
        layers_init(server);
-       regions_init(server, &server->seat);
 
 #if HAVE_XWAYLAND
        xwayland_server_init(server, compositor);
index 4e572b3a4c736c83097e8a5d2f41445267bde4a3..d8364ab66909a874113e0094a2ecc3bf39b6f6d5 100644 (file)
@@ -993,6 +993,7 @@ view_destroy(struct view *view)
                server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
                server->grabbed_view = NULL;
                need_cursor_update = true;
+               regions_hide_overlay(&server->seat);
        }
 
        if (server->focused_view == view) {