diff --git a/src/config/parse_config.h b/src/config/parse_config.h index b2535b1..15857ae 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -243,6 +243,8 @@ typedef struct { int32_t idleinhibit_ignore_visible; int32_t sloppyfocus; int32_t warpcursor; + int32_t drag_corner; + int32_t drag_warp_cursor; /* keyboard */ int32_t repeat_rate; @@ -1475,6 +1477,10 @@ void parse_option(Config *config, char *key, char *value) { config->sloppyfocus = atoi(value); } else if (strcmp(key, "warpcursor") == 0) { config->warpcursor = atoi(value); + } else if (strcmp(key, "drag_corner") == 0) { + config->drag_corner = atoi(value); + } else if (strcmp(key, "drag_warp_cursor") == 0) { + config->drag_warp_cursor = atoi(value); } else if (strcmp(key, "smartgaps") == 0) { config->smartgaps = atoi(value); } else if (strcmp(key, "repeat_rate") == 0) { @@ -2757,6 +2763,8 @@ void override_config(void) { CLAMP_INT(config.idleinhibit_ignore_visible, 0, 1); sloppyfocus = CLAMP_INT(config.sloppyfocus, 0, 1); warpcursor = CLAMP_INT(config.warpcursor, 0, 1); + drag_corner = CLAMP_INT(config.drag_corner, 0, 4); + drag_warp_cursor = CLAMP_INT(config.drag_warp_cursor, 0, 1); focus_cross_monitor = CLAMP_INT(config.focus_cross_monitor, 0, 1); exchange_cross_monitor = CLAMP_INT(config.exchange_cross_monitor, 0, 1); scratchpad_cross_monitor = CLAMP_INT(config.scratchpad_cross_monitor, 0, 1); @@ -2954,6 +2962,8 @@ void set_value_default() { config.cursor_hide_timeout = cursor_hide_timeout; config.warpcursor = warpcursor; /* Warp cursor to focused client */ + config.drag_corner = drag_corner; + config.drag_warp_cursor = drag_warp_cursor; config.repeat_rate = repeat_rate; config.repeat_delay = repeat_delay; diff --git a/src/config/preset.h b/src/config/preset.h index 6f3cd89..935ea0c 100644 --- a/src/config/preset.h +++ b/src/config/preset.h @@ -101,7 +101,9 @@ int32_t overviewgappo = 30; /* overview时 窗口与窗口 缝隙大小 */ * behavior */ float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; -int32_t warpcursor = 1; /* Warp cursor to focused client */ +int32_t warpcursor = 1; +int32_t drag_corner = 3; +int32_t drag_warp_cursor = 1; int32_t xwayland_persistence = 1; /* xwayland persistence */ int32_t syncobj_enable = 0; int32_t adaptive_sync = 0; diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 95d365c..f27ed67 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -338,6 +338,9 @@ int32_t killclient(const Arg *arg) { } int32_t moveresize(const Arg *arg) { + const char *cursors[] = {"nw-resize", "ne-resize", "sw-resize", + "se-resize"}; + if (cursor_mode != CurNormal && cursor_mode != CurPressed) return 0; xytonode(cursor->x, cursor->y, NULL, &grabc, NULL, NULL, NULL); @@ -363,10 +366,29 @@ int32_t moveresize(const Arg *arg) { /* Doesn't work for X11 output - the next absolute motion event * returns the cursor to where it started */ if (grabc->isfloating) { - 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, "bottom_right_corner"); + rzcorner = drag_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 (drag_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]); } else { wlr_cursor_set_xcursor(cursor, cursor_mgr, "grab"); } diff --git a/src/mango.c b/src/mango.c index 3a2331d..f61e27f 100644 --- a/src/mango.c +++ b/src/mango.c @@ -841,6 +841,7 @@ static struct wl_list inputdevices; static struct wl_list keyboard_shortcut_inhibitors; static uint32_t cursor_mode; static Client *grabc; +static int32_t rzcorner; static int32_t grabcx, grabcy; /* client-relative */ static int32_t drag_begin_cursorx, drag_begin_cursory; /* client-relative */ static bool start_drag_window = false; @@ -3988,6 +3989,30 @@ void motionabsolute(struct wl_listener *listener, void *data) { motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy); } +void resize_floating_window(Client *grabc) { + int cdx = (int)round(cursor->x) - grabcx; + int cdy = (int)round(cursor->y) - grabcy; + + cdx = !(rzcorner & 1) && grabc->geom.width - 2 * (int)grabc->bw - cdx < 1 + ? 0 + : cdx; + cdy = !(rzcorner & 2) && grabc->geom.height - 2 * (int)grabc->bw - cdy < 1 + ? 0 + : cdy; + + 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)}; + + grabc->float_geom = box; + + resize(grabc, box, 1); + grabcx += cdx; + grabcy += cdy; +} + void motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy, double dx_unaccel, double dy_unaccel) { double sx = 0, sy = 0, sx_confined, sy_confined; @@ -4065,14 +4090,9 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx, } else if (cursor_mode == CurResize) { if (grabc->isfloating) { grabc->iscustomsize = 1; - grabc->float_geom = (struct wlr_box){ - .x = grabc->geom.x, - .y = grabc->geom.y, - .width = (int32_t)round(cursor->x) - grabc->geom.x, - .height = (int32_t)round(cursor->y) - grabc->geom.y}; if (last_apply_drap_time == 0 || time - last_apply_drap_time > drag_refresh_interval) { - resize(grabc, grabc->float_geom, 1); + resize_floating_window(grabc); last_apply_drap_time = time; } return;