summaryrefslogtreecommitdiffstats
path: root/dwl-patches/patches/dragresize/dragresize.patch
blob: 1e4cfe01501013bba628ac062ad63517616c7d50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
From 83ae7d4816a49f46063ab16ffecd32b2e7e61784 Mon Sep 17 00:00:00 2001
From: choc <notchoc@proton.me>
Date: Fri, 15 Sep 2023 11:45:16 +0800
Subject: [PATCH] dragresize: implement rio-like window resizing

select window to resize then drag out an area for it to occupy
---
 dwl.c | 132 +++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 98 insertions(+), 34 deletions(-)

diff --git a/dwl.c b/dwl.c
index dc0437e..843aa7a 100644
--- a/dwl.c
+++ b/dwl.c
@@ -80,7 +80,7 @@
 #define LISTEN_STATIC(E, H)     do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0)
 
 /* enums */
-enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
+enum { CurNormal, CurPressed, CurSelect, CurMove, CurResize, CurBind }; /* cursor */
 enum { XDGShell, LayerShell, X11 }; /* client types */
 enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock, NUM_LAYERS }; /* scene layers */
 #ifdef XWAYLAND
@@ -603,15 +603,21 @@ buttonpress(struct wl_listener *listener, void *data)
 
 	switch (event->state) {
 	case WLR_BUTTON_PRESSED:
-		cursor_mode = CurPressed;
 		selmon = xytomon(cursor->x, cursor->y);
-		if (locked)
+		if (locked) {
+			cursor_mode = CurPressed;
 			break;
+		}
 
-		/* Change focus if the button was _pressed_ over a client */
-		xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL);
-		if (c && (!client_is_unmanaged(c) || client_wants_focus(c)))
-			focusclient(c, 1);
+		if (cursor_mode == CurNormal)
+			cursor_mode = CurPressed;
+
+		if (cursor_mode != CurResize) {
+			/* Change focus if the button was _pressed_ over a client */
+			xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL);
+			if (c && (!client_is_unmanaged(c) || client_wants_focus(c)))
+				focusclient(c, 1);
+		}
 
 		keyboard = wlr_seat_get_keyboard(seat);
 		mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
@@ -624,17 +630,42 @@ buttonpress(struct wl_listener *listener, void *data)
 		}
 		break;
 	case WLR_BUTTON_RELEASED:
+		if (locked) {
+			cursor_mode = CurNormal;
+			break;
+		}
 		/* If you released any buttons, we exit interactive move/resize mode. */
-		/* TODO should reset to the pointer focus's current setcursor */
-		if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) {
-			wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
+		switch (cursor_mode) {
+		case CurPressed:
 			cursor_mode = CurNormal;
-			/* Drop the window off on its new monitor */
-			selmon = xytomon(cursor->x, cursor->y);
-			setmon(grabc, selmon, 0);
+		case CurNormal:
+			break;
+		case CurSelect:
 			return;
-		} else {
+		case CurResize:
+			/* a label can only be part of a statement - Wpedantic */
+			{
+				int nw = abs((int) cursor->x - grabcx);
+				int nh = abs((int) cursor->y - grabcy);
+				if (nw > 1 && nh > 1) {
+					setfloating(grabc, 1);
+					resize(grabc, (struct wlr_box){.x = MIN(ROUND(cursor->x), grabcx),
+							.y = MIN(ROUND(cursor->y), grabcy),
+							.width = nw, .height = nh}, 1);
+				}
+			}
+			/* fallthrough */
+		default:
+			/* TODO should reset to the pointer focus's current setcursor */
+			wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
+			/* Drop the window off on its new monitor */
+			if (grabc && cursor_mode != CurBind) {
+				selmon = xytomon(cursor->x, cursor->y);
+				setmon(grabc, selmon, 0);
+				grabc = NULL;
+			}
 			cursor_mode = CurNormal;
+			return;
 		}
 		break;
 	}
@@ -1815,15 +1846,33 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
 	wlr_scene_node_set_position(&drag_icon->node, (int)round(cursor->x), (int)round(cursor->y));
 
 	/* If we are currently grabbing the mouse, handle and return */
-	if (cursor_mode == CurMove) {
+	switch (cursor_mode) {
+	case CurSelect:
+		return;
+	case CurMove:
 		/* Move the grabbed client to the new position. */
 		resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy,
 			.width = grabc->geom.width, .height = grabc->geom.height}, 1);
 		return;
-	} else if (cursor_mode == CurResize) {
-		resize(grabc, (struct wlr_box){.x = grabc->geom.x, .y = grabc->geom.y,
-			.width = (int)round(cursor->x) - grabc->geom.x, .height = (int)round(cursor->y) - grabc->geom.y}, 1);
-		return;
+	case CurResize:
+		{
+			int w, h, x, y;
+			if (!grabc)
+				return;
+			w = abs(grabcx - (int)round(cursor->x));
+			h = abs(grabcy - (int)round(cursor->y));
+			x = MIN(grabcx, (int)round(cursor->x)) - grabc->geom.x;
+			y = MIN(grabcy, (int)round(cursor->y)) - grabc->geom.y;
+			wlr_scene_rect_set_size(grabc->border[0], w, grabc->bw);
+			wlr_scene_rect_set_size(grabc->border[1], w, grabc->bw);
+			wlr_scene_rect_set_size(grabc->border[2], grabc->bw, h - 2 * grabc->bw);
+			wlr_scene_rect_set_size(grabc->border[3], grabc->bw, h - 2 * grabc->bw);
+			wlr_scene_node_set_position(&grabc->border[0]->node, x, y);
+			wlr_scene_node_set_position(&grabc->border[1]->node, x, y + h - grabc->bw);
+			wlr_scene_node_set_position(&grabc->border[2]->node, x, y + grabc->bw);
+			wlr_scene_node_set_position(&grabc->border[3]->node, x + w - grabc->bw, y + grabc->bw);
+			return;
+		}
 	}
 
 	/* If there's no client surface under the cursor, set the cursor image to a
@@ -1853,29 +1902,43 @@ motionrelative(struct wl_listener *listener, void *data)
 void
 moveresize(const Arg *arg)
 {
-	if (cursor_mode != CurNormal && cursor_mode != CurPressed)
-		return;
-	xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL);
-	if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen)
+	/* Consider global select bool instead of this + CurSelect enum */
+	bool selected = (cursor_mode == CurSelect);
+	if (!selected) {
+		if (cursor_mode != CurNormal && cursor_mode != CurPressed)
+			return;
+		xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL);
+	}
+
+	if (!grabc || client_is_unmanaged(grabc) || grabc->isfullscreen) {
+		grabc = NULL;
+		cursor_mode = CurNormal;
 		return;
+	}
 
-	/* Float the window and tell motionnotify to grab it */
-	setfloating(grabc, 1);
+	/* TODO: factor out selected bool */
 	switch (cursor_mode = arg->ui) {
+	case CurResize:
+		if (!selected) break;
+		grabcx = ROUND(cursor->x);
+		grabcy = ROUND(cursor->y);
+		wlr_cursor_set_xcursor(cursor, cursor_mgr, "tcross");
+		return;
 	case CurMove:
 		grabcx = (int)round(cursor->x) - grabc->geom.x;
 		grabcy = (int)round(cursor->y) - grabc->geom.y;
+		setfloating(grabc, 1);
 		wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur");
-		break;
-	case CurResize:
-		/* Doesn't work for X11 output - the next absolute motion event
-		 * returns the cursor to where it started */
-		wlr_cursor_warp_closest(cursor, NULL,
-				grabc->geom.x + grabc->geom.width,
-				grabc->geom.y + grabc->geom.height);
-		wlr_cursor_set_xcursor(cursor, cursor_mgr, "se-resize");
-		break;
+		return;
+	default:
+		grabc = NULL;
+		cursor_mode = CurNormal;
+		wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
+		return;
 	}
+
+	cursor_mode = CurSelect;
+	wlr_cursor_set_xcursor(cursor, cursor_mgr, "crosshair");
 }
 
 void
@@ -2149,6 +2212,7 @@ resize(Client *c, struct wlr_box geo, int interact)
 	wlr_scene_rect_set_size(c->border[1], c->geom.width, c->bw);
 	wlr_scene_rect_set_size(c->border[2], c->bw, c->geom.height - 2 * c->bw);
 	wlr_scene_rect_set_size(c->border[3], c->bw, c->geom.height - 2 * c->bw);
+	wlr_scene_node_set_position(&c->border[0]->node, 0, 0);
 	wlr_scene_node_set_position(&c->border[1]->node, 0, c->geom.height - c->bw);
 	wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
 	wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
-- 
2.43.0