From f109808140cd6323b3a100663a10e048ae32e3a0 Mon Sep 17 00:00:00 2001
From: mmistika <mistikasoft@gmail.com>
Date: Thu, 17 Jul 2025 11:59:18 +0200
Subject: [PATCH] Add configurable window resize

Signed-off-by: mmistika <mistikasoft@gmail.com>
---
 config.def.h | 12 ++++++++++++
 dwl.c        | 45 +++++++++++++++++++++++++++++++++++++--------
 2 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/config.def.h b/config.def.h
index 22d2171..e404549 100644
--- a/config.def.h
+++ b/config.def.h
@@ -20,6 +20,18 @@ static const float fullscreen_bg[]         = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca
 /* logging */
 static int log_level = WLR_ERROR;
 
+/* window resizing */
+/* resize_corner:
+ * 0: top-left
+ * 1: top-right
+ * 2: bottom-left
+ * 3: bottom-right
+ * 4: closest to the cursor
+ */
+static const int resize_corner = 4;
+static const int warp_cursor = 1;	/* 1: warp to corner, 0: don’t warp */
+static const int lock_cursor = 0;	/* 1: lock cursor, 0: don't lock */
+
 /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
 static const Rule rules[] = {
 	/* app_id             title       tags mask     isfloating   monitor */
diff --git a/dwl.c b/dwl.c
index c717c1d..aacd074 100644
--- a/dwl.c
+++ b/dwl.c
@@ -407,6 +407,7 @@ static KeyboardGroup *kb_group;
 static unsigned int cursor_mode;
 static Client *grabc;
 static int grabcx, grabcy; /* client-relative */
+static int rzcorner;
 
 static struct wlr_output_layout *output_layout;
 static struct wlr_box sgeom;
@@ -1873,8 +1874,24 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
 			.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);
+		int cdx = (int)round(cursor->x) - grabcx;
+		int cdy = (int)round(cursor->y) - grabcy;
+
+		const struct wlr_box box = {
+			.x      = grabc->geom.x      + (rzcorner & 1 ? 0   :  cdx),
+			.y      = grabc->geom.y      + (rzcorner & 2 ? 0   :  cdy),
+			.width  = grabc->geom.width  + (rzcorner & 1 ? cdx : -cdx),
+			.height = grabc->geom.height + (rzcorner & 2 ? cdy : -cdy)
+		};
+		resize(grabc, box, 1);
+
+		if (!lock_cursor) {
+			grabcx += cdx;
+			grabcy += cdy;
+		} else {
+			wlr_cursor_warp_closest(cursor, NULL, grabcx, grabcy);
+		}
+
 		return;
 	}
 
@@ -1920,12 +1937,24 @@ moveresize(const Arg *arg)
 		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");
+		const char *cursors[] = { "nw-resize", "ne-resize", "sw-resize", "se-resize" };
+
+		rzcorner = resize_corner;
+		grabcx = (int)round(cursor->x);
+		grabcy = (int)round(cursor->y);
+
+		if (rzcorner == 4)
+			/* identify the closest corner index */
+			rzcorner = (grabcx - grabc->geom.x < grabc->geom.x + grabc->geom.width  - grabcx ? 0 : 1)
+			         + (grabcy - grabc->geom.y < grabc->geom.y + grabc->geom.height - grabcy ? 0 : 2);
+
+		if (warp_cursor) {
+			grabcx = rzcorner & 1 ? grabc->geom.x + grabc->geom.width  : grabc->geom.x;
+			grabcy = rzcorner & 2 ? grabc->geom.y + grabc->geom.height : grabc->geom.y;
+			wlr_cursor_warp_closest(cursor, NULL, grabcx, grabcy);
+		}
+
+		wlr_cursor_set_xcursor(cursor, cursor_mgr, cursors[rzcorner]);
 		break;
 	}
 }
-- 
2.50.1

