Add support to drag and resize floating window panes.

This commit is contained in:
Michael Grant 2025-10-30 21:42:32 +01:00
parent 39d2839e37
commit 34e858ea05
4 changed files with 152 additions and 5 deletions

View File

@ -29,7 +29,9 @@
static enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmdq_item *);
static void cmd_resize_pane_mouse_update(struct client *,
static void cmd_resize_pane_mouse_update_floating(struct client *,
struct mouse_event *);
static void cmd_resize_pane_mouse_update_tiled(struct client *,
struct mouse_event *);
const struct cmd_entry cmd_resize_pane_entry = {
@ -80,8 +82,13 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
if (c == NULL || c->session != s)
return (CMD_RETURN_NORMAL);
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
cmd_resize_pane_mouse_update(c, &event->m);
if (c->tty.mouse_wp->layout_cell != NULL) {
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_tiled;
cmd_resize_pane_mouse_update_tiled(c, &event->m);
} else {
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_floating;
cmd_resize_pane_mouse_update_floating(c, &event->m);
}
return (CMD_RETURN_NORMAL);
}
@ -149,7 +156,125 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
}
static void
cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
cmd_resize_pane_mouse_update_floating(struct client *c, struct mouse_event *m)
{
struct winlink *wl;
struct window *w;
struct window_pane *wp;
u_int y, ly, x, lx, new_sx, new_sy;
wl = cmd_mouse_window(m, NULL);
if (wl == NULL) {
c->tty.mouse_drag_update = NULL;
return;
}
w = wl->window;
y = m->y + m->oy; x = m->x + m->ox;
if (m->statusat == 0 && y >= m->statuslines)
y -= m->statuslines;
else if (m->statusat > 0 && y >= (u_int)m->statusat)
y = m->statusat - 1;
ly = m->ly + m->oy; lx = m->lx + m->ox;
if (m->statusat == 0 && ly >= m->statuslines)
ly -= m->statuslines;
else if (m->statusat > 0 && ly >= (u_int)m->statusat)
ly = m->statusat - 1;
wp = c->tty.mouse_wp;
log_debug("%s: %%%u resize_pane xoff=%u sx=%u xy=%ux%u lxy=%ux%u",
__func__, wp->id, wp->xoff, wp->sx, x, y, lx, ly);
if (((m->lx == wp->xoff - 1) || (m->lx == wp->xoff)) &&
(m->ly == wp->yoff - 1)) {
/* Top left border */
new_sx = wp->sx + (lx - x);
if (new_sx < PANE_MINIMUM)
new_sx = PANE_MINIMUM;
new_sy = wp->sy + (ly - y);
if (new_sy < PANE_MINIMUM)
new_sy = PANE_MINIMUM;
window_pane_move(wp, x + 1, y + 1);
window_pane_resize(wp, new_sx, new_sy);
server_redraw_window(w);
} else if (((m->lx == wp->xoff + wp->sx + 1) ||
(m->lx == wp->xoff + wp->sx)) &&
(m->ly == wp->yoff - 1)) {
/* Top right border */
new_sx = x - wp->xoff - 1;
if (new_sx < PANE_MINIMUM)
new_sx = PANE_MINIMUM;
new_sy = wp->sy + (ly - y);
if (new_sy < PANE_MINIMUM)
new_sy = PANE_MINIMUM;
window_pane_move(wp, wp->xoff, y + 1);
window_pane_resize(wp, new_sx, new_sy);
server_redraw_window(w);
} else if (((m->lx == wp->xoff - 1) || (m->lx == wp->xoff)) &&
(m->ly == wp->yoff + wp->sy)) {
/* Bottom left border */
new_sx = wp->sx + (lx - x);
if (new_sx < PANE_MINIMUM)
new_sx = PANE_MINIMUM;
new_sy = y - wp->yoff;
if (new_sy < PANE_MINIMUM)
return;
window_pane_move(wp, x + 1, wp->yoff);
window_pane_resize(wp, new_sx, new_sy);
server_redraw_window(w);
} else if (((m->lx == wp->xoff + wp->sx + 1) ||
(m->lx == wp->xoff + wp->sx)) &&
(m->ly == wp->yoff + wp->sy)) {
/* Bottom right corner */
new_sx = x - wp->xoff - 1;
if (new_sx < PANE_MINIMUM)
new_sx = PANE_MINIMUM;
new_sy = y - wp->yoff;
if (new_sy < PANE_MINIMUM)
new_sy = PANE_MINIMUM;
window_pane_resize(wp, new_sx, new_sy);
server_redraw_window(w);
} else if (m->lx == wp->xoff + wp->sx + 1) {
/* Right border */
new_sx = x - wp->xoff - 1;
if (new_sx < PANE_MINIMUM)
return;
window_pane_resize(wp, new_sx, wp->sy);
server_redraw_window(w);
} else if (m->lx == wp->xoff - 1) {
/* Left border */
new_sx = wp->sx + (lx - x);
if (new_sx < PANE_MINIMUM)
return;
window_pane_move(wp, x + 1, wp->yoff);
window_pane_resize(wp, new_sx, wp->sy);
server_redraw_window(w);
} else if (m->ly == wp->yoff + wp->sy) {
/* Bottom border */
new_sy = y - wp->yoff;
if (new_sy < PANE_MINIMUM)
return;
window_pane_resize(wp, wp->sx, new_sy);
server_redraw_window(w);
} else if (m->ly == wp->yoff - 1) {
/* Top border */
window_pane_move(wp, wp->xoff + (x - lx), y + 1);
/*
new_sy = wp->sy + (ly - y);
if (new_sy < PANE_MINIMUM)
return;
window_pane_move(wp, wp->xoff, y + 1);
window_pane_resize(wp, wp->sx, new_sy);
*/
server_redraw_window(w);
} else {
log_debug("%s: %%%u resize_pane xoff=%u sx=%u xy=%ux%u lxy=%ux%u <else>",
__func__, wp->id, wp->xoff, wp->sx, x, y, lx, ly);
}
}
static void
cmd_resize_pane_mouse_update_tiled(struct client *c, struct mouse_event *m)
{
struct winlink *wl;
struct window *w;

View File

@ -637,6 +637,10 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
return (SCROLLBAR_SLIDER);
} else /* py > sl_bottom */
return (SCROLLBAR_DOWN);
} else if (wp->layout_cell == NULL &&
(px == wp->xoff - 1 || py == wp->yoff -1)) {
/* Floating pane left or top border. */
return (BORDER);
} else {
/* Must be inside the pane. */
return (PANE);
@ -1063,6 +1067,7 @@ have_event:
break;
}
c->tty.mouse_drag_flag = 0;
c->tty.mouse_wp = NULL;
c->tty.mouse_slider_mpos = -1;
goto out;
}
@ -1281,6 +1286,10 @@ have_event:
* where the user grabbed.
*/
c->tty.mouse_drag_flag = MOUSE_BUTTONS(b) + 1;
/* Only change pane if not already dragging a pane border. */
if (c->tty.mouse_wp == NULL) {
c->tty.mouse_wp = wp;
}
if (c->tty.mouse_scrolling_flag == 0 &&
where == SCROLLBAR_SLIDER) {
c->tty.mouse_scrolling_flag = 1;

3
tmux.h
View File

@ -1596,7 +1596,7 @@ struct tty {
int mouse_drag_flag;
int mouse_scrolling_flag;
int mouse_slider_mpos;
struct window_pane *mouse_wp;
void (*mouse_drag_update)(struct client *,
struct mouse_event *);
void (*mouse_drag_release)(struct client *,
@ -3266,6 +3266,7 @@ struct window_pane *window_pane_find_by_id_str(const char *);
struct window_pane *window_pane_find_by_id(u_int);
int window_pane_destroy_ready(struct window_pane *);
void window_pane_resize(struct window_pane *, u_int, u_int);
void window_pane_move(struct window_pane *, u_int, u_int);
int window_pane_set_mode(struct window_pane *,
struct window_pane *, const struct window_mode *,
struct cmd_find_state *, struct args *);

View File

@ -1117,6 +1117,18 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
wme->mode->resize(wme, sx, sy);
}
void
window_pane_move(struct window_pane *wp, u_int xoff, u_int yoff)
{
if (xoff == wp->xoff && yoff == wp->yoff)
return;
wp->xoff = xoff;
wp->yoff = yoff;
log_debug("%s: %%%u resize %ux%u", __func__, wp->id, xoff, yoff);
}
int
window_pane_set_mode(struct window_pane *wp, struct window_pane *swp,
const struct window_mode *mode, struct cmd_find_state *fs,