Add resistance when dragging tiled windows

Adds a config option <snapping><dragResistance> with default value 20.
This prevents tiled/maximized windows from being unintentionally untiled.
This commit is contained in:
tokyo4j 2024-07-20 16:58:39 +09:00 committed by Consolatis
parent 750d37b16c
commit c202d77c2d
8 changed files with 82 additions and 4 deletions

View 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;

View 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;

View 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);

View file

@ -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;