mirror of
https://github.com/tmux/tmux.git
synced 2026-01-10 07:10:23 +00:00
Fix pane borders, including fixing 2 side-by-side or top-bottom panes with split coulering.
This commit is contained in:
228
screen-redraw.c
228
screen-redraw.c
@@ -137,9 +137,30 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
|
||||
sb_pos = 0;
|
||||
|
||||
/* Inside pane. */
|
||||
if ((int)px >= wp->xoff && (int)px < ex && (int)py >= wp->yoff && (int)py < ey)
|
||||
if ((int)px >= wp->xoff && (int)px < ex &&
|
||||
(int)py >= wp->yoff && (int)py < ey)
|
||||
return (SCREEN_REDRAW_INSIDE);
|
||||
|
||||
/* Are scrollbars enabled? */
|
||||
if (window_pane_show_scrollbar(wp, pane_scrollbars))
|
||||
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
|
||||
|
||||
/* Floating pane borders */
|
||||
if (wp->layout_cell == NULL) {
|
||||
if ((int)px == wp->xoff - 1 &&
|
||||
(int)py >= wp->yoff - 1 && (int)py <= wp->yoff + (int)wp->sy)
|
||||
return (SCREEN_REDRAW_BORDER_LEFT);
|
||||
if ((int)px == wp->xoff + (int)wp->sx + sb_w &&
|
||||
(int)py >= wp->yoff && (int)py <= wp->yoff + (int)wp->sy)
|
||||
return (SCREEN_REDRAW_BORDER_RIGHT);
|
||||
if ((int)py == wp->yoff - 1 &&
|
||||
(int)px >= wp->xoff && (int)px <= wp->xoff + (int)wp->sx)
|
||||
return (SCREEN_REDRAW_BORDER_TOP);
|
||||
if ((int)py == wp->yoff + (int)wp->sy &&
|
||||
(int)px >= wp->xoff && (int)px <= wp->xoff + (int)wp->sx)
|
||||
return (SCREEN_REDRAW_BORDER_BOTTOM);
|
||||
}
|
||||
|
||||
/* Get pane indicator. */
|
||||
switch (options_get_number(oo, "pane-border-indicators")) {
|
||||
case PANE_BORDER_COLOUR:
|
||||
@@ -151,10 +172,6 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Are scrollbars enabled? */
|
||||
if (window_pane_show_scrollbar(wp, pane_scrollbars))
|
||||
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
|
||||
|
||||
/*
|
||||
* Left/right borders. The wp->sy / 2 test is to colour only half the
|
||||
* active window's border when there are two panes.
|
||||
@@ -177,7 +194,8 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
|
||||
return (SCREEN_REDRAW_BORDER_RIGHT);
|
||||
if (wp->xoff != 0) {
|
||||
if ((int)px == wp->xoff - 1 &&
|
||||
(!hsplit || (hsplit && py > wp->sy / 2)))
|
||||
(!hsplit ||
|
||||
(hsplit && py > wp->sy / 2)))
|
||||
return (SCREEN_REDRAW_BORDER_LEFT);
|
||||
if (px == wp->xoff + wp->sx + sb_w)
|
||||
return (SCREEN_REDRAW_BORDER_RIGHT);
|
||||
@@ -193,8 +211,10 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
|
||||
return (SCREEN_REDRAW_BORDER_TOP);
|
||||
} else {
|
||||
if (sb_pos == PANE_SCROLLBARS_LEFT) {
|
||||
if ((wp->xoff - sb_w == 0 || (int)px >= wp->xoff - sb_w) &&
|
||||
((int)px <= ex || (sb_w != 0 && (int)px < ex + sb_w))) {
|
||||
if ((wp->xoff - sb_w == 0 ||
|
||||
(int)px >= wp->xoff - sb_w) &&
|
||||
((int)px <= ex ||
|
||||
(sb_w != 0 && (int)px < ex + sb_w))) {
|
||||
if (wp->yoff != 0 && (int)py == wp->yoff - 1)
|
||||
return (SCREEN_REDRAW_BORDER_TOP);
|
||||
if ((int)py == ey)
|
||||
@@ -202,7 +222,8 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
|
||||
}
|
||||
} else { /* sb_pos == PANE_SCROLLBARS_RIGHT */
|
||||
if ((wp->xoff == 0 || (int)px >= wp->xoff) &&
|
||||
((int)px <= ex || (sb_w != 0 && (int)px < ex + sb_w))) {
|
||||
((int)px <= ex ||
|
||||
(sb_w != 0 && (int)px < ex + sb_w))) {
|
||||
if (wp->yoff != 0 && (int)py == wp->yoff - 1)
|
||||
return (SCREEN_REDRAW_BORDER_TOP);
|
||||
if ((int)py == ey)
|
||||
@@ -217,12 +238,17 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
|
||||
|
||||
/* Check if a cell is on a border. */
|
||||
static int
|
||||
screen_redraw_cell_border(struct screen_redraw_ctx *ctx, u_int px, u_int py)
|
||||
screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
|
||||
u_int px, u_int py)
|
||||
{
|
||||
struct client *c = ctx->c;
|
||||
struct window *w = c->session->curw->window;
|
||||
struct window_pane *wp;
|
||||
struct window_pane *wp2;
|
||||
u_int sy = w->sy;
|
||||
int sb_w, floating = 0;
|
||||
|
||||
sb_w = wp->scrollbar_style.width +
|
||||
wp->scrollbar_style.pad;
|
||||
|
||||
if (ctx->pane_status == PANE_STATUS_BOTTOM)
|
||||
sy--;
|
||||
@@ -235,11 +261,29 @@ screen_redraw_cell_border(struct screen_redraw_ctx *ctx, u_int px, u_int py)
|
||||
if (px == w->sx || py == sy)
|
||||
return (1);
|
||||
|
||||
/* If checking a cell from a tiled pane, ignore floating panes
|
||||
* because 2 side-by-side or top-bottom panes share a border
|
||||
* which is used to do split coulering. Essentially treat all
|
||||
* non-floating panes as being in a single z-index.
|
||||
*
|
||||
* If checking a cell from a floating pane, only check cells
|
||||
* from this floating pane, again, essentially only this z-index.
|
||||
*/
|
||||
floating = (wp->layout_cell == NULL);
|
||||
|
||||
/* Check all the panes. */
|
||||
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||
if (!window_pane_visible(wp))
|
||||
TAILQ_FOREACH(wp2, &w->z_index, zentry) {
|
||||
if (!window_pane_visible(wp2) ||
|
||||
(wp->flags & PANE_MINIMISED) ||
|
||||
(!floating && wp2->layout_cell==NULL) ||
|
||||
(floating && wp2 != wp))
|
||||
continue;
|
||||
switch (screen_redraw_pane_border(ctx, wp, px, py)) {
|
||||
if (((int)px < wp2->xoff - 1 ||
|
||||
(int)px > wp2->xoff + (int)wp2->sx + sb_w) &&
|
||||
((int)py < wp2->yoff - 1 ||
|
||||
(int)py > wp2->yoff + (int)wp2->sy))
|
||||
continue;
|
||||
switch (screen_redraw_pane_border(ctx, wp2, px, py)) {
|
||||
case SCREEN_REDRAW_INSIDE:
|
||||
return (0);
|
||||
case SCREEN_REDRAW_OUTSIDE:
|
||||
@@ -254,7 +298,8 @@ screen_redraw_cell_border(struct screen_redraw_ctx *ctx, u_int px, u_int py)
|
||||
|
||||
/* Work out type of border cell from surrounding cells. */
|
||||
static int
|
||||
screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py)
|
||||
screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx,
|
||||
struct window_pane *wp, u_int px, u_int py)
|
||||
{
|
||||
struct client *c = ctx->c;
|
||||
int pane_status = ctx->pane_status;
|
||||
@@ -277,28 +322,28 @@ screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py)
|
||||
* 8 + 4
|
||||
* 1
|
||||
*/
|
||||
if (px == 0 || screen_redraw_cell_border(ctx, px - 1, py))
|
||||
if (px == 0 || screen_redraw_cell_border(ctx, wp, px - 1, py))
|
||||
borders |= 8;
|
||||
if (px <= sx && screen_redraw_cell_border(ctx, px + 1, py))
|
||||
if (px <= sx && screen_redraw_cell_border(ctx, wp, px + 1, py))
|
||||
borders |= 4;
|
||||
if (pane_status == PANE_STATUS_TOP) {
|
||||
if (py != 0 &&
|
||||
screen_redraw_cell_border(ctx, px, py - 1))
|
||||
screen_redraw_cell_border(ctx, wp, px, py - 1))
|
||||
borders |= 2;
|
||||
if (screen_redraw_cell_border(ctx, px, py + 1))
|
||||
if (screen_redraw_cell_border(ctx, wp, px, py + 1))
|
||||
borders |= 1;
|
||||
} else if (pane_status == PANE_STATUS_BOTTOM) {
|
||||
if (py == 0 ||
|
||||
screen_redraw_cell_border(ctx, px, py - 1))
|
||||
screen_redraw_cell_border(ctx, wp, px, py - 1))
|
||||
borders |= 2;
|
||||
if (py != sy &&
|
||||
screen_redraw_cell_border(ctx, px, py + 1))
|
||||
screen_redraw_cell_border(ctx, wp, px, py + 1))
|
||||
borders |= 1;
|
||||
} else {
|
||||
if (py == 0 ||
|
||||
screen_redraw_cell_border(ctx, px, py - 1))
|
||||
screen_redraw_cell_border(ctx, wp, px, py - 1))
|
||||
borders |= 2;
|
||||
if (screen_redraw_cell_border(ctx, px, py + 1))
|
||||
if (screen_redraw_cell_border(ctx, wp, px, py + 1))
|
||||
borders |= 1;
|
||||
}
|
||||
|
||||
@@ -345,61 +390,24 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
|
||||
int pane_status = ctx->pane_status;
|
||||
u_int sx = w->sx, sy = w->sy;
|
||||
int border, pane_scrollbars = ctx->pane_scrollbars;
|
||||
u_int right, line;
|
||||
u_int pane_status_line;
|
||||
int sb_pos = ctx->pane_scrollbars_pos;
|
||||
int sb_w;
|
||||
int sb_w, left, right, tiled_only=0;
|
||||
|
||||
*wpp = NULL;
|
||||
|
||||
if (px > sx || py > sy)
|
||||
return (CELL_OUTSIDE);
|
||||
if (px == sx || py == sy) /* window border */
|
||||
return (screen_redraw_type_of_cell(ctx, px, py));
|
||||
|
||||
if (pane_status != PANE_STATUS_OFF) {
|
||||
/* Look for higest z-index window at px,py. xxxx scrollbars? */
|
||||
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||
if (! (wp->flags & PANE_MINIMISED) &&
|
||||
((int)px >= wp->xoff - 1 && (int)px <= wp->xoff + (int)wp->sx + 1) &&
|
||||
((int)py >= wp->yoff - 1 && (int)py <= wp->yoff + (int)wp->sy + 1))
|
||||
break;
|
||||
}
|
||||
if (wp != NULL)
|
||||
start = wp;
|
||||
else
|
||||
start = wp = server_client_get_pane(c);
|
||||
|
||||
do {
|
||||
if (!window_pane_visible(wp))
|
||||
goto next1;
|
||||
|
||||
/* Pane border status inside top/bottom border
|
||||
* is CELL_INSIDE so it doesn't get overdrawn.
|
||||
*/
|
||||
if (pane_status == PANE_STATUS_TOP)
|
||||
line = wp->yoff - 1;
|
||||
else
|
||||
line = wp->yoff + sy;
|
||||
right = wp->xoff + 2 + wp->status_size - 1;
|
||||
|
||||
if (py == line && (int)px >= wp->xoff + 2 && px <= right)
|
||||
return (CELL_INSIDE);
|
||||
|
||||
next1:
|
||||
wp = TAILQ_NEXT(wp, entry);
|
||||
if (wp == NULL)
|
||||
wp = TAILQ_FIRST(&w->panes);
|
||||
} while (wp != start);
|
||||
}
|
||||
|
||||
|
||||
/* Look for higest z-index window at px,py. */
|
||||
/* Look through panes in z-index order starting with active pane. */
|
||||
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||
sb_w = wp->scrollbar_style.width +
|
||||
wp->scrollbar_style.pad;
|
||||
if (! (wp->flags & PANE_MINIMISED) &&
|
||||
((int)px >= wp->xoff - 1 && (int)px <= wp->xoff + (int)wp->sx + sb_w) &&
|
||||
((int)py >= wp->yoff - 1 && (int)py <= wp->yoff + (int)wp->sy))
|
||||
((int)px >= wp->xoff - 1 &&
|
||||
(int)px <= wp->xoff + (int)wp->sx + sb_w) &&
|
||||
((int)py >= wp->yoff - 1 &&
|
||||
(int)py <= wp->yoff + (int)wp->sy))
|
||||
break;
|
||||
}
|
||||
if (wp == NULL)
|
||||
@@ -407,25 +415,63 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
|
||||
else
|
||||
start = wp;
|
||||
|
||||
do {
|
||||
if (!window_pane_visible(wp))
|
||||
goto next2;
|
||||
if (px == sx || py == sy) /* window border */
|
||||
return (screen_redraw_type_of_cell(ctx, wp, px, py));
|
||||
|
||||
/* If this is a tiled window, then only check other tiled
|
||||
* windows. This is necessary if there are 2 side-by-side or
|
||||
* top-bottom windows with a shared border and half the shared
|
||||
* border is the active border.
|
||||
*/
|
||||
if (wp->layout_cell != NULL)
|
||||
tiled_only = 1;
|
||||
|
||||
do { /* Loop until back to wp==start.*/
|
||||
|
||||
if (!window_pane_visible(wp) ||
|
||||
(wp->flags & PANE_MINIMISED) ||
|
||||
(tiled_only && wp->layout_cell==NULL))
|
||||
goto next;
|
||||
*wpp = wp;
|
||||
|
||||
sb_w = wp->scrollbar_style.width +
|
||||
wp->scrollbar_style.pad;
|
||||
|
||||
if (((int)px < wp->xoff - 1 ||
|
||||
(int)px > wp->xoff + (int)wp->sx + sb_w) &&
|
||||
((int)py < wp->yoff - 1 ||
|
||||
(int)py > wp->yoff + (int)wp->sy))
|
||||
goto next;
|
||||
|
||||
if (pane_status != PANE_STATUS_OFF) {
|
||||
/* Pane border status inside top/bottom border is
|
||||
* CELL_INSIDE so it doesn't get overdrawn by a border
|
||||
* line.
|
||||
*/
|
||||
if (pane_status == PANE_STATUS_TOP)
|
||||
pane_status_line = wp->yoff - 1;
|
||||
else
|
||||
pane_status_line = wp->yoff + sy;
|
||||
left = wp->xoff + 2;
|
||||
right = wp->xoff + 2 + wp->status_size - 1;
|
||||
|
||||
if (py == pane_status_line &&
|
||||
(int)px >= left && (int)px <= right)
|
||||
return (CELL_INSIDE);
|
||||
}
|
||||
|
||||
/* Check if CELL_SCROLLBAR */
|
||||
if (window_pane_show_scrollbar(wp, pane_scrollbars)) {
|
||||
|
||||
line = wp->yoff + wp->sy;
|
||||
|
||||
/*
|
||||
* Check if py could lie within a scrollbar. If the
|
||||
* pane is at the top then py == 0 to sy; if the pane
|
||||
* is not at the top, then yoff to yoff + sy.
|
||||
*/
|
||||
sb_w = wp->scrollbar_style.width +
|
||||
wp->scrollbar_style.pad;
|
||||
wp->scrollbar_style.pad;
|
||||
if ((wp->yoff == 0 && py < wp->sy) ||
|
||||
((int)py >= wp->yoff && (int)py < wp->yoff + (int)wp->sy)) {
|
||||
((int)py >= wp->yoff &&
|
||||
(int)py < wp->yoff + (int)wp->sy)) {
|
||||
/* Check if px lies within a scrollbar. */
|
||||
if ((sb_pos == PANE_SCROLLBARS_RIGHT &&
|
||||
((int)px >= wp->xoff + (int)wp->sx &&
|
||||
@@ -445,13 +491,13 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
|
||||
if (border == SCREEN_REDRAW_INSIDE)
|
||||
return (CELL_INSIDE);
|
||||
if (border == SCREEN_REDRAW_OUTSIDE)
|
||||
goto next2;
|
||||
return (screen_redraw_type_of_cell(ctx, px, py));
|
||||
goto next;
|
||||
return (screen_redraw_type_of_cell(ctx, wp, px, py));
|
||||
|
||||
next2:
|
||||
wp = TAILQ_NEXT(wp, entry);
|
||||
next:
|
||||
wp = TAILQ_NEXT(wp, zentry);
|
||||
if (wp == NULL)
|
||||
wp = TAILQ_FIRST(&w->panes);
|
||||
wp = TAILQ_FIRST(&w->z_index);
|
||||
} while (wp != start);
|
||||
|
||||
return (CELL_OUTSIDE);
|
||||
@@ -516,7 +562,7 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
|
||||
py = wp->yoff - 1;
|
||||
else
|
||||
py = wp->yoff + wp->sy;
|
||||
cell_type = screen_redraw_type_of_cell(rctx, px, py);
|
||||
cell_type = screen_redraw_type_of_cell(rctx, wp, px, py);
|
||||
screen_redraw_border_set(w, wp, pane_lines, cell_type, &gc);
|
||||
screen_write_cell(&ctx, &gc);
|
||||
}
|
||||
@@ -594,12 +640,14 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
|
||||
|
||||
if (ctx->statustop)
|
||||
yoff += ctx->statuslines;
|
||||
vr = screen_redraw_get_visible_ranges(wp, x, yoff - ctx->oy, width);
|
||||
vr = screen_redraw_get_visible_ranges(wp, x, yoff - ctx->oy,
|
||||
width);
|
||||
|
||||
for (r=0; r < vr->used; r++) {
|
||||
if (vr->nx[r] == 0)
|
||||
continue;
|
||||
tty_draw_line(tty, s, i + (vr->px[r] - x), 0, vr->nx[r], vr->px[r], yoff - ctx->oy,
|
||||
tty_draw_line(tty, s, i + (vr->px[r] - x), 0, vr->nx[r],
|
||||
vr->px[r], yoff - ctx->oy,
|
||||
&grid_default_cell, NULL);
|
||||
}
|
||||
}
|
||||
@@ -992,7 +1040,8 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
|
||||
|
||||
/* Are scrollbars enabled? */
|
||||
if (window_pane_show_scrollbar(wp, pane_scrollbars))
|
||||
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
|
||||
sb_w = wp->scrollbar_style.width +
|
||||
wp->scrollbar_style.pad;
|
||||
|
||||
for (r=0; r < vr.used; r++) {
|
||||
if (wp->xoff > 0)
|
||||
@@ -1009,7 +1058,6 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
|
||||
if (lb > vr.px[r] &&
|
||||
lb < vr.px[r] + vr.nx[r] &&
|
||||
rb >= vr.px[r] + vr.nx[r]) {
|
||||
/* vr.nx[r] = vr.nx[r] - ((vr.px[r] + vr.nx[r]) - lb); */
|
||||
vr.nx[r] = lb - vr.px[r];
|
||||
}
|
||||
/* Else if the right edge of floating wp
|
||||
@@ -1077,7 +1125,8 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
|
||||
|
||||
log_debug("%s: %s @%u %%%u", __func__, c->name, w->id, wp->id);
|
||||
|
||||
if (wp->xoff + (int)wp->sx <= ctx->ox || wp->xoff >= ctx->ox + (int)ctx->sx)
|
||||
if (wp->xoff + (int)wp->sx <= ctx->ox ||
|
||||
wp->xoff >= ctx->ox + (int)ctx->sx)
|
||||
return;
|
||||
if (ctx->statustop)
|
||||
top = ctx->statuslines;
|
||||
@@ -1085,11 +1134,14 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
|
||||
top = 0;
|
||||
|
||||
for (j = 0; j < wp->sy; j++) {
|
||||
if (wp->yoff + (int)j < ctx->oy || wp->yoff + j >= ctx->oy + ctx->sy)
|
||||
if (wp->yoff + (int)j < ctx->oy ||
|
||||
wp->yoff + j >= ctx->oy + ctx->sy)
|
||||
continue;
|
||||
y = top + wp->yoff + j - ctx->oy;
|
||||
|
||||
/* xxx i apparenty unneeded now that the vr array returns where in s to read from. */
|
||||
/* Note: i is apparenty not used now that the vr array
|
||||
* returns where in s to read from.
|
||||
*/
|
||||
if (wp->xoff >= ctx->ox &&
|
||||
wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
|
||||
/* All visible. */
|
||||
|
||||
12
window.c
12
window.c
@@ -586,11 +586,17 @@ window_redraw_active_switch(struct window *w, struct window_pane *wp)
|
||||
}
|
||||
if (wp == w->active)
|
||||
break;
|
||||
|
||||
/* If you want tiled planes to be able to bury
|
||||
* floating planes then do this regardless of
|
||||
* wp->layout_cell==NULL or not. A new option?
|
||||
*/
|
||||
if (wp->layout_cell == NULL) {
|
||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
|
||||
wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
|
||||
wp = w->active;
|
||||
}
|
||||
}
|
||||
@@ -767,7 +773,11 @@ window_add_pane(struct window *w, struct window_pane *other, u_int hlimit,
|
||||
else
|
||||
TAILQ_INSERT_AFTER(&w->panes, other, wp, entry);
|
||||
}
|
||||
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
|
||||
/* Floating panes are created above tiled planes. */
|
||||
if (flags & (SPAWN_FLOATING))
|
||||
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
|
||||
else
|
||||
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
|
||||
return (wp);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user