mirror of
https://github.com/tmux/tmux.git
synced 2026-01-11 08:21:52 +00:00
Add support in screen-write.c to properly display cmd output when there are floating panes on the screen.
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 = 0;
|
sc.xoff = 10;
|
||||||
sc.yoff = 0;
|
sc.yoff = 10;
|
||||||
sc.sx = sx;
|
sc.sx = sx;
|
||||||
sc.sy = sy;
|
sc.sy = sy;
|
||||||
|
|
||||||
|
|||||||
@@ -885,34 +885,41 @@ screen_redraw_draw_status(struct screen_redraw_ctx *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct visual_range {
|
/* Construct ranges of line at px,py of width cells of base_wp that are
|
||||||
u_int px;
|
unobsructed. */
|
||||||
u_int nx;
|
void
|
||||||
};
|
screen_redraw_get_visible_ranges(u_int px, u_int py, u_int width,
|
||||||
|
struct window_pane *base_wp, struct visible_range **vr_p,
|
||||||
|
int *vr_count_p) {
|
||||||
|
struct window_pane *wp;
|
||||||
|
struct window *w;
|
||||||
|
struct visible_range *vr;
|
||||||
|
int found_self, r, s;
|
||||||
|
int vr_len, vr_count;
|
||||||
|
|
||||||
static void
|
/* Caller must call free(vr). */
|
||||||
screen_redraw_get_visual_ranges(u_int px, u_int py, u_int width,
|
vr = xcalloc(4, sizeof(struct visible_range *));
|
||||||
struct window_pane *base_wp, struct window *w,
|
vr_len = 4;
|
||||||
struct visual_range **vr_p, int *vr_count_p) {
|
vr[0].px = px;
|
||||||
struct visual_range *vr;
|
|
||||||
int found_self, r, s;
|
|
||||||
int vr_len, vr_count;
|
|
||||||
struct window_pane *wp;
|
|
||||||
|
|
||||||
vr = xcalloc(4, sizeof(struct visual_range *));
|
|
||||||
vr_len = 4; // 4 initial slots
|
|
||||||
vr[0].px = px; // initialise first slot
|
|
||||||
vr[0].nx = width;
|
vr[0].nx = width;
|
||||||
vr_count = 1;
|
vr_count = 1;
|
||||||
|
|
||||||
|
if (base_wp == NULL) {
|
||||||
|
*vr_p = vr;
|
||||||
|
*vr_count_p = vr_count;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
w = base_wp->window;
|
||||||
|
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
if (wp == base_wp) { // wp == current pane
|
if (wp == base_wp) {
|
||||||
found_self = 1;
|
found_self = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (found_self && wp->layout_cell == NULL &&
|
if (found_self && wp->layout_cell == NULL &&
|
||||||
!(wp->flags & PANE_MINIMISED) &&
|
!(wp->flags & PANE_MINIMISED) &&
|
||||||
(wp->yoff >= py && py <= wp->yoff + wp->sy)) {
|
(py >= wp->yoff && py <= wp->yoff + wp->sy)) {
|
||||||
for (r=0; r<vr_count; r++) {
|
for (r=0; r<vr_count; r++) {
|
||||||
/* if the left edge of wp
|
/* if the left edge of wp
|
||||||
falls inside this range and right
|
falls inside this range and right
|
||||||
@@ -920,19 +927,20 @@ screen_redraw_get_visual_ranges(u_int px, u_int py, u_int width,
|
|||||||
then shrink nx */
|
then shrink nx */
|
||||||
if (wp->xoff > vr[r].px &&
|
if (wp->xoff > vr[r].px &&
|
||||||
wp->xoff < vr[r].px + vr[r].nx &&
|
wp->xoff < vr[r].px + vr[r].nx &&
|
||||||
wp->xoff + wp->sx > vr[r].px + vr[r].nx)
|
wp->xoff + wp->sx > vr[r].px + vr[r].nx) {
|
||||||
vr[r].nx = wp->xoff;
|
vr[r].nx = wp->xoff;
|
||||||
/* else if the right edge of wp
|
/* else if the right edge of wp
|
||||||
falls inside of this range and left
|
falls inside of this range and left
|
||||||
edge is less than the start of the range,
|
edge is less than the start of the range,
|
||||||
then move px forward */
|
then move px forward */
|
||||||
else if (wp->xoff + wp->sx > vr[r].px &&
|
} else if (wp->xoff + wp->sx > vr[r].px &&
|
||||||
wp->xoff + wp->sx < vr[r].px + vr[r].nx &&
|
wp->xoff + wp->sx < vr[r].px + vr[r].nx &&
|
||||||
wp->xoff < vr[r].px + vr[r].nx)
|
wp->xoff < vr[r].px) {
|
||||||
vr[r].px = wp->xoff + wp->sx;
|
vr[r].px = vr[r].px + (wp->xoff + wp->sx);
|
||||||
|
vr[r].nx = vr[r].nx - (wp->xoff + wp->sx);
|
||||||
/* 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 (wp->xoff > vr[r].px &&
|
||||||
wp->xoff + wp->sx < vr[r].px + vr[r].nx) {
|
wp->xoff + wp->sx < vr[r].px + vr[r].nx) {
|
||||||
/* make space */
|
/* make space */
|
||||||
if (vr_len == vr_count) {
|
if (vr_len == vr_count) {
|
||||||
@@ -946,7 +954,8 @@ screen_redraw_get_visual_ranges(u_int px, u_int py, u_int width,
|
|||||||
}
|
}
|
||||||
vr[r].nx = wp->xoff;
|
vr[r].nx = wp->xoff;
|
||||||
vr[r+1].px = wp->xoff + wp->sx;
|
vr[r+1].px = wp->xoff + wp->sx;
|
||||||
}
|
vr_count++;
|
||||||
|
} /* XXX what if it's completely obscured? */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -965,7 +974,7 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
|
|||||||
struct screen *s = wp->screen;
|
struct screen *s = wp->screen;
|
||||||
struct colour_palette *palette = &wp->palette;
|
struct colour_palette *palette = &wp->palette;
|
||||||
struct grid_cell defaults;
|
struct grid_cell defaults;
|
||||||
struct visual_range *vr;
|
struct visible_range *vr;
|
||||||
int vr_count, r;
|
int vr_count, r;
|
||||||
u_int i, j, top, x, y, width;
|
u_int i, j, top, x, y, width;
|
||||||
|
|
||||||
@@ -1009,12 +1018,15 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
|
|||||||
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, x, y, width);
|
||||||
|
|
||||||
screen_redraw_get_visual_ranges(x, y, width, wp, w, &vr, &vr_count);
|
/* Get visible ranges of line before we draw it. */
|
||||||
|
screen_redraw_get_visible_ranges(x, y, width, wp,
|
||||||
|
&vr, &vr_count);
|
||||||
|
|
||||||
tty_default_colours(&defaults, wp);
|
tty_default_colours(&defaults, wp);
|
||||||
|
|
||||||
for (r=0; r<vr_count; r++)
|
for (r=0; r<vr_count; r++)
|
||||||
tty_draw_line(tty, s, i, j, vr[r].nx, vr[r].px, y, &defaults, palette);
|
tty_draw_line(tty, s, i + vr[r].px, j,
|
||||||
|
vr[r].nx, vr[r].px, y, &defaults, palette);
|
||||||
free(vr);
|
free(vr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
157
screen-write.c
157
screen-write.c
@@ -1745,30 +1745,72 @@ 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;
|
struct screen_write_cline *cl_src, *cl_dst;
|
||||||
u_int y;
|
u_int y, r_start, r_end;
|
||||||
char *saved;
|
u_int ci_start, ci_end, new_end;
|
||||||
struct screen_write_citem *ci;
|
char *saved;
|
||||||
|
struct screen_write_citem *ci, *new_ci;
|
||||||
|
struct window_pane *wp = ctx->wp;
|
||||||
|
struct visible_range *vr;
|
||||||
|
int vr_count, r;
|
||||||
|
|
||||||
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 = ctx->s->write_list[s->rupper].data;
|
saved = s->write_list[s->rupper].data;
|
||||||
for (y = s->rupper; y < s->rlower; y++) {
|
|
||||||
cl = &ctx->s->write_list[y + 1];
|
|
||||||
TAILQ_CONCAT(&ctx->s->write_list[y].items, &cl->items, entry);
|
|
||||||
ctx->s->write_list[y].data = cl->data;
|
|
||||||
}
|
|
||||||
ctx->s->write_list[s->rlower].data = saved;
|
|
||||||
|
|
||||||
ci = screen_write_get_citem();
|
/* For each line being scrolled, copy visible ranges from the line
|
||||||
ci->x = 0;
|
below to the line above. */
|
||||||
ci->used = screen_size_x(s);
|
for (y = s->rupper; y < s->rlower; y++) {
|
||||||
ci->type = CLEAR;
|
cl_src = &s->write_list[y + 1];
|
||||||
ci->bg = bg;
|
cl_dst = &s->write_list[y];
|
||||||
TAILQ_INSERT_TAIL(&ctx->s->write_list[s->rlower].items, ci, entry);
|
vr = NULL;
|
||||||
|
vr_count = 0;
|
||||||
|
|
||||||
|
screen_redraw_get_visible_ranges(0, y, screen_size_x(s), wp,
|
||||||
|
&vr, &vr_count);
|
||||||
|
|
||||||
|
TAILQ_INIT(&cl_dst->items);
|
||||||
|
|
||||||
|
if (cl_dst->data == NULL)
|
||||||
|
cl_dst->data = xmalloc(screen_size_x(s));
|
||||||
|
|
||||||
|
/* For each visible range, copy corresponding items from cl_src
|
||||||
|
to cl_dst. */
|
||||||
|
for (r = 0; r < vr_count; r++) {
|
||||||
|
r_start = vr[r].px;
|
||||||
|
r_end = vr[r].px + vr[r].nx;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(ci, &cl_src->items, entry) {
|
||||||
|
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));
|
||||||
|
if (ci->type == TEXT)
|
||||||
|
memcpy(cl_dst->data, cl_src->data,
|
||||||
|
screen_size_x(s));
|
||||||
|
TAILQ_INSERT_TAIL(&cl_dst->items, new_ci,
|
||||||
|
entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(vr);
|
||||||
|
}
|
||||||
|
s->write_list[s->rlower].data = saved;
|
||||||
|
|
||||||
|
screen_write_collect_clear(ctx, s->rlower, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush collected lines. */
|
/* Flush collected lines. */
|
||||||
@@ -1780,7 +1822,12 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
|||||||
struct screen_write_citem *ci, *tmp;
|
struct screen_write_citem *ci, *tmp;
|
||||||
struct screen_write_cline *cl;
|
struct screen_write_cline *cl;
|
||||||
u_int y, cx, cy, last, items = 0;
|
u_int y, cx, cy, last, items = 0;
|
||||||
|
u_int r_start, r_end, ci_start, ci_end;
|
||||||
|
u_int wr_start, wr_end, wr_length;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
|
struct visible_range *vr = NULL;
|
||||||
|
int vr_count = 0;
|
||||||
|
struct window_pane *wp = ctx->wp;
|
||||||
|
|
||||||
if (ctx->scrolled != 0) {
|
if (ctx->scrolled != 0) {
|
||||||
log_debug("%s: scrolled %u (region %u-%u)", __func__,
|
log_debug("%s: scrolled %u (region %u-%u)", __func__,
|
||||||
@@ -1803,34 +1850,57 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
cx = s->cx; cy = s->cy;
|
cx = s->cx; cy = s->cy;
|
||||||
|
|
||||||
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];
|
||||||
|
|
||||||
|
screen_redraw_get_visible_ranges(0, y, screen_size_x(s), wp,
|
||||||
|
&vr, &vr_count);
|
||||||
|
|
||||||
last = UINT_MAX;
|
last = UINT_MAX;
|
||||||
TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
|
TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
|
||||||
if (last != UINT_MAX && ci->x <= last) {
|
if (last != UINT_MAX && ci->x <= last) {
|
||||||
fatalx("collect list not in order: %u <= %u",
|
fatalx("collect list not in order: %u <= %u",
|
||||||
ci->x, last);
|
ci->x, last);
|
||||||
}
|
}
|
||||||
screen_write_set_cursor(ctx, ci->x, y);
|
for (int r = 0; r < vr_count; r++) {
|
||||||
if (ci->type == CLEAR) {
|
r_start = vr[r].px;
|
||||||
screen_write_initctx(ctx, &ttyctx, 1);
|
r_end = vr[r].px + vr[r].nx;
|
||||||
ttyctx.bg = ci->bg;
|
ci_start = ci->x;
|
||||||
ttyctx.num = ci->used;
|
ci_end = ci->x + ci->used;
|
||||||
tty_write(tty_cmd_clearcharacter, &ttyctx);
|
|
||||||
} else {
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
|
||||||
ttyctx.cell = &ci->gc;
|
|
||||||
ttyctx.wrapped = ci->wrapped;
|
|
||||||
ttyctx.ptr = cl->data + ci->x;
|
|
||||||
ttyctx.num = ci->used;
|
|
||||||
tty_write(tty_cmd_cells, &ttyctx);
|
|
||||||
}
|
|
||||||
items++;
|
|
||||||
|
|
||||||
|
if (ci_end <= r_start || ci_start >= r_end)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wr_start = (ci_start < r_start) ? r_start :
|
||||||
|
ci_start;
|
||||||
|
wr_end = (ci_end > r_end) ? r_end : ci_end;
|
||||||
|
wr_length = wr_end - wr_start;
|
||||||
|
if (wr_length == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
screen_write_set_cursor(ctx, wr_start, y);
|
||||||
|
if (ci->type == CLEAR) {
|
||||||
|
screen_write_initctx(ctx, &ttyctx, 1);
|
||||||
|
ttyctx.bg = ci->bg;
|
||||||
|
ttyctx.num = wr_length;
|
||||||
|
tty_write(tty_cmd_clearcharacter,
|
||||||
|
&ttyctx);
|
||||||
|
} else {
|
||||||
|
screen_write_initctx(ctx, &ttyctx, 0);
|
||||||
|
ttyctx.cell = &ci->gc;
|
||||||
|
ttyctx.wrapped = ci->wrapped;
|
||||||
|
ttyctx.ptr = cl->data + wr_start;
|
||||||
|
ttyctx.num = wr_length;
|
||||||
|
tty_write(tty_cmd_cells, &ttyctx);
|
||||||
|
}
|
||||||
|
items++;
|
||||||
|
}
|
||||||
TAILQ_REMOVE(&cl->items, ci, entry);
|
TAILQ_REMOVE(&cl->items, ci, entry);
|
||||||
screen_write_free_citem(ci);
|
screen_write_free_citem(ci);
|
||||||
last = ci->x;
|
last = ci->x;
|
||||||
}
|
}
|
||||||
|
free(vr);
|
||||||
}
|
}
|
||||||
s->cx = cx; s->cy = cy;
|
s->cx = cx; s->cy = cy;
|
||||||
|
|
||||||
@@ -1967,6 +2037,27 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||||
u_int width = ud->width, xx, not_wrap;
|
u_int width = ud->width, xx, not_wrap;
|
||||||
int selected, skip = 1;
|
int selected, skip = 1;
|
||||||
|
struct window_pane *base_wp = ctx->wp, *wp;
|
||||||
|
struct window *w;
|
||||||
|
u_int found_self, px, py;
|
||||||
|
|
||||||
|
|
||||||
|
if (base_wp != NULL) {
|
||||||
|
w = base_wp->window;
|
||||||
|
px = ctx->s->cx;
|
||||||
|
py = ctx->s->cy;
|
||||||
|
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) &&
|
||||||
|
(py >= wp->yoff && py <= wp->yoff + wp->sy) &&
|
||||||
|
(px >= wp->xoff && px <= wp->xoff + wp->sx))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Ignore padding cells. */
|
/* Ignore padding cells. */
|
||||||
if (gc->flags & GRID_FLAG_PADDING)
|
if (gc->flags & GRID_FLAG_PADDING)
|
||||||
|
|||||||
8
tmux.h
8
tmux.h
@@ -2234,6 +2234,11 @@ struct mode_tree_sort_criteria {
|
|||||||
int reversed;
|
int reversed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct visible_range {
|
||||||
|
u_int px;
|
||||||
|
u_int nx;
|
||||||
|
};
|
||||||
|
|
||||||
/* tmux.c */
|
/* tmux.c */
|
||||||
extern struct options *global_options;
|
extern struct options *global_options;
|
||||||
extern struct options *global_s_options;
|
extern struct options *global_s_options;
|
||||||
@@ -3164,6 +3169,9 @@ 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);
|
||||||
|
void screen_redraw_get_visible_ranges(u_int, u_int, u_int,
|
||||||
|
struct window_pane *, struct visible_range **, int *);
|
||||||
|
|
||||||
|
|
||||||
/* screen.c */
|
/* screen.c */
|
||||||
void screen_init(struct screen *, u_int, u_int, u_int);
|
void screen_init(struct screen *, u_int, u_int, u_int);
|
||||||
|
|||||||
Reference in New Issue
Block a user