From 7e99d8ba08c5bed2fa9e0f7d0dfda4f9267cf715 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Wed, 6 Jul 2022 07:19:28 +0200 Subject: [PATCH] SnapToRegion: Add overlay while moving and pressing a modifier --- include/labwc.h | 2 ++ include/regions.h | 2 ++ src/cursor.c | 15 +++++++++++++ src/debug.c | 4 ++-- src/desktop.c | 13 ++++++++++++ src/interactive.c | 2 ++ src/keyboard.c | 7 +++++- src/osd.c | 13 ++++++++++++ src/regions.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++- src/server.c | 2 ++ 10 files changed, 110 insertions(+), 4 deletions(-) diff --git a/include/labwc.h b/include/labwc.h index 9f728a00..230a6401 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -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; diff --git a/include/regions.h b/include/regions.h index 5717d4f8..180d83aa 100644 --- a/include/regions.h +++ b/include/regions.h @@ -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 */ diff --git a/src/cursor.c b/src/cursor.c index 3cfc6b1c..9b534e23 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -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 diff --git a/src/debug.c b/src/debug.c index 2af52ca3..9ad0910b 100644 --- a/src/debug.c +++ b/src/debug.c @@ -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); diff --git a/src/desktop.c b/src/desktop.c index 28a7518f..ce17d8d3 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -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; diff --git a/src/interactive.c b/src/interactive.c index f21c915e..bd4b87d0 100644 --- a/src/interactive.c +++ b/src/interactive.c @@ -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) { diff --git a/src/keyboard.c b/src/keyboard.c index b1aca0d4..edac5ed8 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -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); diff --git a/src/osd.c b/src/osd.c index 582842da..b1b6b843 100644 --- 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; diff --git a/src/regions.c b/src/regions.c index e7063d95..28333466 100644 --- a/src/regions.c +++ b/src/regions.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -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) { diff --git a/src/server.c b/src/server.c index e36c2880..e4c41e09 100644 --- a/src/server.c +++ b/src/server.c @@ -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); -- 2.52.0