From 0da26b9320d17c7271436ba77828c90cb360081e Mon Sep 17 00:00:00 2001 From: Michael Grant Date: Tue, 16 Jun 2026 18:28:00 +0200 Subject: [PATCH] Implemented move-pane -M to allow one to bind alt-mouse1-drag to move a floating pane with the mouse. --- cmd-join-pane.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++-- key-bindings.c | 1 + 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/cmd-join-pane.c b/cmd-join-pane.c index 04cc0676..9712eab5 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -30,6 +30,9 @@ */ static enum cmd_retval cmd_join_pane_exec(struct cmd *, struct cmdq_item *); +static enum cmd_retval cmd_join_pane_mouse_update(struct cmdq_item *); +static void cmd_join_pane_mouse_update_move(struct client *, + struct mouse_event *); const struct cmd_entry cmd_join_pane_entry = { .name = "join-pane", @@ -49,8 +52,8 @@ const struct cmd_entry cmd_move_pane_entry = { .name = "move-pane", .alias = "movep", - .args = { "bdfhvl:L::P:R::s:t:U::X:Y:z:", 0, 0, NULL }, - .usage = "[-bdfhv] [-D lines] [-l size] [-L columns] [-P position] " + .args = { "bdfhMvl:L::P:R::s:t:U::X:Y:z:", 0, 0, NULL }, + .usage = "[-bdfhMv] [-D lines] [-l size] [-L columns] [-P position] " "[-R columns] " CMD_SRCDST_PANE_USAGE " [-U lines] " "[-X x-position] [-Y y-position] [-z z-index]", @@ -254,6 +257,78 @@ cmd_join_pane_move(struct cmdq_item *item, struct args *args, return (CMD_RETURN_NORMAL); } +static enum cmd_retval +cmd_join_pane_mouse_update(struct cmdq_item *item) +{ + struct cmd_find_state *target = cmdq_get_target(item); + struct key_event *event = cmdq_get_event(item); + struct client *c = cmdq_get_client(item); + struct session *s = target->s; + struct winlink *wl; + struct window *w; + struct window_pane *wp; + + if (!event->m.valid) + return (CMD_RETURN_NORMAL); + wp = cmd_mouse_pane(&event->m, &s, &wl); + if (wp == NULL || c == NULL || c->session != s) + return (CMD_RETURN_NORMAL); + if (!window_pane_is_floating(wp)) + return (CMD_RETURN_NORMAL); + + w = wl->window; + window_redraw_active_switch(w, wp); + window_set_active_pane(w, wp, 1); + + /* Set up mouse_drag_update callback. */ + c->tty.mouse_drag_update = + cmd_join_pane_mouse_update_move; + cmd_join_pane_mouse_update_move(c, &event->m); + return (CMD_RETURN_NORMAL); +} + +/* + * Moves the pane by dragging. + * server-client.c calls c->tty.mouse_drag_update(c, m) which + * calls this function. + */ +static void cmd_join_pane_mouse_update_move(struct client *c, + struct mouse_event *m) +{ + struct winlink *wl; + struct window *w; + struct window_pane *wp; + struct layout_cell *lc; + int y, ly, x, lx; + + wp = cmd_mouse_pane(m, NULL, &wl); + if (wp == NULL) { + c->tty.mouse_drag_update = NULL; + return; + } + w = wl->window; + lc = wp->layout_cell; + + y = m->y + m->oy; x = m->x + m->ox; + if (m->statusat == 0 && y >= (int)m->statuslines) + y -= m->statuslines; + else if (m->statusat > 0 && y >= m->statusat) + y = m->statusat - 1; + ly = m->ly + m->oy; lx = m->lx + m->ox; + if (m->statusat == 0 && ly >= (int)m->statuslines) + ly -= m->statuslines; + else if (m->statusat > 0 && ly >= m->statusat) + ly = m->statusat - 1; + + if (x != lx || y != ly) { + lc->xoff += x - lx; + lc->yoff += y - ly; + layout_fix_panes(w, NULL); + server_redraw_window(w); + server_redraw_window_borders(w); + } +} + static enum cmd_retval cmd_join_pane_zindex(struct cmdq_item *item, struct winlink *wl, struct window_pane *wp, const char *s) @@ -314,6 +389,8 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) server_unzoom_window(dst_w); if (cmd_get_entry(self) == &cmd_move_pane_entry) { + if (args_has(args, 'M')) + return (cmd_join_pane_mouse_update(item)); if (!window_pane_is_floating(dst_wp)) { cmdq_error(item, "pane is not floating"); return (CMD_RETURN_ERROR); diff --git a/key-bindings.c b/key-bindings.c index 08d4c5f6..afdd5728 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -468,6 +468,7 @@ key_bindings_init(void) /* Mouse button 1 drag on border. */ "bind -n MouseDrag1Border { resize-pane -M }", + "bind -n M-MouseDrag1Border { move-pane -M }", /* Mouse button 1 down on status line. */ "bind -n MouseDown1Status { switch-client -t= }",