]> git.mdlowis.com Git - proto/labwc.git/commitdiff
SnapToRegion: Add overlay while moving and pressing a modifier
authorConsolatis <35009135+Consolatis@users.noreply.github.com>
Wed, 6 Jul 2022 05:19:28 +0000 (07:19 +0200)
committerConsolatis <35009135+Consolatis@users.noreply.github.com>
Wed, 11 Jan 2023 17:52:24 +0000 (18:52 +0100)
include/labwc.h
include/regions.h
src/cursor.c
src/debug.c
src/desktop.c
src/interactive.c
src/keyboard.c
src/osd.c
src/regions.c
src/server.c

index 9f728a005fc850ff30543cec1e7fd3140bd65f6c..230a640114ffe13abd9603102bed04984369e916 100644 (file)
@@ -156,6 +156,8 @@ struct seat {
                struct wlr_scene_tree *icons;
        } drag;
 
+       struct wlr_scene_rect *region_overlay;
+
        struct wl_client *active_client_while_inhibited;
        struct wl_list inputs;
        struct wl_listener new_input;
index 5717d4f8ba843a9a83219231380b2eaf40fdb8a9..180d83aa4fdddd5b243fc098a2801098c581eb69 100644 (file)
@@ -32,5 +32,7 @@ void regions_destroy(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);
 
 #endif /* __LABWC_REGIONS_H */
index 3cfc6b1cf49a5b527054e9a50d076822c4499320..9b534e23c92c106fd0dea18205057abd6a6f69d0 100644 (file)
@@ -12,6 +12,7 @@
 #include "dnd.h"
 #include "labwc.h"
 #include "menu/menu.h"
+#include "regions.h"
 #include "resistance.h"
 #include "ssd.h"
 #include "view.h"
@@ -186,6 +187,20 @@ process_cursor_move(struct server *server, uint32_t time)
        dy += server->grab_box.y;
        resistance_move_apply(view, &dx, &dy);
        view_move(view, dx, dy);
+
+       /* Region overlay */
+       if (!regions_available()) {
+               return;
+       }
+       struct wlr_keyboard *keyboard = &server->seat.keyboard_group->keyboard;
+       if (keyboard_any_modifiers_pressed(keyboard)) {
+               struct region *region = regions_from_cursor(server);
+               if (region) {
+                       regions_show_overlay(view, &server->seat, region);
+               } else {
+                       regions_hide_overlay(server, &server->seat);
+               }
+       }
 }
 
 static void
index 2af52ca3c4104b2ace8545019e297942d2900094..9ad0910b7a2bcc7a2821d4a37de67cbfd593761b 100644 (file)
@@ -110,10 +110,10 @@ get_special(struct server *server, struct wlr_scene_node *node)
 #endif
        struct wlr_scene_tree *grand_parent =
                node->parent ? node->parent->node.parent : NULL;
-       if (grand_parent == server->view_tree) {
+       if (grand_parent == server->view_tree && node->data) {
                last_view = node_view_from_node(node);
        }
-       if (node->parent == server->view_tree_always_on_top) {
+       if (node->parent == server->view_tree_always_on_top && node->data) {
                last_view = node_view_from_node(node);
        }
        const char *view_part = get_view_part(last_view, node);
index 28a7518f0bcb34bb314da39bf8831b9a7e6df554..ce17d8d3f56d91e0be93536aa416cf0a2ed89d5a 100644 (file)
@@ -135,6 +135,10 @@ first_view(struct server *server)
        struct wl_list *list_head =
                &server->workspace_current->tree->children;
        wl_list_for_each_reverse(node, list_head, link) {
+               if (!node->data) {
+                       /* We found some non-view, most likely the region overlay */
+                       continue;
+               }
                struct view *view = node_view_from_node(node);
                if (isfocusable(view)) {
                        return view;
@@ -200,6 +204,11 @@ desktop_cycle_view(struct server *server, struct view *start_view,
                        list_item = iter(list_item);
                }
                node = wl_container_of(list_item, node, link);
+               if (!node->data) {
+                       /* We found some non-view, most likely the region overlay */
+                       view = NULL;
+                       continue;
+               }
                view = node_view_from_node(node);
                if (isfocusable(view)) {
                        return view;
@@ -218,6 +227,10 @@ topmost_mapped_view(struct server *server)
        struct wlr_scene_node *node;
        node_list = &server->workspace_current->tree->children;
        wl_list_for_each_reverse(node, node_list, link) {
+               if (!node->data) {
+                       /* We found some non-view, most likely the region overlay */
+                       continue;
+               }
                view = node_view_from_node(node);
                if (view->mapped) {
                        return view;
index f21c915eb0563091dd47bab6ebd7622f63353345..bd4b87d00ea86ee6fa45b234ea3c9b374c599b27 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #include "labwc.h"
+#include "regions.h"
 #include "view.h"
 
 static int
@@ -141,6 +142,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);
                view->server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
                view->server->grabbed_view = NULL;
                if (mode == LAB_INPUT_STATE_MOVE) {
index b1aca0d4ce2cc0f0d6243cffe651b8f30e591c7b..edac5ed89b6139970435db732cafa1d779aae853 100644 (file)
@@ -5,6 +5,7 @@
 #include "action.h"
 #include "key-state.h"
 #include "labwc.h"
+#include "regions.h"
 #include "workspaces.h"
 
 static bool should_cancel_cycling_on_next_key_release;
@@ -55,7 +56,8 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data)
        struct wlr_keyboard_key_event *event = data;
        struct wlr_keyboard *wlr_keyboard = keyboard->wlr_keyboard;
 
-       if (server->osd_state.cycle_view || seat->workspace_osd_shown_by_modifier) {
+       if (server->osd_state.cycle_view || server->grabbed_view
+                       || seat->workspace_osd_shown_by_modifier) {
                if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED
                                && !keyboard_any_modifiers_pressed(wlr_keyboard))  {
                        if (server->osd_state.cycle_view) {
@@ -68,6 +70,9 @@ 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(server, seat);
+                       }
                }
        }
        wlr_seat_keyboard_notify_modifiers(seat->seat, &wlr_keyboard->modifiers);
index 582842da01b70b30ec54fe3de93ca8e52748de83..b1b6b843b21a1a104a29e0e1a3b6064ff30bffa0 100644 (file)
--- a/src/osd.c
+++ b/src/osd.c
@@ -66,6 +66,10 @@ get_osd_height(struct wl_list *node_list)
        struct view *view;
        struct wlr_scene_node *node;
        wl_list_for_each(node, node_list, link) {
+               if (!node->data) {
+                       /* We found some non-view, most likely the region overlay */
+                       continue;
+               }
                view = node_view_from_node(node);
                if (!isfocusable(view)) {
                        continue;
@@ -215,6 +219,11 @@ preview_cycled_view(struct view *view)
        osd_state->preview_node = &view->scene_tree->node;
        osd_state->preview_anchor = lab_wlr_scene_get_prev_node(
                osd_state->preview_node);
+       while (osd_state->preview_anchor && !osd_state->preview_anchor->data) {
+               /* Ignore non-view nodes */
+               osd_state->preview_anchor = lab_wlr_scene_get_prev_node(
+                       osd_state->preview_anchor);
+       }
 
        /* Store node enabled / minimized state and force-enable if disabled */
        osd_state->preview_was_enabled = osd_state->preview_node->enabled;
@@ -288,6 +297,10 @@ render_osd(cairo_t *cairo, int w, int h, struct wl_list *node_list,
 
        /* Draw text for each node */
        wl_list_for_each_reverse(node, node_list, link) {
+               if (!node->data) {
+                       /* We found some non-view, most likely the region overlay */
+                       continue;
+               }
                struct view *view = node_view_from_node(node);
                if (!isfocusable(view)) {
                        continue;
index e7063d95d2c9ecf4c80f0027667c049cf6769737..283334667c8771d31e0bec7f93b18e7dd9647fe6 100644 (file)
@@ -5,6 +5,7 @@
 #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>
@@ -13,6 +14,7 @@
 #include "common/mem.h"
 #include "labwc.h"
 #include "regions.h"
+#include "view.h"
 
 bool
 regions_available(void)
@@ -23,7 +25,19 @@ regions_available(void)
 void
 regions_init(struct server *server, struct seat *seat)
 {
-       /* To be filled later */
+       assert(server);
+       assert(seat);
+
+       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;
+       } else {
+               color = trans;
+       }
+       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 *
@@ -71,6 +85,44 @@ 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);
+       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;
+       }
+       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 (!overlay->node.enabled) {
+               wlr_scene_node_set_enabled(&overlay->node, true);
+       }
+}
+
+void
+regions_hide_overlay(struct server *server, 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 (overlay->node.parent != &server->scene->tree) {
+               wlr_scene_node_reparent(&overlay->node, &server->scene->tree);
+       }
+}
+
 void
 regions_update(struct output *output)
 {
index e36c2880a8e735d1bdc05320a3d75d10bb1ec397..e4c41e0977c6e0b66a6bee315b71f5ec349c1302 100644 (file)
@@ -20,6 +20,7 @@
 #include "labwc.h"
 #include "layers.h"
 #include "menu/menu.h"
+#include "regions.h"
 #include "theme.h"
 #include "view.h"
 #include "workspaces.h"
@@ -388,6 +389,7 @@ 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);