mirror of
https://github.com/tmux/tmux.git
synced 2026-03-07 08:15:36 +00:00
Fix scrolling, redraw, and borders of floating panes.
This commit is contained in:
@@ -262,8 +262,8 @@ cmd_new_floating_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sc.xoff = 20;
|
sc.xoff = 10;
|
||||||
sc.yoff = 20;
|
sc.yoff = 10;
|
||||||
sc.sx = sx;
|
sc.sx = sx;
|
||||||
sc.sy = sy;
|
sc.sy = sy;
|
||||||
|
|
||||||
|
|||||||
2
menu.c
2
menu.c
@@ -217,7 +217,7 @@ menu_draw_cb(struct client *c, void *data,
|
|||||||
|
|
||||||
for (i = 0; i < screen_size_y(&md->s); i++) {
|
for (i = 0; i < screen_size_y(&md->s); i++) {
|
||||||
tty_draw_line(tty, s, 0, i, menu->width + 4, px, py + i,
|
tty_draw_line(tty, s, 0, i, menu->width + 4, px, py + i,
|
||||||
&grid_default_cell, NULL);
|
&grid_default_cell, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
popup.c
2
popup.c
@@ -250,7 +250,7 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
|
|||||||
}
|
}
|
||||||
for (i = 0; i < pd->sy; i++) {
|
for (i = 0; i < pd->sy; i++) {
|
||||||
tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &defaults,
|
tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &defaults,
|
||||||
palette);
|
palette, NULL);
|
||||||
}
|
}
|
||||||
screen_free(&s);
|
screen_free(&s);
|
||||||
if (pd->md != NULL) {
|
if (pd->md != NULL) {
|
||||||
|
|||||||
109
screen-redraw.c
109
screen-redraw.c
@@ -104,7 +104,11 @@ screen_redraw_two_panes(struct window *w, int direction)
|
|||||||
{
|
{
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
|
|
||||||
wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry);
|
wp = TAILQ_FIRST(&w->panes);
|
||||||
|
do {
|
||||||
|
wp = TAILQ_NEXT(wp, entry);
|
||||||
|
} while (wp && wp->layout_cell == NULL);
|
||||||
|
|
||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
return (0); /* one pane */
|
return (0); /* one pane */
|
||||||
if (TAILQ_NEXT(wp, entry) != NULL)
|
if (TAILQ_NEXT(wp, entry) != NULL)
|
||||||
@@ -230,7 +234,7 @@ screen_redraw_cell_border(struct screen_redraw_ctx *ctx, u_int px, u_int py)
|
|||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
/* Check all the panes. */
|
/* Check all the panes. */
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH_REVERSE(wp, &w->panes, window_panes, entry) {
|
||||||
if (!window_pane_visible(wp))
|
if (!window_pane_visible(wp))
|
||||||
continue;
|
continue;
|
||||||
switch (screen_redraw_pane_border(ctx, wp, px, py)) {
|
switch (screen_redraw_pane_border(ctx, wp, px, py)) {
|
||||||
@@ -335,7 +339,7 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
|
|||||||
{
|
{
|
||||||
struct client *c = ctx->c;
|
struct client *c = ctx->c;
|
||||||
struct window *w = c->session->curw->window;
|
struct window *w = c->session->curw->window;
|
||||||
struct window_pane *wp, *active;
|
struct window_pane *wp, *start;
|
||||||
int pane_status = ctx->pane_status;
|
int pane_status = ctx->pane_status;
|
||||||
u_int sx = w->sx, sy = w->sy;
|
u_int sx = w->sx, sy = w->sy;
|
||||||
int border, pane_scrollbars = ctx->pane_scrollbars;
|
int border, pane_scrollbars = ctx->pane_scrollbars;
|
||||||
@@ -351,7 +355,18 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
|
|||||||
return (screen_redraw_type_of_cell(ctx, px, py));
|
return (screen_redraw_type_of_cell(ctx, px, py));
|
||||||
|
|
||||||
if (pane_status != PANE_STATUS_OFF) {
|
if (pane_status != PANE_STATUS_OFF) {
|
||||||
active = wp = server_client_get_pane(c);
|
/* Look for higest z-index window at px,py. xxxx scrollbars? */
|
||||||
|
TAILQ_FOREACH_REVERSE(wp, &w->panes, window_panes, entry) {
|
||||||
|
if (! (wp->flags & PANE_MINIMISED) &&
|
||||||
|
(px >= wp->xoff - 1 && px<= wp->xoff + wp->sx + 1) &&
|
||||||
|
(py >= wp->yoff - 1 && py<= wp->yoff + wp->sy + 1))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (wp != NULL)
|
||||||
|
start = wp;
|
||||||
|
else
|
||||||
|
start = wp = server_client_get_pane(c);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!window_pane_visible(wp))
|
if (!window_pane_visible(wp))
|
||||||
goto next1;
|
goto next1;
|
||||||
@@ -369,10 +384,22 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
|
|||||||
wp = TAILQ_NEXT(wp, entry);
|
wp = TAILQ_NEXT(wp, entry);
|
||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
wp = TAILQ_FIRST(&w->panes);
|
||||||
} while (wp != active);
|
} while (wp != start);
|
||||||
}
|
}
|
||||||
|
|
||||||
active = wp = server_client_get_pane(c);
|
|
||||||
|
/* Look for higest z-index window at px,py. xxxx scrollbars? */
|
||||||
|
TAILQ_FOREACH_REVERSE(wp, &w->panes, window_panes, entry) {
|
||||||
|
if (! (wp->flags & PANE_MINIMISED) &&
|
||||||
|
(px >= wp->xoff-1 && px<= wp->xoff+wp->sx+1) &&
|
||||||
|
(py >= wp->yoff-1 && py<= wp->yoff+wp->sy+1))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (wp == NULL)
|
||||||
|
start = wp = server_client_get_pane(c);
|
||||||
|
else
|
||||||
|
start = wp;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!window_pane_visible(wp))
|
if (!window_pane_visible(wp))
|
||||||
goto next2;
|
goto next2;
|
||||||
@@ -422,7 +449,7 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
|
|||||||
wp = TAILQ_NEXT(wp, entry);
|
wp = TAILQ_NEXT(wp, entry);
|
||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
wp = TAILQ_FIRST(&w->panes);
|
||||||
} while (wp != active);
|
} while (wp != start);
|
||||||
|
|
||||||
return (CELL_OUTSIDE);
|
return (CELL_OUTSIDE);
|
||||||
}
|
}
|
||||||
@@ -516,6 +543,7 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
|
|||||||
struct tty *tty = &c->tty;
|
struct tty *tty = &c->tty;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct screen *s;
|
struct screen *s;
|
||||||
|
struct visible_ranges *visible_ranges;
|
||||||
u_int i, x, width, xoff, yoff, size;
|
u_int i, x, width, xoff, yoff, size;
|
||||||
|
|
||||||
log_debug("%s: %s @%u", __func__, c->name, w->id);
|
log_debug("%s: %s @%u", __func__, c->name, w->id);
|
||||||
@@ -562,8 +590,11 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
|
|||||||
|
|
||||||
if (ctx->statustop)
|
if (ctx->statustop)
|
||||||
yoff += ctx->statuslines;
|
yoff += ctx->statuslines;
|
||||||
|
visible_ranges = screen_redraw_get_visible_ranges(wp, i, 0,
|
||||||
|
width);
|
||||||
|
|
||||||
tty_draw_line(tty, s, i, 0, width, x, yoff - ctx->oy,
|
tty_draw_line(tty, s, i, 0, width, x, yoff - ctx->oy,
|
||||||
&grid_default_cell, NULL);
|
&grid_default_cell, NULL, visible_ranges);
|
||||||
}
|
}
|
||||||
tty_cursor(tty, 0, 0);
|
tty_cursor(tty, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -722,6 +753,7 @@ screen_redraw_draw_borders_style(struct screen_redraw_ctx *ctx, u_int x,
|
|||||||
wp->border_gc_set = 1;
|
wp->border_gc_set = 1;
|
||||||
|
|
||||||
ft = format_create_defaults(NULL, c, s, s->curw, wp);
|
ft = format_create_defaults(NULL, c, s, s->curw, wp);
|
||||||
|
|
||||||
if (screen_redraw_check_is(ctx, x, y, active))
|
if (screen_redraw_check_is(ctx, x, y, active))
|
||||||
style_apply(&wp->border_gc, oo, "pane-active-border-style", ft);
|
style_apply(&wp->border_gc, oo, "pane-active-border-style", ft);
|
||||||
else
|
else
|
||||||
@@ -881,21 +913,22 @@ screen_redraw_draw_status(struct screen_redraw_ctx *ctx)
|
|||||||
y = c->tty.sy - ctx->statuslines;
|
y = c->tty.sy - ctx->statuslines;
|
||||||
for (i = 0; i < ctx->statuslines; i++) {
|
for (i = 0; i < ctx->statuslines; i++) {
|
||||||
tty_draw_line(tty, s, 0, i, UINT_MAX, 0, y + i,
|
tty_draw_line(tty, s, 0, i, UINT_MAX, 0, y + i,
|
||||||
&grid_default_cell, NULL);
|
&grid_default_cell, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct ranges of line at px,py of width cells of base_wp that are
|
/* Construct ranges of line at px,py of width cells of base_wp that are
|
||||||
unobsructed. */
|
unobsructed. */
|
||||||
struct visible_ranges *
|
struct visible_ranges *
|
||||||
screen_redraw_get_visible_ranges(u_int px, u_int py, u_int width,
|
screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
|
||||||
struct window_pane *base_wp) {
|
u_int py, u_int width) {
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
static struct visible_ranges ranges = { NULL, 0, 0 };
|
static struct visible_ranges ranges = { NULL, 0, 0 };
|
||||||
static struct visible_range *vr;
|
static struct visible_range *vr;
|
||||||
int found_self;
|
int found_self, sb_w;
|
||||||
u_int r, s;
|
u_int r, s, lb, rb, tb, bb;
|
||||||
|
int pane_scrollbars;
|
||||||
|
|
||||||
/* For efficiency ranges is static and space reused. */
|
/* For efficiency ranges is static and space reused. */
|
||||||
if (ranges.array == NULL) {
|
if (ranges.array == NULL) {
|
||||||
@@ -913,6 +946,7 @@ screen_redraw_get_visible_ranges(u_int px, u_int py, u_int width,
|
|||||||
return (&ranges);
|
return (&ranges);
|
||||||
|
|
||||||
w = base_wp->window;
|
w = base_wp->window;
|
||||||
|
pane_scrollbars = options_get_number(w->options, "pane-scrollbars");
|
||||||
|
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
if (wp == base_wp) {
|
if (wp == base_wp) {
|
||||||
@@ -920,35 +954,43 @@ screen_redraw_get_visible_ranges(u_int px, u_int py, u_int width,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tb = wp->yoff-1;
|
||||||
|
bb = wp->yoff + wp->sy;
|
||||||
if (!found_self || wp->layout_cell != NULL ||
|
if (!found_self || wp->layout_cell != NULL ||
|
||||||
(wp->flags & PANE_MINIMISED) ||
|
(wp->flags & PANE_MINIMISED) ||
|
||||||
(py < wp->yoff || py > wp->yoff + wp->sy))
|
(py < tb || py > bb))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Are scrollbars enabled? */
|
||||||
|
if (window_pane_show_scrollbar(wp, pane_scrollbars))
|
||||||
|
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
|
||||||
|
|
||||||
for (r=0; r<ranges.n; r++) {
|
for (r=0; r<ranges.n; r++) {
|
||||||
|
lb = wp->xoff - 1;
|
||||||
|
rb = wp->xoff + wp->sx + sb_w + 1;
|
||||||
/* If the left edge of floating wp
|
/* If the left edge of floating wp
|
||||||
falls inside this range and right
|
falls inside this range and right
|
||||||
edge covers up to right of range,
|
edge covers up to right of range,
|
||||||
then shrink left edge of range. */
|
then shrink left edge of range. */
|
||||||
if (wp->xoff > vr[r].px &&
|
if (lb > vr[r].px &&
|
||||||
wp->xoff < vr[r].px + vr[r].nx &&
|
lb < vr[r].px + vr[r].nx &&
|
||||||
wp->xoff + wp->sx >= vr[r].px + vr[r].nx) {
|
rb >= vr[r].px + vr[r].nx) {
|
||||||
vr[r].nx = wp->xoff;
|
vr[r].nx = lb;
|
||||||
}
|
}
|
||||||
/* Else if the right edge of floating wp
|
/* Else if the right edge of floating wp
|
||||||
falls inside of this range and left
|
falls inside of this range and left
|
||||||
edge covers the left of range,
|
edge covers the left of range,
|
||||||
then move px forward to right edge of wp. */
|
then move px forward to right edge of wp. */
|
||||||
else if (wp->xoff + wp->sx > vr[r].px &&
|
else if (rb > vr[r].px &&
|
||||||
wp->xoff + wp->sx < vr[r].px + vr[r].nx &&
|
rb < vr[r].px + vr[r].nx &&
|
||||||
wp->xoff <= vr[r].px) {
|
lb <= vr[r].px) {
|
||||||
vr[r].px = vr[r].px + (wp->xoff + wp->sx);
|
vr[r].px = vr[r].px + rb;
|
||||||
vr[r].nx = vr[r].nx - (wp->xoff + wp->sx);
|
vr[r].nx = vr[r].nx - rb;
|
||||||
}
|
}
|
||||||
/* Else if wp fully inside range
|
/* Else if wp fully inside range
|
||||||
then split range into 2 ranges. */
|
then split range into 2 ranges. */
|
||||||
else if (wp->xoff > vr[r].px &&
|
else if (lb > vr[r].px &&
|
||||||
wp->xoff + wp->sx < vr[r].px + vr[r].nx) {
|
rb < vr[r].px + vr[r].nx) {
|
||||||
if (ranges.size == ranges.n) {
|
if (ranges.size == ranges.n) {
|
||||||
ranges.array = xreallocarray(vr,
|
ranges.array = xreallocarray(vr,
|
||||||
ranges.size += 4, sizeof *vr);
|
ranges.size += 4, sizeof *vr);
|
||||||
@@ -958,14 +1000,14 @@ screen_redraw_get_visible_ranges(u_int px, u_int py, u_int width,
|
|||||||
vr[s].px = vr[s-1].px;
|
vr[s].px = vr[s-1].px;
|
||||||
vr[s].nx = vr[s-1].nx;
|
vr[s].nx = vr[s-1].nx;
|
||||||
}
|
}
|
||||||
vr[r].nx = wp->xoff;
|
vr[r].nx = lb;
|
||||||
vr[r+1].px = wp->xoff + wp->sx;
|
vr[r+1].px = rb;
|
||||||
ranges.n++;
|
ranges.n++;
|
||||||
}
|
}
|
||||||
/* If floating wp completely covers this range
|
/* If floating wp completely covers this range
|
||||||
then delete it (make it 0 length). */
|
then delete it (make it 0 length). */
|
||||||
else if (wp->xoff <= vr[r].px &&
|
else if (lb <= vr[r].px &&
|
||||||
wp->xoff+wp->sx >= vr[r].px+vr[r].nx) {
|
rb >= vr[r].px+vr[r].nx) {
|
||||||
vr[r].nx = 0;
|
vr[r].nx = 0;
|
||||||
}
|
}
|
||||||
/* Else the range is already obscured, do nothing. */
|
/* Else the range is already obscured, do nothing. */
|
||||||
@@ -1030,11 +1072,13 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
|
|||||||
__func__, c->name, wp->id, i, j, x, y, width);
|
__func__, c->name, wp->id, i, j, x, y, width);
|
||||||
|
|
||||||
/* Get visible ranges of line before we draw it. */
|
/* Get visible ranges of line before we draw it. */
|
||||||
visible_ranges = screen_redraw_get_visible_ranges(x, y, width,
|
visible_ranges = screen_redraw_get_visible_ranges(wp, x, y,
|
||||||
wp);
|
width);
|
||||||
vr = visible_ranges->array;
|
vr = visible_ranges->array;
|
||||||
|
|
||||||
tty_default_colours(&defaults, wp);
|
tty_default_colours(&defaults, wp);
|
||||||
|
/* xxxx tty_draw_line should drawn only visible ranges. see xxxx commment in tty_draw_line. */
|
||||||
|
/*tty_draw_line(tty, s, i, j, width, x, y, &defaults, palette, visible_ranges); */
|
||||||
|
|
||||||
for (r=0; r<visible_ranges->n; r++) {
|
for (r=0; r<visible_ranges->n; r++) {
|
||||||
if (vr[r].nx == 0)
|
if (vr[r].nx == 0)
|
||||||
@@ -1043,7 +1087,8 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
|
|||||||
pane offset. If you don't sub offset,
|
pane offset. If you don't sub offset,
|
||||||
contents of pane shifted. */
|
contents of pane shifted. */
|
||||||
tty_draw_line(tty, s, i+vr[r].px-wp->xoff, j,
|
tty_draw_line(tty, s, i+vr[r].px-wp->xoff, j,
|
||||||
vr[r].nx, vr[r].px, y, &defaults, palette);
|
vr[r].nx, vr[r].px, y, &defaults, palette,
|
||||||
|
visible_ranges);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1745,67 +1745,24 @@ screen_write_collect_clear(struct screen_write_ctx *ctx, u_int y, u_int n)
|
|||||||
static void
|
static void
|
||||||
screen_write_collect_scroll(struct screen_write_ctx *ctx, u_int bg)
|
screen_write_collect_scroll(struct screen_write_ctx *ctx, u_int bg)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct screen_write_cline *cl_src, *cl_dst;
|
struct screen_write_cline *cl;
|
||||||
u_int y, r, r_start, r_end;
|
u_int y;
|
||||||
u_int ci_start, ci_end, new_end;
|
char *saved;
|
||||||
char *saved;
|
struct screen_write_citem *ci;
|
||||||
struct screen_write_citem *ci, *ci_tmp, *new_ci;
|
|
||||||
struct window_pane *wp = ctx->wp;
|
|
||||||
struct visible_ranges *visible_ranges;
|
|
||||||
struct visible_range *vr;
|
|
||||||
|
|
||||||
log_debug("%s: at %u,%u (region %u-%u)", __func__, s->cx, s->cy,
|
log_debug("%s: at %u,%u (region %u-%u)", __func__, s->cx, s->cy,
|
||||||
s->rupper, s->rlower);
|
s->rupper, s->rlower);
|
||||||
|
|
||||||
screen_write_collect_clear(ctx, s->rupper, 1);
|
screen_write_collect_clear(ctx, s->rupper, 1);
|
||||||
saved = s->write_list[s->rupper].data;
|
saved = ctx->s->write_list[s->rupper].data;
|
||||||
for (y = s->rupper; y < s->rlower; y++) {
|
for (y = s->rupper; y < s->rlower; y++) {
|
||||||
cl_src = &s->write_list[y + 1];
|
cl = &ctx->s->write_list[y + 1];
|
||||||
cl_dst = &s->write_list[y];
|
TAILQ_CONCAT(&ctx->s->write_list[y].items, &cl->items, entry);
|
||||||
|
ctx->s->write_list[y].data = cl->data;
|
||||||
visible_ranges = screen_redraw_get_visible_ranges(0, y,
|
|
||||||
screen_size_x(s), wp);
|
|
||||||
vr = visible_ranges->array;
|
|
||||||
|
|
||||||
/* For each visible range, copy corresponding items from cl_src
|
|
||||||
to cl_dst. */
|
|
||||||
for (r = 0; r < visible_ranges->n; r++) {
|
|
||||||
if (vr[r].nx == 0) continue;
|
|
||||||
r_start = vr[r].px;
|
|
||||||
r_end = vr[r].px + vr[r].nx;
|
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(ci, &cl_src->items, entry, ci_tmp) {
|
|
||||||
ci_start = ci->x;
|
|
||||||
ci_end = ci->x + ci->used;
|
|
||||||
|
|
||||||
if (ci_end <= r_start || ci_start >= r_end)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
new_ci = screen_write_get_citem();
|
|
||||||
new_ci->x = (ci_start < r_start) ?
|
|
||||||
r_start : ci_start;
|
|
||||||
new_end = (ci_end > r_end) ?
|
|
||||||
r_end : ci_end;
|
|
||||||
new_ci->used = new_end - new_ci->x;
|
|
||||||
new_ci->type = ci->type;
|
|
||||||
new_ci->wrapped = ci->wrapped;
|
|
||||||
new_ci->bg = bg;
|
|
||||||
memcpy(&new_ci->gc, &ci->gc, sizeof(ci->gc));
|
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&cl_dst->items, new_ci, entry);
|
|
||||||
TAILQ_REMOVE(&cl_src->items, ci, entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (! TAILQ_EMPTY(&cl_src->items)) {
|
|
||||||
screen_write_collect_clear(ctx, y+1, 1);
|
|
||||||
TAILQ_INIT(&cl_src->items);
|
|
||||||
}
|
|
||||||
ctx->s->write_list[y].data = cl_src->data;
|
|
||||||
}
|
}
|
||||||
s->write_list[s->rlower].data = saved;
|
ctx->s->write_list[s->rlower].data = saved;
|
||||||
return;
|
|
||||||
/* Also worked without this clear, is this needed? */
|
|
||||||
ci = screen_write_get_citem();
|
ci = screen_write_get_citem();
|
||||||
ci->x = 0;
|
ci->x = 0;
|
||||||
ci->used = screen_size_x(s);
|
ci->used = screen_size_x(s);
|
||||||
@@ -1855,8 +1812,8 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
|||||||
for (y = 0; y < screen_size_y(s); y++) {
|
for (y = 0; y < screen_size_y(s); y++) {
|
||||||
cl = &ctx->s->write_list[y];
|
cl = &ctx->s->write_list[y];
|
||||||
|
|
||||||
visible_ranges = screen_redraw_get_visible_ranges(0, y,
|
visible_ranges = screen_redraw_get_visible_ranges(wp, 0, y,
|
||||||
screen_size_x(s), wp);
|
screen_size_x(s));
|
||||||
vr = visible_ranges->array;
|
vr = visible_ranges->array;
|
||||||
|
|
||||||
last = UINT_MAX;
|
last = UINT_MAX;
|
||||||
@@ -1865,6 +1822,7 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
|||||||
fatalx("collect list not in order: %u <= %u",
|
fatalx("collect list not in order: %u <= %u",
|
||||||
ci->x, last);
|
ci->x, last);
|
||||||
}
|
}
|
||||||
|
wr_length = 0;
|
||||||
for (r = 0; r < visible_ranges->n; r++) {
|
for (r = 0; r < visible_ranges->n; r++) {
|
||||||
if (vr[r].nx == 0) continue;
|
if (vr[r].nx == 0) continue;
|
||||||
r_start = vr[r].px;
|
r_start = vr[r].px;
|
||||||
@@ -1880,6 +1838,7 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
|||||||
wr_end = (ci_end > r_end) ?
|
wr_end = (ci_end > r_end) ?
|
||||||
r_end : ci_end;
|
r_end : ci_end;
|
||||||
wr_length = wr_end - wr_start;
|
wr_length = wr_end - wr_start;
|
||||||
|
|
||||||
if (wr_length == 0)
|
if (wr_length == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -1889,7 +1848,7 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
|||||||
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);
|
||||||
ttyctx.cell = &ci->gc;
|
ttyctx.cell = &ci->gc;
|
||||||
@@ -1899,10 +1858,11 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
|||||||
tty_write(tty_cmd_cells, &ttyctx);
|
tty_write(tty_cmd_cells, &ttyctx);
|
||||||
}
|
}
|
||||||
items++;
|
items++;
|
||||||
|
|
||||||
|
TAILQ_REMOVE(&cl->items, ci, entry);
|
||||||
|
screen_write_free_citem(ci);
|
||||||
|
last = ci->x;
|
||||||
}
|
}
|
||||||
TAILQ_REMOVE(&cl->items, ci, entry);
|
|
||||||
screen_write_free_citem(ci);
|
|
||||||
last = ci->x;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s->cx = cx; s->cy = cy;
|
s->cx = cx; s->cy = cy;
|
||||||
|
|||||||
7
tmux.h
7
tmux.h
@@ -2531,7 +2531,8 @@ void tty_set_title(struct tty *, const char *);
|
|||||||
void tty_set_path(struct tty *, const char *);
|
void tty_set_path(struct tty *, const char *);
|
||||||
void tty_update_mode(struct tty *, int, struct screen *);
|
void tty_update_mode(struct tty *, int, struct screen *);
|
||||||
void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int,
|
void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int,
|
||||||
u_int, u_int, const struct grid_cell *, struct colour_palette *);
|
u_int, u_int, const struct grid_cell *, struct colour_palette *,
|
||||||
|
struct visible_ranges *);
|
||||||
|
|
||||||
#ifdef ENABLE_SIXEL
|
#ifdef ENABLE_SIXEL
|
||||||
void tty_draw_images(struct client *, struct window_pane *, struct screen *);
|
void tty_draw_images(struct client *, struct window_pane *, struct screen *);
|
||||||
@@ -3174,8 +3175,8 @@ void screen_write_alternateoff(struct screen_write_ctx *,
|
|||||||
/* screen-redraw.c */
|
/* screen-redraw.c */
|
||||||
void screen_redraw_screen(struct client *);
|
void screen_redraw_screen(struct client *);
|
||||||
void screen_redraw_pane(struct client *, struct window_pane *, int);
|
void screen_redraw_pane(struct client *, struct window_pane *, int);
|
||||||
struct visible_ranges *screen_redraw_get_visible_ranges(u_int, u_int, u_int,
|
struct visible_ranges *screen_redraw_get_visible_ranges(struct window_pane *,
|
||||||
struct window_pane *);
|
u_int, u_int, u_int);
|
||||||
|
|
||||||
|
|
||||||
/* screen.c */
|
/* screen.c */
|
||||||
|
|||||||
98
tty.c
98
tty.c
@@ -1365,22 +1365,30 @@ tty_clear_pane_area(struct tty *tty, const struct tty_ctx *ctx, u_int py,
|
|||||||
tty_clear_area(tty, &ctx->defaults, y, ry, x, rx, bg);
|
tty_clear_area(tty, &ctx->defaults, y, ry, x, rx, bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Redraw a line at py of a screen taking into account obscured ranges.
|
||||||
|
* Menus and popups are always on top, ctx->arg == NULL.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py)
|
tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
u_int nx = ctx->sx, i, x, rx, ry;
|
struct window_pane *wp = ctx->arg;
|
||||||
|
struct visible_ranges *visible_ranges = NULL;
|
||||||
|
u_int nx = ctx->sx, i, x, rx, ry;
|
||||||
|
|
||||||
log_debug("%s: %s %u %d", __func__, tty->client->name, py, ctx->bigger);
|
log_debug("%s: %s %u %d", __func__, tty->client->name, py, ctx->bigger);
|
||||||
|
|
||||||
|
if (wp)
|
||||||
|
visible_ranges = screen_redraw_get_visible_ranges(wp, 0, py, nx);
|
||||||
|
|
||||||
if (!ctx->bigger) {
|
if (!ctx->bigger) {
|
||||||
tty_draw_line(tty, s, 0, py, nx, ctx->xoff, ctx->yoff + py,
|
tty_draw_line(tty, s, 0, py, nx, ctx->xoff, ctx->yoff + py,
|
||||||
&ctx->defaults, ctx->palette);
|
&ctx->defaults, ctx->palette, visible_ranges);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tty_clamp_line(tty, ctx, 0, py, nx, &i, &x, &rx, &ry)) {
|
if (tty_clamp_line(tty, ctx, 0, py, nx, &i, &x, &rx, &ry)) {
|
||||||
tty_draw_line(tty, s, i, py, rx, x, ry, &ctx->defaults,
|
tty_draw_line(tty, s, i, py, rx, x, ry, &ctx->defaults,
|
||||||
ctx->palette);
|
ctx->palette, visible_ranges);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1457,10 +1465,38 @@ tty_check_overlay_range(struct tty *tty, u_int px, u_int py, u_int nx,
|
|||||||
c->overlay_check(c, c->overlay_data, px, py, nx, r);
|
c->overlay_check(c, c->overlay_data, px, py, nx, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if a single character is within a visible range (not obscured by a
|
||||||
|
* floating window pane). Returns a boolean.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
tty_check_in_visible_range(struct visible_ranges *visible_ranges, u_int px)
|
||||||
|
{
|
||||||
|
struct visible_range *vr;
|
||||||
|
u_int r;
|
||||||
|
|
||||||
|
/* No visible_ranges if called from a popup or menu. Always on top. */
|
||||||
|
if (visible_ranges == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
vr = visible_ranges->array;
|
||||||
|
|
||||||
|
/* Verify if px is in a visible range. */
|
||||||
|
for (r=0; r<visible_ranges->n; r++) {
|
||||||
|
if (vr[r].nx == 0)
|
||||||
|
continue;
|
||||||
|
if (px >= vr[r].px &&
|
||||||
|
px <= (vr[r].px + vr[r].nx))
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* px not found in any visible range, it is obscured by a pane. */
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||||
u_int atx, u_int aty, const struct grid_cell *defaults,
|
u_int atx, u_int aty, const struct grid_cell *defaults,
|
||||||
struct colour_palette *palette)
|
struct colour_palette *palette, struct visible_ranges *visible_ranges)
|
||||||
{
|
{
|
||||||
struct grid *gd = s->grid;
|
struct grid *gd = s->grid;
|
||||||
struct grid_cell gc, last;
|
struct grid_cell gc, last;
|
||||||
@@ -1517,6 +1553,10 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
|||||||
atx != 0 ||
|
atx != 0 ||
|
||||||
tty->cx < tty->sx ||
|
tty->cx < tty->sx ||
|
||||||
nx < tty->sx) {
|
nx < tty->sx) {
|
||||||
|
/* Do I need to check
|
||||||
|
!tty_is_obstructed(c->session->curw->window->active
|
||||||
|
here too? It's not certain that the active pane is
|
||||||
|
the one being drawn in. (delete this comment) */
|
||||||
if (nx < tty->sx &&
|
if (nx < tty->sx &&
|
||||||
atx == 0 &&
|
atx == 0 &&
|
||||||
px + sx != nx &&
|
px + sx != nx &&
|
||||||
@@ -1543,6 +1583,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
|||||||
gcp = tty_check_codeset(tty, &gc);
|
gcp = tty_check_codeset(tty, &gc);
|
||||||
if (len != 0 &&
|
if (len != 0 &&
|
||||||
(!tty_check_overlay(tty, atx + ux + width, aty) ||
|
(!tty_check_overlay(tty, atx + ux + width, aty) ||
|
||||||
|
!tty_check_in_visible_range(visible_ranges,
|
||||||
|
atx + ux + width) ||
|
||||||
(gcp->attr & GRID_ATTR_CHARSET) ||
|
(gcp->attr & GRID_ATTR_CHARSET) ||
|
||||||
gcp->flags != last.flags ||
|
gcp->flags != last.flags ||
|
||||||
gcp->attr != last.attr ||
|
gcp->attr != last.attr ||
|
||||||
@@ -1577,7 +1619,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
|||||||
|
|
||||||
tty_check_overlay_range(tty, atx + ux, aty, gcp->data.width,
|
tty_check_overlay_range(tty, atx + ux, aty, gcp->data.width,
|
||||||
&r);
|
&r);
|
||||||
hidden = 0;
|
hidden = 0; /* need to check visible_ranges too? xxxx */
|
||||||
for (j = 0; j < OVERLAY_MAX_RANGES; j++)
|
for (j = 0; j < OVERLAY_MAX_RANGES; j++)
|
||||||
hidden += r.nx[j];
|
hidden += r.nx[j];
|
||||||
hidden = gcp->data.width - hidden;
|
hidden = gcp->data.width - hidden;
|
||||||
@@ -1997,11 +2039,40 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
tty_putc(tty, '\n');
|
tty_putc(tty, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return 1 if there is a floating window pane overlapping this pane. */
|
||||||
|
static int
|
||||||
|
tty_is_obscured(const struct tty_ctx *ctx)
|
||||||
|
{
|
||||||
|
struct window_pane *base_wp = ctx->arg, *wp;
|
||||||
|
struct window *w;
|
||||||
|
int found_self = 0;
|
||||||
|
|
||||||
|
if (base_wp == NULL)
|
||||||
|
return(0);
|
||||||
|
w = base_wp->window;
|
||||||
|
|
||||||
|
/* Check if there is a floating pane. xxxx borders? scrollbars? */
|
||||||
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
|
if (wp == base_wp) {
|
||||||
|
found_self = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (found_self && wp->layout_cell == NULL &&
|
||||||
|
! (wp->flags & PANE_MINIMISED) &&
|
||||||
|
(wp->yoff > base_wp->yoff &&
|
||||||
|
wp->yoff + wp->sy < base_wp->yoff + base_wp->sy) &&
|
||||||
|
(wp->xoff > base_wp->xoff &&
|
||||||
|
wp->xoff + wp->sx < base_wp->xoff + base_wp->sx))
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
|
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->bigger ||
|
||||||
(!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
|
(!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
|
||||||
@@ -2009,7 +2080,8 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
!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 ||
|
||||||
|
tty_is_obscured(ctx)) {
|
||||||
tty_redraw_region(tty, ctx);
|
tty_redraw_region(tty, ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2168,6 +2240,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
const struct grid_cell *gcp = ctx->cell;
|
const struct grid_cell *gcp = ctx->cell;
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct overlay_ranges r;
|
struct overlay_ranges r;
|
||||||
|
struct window_pane *wp = ctx->arg;
|
||||||
|
struct visible_ranges *visible_ranges;
|
||||||
u_int px, py, i, vis = 0;
|
u_int px, py, i, vis = 0;
|
||||||
|
|
||||||
px = ctx->xoff + ctx->ocx - ctx->wox;
|
px = ctx->xoff + ctx->ocx - ctx->wox;
|
||||||
@@ -2176,6 +2250,9 @@ 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 (wp)
|
||||||
|
visible_ranges = screen_redraw_get_visible_ranges(wp, px, py, 1);
|
||||||
|
|
||||||
/* Handle partially obstructed wide characters. */
|
/* Handle partially obstructed wide characters. */
|
||||||
if (gcp->data.width > 1) {
|
if (gcp->data.width > 1) {
|
||||||
tty_check_overlay_range(tty, px, py, gcp->data.width, &r);
|
tty_check_overlay_range(tty, px, py, gcp->data.width, &r);
|
||||||
@@ -2183,7 +2260,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
vis += r.nx[i];
|
vis += r.nx[i];
|
||||||
if (vis < gcp->data.width) {
|
if (vis < gcp->data.width) {
|
||||||
tty_draw_line(tty, s, s->cx, s->cy, gcp->data.width,
|
tty_draw_line(tty, s, s->cx, s->cy, gcp->data.width,
|
||||||
px, py, &ctx->defaults, ctx->palette);
|
px, py, &ctx->defaults, ctx->palette,
|
||||||
|
visible_ranges);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user