Merge branch 'master' into floating_panes

This commit is contained in:
Nicholas Marriott
2026-05-21 12:07:17 +01:00
5 changed files with 154 additions and 126 deletions

View File

@@ -1,3 +1,8 @@
CHANGES FROM 3.6a TO 3.6b
* Remove images from the correct list when they are removed while in the
alternate screen (reported by xlabai at tencent dot com).
CHANGES FROM 3.6 TO 3.6a CHANGES FROM 3.6 TO 3.6a
* Fix a buffer overread and an infinite loop in format processing (reported by * Fix a buffer overread and an infinite loop in format processing (reported by

View File

@@ -29,10 +29,12 @@
static enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmdq_item *); static enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmdq_item *);
static void cmd_resize_pane_mouse_update_floating(struct client *, static enum cmd_retval cmd_resize_pane_mouse_update(struct cmd *,
struct mouse_event *); struct cmdq_item *);
static void cmd_resize_pane_mouse_update_tiled(struct client *, static void cmd_resize_pane_mouse_update_floating(struct client *,
struct mouse_event *); struct mouse_event *);
static void cmd_resize_pane_mouse_update_tiled(struct client *,
struct mouse_event *);
const struct cmd_entry cmd_resize_pane_entry = { const struct cmd_entry cmd_resize_pane_entry = {
.name = "resize-pane", .name = "resize-pane",
@@ -53,13 +55,10 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
{ {
struct args *args = cmd_get_args(self); struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item); struct cmd_find_state *target = cmdq_get_target(item);
struct key_event *event = cmdq_get_event(item);
struct window_pane *wp = target->wp; struct window_pane *wp = target->wp;
struct winlink *wl = target->wl; struct winlink *wl = target->wl;
struct window *w = wl->window; struct window *w = wl->window;
struct client *c = cmdq_get_client(item); const char *errstr;
struct session *s = target->s;
const char *errstr;
char *cause; char *cause;
u_int adjust; u_int adjust;
int x, y, status; int x, y, status;
@@ -77,23 +76,8 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
if (args_has(args, 'M')) { if (args_has(args, 'M'))
if (!event->m.valid) return (cmd_resize_pane_mouse_update(self, item));
return (CMD_RETURN_NORMAL);
wp = cmd_mouse_pane(&event->m, &s, NULL);
if (wp == NULL || c == NULL || c->session != s)
return (CMD_RETURN_NORMAL);
if (wp->flags & PANE_FLOATING) {
window_redraw_active_switch(w, wp);
window_set_active_pane(w, wp, 1);
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_floating;
cmd_resize_pane_mouse_update_floating(c, &event->m);
} else {
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_tiled;
cmd_resize_pane_mouse_update_tiled(c, &event->m);
}
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'Z')) { if (args_has(args, 'Z')) {
if (w->flags & WINDOW_ZOOMED) if (w->flags & WINDOW_ZOOMED)
@@ -158,6 +142,37 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
static enum cmd_retval
cmd_resize_pane_mouse_update(__unused struct cmd *self, struct cmdq_item *item)
{
struct cmd_find_state *target = cmdq_get_target(item);
struct key_event *event = cmdq_get_event(item);
struct window_pane *wp = target->wp;
struct winlink *wl = target->wl;
struct window *w = wl->window;
struct client *c = cmdq_get_client(item);
struct session *s = target->s;
if (!event->m.valid)
return (CMD_RETURN_NORMAL);
wp = cmd_mouse_pane(&event->m, &s, NULL);
if (wp == NULL || c == NULL || c->session != s)
return (CMD_RETURN_NORMAL);
if (~wp->flags & PANE_FLOATING) {
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_tiled;
cmd_resize_pane_mouse_update_tiled(c, &event->m);
return (CMD_RETURN_NORMAL);
}
window_redraw_active_switch(w, wp);
window_set_active_pane(w, wp, 1);
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_floating;
cmd_resize_pane_mouse_update_floating(c, &event->m);
return (CMD_RETURN_NORMAL);
}
static void static void
cmd_resize_pane_mouse_update_floating(struct client *c, struct mouse_event *m) cmd_resize_pane_mouse_update_floating(struct client *c, struct mouse_event *m)
{ {
@@ -165,8 +180,7 @@ cmd_resize_pane_mouse_update_floating(struct client *c, struct mouse_event *m)
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
struct layout_cell *lc; struct layout_cell *lc;
u_int y, ly, x, lx; int y, ly, x, lx, sx, sy, new_sx, new_sy;
int new_sx, new_sy;
int new_xoff, new_yoff, resizes = 0; int new_xoff, new_yoff, resizes = 0;
wp = cmd_mouse_pane(m, NULL, &wl); wp = cmd_mouse_pane(m, NULL, &wl);
@@ -176,108 +190,95 @@ cmd_resize_pane_mouse_update_floating(struct client *c, struct mouse_event *m)
} }
w = wl->window; w = wl->window;
lc = wp->layout_cell; lc = wp->layout_cell;
sx = wp->sx;
sy = wp->sy;
y = m->y + m->oy; x = m->x + m->ox; y = m->y + m->oy; x = m->x + m->ox;
if (m->statusat == 0 && y >= m->statuslines) if (m->statusat == 0 && y >= (int)m->statuslines)
y -= m->statuslines; y -= m->statuslines;
else if (m->statusat > 0 && y >= (u_int)m->statusat) else if (m->statusat > 0 && y >= m->statusat)
y = m->statusat - 1; y = m->statusat - 1;
ly = m->ly + m->oy; lx = m->lx + m->ox; ly = m->ly + m->oy; lx = m->lx + m->ox;
if (m->statusat == 0 && ly >= (u_int)m->statuslines) if (m->statusat == 0 && ly >= (int)m->statuslines)
ly -= m->statuslines; ly -= m->statuslines;
else if (m->statusat > 0 && ly >= (u_int)m->statusat) else if (m->statusat > 0 && ly >= m->statusat)
ly = m->statusat - 1; ly = m->statusat - 1;
log_debug("%s: %%%u resize_pane xoff=%d sx=%u xy=%ux%u lxy=%ux%u", if ((lx == wp->xoff - 1 || lx == wp->xoff) && ly == wp->yoff - 1) {
__func__, wp->id, wp->xoff, wp->sx, x, y, lx, ly); /* Top left corner. */
if ((((int)lx == wp->xoff - 1) || ((int)lx == wp->xoff)) && new_sx = lc->sx + (lx - x);
((int)ly == wp->yoff - 1)) {
/* Top left corner */
new_sx = (int)lc->sx + ((int)lx - (int)x);
if (new_sx < PANE_MINIMUM) if (new_sx < PANE_MINIMUM)
new_sx = PANE_MINIMUM; new_sx = PANE_MINIMUM;
new_sy = (int)lc->sy + ((int)ly - (int)y); new_sy = lc->sy + (ly - y);
if (new_sy < PANE_MINIMUM) if (new_sy < PANE_MINIMUM)
new_sy = PANE_MINIMUM; new_sy = PANE_MINIMUM;
new_xoff = x + 1; /* Because mouse is on border at xoff - 1 */ new_xoff = x + 1; /* because mouse is on border at xoff - 1 */
new_yoff = y + 1; new_yoff = y + 1;
layout_set_size(lc, (u_int)new_sx, (u_int)new_sy, new_xoff, new_yoff); layout_set_size(lc, new_sx, new_sy, new_xoff, new_yoff);
resizes++; resizes++;
} else if ((((int)lx == wp->xoff + (int)wp->sx + 1) || } else if ((lx == wp->xoff + sx + 1 || lx == wp->xoff + sx) &&
((int)lx == wp->xoff + (int)wp->sx)) && ly == wp->yoff - 1) {
((int)ly == wp->yoff - 1)) { /* Top right corner. */
/* Top right corner */ new_sx = x - lc->xoff;
new_sx = (int)x - lc->xoff;
if (new_sx < PANE_MINIMUM) if (new_sx < PANE_MINIMUM)
new_sx = PANE_MINIMUM; new_sx = PANE_MINIMUM;
new_sy = (int)lc->sy + ((int)ly - (int)y); new_sy = lc->sy + (ly - y);
if (new_sy < PANE_MINIMUM) if (new_sy < PANE_MINIMUM)
new_sy = PANE_MINIMUM; new_sy = PANE_MINIMUM;
new_yoff = y + 1; new_yoff = y + 1;
layout_set_size(lc, (u_int)new_sx, (u_int)new_sy, lc->xoff, new_yoff); layout_set_size(lc, new_sx, new_sy, lc->xoff, new_yoff);
resizes++; resizes++;
} else if ((((int)lx == wp->xoff - 1) || ((int)lx == wp->xoff)) && } else if ((lx == wp->xoff - 1 || lx == wp->xoff) &&
((int)ly == wp->yoff + (int)wp->sy)) { ly == wp->yoff + sy) {
/* Bottom left corner */ /* Bottom left corner. */
new_sx = (int)lc->sx + ((int)lx - (int)x); new_sx = lc->sx + (lx - x);
if (new_sx < PANE_MINIMUM) if (new_sx < PANE_MINIMUM)
new_sx = PANE_MINIMUM; new_sx = PANE_MINIMUM;
new_sy = (int)y - lc->yoff; new_sy = y - lc->yoff;
if (new_sy < PANE_MINIMUM) if (new_sy < PANE_MINIMUM)
return; return;
new_xoff = x + 1; new_xoff = x + 1;
layout_set_size(lc, (u_int)new_sx, (u_int)new_sy, new_xoff, lc->yoff); layout_set_size(lc, new_sx, new_sy, new_xoff, lc->yoff);
resizes++; resizes++;
} else if ((((int)lx == wp->xoff + (int)wp->sx + 1) || } else if ((lx == wp->xoff + sx + 1 || lx == wp->xoff + sx) &&
((int)lx == wp->xoff + (int)wp->sx)) && ly == wp->yoff + sy) {
((int)ly == wp->yoff + (int)wp->sy)) { /* Bottom right corner. */
/* Bottom right corner */ new_sx = x - lc->xoff;
new_sx = (int)x - lc->xoff;
if (new_sx < PANE_MINIMUM) if (new_sx < PANE_MINIMUM)
new_sx = PANE_MINIMUM; new_sx = PANE_MINIMUM;
new_sy = (int)y - lc->yoff; new_sy = y - lc->yoff;
if (new_sy < PANE_MINIMUM) if (new_sy < PANE_MINIMUM)
new_sy = PANE_MINIMUM; new_sy = PANE_MINIMUM;
layout_set_size(lc, (u_int)new_sx, (u_int)new_sy, lc->xoff, lc->yoff); layout_set_size(lc, new_sx, new_sy, lc->xoff, lc->yoff);
resizes++; resizes++;
} else if ((int)lx == wp->xoff + (int)wp->sx + 1) { } else if (lx == wp->xoff + sx + 1) {
/* Right border */ /* Right border. */
new_sx = (int)x - lc->xoff; new_sx = x - lc->xoff;
if (new_sx < PANE_MINIMUM) if (new_sx < PANE_MINIMUM)
return; return;
layout_set_size(lc, (u_int)new_sx, lc->sy, lc->xoff, lc->yoff); layout_set_size(lc, new_sx, lc->sy, lc->xoff, lc->yoff);
resizes++; resizes++;
} else if ((int)lx == wp->xoff - 1) { } else if (lx == wp->xoff - 1) {
/* Left border */ /* Left border. */
new_sx = (int)lc->sx + ((int)lx - (int)x); new_sx = lc->sx + (lx - x);
if (new_sx < PANE_MINIMUM) if (new_sx < PANE_MINIMUM)
return; return;
new_xoff = x + 1; new_xoff = x + 1;
layout_set_size(lc, (u_int)new_sx, lc->sy, new_xoff, lc->yoff); layout_set_size(lc, new_sx, lc->sy, new_xoff, lc->yoff);
resizes++; resizes++;
} else if ((int)ly == wp->yoff + (int)wp->sy) { } else if (ly == wp->yoff + sy) {
/* Bottom border */ /* Bottom border. */
new_sy = (int)y - lc->yoff; new_sy = y - lc->yoff;
if (new_sy < PANE_MINIMUM) if (new_sy < PANE_MINIMUM)
return; return;
layout_set_size(lc, lc->sx, (u_int)new_sy, lc->xoff, lc->yoff); layout_set_size(lc, lc->sx, new_sy, lc->xoff, lc->yoff);
resizes++; resizes++;
} else if ((int)ly == wp->yoff - 1) { } else if (ly == wp->yoff - 1) {
/* Top border (move instead of resize) */ /* Top border (move instead of resize). */
new_xoff = lc->xoff + ((int)x - (int)lx); new_xoff = lc->xoff + (x - lx);
new_yoff = y + 1; new_yoff = y + 1;
layout_set_size(lc, lc->sx, lc->sy, new_xoff, new_yoff); layout_set_size(lc, lc->sx, lc->sy, new_xoff, new_yoff);
/* To resize instead of move:
new_sy = wp->sy + (ly - y);
if (new_sy < PANE_MINIMUM)
return;
new_yoff = y + 1;
layout_set_size(lc, lc->sx, new_sy, lc->xoff, new_yoff);
*/
resizes++; resizes++;
} else {
log_debug("%s: %%%u resize_pane xoff=%d sx=%u xy=%ux%u lxy=%ux%u <else>",
__func__, wp->id, wp->xoff, wp->sx, x, y, lx, ly);
} }
if (resizes != 0) { if (resizes != 0) {
layout_fix_panes(w, NULL); layout_fix_panes(w, NULL);
@@ -292,7 +293,7 @@ cmd_resize_pane_mouse_update_tiled(struct client *c, struct mouse_event *m)
struct winlink *wl; struct winlink *wl;
struct window *w; struct window *w;
u_int y, ly, x, lx; u_int y, ly, x, lx;
static const int offsets[][2] = { static const int offsets[][2] = {
{ 0, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 },
}; };
struct layout_cell *cells[nitems(offsets)], *lc; struct layout_cell *cells[nitems(offsets)], *lc;

View File

@@ -599,7 +599,7 @@ server_client_exec(struct client *c, const char *cmd)
} }
static enum key_code_mouse_location static enum key_code_mouse_location
server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py, server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
u_int *sl_mpos) u_int *sl_mpos)
{ {
struct window *w = wp->window; struct window *w = wp->window;
@@ -630,36 +630,35 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
/* Check if point is within the pane or scrollbar. */ /* Check if point is within the pane or scrollbar. */
if (((pane_status != PANE_STATUS_OFF && if (((pane_status != PANE_STATUS_OFF &&
(int)py != pane_status_line && (int)py != wp->yoff + (int)wp->sy) || py != pane_status_line && py != wp->yoff + (int)wp->sy) ||
(wp->yoff == 0 && py < wp->sy) || (wp->yoff == 0 && py < (int)wp->sy) ||
((int)py >= wp->yoff && (int)py < wp->yoff + (int)wp->sy)) && (py >= wp->yoff && py < wp->yoff + (int)wp->sy)) &&
((sb_pos == PANE_SCROLLBARS_RIGHT && ((sb_pos == PANE_SCROLLBARS_RIGHT &&
(int)px < (int)wp->xoff + (int)wp->sx + sb_pad + sb_w) || px < wp->xoff + (int)wp->sx + sb_pad + sb_w) ||
(sb_pos == PANE_SCROLLBARS_LEFT && (sb_pos == PANE_SCROLLBARS_LEFT &&
(int)px < (int)wp->xoff + (int)wp->sx - sb_pad - sb_w))) { px < wp->xoff + (int)wp->sx - sb_pad - sb_w))) {
/* Check if in the scrollbar. */ /* Check if in the scrollbar. */
if ((sb_pos == PANE_SCROLLBARS_RIGHT && if ((sb_pos == PANE_SCROLLBARS_RIGHT &&
((int)px >= (int)wp->xoff + (int)wp->sx + sb_pad && (px >= wp->xoff + (int)wp->sx + sb_pad &&
(int)px < (int)wp->xoff + (int)wp->sx + sb_pad + sb_w)) || px < wp->xoff + (int)wp->sx + sb_pad + sb_w)) ||
(sb_pos == PANE_SCROLLBARS_LEFT && (sb_pos == PANE_SCROLLBARS_LEFT &&
((int)px >= (int)wp->xoff - sb_pad - sb_w && (px >= wp->xoff - sb_pad - sb_w &&
(int)px < (int)wp->xoff - sb_pad))) { px < wp->xoff - sb_pad))) {
/* Check where inside the scrollbar. */ /* Check where inside the scrollbar. */
sl_top = wp->yoff + wp->sb_slider_y; sl_top = wp->yoff + wp->sb_slider_y;
sl_bottom = (wp->yoff + wp->sb_slider_y + sl_bottom = (wp->yoff + wp->sb_slider_y +
wp->sb_slider_h - 1); wp->sb_slider_h - 1);
if ((int)py < sl_top) if (py < sl_top)
return (KEYC_MOUSE_LOCATION_SCROLLBAR_UP); return (KEYC_MOUSE_LOCATION_SCROLLBAR_UP);
else if ((int)py >= sl_top && else if (py >= sl_top && py <= sl_bottom) {
(int)py <= sl_bottom) {
*sl_mpos = (py - wp->sb_slider_y - wp->yoff); *sl_mpos = (py - wp->sb_slider_y - wp->yoff);
return (KEYC_MOUSE_LOCATION_SCROLLBAR_SLIDER); return (KEYC_MOUSE_LOCATION_SCROLLBAR_SLIDER);
} else /* py > sl_bottom */ } else /* py > sl_bottom */
return (KEYC_MOUSE_LOCATION_SCROLLBAR_DOWN); return (KEYC_MOUSE_LOCATION_SCROLLBAR_DOWN);
} else if (wp->flags & PANE_FLOATING && } else if (wp->flags & PANE_FLOATING &&
((int)px == wp->xoff - 1 || (px == wp->xoff - 1 ||
(int)py == wp->yoff - 1 || py == wp->yoff - 1 ||
(int)py == wp->yoff + (int)wp->sy)) { py == wp->yoff + (int)wp->sy)) {
/* Floating pane left, bottom or top border. */ /* Floating pane left, bottom or top border. */
return (KEYC_MOUSE_LOCATION_BORDER); return (KEYC_MOUSE_LOCATION_BORDER);
} else { } else {
@@ -673,33 +672,33 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
(~fwp->flags & PANE_ZOOMED)) (~fwp->flags & PANE_ZOOMED))
continue; continue;
bdr_top = fwp->yoff - 1; bdr_top = fwp->yoff - 1;
bdr_bottom = fwp->yoff + (int)fwp->sy; bdr_bottom = fwp->yoff + fwp->sy;
if (sb_pos == PANE_SCROLLBARS_LEFT) if (sb_pos == PANE_SCROLLBARS_LEFT)
bdr_right = fwp->xoff + (int)fwp->sx; bdr_right = fwp->xoff + fwp->sx;
else else {
/* PANE_SCROLLBARS_RIGHT or none. */ /* PANE_SCROLLBARS_RIGHT or none. */
bdr_right = fwp->xoff + (int)fwp->sx + bdr_right = fwp->xoff + fwp->sx + sb_pad + sb_w;
sb_pad + sb_w; }
if ((int)py >= fwp->yoff - 1 && if (py >= fwp->yoff - 1 &&
(int)py <= fwp->yoff + (int)fwp->sy) { py <= fwp->yoff + (int)fwp->sy) {
if ((int)px == bdr_right) if (px == bdr_right)
break; break;
if (wp->flags & PANE_FLOATING) { if (wp->flags & PANE_FLOATING) {
/* Floating pane, check if left border. */ /* Floating pane, check left border. */
bdr_left = fwp->xoff - 1; bdr_left = fwp->xoff - 1;
if ((int)px == bdr_left) if (px == bdr_left)
break; break;
} }
} }
if ((int)px >= fwp->xoff - 1 && if (px >= fwp->xoff - 1 &&
(int)px <= fwp->xoff + (int)fwp->sx) { px <= fwp->xoff + (int)fwp->sx) {
bdr_bottom = fwp->yoff + (int)fwp->sy; bdr_bottom = fwp->yoff + fwp->sy;
if ((int)py == bdr_bottom) if (py == bdr_bottom)
break; break;
if (wp->flags & PANE_FLOATING) { if (wp->flags & PANE_FLOATING) {
/* Floating pane, check if top border. */ /* Floating pane, check top border. */
bdr_top = fwp->yoff - 1; bdr_top = fwp->yoff - 1;
if ((int)py == bdr_top) if (py == bdr_top)
break; break;
} }
} }
@@ -989,7 +988,7 @@ have_event:
type = KEYC_TYPE_MOUSEDRAGEND; type = KEYC_TYPE_MOUSEDRAGEND;
c->tty.mouse_drag_flag = 0; c->tty.mouse_drag_flag = 0;
c->tty.mouse_slider_mpos = -1; c->tty.mouse_slider_mpos = -1;
c->tty.mouse_last_pane = -1; c->tty.mouse_last_pane = -1;
} }
/* Convert to a key binding. */ /* Convert to a key binding. */
@@ -998,7 +997,7 @@ have_event:
if (wp != NULL && if (wp != NULL &&
wp != w->active && wp != w->active &&
options_get_number(s->options, "focus-follows-mouse")) { options_get_number(s->options, "focus-follows-mouse")) {
window_redraw_active_switch(w, wp); /* xxx needed? */ window_redraw_active_switch(w, wp);
window_set_active_pane(w, wp, 1); window_set_active_pane(w, wp, 1);
server_redraw_window_borders(w); server_redraw_window_borders(w);
server_status_window(w); server_status_window(w);
@@ -1799,6 +1798,7 @@ server_client_reset_state(struct client *c)
struct options *oo = c->session->options; struct options *oo = c->session->options;
int mode = 0, cursor, flags; int mode = 0, cursor, flags;
u_int cx = 0, cy = 0, ox, oy, sx, sy, n; u_int cx = 0, cy = 0, ox, oy, sx, sy, n;
struct visible_ranges *r;
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
return; return;
@@ -1848,14 +1848,14 @@ server_client_reset_state(struct client *c)
wp->yoff + (int)s->cy <= (int)oy + (int)sy) { wp->yoff + (int)s->cy <= (int)oy + (int)sy) {
cursor = 1; cursor = 1;
cx = (u_int)(wp->xoff + (int)s->cx - (int)ox); cx = wp->xoff + (int)s->cx - (int)ox;
cy = (u_int)(wp->yoff + (int)s->cy - (int)oy); cy = wp->yoff + (int)s->cy - (int)oy;
if (status_at_line(c) == 0) if (status_at_line(c) == 0)
cy += status_line_size(c); cy += status_line_size(c);
} }
if (!screen_redraw_is_visible( r = screen_redraw_get_visible_ranges(wp, cx, cy, 1, NULL);
screen_redraw_get_visible_ranges(wp, cx, cy, 1, NULL), cx)) if (!screen_redraw_is_visible(r, cx))
cursor = 0; cursor = 0;
if (!cursor) if (!cursor)

3
tmux.h
View File

@@ -1707,6 +1707,7 @@ struct tty {
#define TTY_WINSIZEQUERY 0x1000 #define TTY_WINSIZEQUERY 0x1000
#define TTY_WAITFG 0x2000 #define TTY_WAITFG 0x2000
#define TTY_WAITBG 0x4000 #define TTY_WAITBG 0x4000
#define TTY_BRACKETPASTE 0x8000
#define TTY_ALL_REQUEST_FLAGS \ #define TTY_ALL_REQUEST_FLAGS \
(TTY_HAVEDA|TTY_HAVEDA2|TTY_HAVEXDA) (TTY_HAVEDA|TTY_HAVEDA2|TTY_HAVEXDA)
int flags; int flags;
@@ -1719,7 +1720,7 @@ struct tty {
int mouse_drag_flag; int mouse_drag_flag;
int mouse_scrolling_flag; int mouse_scrolling_flag;
int mouse_slider_mpos; int mouse_slider_mpos;
int mouse_last_pane; int mouse_last_pane;
void (*mouse_drag_update)(struct client *, void (*mouse_drag_update)(struct client *,
struct mouse_event *); struct mouse_event *);
void (*mouse_drag_release)(struct client *, void (*mouse_drag_release)(struct client *,

View File

@@ -605,6 +605,17 @@ tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size)
return (tty_keys_find1(tk, buf, len, size)); return (tty_keys_find1(tk, buf, len, size));
} }
static int
tty_keys_partial_paste_end(const char *buf, size_t len)
{
static const char paste_end[] = "\033[201~";
size_t paste_end_len = (sizeof paste_end) - 1;
if (len == 0 || len >= paste_end_len)
return (0);
return (memcmp(buf, paste_end, len) == 0);
}
/* Look up part of the next key. */ /* Look up part of the next key. */
static int static int
tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key, tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key,
@@ -630,6 +641,10 @@ tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key,
if (tk->next != NULL && !expired) if (tk->next != NULL && !expired)
return (1); return (1);
*key = tk->key; *key = tk->key;
if ((*key & KEYC_MASK_KEY) == KEYC_PASTE_START)
tty->flags |= TTY_BRACKETPASTE;
else if ((*key & KEYC_MASK_KEY) == KEYC_PASTE_END)
tty->flags &= ~TTY_BRACKETPASTE;
return (0); return (0);
} }
@@ -955,10 +970,16 @@ partial_key:
delay = options_get_number(global_options, "escape-time"); delay = options_get_number(global_options, "escape-time");
if (delay == 0) if (delay == 0)
delay = 1; delay = 1;
if ((tty->flags & TTY_BRACKETPASTE) &&
tty_keys_partial_paste_end(buf, len)) {
log_debug("%s: increasing delay (partial paste end)", c->name);
if (delay < 500)
delay = 500;
}
if ((tty->flags & (TTY_WAITFG|TTY_WAITBG) || if ((tty->flags & (TTY_WAITFG|TTY_WAITBG) ||
(tty->flags & TTY_ALL_REQUEST_FLAGS) != TTY_ALL_REQUEST_FLAGS) || (tty->flags & TTY_ALL_REQUEST_FLAGS) != TTY_ALL_REQUEST_FLAGS) ||
!TAILQ_EMPTY(&c->input_requests)) { !TAILQ_EMPTY(&c->input_requests)) {
log_debug("%s: increasing delay for active query", c->name); log_debug("%s: increasing delay (active query)", c->name);
if (delay < 500) if (delay < 500)
delay = 500; delay = 500;
} }