Fix some of the offset issues when windows size is greater than tty size.

This commit is contained in:
Michael Grant
2026-01-07 22:28:23 +00:00
parent f2f6a05e2c
commit 95f85efc49
2 changed files with 70 additions and 49 deletions

View File

@@ -232,15 +232,13 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
if ((wp->xoff == 0 || (int)px >= wp->xoff) && if ((wp->xoff == 0 || (int)px >= wp->xoff) &&
((int)px <= ex || ((int)px <= ex ||
(sb_w != 0 && (int)px < ex + sb_w))) { (sb_w != 0 && (int)px < ex + sb_w))) {
if (pane_status == PANE_STATUS_TOP) { if (pane_status != PANE_STATUS_BOTTOM &&
if ((int)py == wp->yoff - 1) wp->yoff != 0 &&
return (SCREEN_REDRAW_BORDER_TOP); (int)py == wp->yoff - 1)
} else { /* PANE_STATUS_BOTTOM or OFF. */ return (SCREEN_REDRAW_BORDER_TOP);
if (wp->yoff != 0 && (int)py == wp->yoff - 1) if (pane_status != PANE_STATUS_TOP &&
return (SCREEN_REDRAW_BORDER_TOP); (int)py == ey)
if ((int)py == ey)
return (SCREEN_REDRAW_BORDER_BOTTOM); return (SCREEN_REDRAW_BORDER_BOTTOM);
}
} }
} }
} }
@@ -456,6 +454,9 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
/* Find pane higest in z-index at this point. */ /* Find pane higest in z-index at this point. */
TAILQ_FOREACH(wp, &w->z_index, zentry) { TAILQ_FOREACH(wp, &w->z_index, zentry) {
if (wp->flags & PANE_FLOATING && (px >= sx || py >= sy))
/* Clip floating panes to window. */
continue;
sb_w = wp->scrollbar_style.width + sb_w = wp->scrollbar_style.width +
wp->scrollbar_style.pad; wp->scrollbar_style.pad;
if (sb_pos == PANE_SCROLLBARS_LEFT) { if (sb_pos == PANE_SCROLLBARS_LEFT) {
@@ -525,11 +526,11 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
if (pane_status == PANE_STATUS_TOP) if (pane_status == PANE_STATUS_TOP)
pane_status_line = wp->yoff - 1; pane_status_line = wp->yoff - 1;
else else
pane_status_line = wp->yoff + sy; pane_status_line = wp->yoff + wp->sy;
left = wp->xoff + 2; left = wp->xoff + 2;
right = wp->xoff + 2 + wp->status_size - 1; right = wp->xoff + 2 + wp->status_size - 1;
if (py == pane_status_line && if (py == pane_status_line + ctx->oy && /* XXX unsure about adding oy here, needs more testing. */
(int)px >= left && (int)px <= right) (int)px >= left && (int)px <= right)
return (CELL_INSIDE); return (CELL_INSIDE);
} }
@@ -719,8 +720,7 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
width = size - x; width = size - x;
} }
vr = screen_redraw_get_visible_ranges(wp, x, yoff - ctx->oy, vr = screen_redraw_get_visible_ranges(wp, x, yoff, width);
width);
if (ctx->statustop) if (ctx->statustop)
yoff += ctx->statuslines; yoff += ctx->statuslines;
@@ -1083,10 +1083,9 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
struct window_pane *wp; struct window_pane *wp;
struct window *w; struct window *w;
static struct visible_ranges vr = {NULL, NULL, 0, 0}; static struct visible_ranges vr = {NULL, NULL, 0, 0};
int found_self, sb_w; int found_self, sb_w, sb_pos;
u_int lb, rb, tb, bb; u_int lb, rb, tb, bb;
u_int r, s; u_int r, s;
int pane_scrollbars, pane_scrollbars_pos;
/* For efficiency vr is static and space reused. */ /* For efficiency vr is static and space reused. */
if (vr.size == 0) { if (vr.size == 0) {
@@ -1095,6 +1094,11 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
vr.size = 1; vr.size = 1;
} }
/* debugging:
* display *vr.px@vr.used
* display *vr.nx@vr.used
*/
/* Start with the entire width of the range. */ /* Start with the entire width of the range. */
vr.px[0] = px; vr.px[0] = px;
vr.nx[0] = width; vr.nx[0] = width;
@@ -1104,8 +1108,7 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
return (&vr); return (&vr);
w = base_wp->window; w = base_wp->window;
pane_scrollbars = options_get_number(w->options, "pane-scrollbars"); sb_pos = options_get_number(w->options, "pane-scrollbars-position");
pane_scrollbars_pos = options_get_number(w->options, "pane-scrollbars-position");
found_self = 0; found_self = 0;
TAILQ_FOREACH_REVERSE(wp, &w->z_index, window_panes_zindex, zentry) { TAILQ_FOREACH_REVERSE(wp, &w->z_index, window_panes_zindex, zentry) {
@@ -1118,18 +1121,23 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
bb = wp->yoff + wp->sy; bb = wp->yoff + wp->sy;
if (!found_self || if (!found_self ||
!window_pane_visible(wp) || !window_pane_visible(wp) ||
py < tb || py < tb || py > bb)
((wp->flags & PANE_FLOATING) && py > bb) || continue;
(~(wp->flags & PANE_FLOATING) && py > bb)) if (~wp->flags & PANE_FLOATING && py == bb)
continue; continue;
/* Are scrollbars enabled? */ /* Are scrollbars enabled? */
if (window_pane_show_scrollbar(wp, pane_scrollbars)) if (window_pane_show_scrollbar(wp,
options_get_number(w->options, "pane-scrollbars")))
sb_w = wp->scrollbar_style.width + sb_w = wp->scrollbar_style.width +
wp->scrollbar_style.pad; wp->scrollbar_style.pad;
else {
sb_w = 0;
sb_pos = 0;
}
for (r=0; r < vr.used; r++) { for (r=0; r < vr.used; r++) {
if (pane_scrollbars_pos == PANE_SCROLLBARS_LEFT) { if (sb_pos == PANE_SCROLLBARS_LEFT) {
if (wp->xoff > sb_w) if (wp->xoff > sb_w)
lb = wp->xoff - 1 - sb_w; lb = wp->xoff - 1 - sb_w;
else else
@@ -1140,7 +1148,7 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
else else
lb = 0; lb = 0;
} }
if (pane_scrollbars_pos == PANE_SCROLLBARS_LEFT) if (sb_pos == PANE_SCROLLBARS_LEFT)
rb = wp->xoff + wp->sx; rb = wp->xoff + wp->sx;
else /* PANE_SCROLLBARS_RIGHT or none. */ else /* PANE_SCROLLBARS_RIGHT or none. */
rb = wp->xoff + wp->sx + sb_w; rb = wp->xoff + wp->sx + sb_w;
@@ -1216,7 +1224,7 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
struct colour_palette *palette = &wp->palette; struct colour_palette *palette = &wp->palette;
struct grid_cell defaults; struct grid_cell defaults;
struct visible_ranges *vr; struct visible_ranges *vr;
u_int i, j, top, x, y, width, r; u_int i, j, woy, wx, wy, px, py, width, r;
if (wp->base.mode & MODE_SYNC) if (wp->base.mode & MODE_SYNC)
screen_write_stop_sync(wp); screen_write_stop_sync(wp);
@@ -1226,16 +1234,22 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
if (wp->xoff + (int)wp->sx <= ctx->ox || if (wp->xoff + (int)wp->sx <= ctx->ox ||
wp->xoff >= ctx->ox + (int)ctx->sx) wp->xoff >= ctx->ox + (int)ctx->sx)
return; return;
/* woy is window y offset in tty. */
if (ctx->statustop) if (ctx->statustop)
top = ctx->statuslines; woy = ctx->statuslines;
else else
top = 0; woy = 0;
for (j = 0; j < wp->sy; j++) { for (j = 0; j < wp->sy; j++) {
if (wp->yoff + (int)j < ctx->oy || if (wp->yoff + (int)j < ctx->oy ||
wp->yoff + j >= ctx->oy + ctx->sy) wp->yoff + j >= ctx->oy + ctx->sy)
continue; continue;
y = wp->yoff + j - ctx->oy; wy = wp->yoff + j; /* y line within window w. */
py = woy + wy - ctx->oy; /* y line within tty. */
if (py > tty->sy)
/* Continue if this line is off of tty. */
continue;
/* Note: i is apparenty not used now that the vr array /* Note: i is apparenty not used now that the vr array
* returns where in s to read from. * returns where in s to read from.
@@ -1244,42 +1258,44 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
wp->xoff + wp->sx <= ctx->ox + ctx->sx) { wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
/* All visible. */ /* All visible. */
i = 0; i = 0;
x = wp->xoff - ctx->ox; wx = wp->xoff - ctx->ox;
width = wp->sx; width = wp->sx;
} else if (wp->xoff < ctx->ox && } else if (wp->xoff < ctx->ox &&
wp->xoff + wp->sx > ctx->ox + ctx->sx) { wp->xoff + wp->sx > ctx->ox + ctx->sx) {
/* Both left and right not visible. */ /* Both left and right not visible. */
i = ctx->ox; i = ctx->ox;
x = 0; wx = 0;
width = ctx->sx; width = ctx->sx;
} else if (wp->xoff < ctx->ox) { } else if (wp->xoff < ctx->ox) {
/* Left not visible. */ /* Left not visible. */
i = ctx->ox - wp->xoff; i = ctx->ox - wp->xoff;
x = 0; wx = 0;
width = wp->sx - i; width = wp->sx - i;
} else { } else {
/* Right not visible. */ /* Right not visible. */
i = 0; i = 0;
x = wp->xoff - ctx->ox; wx = wp->xoff - ctx->ox;
width = ctx->sx - x; width = ctx->sx - wx;
} }
log_debug("%s: %s %%%u line %u,%u at %u,%u, width %u", log_debug("%s: %s %%%u line %u,%u at %u,%u, width %u",
__func__, c->name, wp->id, i, j, x, y, width); __func__, c->name, wp->id, i, j, wx, wy, width);
/* Get visible ranges of line before we draw it. */ /* Get visible ranges of line before we draw it. */
vr = screen_redraw_get_visible_ranges(wp, x, y, width); vr = screen_redraw_get_visible_ranges(wp, wx, wy, width);
tty_default_colours(&defaults, wp); tty_default_colours(&defaults, wp);
for (r=0; r < vr->used; r++) { for (r=0; r < vr->used; r++) {
if (vr->nx[r] == 0) if (vr->nx[r] == 0)
continue; continue;
/* Convert window coordinates to tty coordinates. */
px = vr->px[r];
/* i is px of cell, add px of region, sub the /* i is px of cell, add px of region, sub the
* pane offset. If you don't sub offset, * pane offset. If you don't sub offset,
* contents of pane shifted. note: i apparently unnec. * contents of pane shifted. note: i apparently unnec.
*/ */
tty_draw_line(tty, s, /* i + */ vr->px[r] - wp->xoff, j, tty_draw_line(tty, s, /* i + */ vr->px[r] - wp->xoff, j,
vr->nx[r], vr->px[r], top + y, &defaults, palette); vr->nx[r], px, py, &defaults, palette);
} }
} }
@@ -1305,7 +1321,7 @@ screen_redraw_draw_pane_scrollbars(struct screen_redraw_ctx *ctx)
} }
} }
/* Draw pane scrollbar. */ /* Calculate position and size of pane scrollbar. */
void void
screen_redraw_draw_pane_scrollbar(struct screen_redraw_ctx *ctx, screen_redraw_draw_pane_scrollbar(struct screen_redraw_ctx *ctx,
struct window_pane *wp) struct window_pane *wp)
@@ -1316,8 +1332,8 @@ screen_redraw_draw_pane_scrollbar(struct screen_redraw_ctx *ctx,
u_int sb_pos = ctx->pane_scrollbars_pos, slider_h, slider_y; u_int sb_pos = ctx->pane_scrollbars_pos, slider_h, slider_y;
int sb_w = wp->scrollbar_style.width; int sb_w = wp->scrollbar_style.width;
int sb_pad = wp->scrollbar_style.pad; int sb_pad = wp->scrollbar_style.pad;
int cm_y, cm_size, xoff = wp->xoff, ox = ctx->ox; int cm_y, cm_size, xoff = wp->xoff;
int sb_x, sb_y = (int)(wp->yoff - ctx->oy); /* sb top */ int sb_x, sb_y = (int)(wp->yoff); /* sb top */
if (window_pane_mode(wp) == WINDOW_PANE_NO_MODE) { if (window_pane_mode(wp) == WINDOW_PANE_NO_MODE) {
if (sb == PANE_SCROLLBARS_MODAL) if (sb == PANE_SCROLLBARS_MODAL)
@@ -1335,13 +1351,13 @@ screen_redraw_draw_pane_scrollbar(struct screen_redraw_ctx *ctx,
total_height = cm_size + sb_h; total_height = cm_size + sb_h;
percent_view = (double)sb_h / (cm_size + sb_h); percent_view = (double)sb_h / (cm_size + sb_h);
slider_h = (double)sb_h * percent_view; slider_h = (double)sb_h * percent_view;
slider_y = (sb_h + 1) * ((double)cm_y / total_height); slider_y = (sb_h + 1) * ((double)cm_y / (total_height));
} }
if (sb_pos == PANE_SCROLLBARS_LEFT) if (sb_pos == PANE_SCROLLBARS_LEFT)
sb_x = xoff - sb_w - sb_pad - ox; sb_x = xoff - sb_w - sb_pad;
else else
sb_x = xoff + wp->sx - ox; sb_x = xoff + wp->sx;
if (slider_h < 1) if (slider_h < 1)
slider_h = 1; slider_h = 1;
@@ -1356,6 +1372,7 @@ screen_redraw_draw_pane_scrollbar(struct screen_redraw_ctx *ctx,
wp->sb_slider_h = slider_h; /* height of slider */ wp->sb_slider_h = slider_h; /* height of slider */
} }
/* Draw pane scrollbar. */
static void static void
screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx, screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx,
struct window_pane *wp, int sb_pos, int sb_x, int sb_y, u_int sb_h, struct window_pane *wp, int sb_pos, int sb_x, int sb_y, u_int sb_h,
@@ -1377,12 +1394,13 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx,
* Status at top offsets window downward. * Status at top offsets window downward.
*/ */
sx = ctx->sx; sx = ctx->sx;
sy = ctx->sy; sy = tty->sy - ctx->statuslines;
ox = ctx->ox; ox = ctx->ox;
oy = ctx->oy; oy = ctx->oy;
if (ctx->statustop) { if (ctx->statustop) {
sy += ctx->statuslines; /* Height of tty. */ sb_y += ctx->statuslines;
oy += ctx->statuslines; /* Top of w in tty. */ sy += ctx->statuslines; /* Height of window in tty. */
oy += ctx->statuslines; /* Top of window in tty. */
} }
@@ -1419,16 +1437,16 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx,
jmax = sy - sb_y; jmax = sy - sb_y;
for (j = jmin; j < jmax; j++) { for (j = jmin; j < jmax; j++) {
py = sb_y + oy + j; /* tty y coordinate. */ py = sb_y + j; /* tty y coordinate. */
wy = sb_y + j; /* window y coordinate. */ wy = sb_y + j + oy; /* window y coordinate. */
vr = screen_redraw_get_visible_ranges(wp, sb_x, wy, imax); vr = screen_redraw_get_visible_ranges(wp, sb_x, wy, imax);
for (i = imin; i < imax; i++) { for (i = imin; i < imax; i++) {
px = sb_x + ox + i; /* tty x coordinate. */ px = sb_x + ox + i; /* tty x coordinate. */
wx = sb_x + i; /* window x coordinate. */ wx = sb_x + i; /* window x coordinate. */
if (wx < xoff - (int)sb_w - (int)sb_pad || if (wx < xoff - (int)sb_w - (int)sb_pad ||
wx >= sx || wx < 0 || px >= sx || px < 0 ||
wy < yoff - 1 || wy < yoff - 1 ||
wy >= sy || wy < 0 || py >= sy || py < 0 ||
! screen_redraw_is_visible(vr, wx)) ! screen_redraw_is_visible(vr, wx))
continue; continue;
tty_cursor(tty, px, py); tty_cursor(tty, px, py);

7
tty.c
View File

@@ -1007,7 +1007,10 @@ tty_window_offset1(struct tty *tty, u_int *ox, u_int *oy, u_int *sx, u_int *sy)
else if (cy > w->sy - *sy) else if (cy > w->sy - *sy)
*oy = w->sy - *sy; *oy = w->sy - *sy;
else else
*oy = cy - *sy / 2; /* cy-sy/2 was causing panned panes to scroll
* when the cursor was half way down the pane.
*/
*oy = cy - *sy + 1; /* cy - *sy / 2; */
} }
c->pan_window = NULL; c->pan_window = NULL;
@@ -1220,7 +1223,7 @@ tty_clear_pane_line(struct tty *tty, const struct tty_ctx *ctx, u_int py,
struct client *c = tty->client; struct client *c = tty->client;
struct window_pane *wp = ctx->arg; struct window_pane *wp = ctx->arg;
struct visible_ranges *vr = NULL; struct visible_ranges *vr = NULL;
u_int r, i, x, rx, ry, oy = 0; u_int r, i, x, rx, ry;
log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py); log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py);