Merge branch 'floating_panes' into floating_panes_staging

This commit is contained in:
Nicholas Marriott
2026-05-22 11:01:34 +01:00
4 changed files with 156 additions and 168 deletions

View File

@@ -185,7 +185,6 @@ popup_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
if (pd->c->flags & CLIENT_REDRAWOVERLAY) if (pd->c->flags & CLIENT_REDRAWOVERLAY)
return (0); return (0);
ttyctx->bigger = 0;
ttyctx->wox = 0; ttyctx->wox = 0;
ttyctx->woy = 0; ttyctx->woy = 0;
ttyctx->wsx = c->tty.sx; ttyctx->wsx = c->tty.sx;
@@ -208,6 +207,7 @@ popup_init_ctx_cb(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
struct popup_data *pd = ctx->arg; struct popup_data *pd = ctx->arg;
memcpy(&ttyctx->defaults, &pd->defaults, sizeof ttyctx->defaults); memcpy(&ttyctx->defaults, &pd->defaults, sizeof ttyctx->defaults);
ttyctx->flags &= ~TTY_CTX_WINDOW_BIGGER;
ttyctx->palette = &pd->palette; ttyctx->palette = &pd->palette;
ttyctx->redraw_cb = popup_redraw_cb; ttyctx->redraw_cb = popup_redraw_cb;
ttyctx->set_client_cb = popup_set_client_cb; ttyctx->set_client_cb = popup_set_client_cb;

View File

@@ -36,7 +36,6 @@ static int screen_write_overwrite(struct screen_write_ctx *,
struct grid_cell *, u_int); struct grid_cell *, u_int);
static int screen_write_combine(struct screen_write_ctx *, static int screen_write_combine(struct screen_write_ctx *,
const struct grid_cell *); const struct grid_cell *);
static int screen_write_pane_obscured(struct window_pane *);
struct screen_write_citem { struct screen_write_citem {
u_int x; u_int x;
@@ -134,7 +133,7 @@ screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
{ {
struct window_pane *wp = ttyctx->arg; struct window_pane *wp = ttyctx->arg;
if (ttyctx->allow_invisible_panes) { if (ttyctx->flags & TTY_CTX_INVISIBLE_PANES) {
if (session_has(c->session, wp->window)) if (session_has(c->session, wp->window))
return (1); return (1);
return (0); return (0);
@@ -158,8 +157,11 @@ screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
return (-1); return (-1);
} }
ttyctx->bigger = tty_window_offset(&c->tty, &ttyctx->wox, &ttyctx->woy, if (tty_window_offset(&c->tty, &ttyctx->wox, &ttyctx->woy, &ttyctx->wsx,
&ttyctx->wsx, &ttyctx->wsy); &ttyctx->wsy))
ttyctx->flags |= TTY_CTX_WINDOW_BIGGER;
else
ttyctx->flags &= ~TTY_CTX_WINDOW_BIGGER;
ttyctx->xoff = ttyctx->rxoff = wp->xoff; ttyctx->xoff = ttyctx->rxoff = wp->xoff;
ttyctx->yoff = ttyctx->ryoff = wp->yoff; ttyctx->yoff = ttyctx->ryoff = wp->yoff;
@@ -170,10 +172,43 @@ screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
return (1); return (1);
} }
/* Return 1 if there is a floating window pane overlapping this pane. */
static int
screen_write_pane_is_obscured(struct screen_write_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
if (ctx->wp == NULL)
return (0);
if (ctx->flags & SCREEN_WRITE_CHECKED_IF_OBSCURED) {
if (ctx->flags & SCREEN_WRITE_OBSCURED)
return (1);
return (0);
}
ctx->flags |= SCREEN_WRITE_CHECKED_IF_OBSCURED;
while ((wp = TAILQ_PREV(wp, window_panes, zentry)) != NULL) {
if ((wp->flags & PANE_FLOATING) &&
((wp->yoff >= ctx->wp->yoff &&
wp->yoff <= ctx->wp->yoff + (int)ctx->wp->sy) ||
(wp->yoff + (int)wp->sy >= ctx->wp->yoff &&
wp->yoff + wp->sy <= ctx->wp->yoff + ctx->wp->sy)) &&
((wp->xoff >= ctx->wp->xoff &&
wp->xoff <= ctx->wp->xoff + (int)ctx->wp->sx) ||
(wp->xoff + (int)wp->sx >= ctx->wp->xoff &&
wp->xoff + wp->sx <= ctx->wp->xoff + ctx->wp->sx))) {
ctx->flags |= SCREEN_WRITE_OBSCURED;
return (1);
}
}
return (0);
}
/* Set up context for TTY command. */ /* Set up context for TTY command. */
static void static void
screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
int sync) int is_sync, int check_obscured)
{ {
struct screen *s = ctx->s; struct screen *s = ctx->s;
@@ -188,6 +223,9 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
ttyctx->orlower = s->rlower; ttyctx->orlower = s->rlower;
ttyctx->orupper = s->rupper; ttyctx->orupper = s->rupper;
if (check_obscured && screen_write_pane_is_obscured(ctx))
ttyctx->flags |= TTY_CTX_PANE_OBSCURED;
memcpy(&ttyctx->defaults, &grid_default_cell, sizeof ttyctx->defaults); memcpy(&ttyctx->defaults, &grid_default_cell, sizeof ttyctx->defaults);
if (ctx->init_ctx_cb != NULL) { if (ctx->init_ctx_cb != NULL) {
ctx->init_ctx_cb(ctx, ttyctx); ctx->init_ctx_cb(ctx, ttyctx);
@@ -214,13 +252,14 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
* move the cursor); for other panes, always use it, since the * move the cursor); for other panes, always use it, since the
* cursor will have to move. * cursor will have to move.
*/ */
if (ctx->wp != NULL) { if (ctx->wp != NULL && ctx->wp != ctx->wp->window->active)
if (ctx->wp != ctx->wp->window->active) ttyctx->flags |= TTY_CTX_SYNC;
ttyctx->num = 1; else {
else if (ctx->wp == NULL)
ttyctx->num = sync; ttyctx->flags |= TTY_CTX_OVERLAY_SYNC;
} else if (is_sync)
ttyctx->num = 0x10|sync; ttyctx->flags |= TTY_CTX_SYNC;
}
tty_write(tty_cmd_syncstart, ttyctx); tty_write(tty_cmd_syncstart, ttyctx);
ctx->flags |= SCREEN_WRITE_SYNC; ctx->flags |= SCREEN_WRITE_SYNC;
} }
@@ -573,6 +612,7 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src,
struct window_pane *wp = ctx->wp; struct window_pane *wp = ctx->wp;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
struct grid *gd = src->grid; struct grid *gd = src->grid;
struct grid_line *gl, *sgl;
struct grid_cell gc; struct grid_cell gc;
u_int xx, yy, cx = s->cx, cy = s->cy; u_int xx, yy, cx = s->cx, cy = s->cy;
int yoff = 0; int yoff = 0;
@@ -585,28 +625,26 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src,
if (yy >= gd->hsize + gd->sy) if (yy >= gd->hsize + gd->sy)
break; break;
s->cx = cx; s->cx = cx;
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0, 0);
if (wp != NULL) { if (wp != NULL)
yoff = wp->yoff; yoff = wp->yoff;
}
r = screen_redraw_get_visible_ranges(wp, px, s->cy + yoff, nx, r = screen_redraw_get_visible_ranges(wp, px, s->cy + yoff, nx,
NULL); NULL);
for (xx = px; xx < px + nx; xx++) { for (xx = px; xx < px + nx; xx++) {
if (xx >= grid_get_line(gd, yy)->cellsize && gl = grid_get_line(gd, yy);
s->cx >= grid_get_line(ctx->s->grid, sgl = grid_get_line(ctx->s->grid, s->cy);
s->cy)->cellsize) if (xx >= gl->cellsize && s->cx >= sgl->cellsize)
break; break;
grid_get_cell(gd, xx, yy, &gc); grid_get_cell(gd, xx, yy, &gc);
if (xx + gc.data.width > px + nx) if (xx + gc.data.width > px + nx)
break; break;
grid_view_set_cell(ctx->s->grid, s->cx, s->cy, &gc); grid_view_set_cell(ctx->s->grid, s->cx, s->cy, &gc);
if (wp != NULL) { if (!screen_redraw_is_visible(r, px))
if (! screen_redraw_is_visible(r, px))
break; break;
ttyctx.cell = &gc; ttyctx.cell = &gc;
ttyctx.flags &= (TTY_CTX_OVERLAY_SYNC|TTY_CTX_SYNC);
tty_write(tty_cmd_cell, &ttyctx); tty_write(tty_cmd_cell, &ttyctx);
ttyctx.ocx++; ttyctx.ocx++;
}
s->cx++; s->cx++;
} }
s->cy++; s->cy++;
@@ -1097,7 +1135,7 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
s->rupper = 0; s->rupper = 0;
s->rlower = screen_size_y(s) - 1; s->rlower = screen_size_y(s) - 1;
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 1);
screen_write_collect_clear(ctx, 0, screen_size_y(s) - 1); screen_write_collect_clear(ctx, 0, screen_size_y(s) - 1);
tty_write(tty_cmd_alignmenttest, &ttyctx); tty_write(tty_cmd_alignmenttest, &ttyctx);
@@ -1126,9 +1164,8 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
ctx->wp->flags |= PANE_REDRAW; ctx->wp->flags |= PANE_REDRAW;
#endif #endif
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
grid_view_insert_cells(s->grid, s->cx, s->cy, nx, bg); grid_view_insert_cells(s->grid, s->cx, s->cy, nx, bg);
@@ -1160,9 +1197,8 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
ctx->wp->flags |= PANE_REDRAW; ctx->wp->flags |= PANE_REDRAW;
#endif #endif
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
grid_view_delete_cells(s->grid, s->cx, s->cy, nx, bg); grid_view_delete_cells(s->grid, s->cx, s->cy, nx, bg);
@@ -1194,7 +1230,7 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
ctx->wp->flags |= PANE_REDRAW; ctx->wp->flags |= PANE_REDRAW;
#endif #endif
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0, 0);
ttyctx.bg = bg; ttyctx.bg = bg;
grid_view_clear(s->grid, s->cx, s->cy, nx, 1, bg); grid_view_clear(s->grid, s->cx, s->cy, nx, 1, bg);
@@ -1230,9 +1266,8 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
if (ny == 0) if (ny == 0)
return; return;
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
grid_view_insert_lines(gd, s->cy, ny, bg); grid_view_insert_lines(gd, s->cy, ny, bg);
@@ -1247,11 +1282,8 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
if (ny == 0) if (ny == 0)
return; return;
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
log_debug("%s: obscured=%d for pane %%%u", __func__,
ttyctx.obscured, ctx->wp != NULL ? ctx->wp->id : 0);
if (s->cy < s->rupper || s->cy > s->rlower) if (s->cy < s->rupper || s->cy > s->rlower)
grid_view_insert_lines(gd, s->cy, ny, bg); grid_view_insert_lines(gd, s->cy, ny, bg);
@@ -1287,9 +1319,8 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
if (ny == 0) if (ny == 0)
return; return;
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
grid_view_delete_lines(gd, s->cy, ny, bg); grid_view_delete_lines(gd, s->cy, ny, bg);
@@ -1304,11 +1335,8 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
if (ny == 0) if (ny == 0)
return; return;
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
log_debug("%s: obscured=%d for pane %%%u", __func__,
ttyctx.obscured, ctx->wp != NULL ? ctx->wp->id : 0);
if (s->cy < s->rupper || s->cy > s->rlower) if (s->cy < s->rupper || s->cy > s->rlower)
grid_view_delete_lines(gd, s->cy, ny, bg); grid_view_delete_lines(gd, s->cy, ny, bg);
@@ -1467,7 +1495,7 @@ screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg)
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg); grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg);
screen_write_collect_flush(ctx, 0, __func__); screen_write_collect_flush(ctx, 0, __func__);
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 0);
ttyctx.bg = bg; ttyctx.bg = bg;
tty_write(tty_cmd_reverseindex, &ttyctx); tty_write(tty_cmd_reverseindex, &ttyctx);
@@ -1578,9 +1606,8 @@ screen_write_scrolldown(struct screen_write_ctx *ctx, u_int lines, u_int bg)
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int i; u_int i;
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
if (lines == 0) if (lines == 0)
lines = 1; lines = 1;
@@ -1624,7 +1651,7 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
ctx->wp->flags |= PANE_REDRAW; ctx->wp->flags |= PANE_REDRAW;
#endif #endif
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
/* Scroll into history if it is enabled and clearing entire screen. */ /* Scroll into history if it is enabled and clearing entire screen. */
@@ -1643,7 +1670,7 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
screen_write_collect_clear(ctx, s->cy + 1, sy - (s->cy + 1)); screen_write_collect_clear(ctx, s->cy + 1, sy - (s->cy + 1));
screen_write_collect_flush(ctx, 0, __func__); screen_write_collect_flush(ctx, 0, __func__);
if (! screen_write_pane_obscured(ctx->wp)) { if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED) {
tty_write(tty_cmd_clearendofscreen, &ttyctx); tty_write(tty_cmd_clearendofscreen, &ttyctx);
return; return;
} }
@@ -1706,7 +1733,7 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg)
ctx->wp->flags |= PANE_REDRAW; ctx->wp->flags |= PANE_REDRAW;
#endif #endif
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
if (s->cy > 0) if (s->cy > 0)
@@ -1719,7 +1746,7 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg)
screen_write_collect_clear(ctx, 0, s->cy); screen_write_collect_clear(ctx, 0, s->cy);
screen_write_collect_flush(ctx, 0, __func__); screen_write_collect_flush(ctx, 0, __func__);
if (! screen_write_pane_obscured(ctx->wp)) { if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED) {
tty_write(tty_cmd_clearstartofscreen, &ttyctx); tty_write(tty_cmd_clearstartofscreen, &ttyctx);
return; return;
} }
@@ -1780,7 +1807,7 @@ screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
ctx->wp->flags |= PANE_REDRAW; ctx->wp->flags |= PANE_REDRAW;
#endif #endif
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
/* Scroll into history if it is enabled. */ /* Scroll into history if it is enabled. */
@@ -1793,7 +1820,7 @@ screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
screen_write_collect_clear(ctx, 0, sy); screen_write_collect_clear(ctx, 0, sy);
if (! screen_write_pane_obscured(ctx->wp)) { if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED) {
tty_write(tty_cmd_clearscreen, &ttyctx); tty_write(tty_cmd_clearscreen, &ttyctx);
return; return;
} }
@@ -1841,7 +1868,7 @@ screen_write_fullredraw(struct screen_write_ctx *ctx)
screen_write_collect_flush(ctx, 0, __func__); screen_write_collect_flush(ctx, 0, __func__);
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 0);
if (ttyctx.redraw_cb != NULL) if (ttyctx.redraw_cb != NULL)
ttyctx.redraw_cb(&ttyctx); ttyctx.redraw_cb(&ttyctx);
} }
@@ -1978,42 +2005,6 @@ screen_write_collect_scroll(struct screen_write_ctx *ctx, u_int bg)
TAILQ_INSERT_TAIL(&ctx->s->write_list[s->rlower].items, ci, entry); TAILQ_INSERT_TAIL(&ctx->s->write_list[s->rlower].items, ci, entry);
} }
/* Return 1 if there is a floating window pane overlapping this pane. */
static int
screen_write_pane_obscured(struct window_pane *base_wp)
{
struct window_pane *wp;
struct window *w;
int found_self = 0;
if (base_wp == NULL)
return(0);
w = base_wp->window;
TAILQ_FOREACH_REVERSE(wp, &w->z_index, window_panes_zindex, zentry) {
if (wp == base_wp) {
found_self = 1;
continue;
}
if (found_self && wp->flags & PANE_FLOATING &&
((wp->yoff >= base_wp->yoff &&
wp->yoff <= base_wp->yoff + (int)base_wp->sy) ||
(wp->yoff + (int)wp->sy >= base_wp->yoff &&
wp->yoff + wp->sy <= base_wp->yoff + base_wp->sy)) &&
((wp->xoff >= base_wp->xoff &&
wp->xoff <= base_wp->xoff + (int)base_wp->sx) ||
(wp->xoff + (int)wp->sx >= base_wp->xoff &&
wp->xoff + wp->sx <= base_wp->xoff + base_wp->sx))) {
log_debug("%s: base %%%u obscured by %%%u "
"(xoff=%u sx=%u vs base xoff=%u sx=%u)", __func__,
base_wp->id, wp->id,
wp->xoff, wp->sx, base_wp->xoff, base_wp->sx);
return (1);
}
}
return (0);
}
/* Flush collected lines. */ /* Flush collected lines. */
static void static void
screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only, screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
@@ -2049,14 +2040,11 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
if (ctx->scrolled > s->rlower - s->rupper + 1) if (ctx->scrolled > s->rlower - s->rupper + 1)
ctx->scrolled = s->rlower - s->rupper + 1; ctx->scrolled = s->rlower - s->rupper + 1;
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 1);
if (wp != NULL && wp->yoff + wp->sy > wp->window->sy) if (wp != NULL && wp->yoff + wp->sy > wp->window->sy)
ttyctx.orlower -= (wp->yoff + wp->sy - wp->window->sy); ttyctx.orlower -= (wp->yoff + wp->sy - wp->window->sy);
ttyctx.num = ctx->scrolled; ttyctx.num = ctx->scrolled;
ttyctx.bg = ctx->bg; ttyctx.bg = ctx->bg;
ttyctx.obscured = screen_write_pane_obscured(wp);
log_debug("%s: obscured=%d for pane %%%u", __func__,
ttyctx.obscured, wp != NULL ? wp->id : 0);
tty_write(tty_cmd_scrollup, &ttyctx); tty_write(tty_cmd_scrollup, &ttyctx);
if (wp != NULL) if (wp != NULL)
log_debug("%s: after scrollup, PANE_REDRAW=%d for %%%u", log_debug("%s: after scrollup, PANE_REDRAW=%d for %%%u",
@@ -2143,15 +2131,16 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
continue; continue;
screen_write_set_cursor(ctx, wr_start, y); screen_write_set_cursor(ctx, wr_start, y);
if (ci->type == CLEAR) { if (ci->type == CLEAR) {
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 0);
ttyctx.bg = ci->bg; ttyctx.bg = ci->bg;
ttyctx.num = wr_length; ttyctx.num = wr_length;
tty_write(tty_cmd_clearcharacter, tty_write(tty_cmd_clearcharacter,
&ttyctx); &ttyctx);
} else { } else {
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0, 0);
ttyctx.cell = &ci->gc; ttyctx.cell = &ci->gc;
ttyctx.wrapped = ci->wrapped; if (ci->wrapped)
ttyctx.flags |= TTY_CTX_WRAPPED;
ttyctx.ptr = cl->data + wr_start; ttyctx.ptr = cl->data + wr_start;
ttyctx.num = wr_length; ttyctx.num = wr_length;
tty_write(tty_cmd_cells, &ttyctx); tty_write(tty_cmd_cells, &ttyctx);
@@ -2378,7 +2367,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
/* Sanity check cursor position. */ /* Sanity check cursor position. */
if (s->cx > sx - width || s->cy > sy - 1) if (s->cx > sx - width || s->cy > sy - 1)
return; return;
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0, 0);
/* Handle overwriting of UTF-8 characters. */ /* Handle overwriting of UTF-8 characters. */
gl = grid_get_line(s->grid, s->grid->hsize + s->cy); gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
@@ -2469,7 +2458,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
} else } else
memcpy(&tmp_gc, gc, sizeof tmp_gc); memcpy(&tmp_gc, gc, sizeof tmp_gc);
ttyctx.cell = &tmp_gc; ttyctx.cell = &tmp_gc;
ttyctx.num = redraw ? 2 : 0; if (redraw)
ttyctx.flags |= TTY_CTX_CELL_DRAW_LINE;
for (i=0, vis=0; i < r->used; i++) vis += r->ranges[i].nx; for (i=0, vis=0; i < r->used; i++) vis += r->ranges[i].nx;
if (vis < width) { if (vis < width) {
/* Wide character or tab partly obscured. Write /* Wide character or tab partly obscured. Write
@@ -2617,9 +2607,10 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
* and what it is going to do now. * and what it is going to do now.
*/ */
screen_write_set_cursor(ctx, cx - n, cy); screen_write_set_cursor(ctx, cx - n, cy);
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0, 0);
ttyctx.cell = &last; ttyctx.cell = &last;
ttyctx.num = force_wide; /* reset cached cursor position */ if (force_wide)
ttyctx.flags |= TTY_CTX_CELL_INVALIDATE;
tty_write(tty_cmd_cell, &ttyctx); tty_write(tty_cmd_cell, &ttyctx);
screen_write_set_cursor(ctx, cx, cy); screen_write_set_cursor(ctx, cx, cy);
@@ -2705,7 +2696,7 @@ screen_write_setselection(struct screen_write_ctx *ctx, const char *clip,
{ {
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0, 0);
ttyctx.ptr = str; ttyctx.ptr = str;
ttyctx.ptr2 = (void *)clip; ttyctx.ptr2 = (void *)clip;
ttyctx.num = len; ttyctx.num = len;
@@ -2720,10 +2711,11 @@ screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len,
{ {
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0, 0);
if (allow_invisible_panes)
ttyctx.flags |= TTY_CTX_INVISIBLE_PANES;
ttyctx.ptr = str; ttyctx.ptr = str;
ttyctx.num = len; ttyctx.num = len;
ttyctx.allow_invisible_panes = allow_invisible_panes;
tty_write(tty_cmd_rawstring, &ttyctx); tty_write(tty_cmd_rawstring, &ttyctx);
} }
@@ -2807,7 +2799,7 @@ screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc,
server_redraw_window_borders(wp->window); server_redraw_window_borders(wp->window);
} }
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 0);
if (ttyctx.redraw_cb != NULL) if (ttyctx.redraw_cb != NULL)
ttyctx.redraw_cb(&ttyctx); ttyctx.redraw_cb(&ttyctx);
} }
@@ -2831,7 +2823,7 @@ screen_write_alternateoff(struct screen_write_ctx *ctx, struct grid_cell *gc,
server_redraw_window_borders(wp->window); server_redraw_window_borders(wp->window);
} }
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1, 0);
if (ttyctx.redraw_cb != NULL) if (ttyctx.redraw_cb != NULL)
ttyctx.redraw_cb(&ttyctx); ttyctx.redraw_cb(&ttyctx);
} }

23
tmux.h
View File

@@ -1055,6 +1055,8 @@ struct screen_write_ctx {
int flags; int flags;
#define SCREEN_WRITE_SYNC 0x1 #define SCREEN_WRITE_SYNC 0x1
#define SCREEN_WRITE_OBSCURED 0x2
#define SCREEN_WRITE_CHECKED_IF_OBSCURED 0x4
screen_write_init_ctx_cb init_ctx_cb; screen_write_init_ctx_cb init_ctx_cb;
void *arg; void *arg;
@@ -1733,19 +1735,20 @@ struct tty_ctx {
void *arg; void *arg;
const struct grid_cell *cell; const struct grid_cell *cell;
int wrapped; int flags;
#define TTY_CTX_WRAPPED 0x1
#define TTY_CTX_INVISIBLE_PANES 0x2
#define TTY_CTX_WINDOW_BIGGER 0x4
#define TTY_CTX_SYNC 0x8
#define TTY_CTX_OVERLAY_SYNC 0x10
#define TTY_CTX_CELL_DRAW_LINE 0x20
#define TTY_CTX_CELL_INVALIDATE 0x40
#define TTY_CTX_PANE_OBSCURED 0x80
u_int num; u_int num;
void *ptr; void *ptr;
void *ptr2; void *ptr2;
/*
* Whether this command should be sent even when the pane is not
* visible (used for a passthrough sequence when allow-passthrough is
* "all").
*/
int allow_invisible_panes;
/* /*
* Cursor and region position before the screen was updated - this is * Cursor and region position before the screen was updated - this is
* where the command should be applied; the values in the screen have * where the command should be applied; the values in the screen have
@@ -1773,14 +1776,10 @@ struct tty_ctx {
struct colour_palette *palette; struct colour_palette *palette;
/* Containing region (usually window) offset and size. */ /* Containing region (usually window) offset and size. */
int bigger;
u_int wox; u_int wox;
u_int woy; u_int woy;
u_int wsx; u_int wsx;
u_int wsy; u_int wsy;
/* tty partly obscured, it will need to be surgically scrolled. */
u_int obscured;
}; };
/* Saved message entry. */ /* Saved message entry. */

67
tty.c
View File

@@ -1099,7 +1099,7 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
log_debug("%s: %s orlower=%u orupper=%u sy=%u large=%d", __func__, log_debug("%s: %s orlower=%u orupper=%u sy=%u large=%d", __func__,
c->name, ctx->orlower, ctx->orupper, ctx->sy, c->name, ctx->orlower, ctx->orupper, ctx->sy,
tty_large_region(tty, ctx)); tty_large_region(tty, ctx));
if (tty_large_region(tty, ctx) && !ctx->obscured) { if (tty_large_region(tty, ctx) && ~ctx->flags & TTY_CTX_PANE_OBSCURED) {
log_debug("%s: %s large region redraw", __func__, c->name); log_debug("%s: %s large region redraw", __func__, c->name);
ctx->redraw_cb(ctx); ctx->redraw_cb(ctx);
return; return;
@@ -1118,7 +1118,7 @@ tty_is_visible(__unused struct tty *tty, const struct tty_ctx *ctx, u_int px,
{ {
u_int xoff = ctx->rxoff + px, yoff = ctx->ryoff + py; u_int xoff = ctx->rxoff + px, yoff = ctx->ryoff + py;
if (!ctx->bigger) if (~ctx->flags & TTY_CTX_WINDOW_BIGGER)
return (1); return (1);
if (xoff + nx <= ctx->wox || xoff >= ctx->wox + ctx->wsx || if (xoff + nx <= ctx->wox || xoff >= ctx->wox + ctx->wsx ||
@@ -1429,11 +1429,11 @@ tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py)
struct visible_range *ri; struct visible_range *ri;
u_int nx = ctx->sx, i, px, x, rx, ry; u_int nx = ctx->sx, i, px, x, rx, ry;
log_debug("%s: %s %u %d", __func__, tty->client->name, py, ctx->bigger); log_debug("%s: %s %u", __func__, tty->client->name, py);
if (!ctx->bigger) { if (~ctx->flags & TTY_CTX_WINDOW_BIGGER) {
if (wp) { if (wp) {
if (ctx->obscured) { if (ctx->flags & TTY_CTX_PANE_OBSCURED) {
/* /*
* Floating pane is present: use physical * Floating pane is present: use physical
* coordinates and clip to visible ranges to * coordinates and clip to visible ranges to
@@ -1644,7 +1644,7 @@ tty_client_ready(const struct tty_ctx *ctx, struct client *c)
* If invisible panes are allowed (used for passthrough), don't care if * If invisible panes are allowed (used for passthrough), don't care if
* redrawing or frozen. * redrawing or frozen.
*/ */
if (ctx->allow_invisible_panes) if (ctx->flags & TTY_CTX_INVISIBLE_PANES)
return (1); return (1);
if (c->flags & CLIENT_REDRAWWINDOW) if (c->flags & CLIENT_REDRAWWINDOW)
@@ -1693,13 +1693,12 @@ tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx)
{ {
struct client *c = tty->client; struct client *c = tty->client;
if (ctx->bigger || if ((ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED)) ||
!tty_full_width(tty, ctx) || !tty_full_width(tty, ctx) ||
tty_fake_bce(tty, &ctx->defaults, ctx->bg) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) ||
(!tty_term_has(tty->term, TTYC_ICH) && (!tty_term_has(tty->term, TTYC_ICH) &&
!tty_term_has(tty->term, TTYC_ICH1)) || !tty_term_has(tty->term, TTYC_ICH1)) ||
c->overlay_check != NULL || c->overlay_check != NULL) {
ctx->obscured) {
tty_draw_pane(tty, ctx, ctx->ocy); tty_draw_pane(tty, ctx, ctx->ocy);
return; return;
} }
@@ -1717,13 +1716,12 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx)
{ {
struct client *c = tty->client; struct client *c = tty->client;
if (ctx->bigger || if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) ||
!tty_full_width(tty, ctx) || !tty_full_width(tty, ctx) ||
tty_fake_bce(tty, &ctx->defaults, ctx->bg) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) ||
(!tty_term_has(tty->term, TTYC_DCH) && (!tty_term_has(tty->term, TTYC_DCH) &&
!tty_term_has(tty->term, TTYC_DCH1)) || !tty_term_has(tty->term, TTYC_DCH1)) ||
c->overlay_check != NULL || c->overlay_check != NULL) {
ctx->obscured) {
tty_draw_pane(tty, ctx, ctx->ocy); tty_draw_pane(tty, ctx, ctx->ocy);
return; return;
} }
@@ -1750,15 +1748,14 @@ tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx)
{ {
struct client *c = tty->client; struct client *c = tty->client;
if (ctx->bigger || if ((ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED)) ||
!tty_full_width(tty, ctx) || !tty_full_width(tty, ctx) ||
tty_fake_bce(tty, &ctx->defaults, ctx->bg) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) ||
!tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_IL1) || !tty_term_has(tty->term, TTYC_IL1) ||
ctx->sx == 1 || ctx->sx == 1 ||
ctx->sy == 1 || ctx->sy == 1 ||
c->overlay_check != NULL || c->overlay_check != NULL) {
ctx->obscured) {
tty_redraw_region(tty, ctx); tty_redraw_region(tty, ctx);
return; return;
} }
@@ -1779,15 +1776,14 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
{ {
struct client *c = tty->client; struct client *c = tty->client;
if (ctx->bigger || if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) ||
!tty_full_width(tty, ctx) || !tty_full_width(tty, ctx) ||
tty_fake_bce(tty, &ctx->defaults, ctx->bg) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) ||
!tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_DL1) || !tty_term_has(tty->term, TTYC_DL1) ||
ctx->sx == 1 || ctx->sx == 1 ||
ctx->sy == 1 || ctx->sy == 1 ||
c->overlay_check != NULL || c->overlay_check != NULL) {
ctx->obscured) {
tty_redraw_region(tty, ctx); tty_redraw_region(tty, ctx);
return; return;
} }
@@ -1840,7 +1836,7 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx)
if (ctx->ocy != ctx->orupper) if (ctx->ocy != ctx->orupper)
return; return;
if (ctx->bigger || if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) ||
(!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
tty_fake_bce(tty, &ctx->defaults, 8) || tty_fake_bce(tty, &ctx->defaults, 8) ||
!tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_CSR) ||
@@ -1874,7 +1870,7 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
if (ctx->ocy != ctx->orlower) if (ctx->ocy != ctx->orlower)
return; return;
if (ctx->bigger || if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) ||
(!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
tty_fake_bce(tty, &ctx->defaults, 8) || tty_fake_bce(tty, &ctx->defaults, 8) ||
!tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_CSR) ||
@@ -1915,14 +1911,13 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
struct client *c = tty->client; struct client *c = tty->client;
u_int i; u_int i;
if (ctx->bigger || if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) ||
(!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
tty_fake_bce(tty, &ctx->defaults, 8) || tty_fake_bce(tty, &ctx->defaults, 8) ||
!tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_CSR) ||
ctx->sx == 1 || ctx->sx == 1 ||
ctx->sy == 1 || ctx->sy == 1 ||
c->overlay_check != NULL || c->overlay_check != NULL) {
ctx->obscured) {
tty_redraw_region(tty, ctx); tty_redraw_region(tty, ctx);
return; return;
} }
@@ -1955,7 +1950,7 @@ tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx)
u_int i; u_int i;
struct client *c = tty->client; struct client *c = tty->client;
if (ctx->bigger || if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) ||
(!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
tty_fake_bce(tty, &ctx->defaults, 8) || tty_fake_bce(tty, &ctx->defaults, 8) ||
!tty_term_has(tty->term, TTYC_CSR) || !tty_term_has(tty->term, TTYC_CSR) ||
@@ -1963,8 +1958,7 @@ tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx)
!tty_term_has(tty->term, TTYC_RIN)) || !tty_term_has(tty->term, TTYC_RIN)) ||
ctx->sx == 1 || ctx->sx == 1 ||
ctx->sy == 1 || ctx->sy == 1 ||
c->overlay_check != NULL || c->overlay_check != NULL) {
ctx->obscured) {
tty_redraw_region(tty, ctx); tty_redraw_region(tty, ctx);
return; return;
} }
@@ -2058,7 +2052,7 @@ tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx)
{ {
u_int i, j; u_int i, j;
if (ctx->bigger) { if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED)) {
ctx->redraw_cb(ctx); ctx->redraw_cb(ctx);
return; return;
} }
@@ -2090,7 +2084,7 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
(gcp->data.width == 1 && !tty_check_overlay(tty, px, py))) (gcp->data.width == 1 && !tty_check_overlay(tty, px, py)))
return; return;
if (ctx->num == 2) { if (ctx->flags & TTY_CTX_CELL_DRAW_LINE) {
tty_draw_line(tty, s, 0, s->cy, screen_size_x(s), tty_draw_line(tty, s, 0, s->cy, screen_size_x(s),
ctx->xoff - ctx->wox, py, &ctx->defaults, ctx->palette); ctx->xoff - ctx->wox, py, &ctx->defaults, ctx->palette);
return; return;
@@ -2120,7 +2114,7 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette, tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette,
ctx->s->hyperlinks); ctx->s->hyperlinks);
if (ctx->num == 1) if (ctx->flags & TTY_CTX_CELL_INVALIDATE)
tty_invalidate(tty); tty_invalidate(tty);
} }
@@ -2135,10 +2129,10 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, ctx->num, 1)) if (!tty_is_visible(tty, ctx, ctx->ocx, ctx->ocy, ctx->num, 1))
return; return;
if (ctx->bigger && if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) &&
(ctx->xoff + ctx->ocx < ctx->wox || (ctx->xoff + ctx->ocx < ctx->wox ||
ctx->xoff + ctx->ocx + ctx->num > ctx->wox + ctx->wsx)) { ctx->xoff + ctx->ocx + ctx->num > ctx->wox + ctx->wsx)) {
if (!ctx->wrapped || if ((~ctx->flags & TTY_CTX_WRAPPED) ||
!tty_full_width(tty, ctx) || !tty_full_width(tty, ctx) ||
(tty->term->flags & TERM_NOAM) || (tty->term->flags & TERM_NOAM) ||
ctx->xoff + ctx->ocx != 0 || ctx->xoff + ctx->ocx != 0 ||
@@ -2401,18 +2395,21 @@ tty_cmd_sixelimage(struct tty *tty, const struct tty_ctx *ctx)
void void
tty_cmd_syncstart(struct tty *tty, const struct tty_ctx *ctx) tty_cmd_syncstart(struct tty *tty, const struct tty_ctx *ctx)
{ {
if (ctx->num == 0x11) { struct client *c = tty->client;
if ((ctx->flags & TTY_CTX_OVERLAY_SYNC) &&
(ctx->flags & TTY_CTX_SYNC)) {
/* /*
* This is an overlay and a command that moves the cursor so * This is an overlay and a command that moves the cursor so
* start synchronized updates. * start synchronized updates.
*/ */
tty_sync_start(tty); tty_sync_start(tty);
} else if (~ctx->num & 0x10) { } else if (~ctx->flags & TTY_CTX_OVERLAY_SYNC) {
/* /*
* This is a pane. If there is an overlay, always start; * This is a pane. If there is an overlay, always start;
* otherwise, only if requested. * otherwise, only if requested.
*/ */
if (ctx->num || tty->client->overlay_draw != NULL) if ((ctx->flags & TTY_CTX_SYNC) || c->overlay_draw != NULL)
tty_sync_start(tty); tty_sync_start(tty);
} }
} }
@@ -2593,7 +2590,7 @@ static void
tty_cursor_pane_unless_wrap(struct tty *tty, const struct tty_ctx *ctx, tty_cursor_pane_unless_wrap(struct tty *tty, const struct tty_ctx *ctx,
u_int cx, u_int cy) u_int cx, u_int cy)
{ {
if (!ctx->wrapped || if ((~ctx->flags & TTY_CTX_WRAPPED) ||
!tty_full_width(tty, ctx) || !tty_full_width(tty, ctx) ||
(tty->term->flags & TERM_NOAM) || (tty->term->flags & TERM_NOAM) ||
ctx->xoff + cx != 0 || ctx->xoff + cx != 0 ||