]> git.mdlowis.com Git - proto/labwc.git/commitdiff
overlay: add snap-to-edge overlay (PR #1652)
authorHiroaki Yamamoto <hrak1529@gmail.com>
Fri, 5 Apr 2024 02:35:31 +0000 (11:35 +0900)
committerGitHub <noreply@github.com>
Fri, 5 Apr 2024 02:35:31 +0000 (04:35 +0200)
...and unify region overlay and snap-to-edge overlay into overlay.c.

Snap-to-edge overlay is delayed for 500ms to prevent flickering when
the view is dragged from an output to another (demo in discussion labwc#1613).

This also fixes a bug that region overlay is not shown when a modifier
key is re-pressed.

16 files changed:
docs/labwc-config.5.scd
docs/rc.xml.all
include/config/rcxml.h
include/labwc.h
include/overlay.h [new file with mode: 0644]
include/regions.h
src/config/rcxml.c
src/debug.c
src/input/cursor.c
src/input/keyboard.c
src/interactive.c
src/meson.build
src/output.c
src/overlay.c [new file with mode: 0644]
src/regions.c
src/view.c

index c7bfaf4cd52feb38f304b960f0ded8219c25f127..3bf8f91f3ec10a9e94375b5ac3daa186f58d380c 100644 (file)
@@ -299,6 +299,16 @@ extending outward from the snapped edge.
        SnapToEdge action for that edge. A *range* of 0 disables snapping via
        interactive moves. Default is 1.
 
+*<snapping><preview><enabled>* [yes|no]
+       Show a preview when snaping to a window to an edge. Default is yes.
+
+*<snapping><preview><delay><inner>*++
+*<snapping><preview><delay><outer>*
+       Sets the delay to show a preview when snapping a window to each type of edges.
+       Defaults are 500 ms.
+       *inner* edges are edges with an adjacent output and *outer* edges are edges
+       without an adjacent output.
+
 *<snapping><topMaximize>* [yes|no]
        If *yes*, an interactive move that snaps a window to the top edge will
        maximize the window. If *no*, snapping will behave as it does with other
index 4de36af1785c9cef40772393acdef59c9c235cb9..9d9f01883ae03a54cf6609a0ab6434e0a3d30281 100644 (file)
@@ -99,6 +99,9 @@
   <snapping>
     <!-- Set range to 0 to disable window snapping completely -->
     <range>1</range>
+    <preview enabled="yes">
+      <delay inner="500" outer="500" />
+    </preview>
     <topMaximize>yes</topMaximize>
     <notifyClient>always</notifyClient>
   </snapping>
index ac4d179518a7bb4790e8cab6895bd4fe94bcba6f..0a4f10a71a016018587929bd30433833294742f6 100644 (file)
@@ -125,6 +125,9 @@ struct rcxml {
 
        /* window snapping */
        int snap_edge_range;
+       bool snap_preview_enabled;
+       int snap_preview_delay_inner;
+       int snap_preview_delay_outer;
        bool snap_top_maximize;
        enum tiling_events_mode snap_tiling_events_mode;
 
index 83f37dcae015f355444da681676437d8751bff78..b60d7647ac74ca1bf54dfc233bc41099f8bd5290 100644 (file)
@@ -47,6 +47,7 @@
 #include "config/rcxml.h"
 #include "input/cursor.h"
 #include "input/ime.h"
+#include "overlay.h"
 #include "regions.h"
 #include "session-lock.h"
 #if HAVE_NLS
@@ -159,9 +160,7 @@ struct seat {
                struct wlr_scene_tree *icons;
        } drag;
 
-       /* Private use by regions.c */
-       struct region *region_active;
-       struct region_overlay region_overlay;
+       struct overlay overlay;
        /* Used to prevent region snapping when starting a move with A-Left */
        bool region_prevent_snap;
 
@@ -479,6 +478,8 @@ void seat_output_layout_changed(struct seat *seat);
 void interactive_begin(struct view *view, enum input_mode mode, uint32_t edges);
 void interactive_finish(struct view *view);
 void interactive_cancel(struct view *view);
+/* Possibly returns VIEW_EDGE_CENTER if <topMaximize> is yes */
+enum view_edge edge_from_cursor(struct seat *seat, struct output **dest_output);
 
 void output_init(struct server *server);
 void output_manager_init(struct server *server);
diff --git a/include/overlay.h b/include/overlay.h
new file mode 100644 (file)
index 0000000..3d56f8d
--- /dev/null
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef LABWC_OVERLAY_H
+#define LABWC_OVERLAY_H
+
+#include <wlr/util/box.h>
+#include "common/graphic-helpers.h"
+#include "regions.h"
+#include "view.h"
+
+struct overlay {
+       struct wlr_scene_tree *tree;
+       union {
+               struct wlr_scene_rect *rect;
+               struct multi_rect *pixman_rect;
+       };
+
+       /* Represents currently shown or delayed overlay */
+       struct {
+               /* Region overlay */
+               struct region *region;
+
+               /* Snap-to-edge overlay */
+               enum view_edge edge;
+               struct output *output;
+       } active;
+
+       /* For delayed snap-to-edge overlay */
+       struct wl_event_source *timer;
+};
+
+/* 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 */
+void overlay_hide(struct seat *seat);
+
+#endif
index 6638f9f3b9784d957bf14584f606def290dbca48..abe472be1b8ae876813627382aec768900bddb78 100644 (file)
@@ -25,14 +25,6 @@ struct region {
        } center;
 };
 
-struct region_overlay {
-       struct wlr_scene_tree *tree;
-       union {
-               struct wlr_scene_rect *overlay;
-               struct multi_rect *pixman_overlay;
-       };
-};
-
 /* Returns true if we should show the region overlay or snap to region */
 bool regions_should_snap(struct server *server);
 
@@ -73,7 +65,4 @@ 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 seat *seat);
-
 #endif /* LABWC_REGIONS_H */
index 62afdc6c091e33bc00dffff0650e5d6deea2b935..5e5ce68b42e84ccbfcca0657dd80d4463000b4cc 100644 (file)
@@ -907,6 +907,12 @@ entry(xmlNode *node, char *nodename, char *content)
                rc.window_edge_strength = atoi(content);
        } else if (!strcasecmp(nodename, "range.snapping")) {
                rc.snap_edge_range = atoi(content);
+       } else if (!strcasecmp(nodename, "enabled.preview.snapping")) {
+               set_bool(content, &rc.snap_preview_enabled);
+       } else if (!strcasecmp(nodename, "inner.delay.preview.snapping")) {
+               rc.snap_preview_delay_inner = atoi(content);
+       } else if (!strcasecmp(nodename, "outer.delay.preview.snapping")) {
+               rc.snap_preview_delay_outer = atoi(content);
        } else if (!strcasecmp(nodename, "topMaximize.snapping")) {
                set_bool(content, &rc.snap_top_maximize);
        } else if (!strcasecmp(nodename, "notifyClient.snapping")) {
@@ -1184,6 +1190,9 @@ rcxml_init(void)
        rc.window_edge_strength = 20;
 
        rc.snap_edge_range = 1;
+       rc.snap_preview_enabled = true;
+       rc.snap_preview_delay_inner = 500;
+       rc.snap_preview_delay_outer = 500;
        rc.snap_top_maximize = true;
        rc.snap_tiling_events_mode = LAB_TILING_EVENTS_ALWAYS;
 
index d8b9c1795b856ee5b76eb5092cdd0a8cf5aac0a3..3b79f7acfae9f0f8b44629891b36467a4d72502a 100644 (file)
@@ -136,10 +136,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.region_overlay.tree
-                       && node == &server->seat.region_overlay.tree->node) {
+       if (server->seat.overlay.tree
+                       && node == &server->seat.overlay.tree->node) {
                /* Created on-demand */
-               return "seat->region_overlay";
+               return "seat->overlay";
        }
        if (server->seat.input_method_relay->popup_tree
                        && node == &server->seat.input_method_relay->popup_tree->node) {
index eb359e717b5f4264dbed7692d855a9971a369c6a..11b71b8297f66ecd6cc839f8b0c2e8c15a01013f 100644 (file)
@@ -225,16 +225,7 @@ process_cursor_move(struct server *server, uint32_t time)
        resistance_move_apply(view, &dx, &dy);
        view_move(view, dx, dy);
 
-       /* Region overlay */
-       if (!regions_should_snap(server)) {
-               return;
-       }
-       struct region *region = regions_from_cursor(server);
-       if (region) {
-               regions_show_overlay(view, &server->seat, region);
-       } else {
-               regions_hide_overlay(&server->seat);
-       }
+       overlay_update(&server->seat);
 }
 
 static void
index 0ca6d390d586c773268c9ec1e4f82f9eb205a535..415edffde1e5baa39c7632fef9d660d8ce31897e 100644 (file)
@@ -80,11 +80,13 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data)
        if (server->input_mode == LAB_INPUT_STATE_MOVE) {
                /* Any change to the modifier state re-enable region snap */
                seat->region_prevent_snap = false;
+               /* Pressing/releasing modifier key may show/hide region overlay */
+               overlay_update(seat);
        }
 
-       if (server->osd_state.cycle_view || server->grabbed_view
+       if (server->osd_state.cycle_view
                        || seat->workspace_osd_shown_by_modifier) {
-               if (!keyboard_any_modifiers_pressed(wlr_keyboard))  {
+               if (!keyboard_any_modifiers_pressed(wlr_keyboard)) {
                        if (server->osd_state.cycle_view) {
                                if (key_state_nr_bound_keys()) {
                                        should_cancel_cycling_on_next_key_release = true;
@@ -95,9 +97,6 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data)
                        if (seat->workspace_osd_shown_by_modifier) {
                                workspaces_osd_hide(seat);
                        }
-                       if (server->grabbed_view) {
-                               regions_hide_overlay(seat);
-                       }
                }
        }
 
index a0b4f2555e06bf05e915ad763e5c7764af27b436..243aaa6a6e1baef6aa1725f23e89da40679ae1b2 100644 (file)
@@ -129,39 +129,53 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
        }
 }
 
-/* Returns true if view was snapped to any edge */
-static bool
-snap_to_edge(struct view *view)
+enum view_edge
+edge_from_cursor(struct seat *seat, struct output **dest_output)
 {
        int snap_range = rc.snap_edge_range;
        if (!snap_range) {
-               return false;
+               return VIEW_EDGE_INVALID;
        }
 
-       struct output *output = output_nearest_to_cursor(view->server);
+       struct output *output = output_nearest_to_cursor(seat->server);
        if (!output_is_usable(output)) {
                wlr_log(WLR_ERROR, "output at cursor is unusable");
-               return false;
+               return VIEW_EDGE_INVALID;
        }
+       *dest_output = output;
 
        /* Translate into output local coordinates */
-       double cursor_x = view->server->seat.cursor->x;
-       double cursor_y = view->server->seat.cursor->y;
-       wlr_output_layout_output_coords(view->server->output_layout,
+       double cursor_x = seat->cursor->x;
+       double cursor_y = seat->cursor->y;
+       wlr_output_layout_output_coords(seat->server->output_layout,
                output->wlr_output, &cursor_x, &cursor_y);
 
        struct wlr_box *area = &output->usable_area;
-       enum view_edge edge;
        if (cursor_x <= area->x + snap_range) {
-               edge = VIEW_EDGE_LEFT;
+               return VIEW_EDGE_LEFT;
        } else if (cursor_x >= area->x + area->width - snap_range) {
-               edge = VIEW_EDGE_RIGHT;
+               return VIEW_EDGE_RIGHT;
        } else if (cursor_y <= area->y + snap_range) {
-               edge = VIEW_EDGE_UP;
+               if (rc.snap_top_maximize) {
+                       return VIEW_EDGE_CENTER;
+               } else {
+                       return VIEW_EDGE_UP;
+               }
        } else if (cursor_y >= area->y + area->height - snap_range) {
-               edge = VIEW_EDGE_DOWN;
+               return VIEW_EDGE_DOWN;
        } else {
                /* Not close to any edge */
+               return VIEW_EDGE_INVALID;
+       }
+}
+
+/* Returns true if view was snapped to any edge */
+static bool
+snap_to_edge(struct view *view)
+{
+       struct output *output;
+       enum view_edge edge = edge_from_cursor(&view->server->seat, &output);
+       if (edge == VIEW_EDGE_INVALID) {
                return false;
        }
 
@@ -170,7 +184,8 @@ snap_to_edge(struct view *view)
         * Don't store natural geometry here (it was
         * stored already in interactive_begin())
         */
-       if (edge == VIEW_EDGE_UP && rc.snap_top_maximize) {
+       if (edge == VIEW_EDGE_CENTER) {
+               /* <topMaximize> */
                view_maximize(view, VIEW_AXIS_BOTH,
                        /*store_natural_geometry*/ false);
        } else {
@@ -226,7 +241,7 @@ interactive_cancel(struct view *view)
                return;
        }
 
-       regions_hide_overlay(&view->server->seat);
+       overlay_hide(&view->server->seat);
 
        resize_indicator_hide(view);
 
index a71eb06bc23e557d3e8143e2d6970f884e6913bd..e08afb822099e826a5bc0be11f046997de11fbab 100644 (file)
@@ -14,6 +14,7 @@ labwc_sources = files(
   'osd.c',
   'output.c',
   'output-virtual.c',
+  'overlay.c',
   'placement.c',
   'regions.c',
   'resistance.c',
index 605b3acb60d7d5cdb71f6d7bde09852ba25bc809..e81abaee46cd50884fb7207da9e0b5823d572967 100644 (file)
@@ -102,13 +102,17 @@ static void
 output_destroy_notify(struct wl_listener *listener, void *data)
 {
        struct output *output = wl_container_of(listener, output, destroy);
+       struct seat *seat = &output->server->seat;
        regions_evacuate_output(output);
-       regions_destroy(&output->server->seat, &output->regions);
+       regions_destroy(seat, &output->regions);
+       if (seat->overlay.active.output == output) {
+               overlay_hide(seat);
+       }
        wl_list_remove(&output->link);
        wl_list_remove(&output->frame.link);
        wl_list_remove(&output->destroy.link);
        wl_list_remove(&output->request_state.link);
-       seat_output_layout_changed(&output->server->seat);
+       seat_output_layout_changed(seat);
 
        for (size_t i = 0; i < ARRAY_SIZE(output->layer_tree); i++) {
                wlr_scene_node_destroy(&output->layer_tree[i]->node);
diff --git a/src/overlay.c b/src/overlay.c
new file mode 100644 (file)
index 0000000..04471b5
--- /dev/null
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <assert.h>
+#include <wlr/render/pixman.h>
+#include "labwc.h"
+#include "overlay.h"
+#include "view.h"
+
+static void
+create_overlay(struct seat *seat)
+{
+       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 */
+               float color[4] = { 0.25, 0.25, 0.35, 0.5 };
+               seat->overlay.rect = wlr_scene_rect_create(parent, 0, 0, color);
+       } else {
+               /* 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->overlay.pixman_rect = multi_rect_create(parent, colors, line_width);
+       }
+}
+
+static void
+show_overlay(struct seat *seat, struct wlr_box *box)
+{
+       struct server *server = seat->server;
+       struct view *view = server->grabbed_view;
+       assert(view);
+
+       if (!seat->overlay.tree) {
+               create_overlay(seat);
+       }
+
+       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);
+       } else {
+               /* Software rendering: Outlines */
+               multi_rect_set_size(seat->overlay.pixman_rect,
+                       box->width, box->height);
+       }
+       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, box->x, box->y);
+       wlr_scene_node_set_enabled(node, true);
+
+       if (seat->overlay.timer) {
+               wl_event_source_timer_update(seat->overlay.timer, 0);
+       }
+}
+
+static void
+show_region_overlay(struct seat *seat, struct region *region)
+{
+       if (region == seat->overlay.active.region) {
+               return;
+       }
+       seat->overlay.active.region = region;
+       seat->overlay.active.edge = VIEW_EDGE_INVALID;
+       seat->overlay.active.output = NULL;
+
+       show_overlay(seat, &region->geo);
+}
+
+/* TODO: share logic with view_get_edge_snap_box() */
+static struct wlr_box get_edge_snap_box(enum view_edge edge, struct output *output)
+{
+       struct wlr_box box = output_usable_area_in_layout_coords(output);
+       switch (edge) {
+       case VIEW_EDGE_RIGHT:
+               box.x += box.width / 2;
+               /* fallthrough */
+       case VIEW_EDGE_LEFT:
+               box.width /= 2;
+               break;
+       case VIEW_EDGE_DOWN:
+               box.y += box.height / 2;
+               /* fallthrough */
+       case VIEW_EDGE_UP:
+               box.height /= 2;
+               break;
+       case VIEW_EDGE_CENTER:
+               /* <topMaximize> */
+               break;
+       default:
+               /* not reached */
+               assert(false);
+       }
+       return box;
+}
+
+static int
+handle_edge_overlay_timeout(void *data)
+{
+       struct seat *seat = data;
+       assert(seat->overlay.active.edge != VIEW_EDGE_INVALID
+               && seat->overlay.active.output);
+       struct wlr_box box = get_edge_snap_box(seat->overlay.active.edge,
+               seat->overlay.active.output);
+       show_overlay(seat, &box);
+       return 0;
+}
+
+static enum wlr_direction
+get_wlr_direction(enum view_edge edge)
+{
+       switch (edge) {
+       case VIEW_EDGE_LEFT:
+               return WLR_DIRECTION_LEFT;
+       case VIEW_EDGE_RIGHT:
+               return WLR_DIRECTION_RIGHT;
+       case VIEW_EDGE_UP:
+       case VIEW_EDGE_CENTER:
+               return WLR_DIRECTION_UP;
+       case VIEW_EDGE_DOWN:
+               return WLR_DIRECTION_DOWN;
+       default:
+               /* not reached */
+               assert(false);
+               return 0;
+       }
+}
+
+static bool
+edge_has_adjacent_output_from_cursor(struct seat *seat, struct output *output,
+               enum view_edge edge)
+{
+       return wlr_output_layout_adjacent_output(
+               seat->server->output_layout, get_wlr_direction(edge),
+               output->wlr_output, seat->cursor->x, seat->cursor->y);
+}
+
+static void
+show_edge_overlay(struct seat *seat, enum view_edge edge,
+               struct output *output)
+{
+       if (!rc.snap_preview_enabled) {
+               return;
+       }
+       if (seat->overlay.active.edge == edge
+                       && seat->overlay.active.output == output) {
+               return;
+       }
+       seat->overlay.active.region = NULL;
+       seat->overlay.active.edge = edge;
+       seat->overlay.active.output = output;
+
+       int delay;
+       if (edge_has_adjacent_output_from_cursor(seat, output, edge)) {
+               delay = rc.snap_preview_delay_inner;
+       } else {
+               delay = rc.snap_preview_delay_outer;
+       }
+
+       if (delay > 0) {
+               if (!seat->overlay.timer) {
+                       seat->overlay.timer = wl_event_loop_add_timer(
+                               seat->server->wl_event_loop,
+                               handle_edge_overlay_timeout, seat);
+               }
+               /* Show overlay <snapping><preview><delay>ms later */
+               wl_event_source_timer_update(seat->overlay.timer, delay);
+       } else {
+               /* Show overlay now */
+               struct wlr_box box = get_edge_snap_box(seat->overlay.active.edge,
+                       seat->overlay.active.output);
+               show_overlay(seat, &box);
+       }
+}
+
+void
+overlay_update(struct seat *seat)
+{
+       struct server *server = seat->server;
+
+       /* Region-snapping overlay */
+       if (regions_should_snap(server)) {
+               struct region *region = regions_from_cursor(server);
+               if (region) {
+                       show_region_overlay(seat, region);
+                       return;
+               }
+       }
+
+       /* Edge-snapping overlay */
+       struct output *output;
+       enum view_edge edge = edge_from_cursor(seat, &output);
+       if (edge != VIEW_EDGE_INVALID) {
+               show_edge_overlay(seat, edge, output);
+               return;
+       }
+
+       overlay_hide(seat);
+}
+
+void
+overlay_hide(struct seat *seat)
+{
+       seat->overlay.active.region = NULL;
+       seat->overlay.active.edge = VIEW_EDGE_INVALID;
+       seat->overlay.active.output = NULL;
+       if (seat->overlay.timer) {
+               wl_event_source_timer_update(seat->overlay.timer, 0);
+       }
+
+       if (!seat->overlay.tree) {
+               return;
+       }
+       struct server *server = seat->server;
+       struct wlr_scene_node *node = &seat->overlay.tree->node;
+
+       wlr_scene_node_set_enabled(node, false);
+       if (node->parent != &server->scene->tree) {
+               wlr_scene_node_reparent(node, &server->scene->tree);
+       }
+}
index f6eb6174da5dcbff9cbb3fd86cacec2fc19f1dc5..1b265fe32278112d14d12d330f2599f55c19984e 100644 (file)
@@ -5,11 +5,9 @@
 #include <float.h>
 #include <math.h>
 #include <string.h>
-#include <wlr/render/pixman.h>
 #include <wlr/types/wlr_scene.h>
 #include <wlr/util/box.h>
 #include <wlr/util/log.h>
-#include "common/graphic-helpers.h"
 #include "common/list.h"
 #include "common/mem.h"
 #include "input/keyboard.h"
@@ -30,32 +28,6 @@ regions_should_snap(struct server *server)
        return keyboard_any_modifiers_pressed(keyboard);
 }
 
-static void
-overlay_create(struct seat *seat)
-{
-       assert(!seat->region_overlay.tree);
-
-       struct server *server = seat->server;
-       struct wlr_scene_tree *parent = wlr_scene_tree_create(&server->scene->tree);
-
-       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 {
-               /* 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);
-       }
-}
-
 struct region *
 regions_from_name(const char *region_name, struct output *output)
 {
@@ -101,61 +73,6 @@ regions_from_cursor(struct server *server)
        return closest_region;
 }
 
-void
-regions_show_overlay(struct view *view, struct seat *seat, struct region *region)
-{
-       assert(view);
-       assert(seat);
-       assert(region);
-
-       /* Don't show active region */
-       if (seat->region_active == region) {
-               return;
-       }
-
-       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 (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 seat *seat)
-{
-       assert(seat);
-       if (!seat->region_active) {
-               return;
-       }
-
-       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
 regions_reconfigure_output(struct output *output)
 {
@@ -246,10 +163,10 @@ regions_destroy(struct seat *seat, struct wl_list *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;
+               if (seat && seat->overlay.active.region == region) {
+                       overlay_hide(seat);
                }
+               zfree(region->name);
                zfree(region);
        }
 }
index 066b8427e8064040394693089754f36e2279a71e..6e8a77691b79fd2a5078f6b1554cf877b2f3417b 100644 (file)
@@ -2223,7 +2223,7 @@ view_destroy(struct view *view)
                /* Application got killed while moving around */
                server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
                server->grabbed_view = NULL;
-               regions_hide_overlay(&server->seat);
+               overlay_hide(&server->seat);
        }
 
        if (server->active_view == view) {