]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Add resistance when dragging tiled windows
authortokyo4j <hrak1529@gmail.com>
Sat, 20 Jul 2024 07:58:39 +0000 (16:58 +0900)
committerConsolatis <35009135+Consolatis@users.noreply.github.com>
Fri, 2 Aug 2024 21:40:26 +0000 (23:40 +0200)
Adds a config option <snapping><dragResistance> with default value 20.
This prevents tiled/maximized windows from being unintentionally untiled.

docs/labwc-config.5.scd
docs/rc.xml.all
include/config/rcxml.h
include/labwc.h
src/config/rcxml.c
src/input/cursor.c
src/interactive.c
src/xdg.c

index 746904d4821c8b0432779ed0a54cf80393e51b2a..cfd46316b50e9f46c2cbe74c22b2b56176fe514d 100644 (file)
@@ -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.
 
+*<snapping><dragResistance>*
+       Sets the movement of cursor in pixel required for a tiled or maximized
+       window to be moved with an interactive move. Default is 20.
+
 *<snapping><overlay><enabled>* [yes|no]
        Show an overlay when snapping to a window to an edge. Default is yes.
 
index c537b03944140dfb3575ddf81cfb73da175bb1f0..ea3313526769bb505e154ae1f0b219e45f862f87 100644 (file)
   <snapping>
     <!-- Set range to 0 to disable window snapping completely -->
     <range>1</range>
+    <dragResistance>20</dragResistance>
     <overlay enabled="yes">
       <delay inner="500" outer="500" />
     </overlay>
index 53263df766d6c297cb80f2ab4ff266a9155d8d24..62fb5e572608983bfabeaab064ee0aabbac2ca87 100644 (file)
@@ -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;
index 77bb41d4cfeee61920191cde5167111ede250508..564f668c736ca2e1303c490208d34fa4bec05387 100644 (file)
@@ -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
+ * <snapping><dragResistance> 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);
index da4bb637b75154e293978f0834e101b8c31b439e..74388b10bc5d4d18ff23b547ae7bc7984e1fe69f 100644 (file)
@@ -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);
 
        /* <windowSwitcher show="" preview="" outlines="" /> */
        } 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;
index 0a705068ffd2049b8c37162ad0a6b97eb2cf42ea..3df48983def4a3c2258afff209341629d200133a 100644 (file)
@@ -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 <snapping><dragResistance>.
+        */
+       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;
index ae5a697278694941c1bffbc63d555769cac1f195..bd9745a03fe548d165cd659a4476968455ed2bbb 100644 (file)
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
+#include <assert.h>
 #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 <snapping><dragResistance> 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);
index f67796da3627c98bf9a020f61c05aecd8fc24ecd..33d26645df5ca19366e773385a20e391b2f6580b 100644 (file)
--- 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;