From: tokyo4j Date: Sat, 20 Jul 2024 07:58:39 +0000 (+0900) Subject: Add resistance when dragging tiled windows X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=c202d77c2d800abccff24b0d9a0be6b5b928bf09;p=proto%2Flabwc.git Add resistance when dragging tiled windows Adds a config option with default value 20. This prevents tiled/maximized windows from being unintentionally untiled. --- diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 746904d4..cfd46316 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -347,6 +347,10 @@ extending outward from the snapped edge. SnapToEdge action for that edge. A *range* of 0 disables snapping via interactive moves. Default is 1. +** + Sets the movement of cursor in pixel required for a tiled or maximized + window to be moved with an interactive move. Default is 20. + ** [yes|no] Show an overlay when snapping to a window to an edge. Default is yes. diff --git a/docs/rc.xml.all b/docs/rc.xml.all index c537b039..ea331352 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -125,6 +125,7 @@ 1 + 20 diff --git a/include/config/rcxml.h b/include/config/rcxml.h index 53263df7..62fb5e57 100644 --- a/include/config/rcxml.h +++ b/include/config/rcxml.h @@ -125,6 +125,7 @@ struct rcxml { int snap_overlay_delay_outer; bool snap_top_maximize; enum tiling_events_mode snap_tiling_events_mode; + int snap_drag_resistance; enum resize_indicator_mode resize_indicator; bool resize_draw_contents; diff --git a/include/labwc.h b/include/labwc.h index 77bb41d4..564f668c 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -256,7 +256,16 @@ struct server { /* cursor interactive */ enum input_mode input_mode; struct view *grabbed_view; + /* + * When an interactive move is requested for tiled/maximized views by CSD + * clients or by Drag actions, the actual motion and untiling of the view + * can be delayed to prevent the view from being unintentionally untiled. + * During this delay, move_pending is set. + */ + bool move_pending; + /* Cursor position when interactive move/resize is requested */ double grab_x, grab_y; + /* View geometry when interactive move/resize is requested */ struct wlr_box grab_box; uint32_t resize_edges; @@ -497,6 +506,15 @@ void seat_output_layout_changed(struct seat *seat); */ void interactive_anchor_to_cursor(struct view *view, struct wlr_box *geometry); +/** + * interactive_move_tiled_view_to() - Un-tile the tiled/maximized view at the + * start of an interactive move or when an interactive move is pending. + * Returns true if the distance of cursor motion exceeds the value of + * and the view is un-tiled. + */ +bool interactive_move_tiled_view_to(struct server *server, struct view *view, + struct wlr_box *geometry); + 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); diff --git a/src/config/rcxml.c b/src/config/rcxml.c index da4bb637..74388b10 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -971,6 +971,8 @@ entry(xmlNode *node, char *nodename, char *content) } else { wlr_log(WLR_ERROR, "ignoring invalid value for notifyClient"); } + } else if (!strcasecmp(nodename, "dragResistance.snapping")) { + rc.snap_drag_resistance = atoi(content); /* */ } else if (!strcasecmp(nodename, "show.windowSwitcher")) { @@ -1278,6 +1280,7 @@ rcxml_init(void) rc.snap_overlay_delay_outer = 500; rc.snap_top_maximize = true; rc.snap_tiling_events_mode = LAB_TILING_EVENTS_ALWAYS; + rc.snap_drag_resistance = 20; rc.window_switcher.show = true; rc.window_switcher.preview = true; diff --git a/src/input/cursor.c b/src/input/cursor.c index 0a705068..3df48983 100644 --- a/src/input/cursor.c +++ b/src/input/cursor.c @@ -232,9 +232,19 @@ request_set_primary_selection_notify(struct wl_listener *listener, void *data) static void process_cursor_move(struct server *server, uint32_t time) { + struct view *view = server->grabbed_view; + + /* + * Un-tile the view when interactive move is delayed and the distance + * of cursor movement exceeds . + */ + if (server->move_pending && !interactive_move_tiled_view_to( + server, server->grabbed_view, &server->grab_box)) { + return; + } + double dx = server->seat.cursor->x - server->grab_x; double dy = server->seat.cursor->y - server->grab_y; - struct view *view = server->grabbed_view; /* Move the grabbed view to the new position. */ dx += server->grab_box.x; diff --git a/src/interactive.c b/src/interactive.c index ae5a6972..bd9745a0 100644 --- a/src/interactive.c +++ b/src/interactive.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only +#include #include "edges.h" #include "input/keyboard.h" #include "labwc.h" @@ -31,6 +32,38 @@ interactive_anchor_to_cursor(struct view *view, struct wlr_box *geometry) view->current.height, geometry->height); } +bool +interactive_move_tiled_view_to(struct server *server, struct view *view, + struct wlr_box *geometry) +{ + assert(!view_is_floating(view)); + + int resistance = rc.snap_drag_resistance; + + if (server->input_mode == LAB_INPUT_STATE_MOVE) { + /* When called from cursor motion handler */ + assert(server->move_pending && server->grabbed_view == view); + + double dx = server->seat.cursor->x - server->grab_x; + double dy = server->seat.cursor->y - server->grab_y; + if (dx * dx + dy * dy < resistance * resistance) { + return false; + } + } else { + /* When called from interactive_begin() */ + if (resistance > 0) { + return false; + } + } + + view_set_shade(view, false); + view_set_untiled(view); + view_restore_to(view, *geometry); + server->move_pending = false; + + return true; +} + void interactive_begin(struct view *view, enum input_mode mode, uint32_t edges) { @@ -83,9 +116,15 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges) interactive_anchor_to_cursor(view, &geometry); } - view_set_shade(view, false); - view_set_untiled(view); - view_restore_to(view, geometry); + /* + * If is non-zero, the + * tiled/maximized view is un-tiled later in cursor + * motion handler. + */ + if (!interactive_move_tiled_view_to( + server, view, &geometry)) { + server->move_pending = true; + } } else { /* Store natural geometry at start of move */ view_store_natural_geometry(view); @@ -261,6 +300,7 @@ interactive_cancel(struct view *view) view->server->input_mode = LAB_INPUT_STATE_PASSTHROUGH; view->server->grabbed_view = NULL; + view->server->move_pending = false; /* Update focus/cursor image */ cursor_update_focus(view->server); diff --git a/src/xdg.c b/src/xdg.c index f67796da..33d26645 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -94,6 +94,7 @@ do_late_positioning(struct view *view) if (server->input_mode == LAB_INPUT_STATE_MOVE && view == server->grabbed_view) { /* Keep view underneath cursor */ + /* TODO: resistance is not considered */ interactive_anchor_to_cursor(view, &view->pending); /* Update grab offsets */ server->grab_x = server->seat.cursor->x;