mirror of
https://github.com/tmux/tmux.git
synced 2026-10-11 13:04:22 +00:00
Instead of redrawing the entire pane or scene when moving or redrawing a
pane, add damage rectangles and redraw only the affected spans. From Michael Grant.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-attach-session.c,v 1.91 2026/07/10 13:38:45 nicm Exp $ */
|
/* $OpenBSD: cmd-attach-session.c,v 1.92 2026/10/02 12:48:52 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -91,8 +91,10 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
|||||||
wp = target.wp;
|
wp = target.wp;
|
||||||
|
|
||||||
if (wl != NULL) {
|
if (wl != NULL) {
|
||||||
if (wp != NULL)
|
if (wp != NULL) {
|
||||||
|
window_redraw_active_switch(wp->window, wp);
|
||||||
window_set_active_pane(wp->window, wp, 1);
|
window_set_active_pane(wp->window, wp, 1);
|
||||||
|
}
|
||||||
session_set_current(s, wl);
|
session_set_current(s, wl);
|
||||||
if (wp != NULL)
|
if (wp != NULL)
|
||||||
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-join-pane.c,v 1.75 2026/09/21 10:33:16 nicm Exp $ */
|
/* $OpenBSD: cmd-join-pane.c,v 1.76 2026/10/02 12:48:52 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
|
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
|
||||||
@@ -308,7 +308,7 @@ cmd_join_pane_mouse_move(struct client *c, struct mouse_event *m)
|
|||||||
struct window *w;
|
struct window *w;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct layout_cell *lc;
|
struct layout_cell *lc;
|
||||||
int y, ly, x, lx;
|
int y, ly, x, lx, oxoff, oyoff, osx, osy;
|
||||||
|
|
||||||
wp = cmd_mouse_pane(m, NULL, &wl);
|
wp = cmd_mouse_pane(m, NULL, &wl);
|
||||||
if (wp == NULL) {
|
if (wp == NULL) {
|
||||||
@@ -330,10 +330,16 @@ cmd_join_pane_mouse_move(struct client *c, struct mouse_event *m)
|
|||||||
ly = m->statusat - 1;
|
ly = m->statusat - 1;
|
||||||
|
|
||||||
if (x != lx || y != ly) {
|
if (x != lx || y != ly) {
|
||||||
|
oxoff = wp->xoff;
|
||||||
|
oyoff = wp->yoff;
|
||||||
|
osx = wp->sx;
|
||||||
|
osy = wp->sy;
|
||||||
|
|
||||||
lc->g.xoff += x - lx;
|
lc->g.xoff += x - lx;
|
||||||
lc->g.yoff += y - ly;
|
lc->g.yoff += y - ly;
|
||||||
layout_fix_panes(w, NULL);
|
layout_fix_panes(w, NULL);
|
||||||
server_redraw_window(w);
|
|
||||||
|
window_redraw_floating_pane(wp, oxoff, oyoff, osx, osy);
|
||||||
server_redraw_window_borders(w);
|
server_redraw_window_borders(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-resize-pane.c,v 1.69 2026/09/21 10:33:16 nicm Exp $ */
|
/* $OpenBSD: cmd-resize-pane.c,v 1.70 2026/10/02 12:48:52 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -237,8 +237,8 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c,
|
|||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct layout_cell *lc;
|
struct layout_cell *lc;
|
||||||
int y, ly, x, lx, sx, sy, new_sx, new_sy;
|
int y, ly, x, lx, sx, sy, new_sx, new_sy;
|
||||||
int left, right;
|
int left, right, resizes = 0;
|
||||||
int new_xoff, new_yoff, resizes = 0;
|
int new_xoff, new_yoff, old_xoff, old_yoff;
|
||||||
|
|
||||||
wp = cmd_mouse_pane(m, NULL, &wl);
|
wp = cmd_mouse_pane(m, NULL, &wl);
|
||||||
if (wp == NULL) {
|
if (wp == NULL) {
|
||||||
@@ -249,6 +249,8 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c,
|
|||||||
lc = wp->layout_cell;
|
lc = wp->layout_cell;
|
||||||
sx = wp->sx;
|
sx = wp->sx;
|
||||||
sy = wp->sy;
|
sy = wp->sy;
|
||||||
|
old_xoff = wp->xoff;
|
||||||
|
old_yoff = wp->yoff;
|
||||||
left = wp->xoff - 1;
|
left = wp->xoff - 1;
|
||||||
right = wp->xoff + sx;
|
right = wp->xoff + sx;
|
||||||
if (window_pane_scrollbar_reserve(wp) &&
|
if (window_pane_scrollbar_reserve(wp) &&
|
||||||
@@ -348,7 +350,7 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c,
|
|||||||
}
|
}
|
||||||
if (resizes != 0) {
|
if (resizes != 0) {
|
||||||
layout_fix_panes(w, NULL);
|
layout_fix_panes(w, NULL);
|
||||||
server_redraw_window(w);
|
window_redraw_floating_pane(wp, old_xoff, old_yoff, sx, sy);
|
||||||
server_redraw_window_borders(w);
|
server_redraw_window_borders(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-split-window.c,v 1.151 2026/09/10 11:02:18 nicm Exp $ */
|
/* $OpenBSD: cmd-split-window.c,v 1.152 2026/10/02 12:48:52 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -363,6 +363,7 @@ cmd_split_window_mouse_resize(struct client *c, struct mouse_event *m)
|
|||||||
enum pane_lines lines;
|
enum pane_lines lines;
|
||||||
u_int sx, sy;
|
u_int sx, sy;
|
||||||
int x, y, xoff, yoff, border;
|
int x, y, xoff, yoff, border;
|
||||||
|
int oxoff, oyoff, osx, osy;
|
||||||
|
|
||||||
if (c->tty.mouse_last_pane == -1)
|
if (c->tty.mouse_last_pane == -1)
|
||||||
return;
|
return;
|
||||||
@@ -418,8 +419,14 @@ cmd_split_window_mouse_resize(struct client *c, struct mouse_event *m)
|
|||||||
if (sy < PANE_MINIMUM)
|
if (sy < PANE_MINIMUM)
|
||||||
sy = PANE_MINIMUM;
|
sy = PANE_MINIMUM;
|
||||||
|
|
||||||
|
oxoff = wp->xoff;
|
||||||
|
oyoff = wp->yoff;
|
||||||
|
osx = wp->sx;
|
||||||
|
osy = wp->sy;
|
||||||
|
|
||||||
layout_set_size(lc, sx, sy, xoff, yoff);
|
layout_set_size(lc, sx, sy, xoff, yoff);
|
||||||
layout_fix_panes(w, NULL);
|
layout_fix_panes(w, NULL);
|
||||||
server_redraw_window(w);
|
|
||||||
|
window_redraw_floating_pane(wp, oxoff, oyoff, osx, osy);
|
||||||
server_redraw_window_borders(w);
|
server_redraw_window_borders(w);
|
||||||
}
|
}
|
||||||
|
|||||||
8
layout.c
8
layout.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: layout.c,v 1.101 2026/09/20 08:42:46 nicm Exp $ */
|
/* $OpenBSD: layout.c,v 1.102 2026/10/02 12:48:52 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -469,7 +469,6 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
|
|||||||
sx = PANE_MINIMUM;
|
sx = PANE_MINIMUM;
|
||||||
else
|
else
|
||||||
sx = sx - sb_w - sb_pad;
|
sx = sx - sb_w - sb_pad;
|
||||||
wp->flags |= PANE_REDRAWSCROLLBAR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window_pane_resize(wp, sx, sy);
|
window_pane_resize(wp, sx, sy);
|
||||||
@@ -477,8 +476,11 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
|
|||||||
if (wp->xoff != old_xoff ||
|
if (wp->xoff != old_xoff ||
|
||||||
wp->yoff != old_yoff ||
|
wp->yoff != old_yoff ||
|
||||||
wp->sx != old_sx ||
|
wp->sx != old_sx ||
|
||||||
wp->sy != old_sy)
|
wp->sy != old_sy) {
|
||||||
|
if (window_pane_scrollbar_reserve(wp))
|
||||||
|
wp->flags |= PANE_REDRAWSCROLLBAR;
|
||||||
changed = 1;
|
changed = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed)
|
||||||
redraw_invalidate_scene(w);
|
redraw_invalidate_scene(w);
|
||||||
|
|||||||
303
screen-redraw.c
303
screen-redraw.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: screen-redraw.c,v 1.162 2026/09/24 11:19:39 nicm Exp $ */
|
/* $OpenBSD: screen-redraw.c,v 1.163 2026/10/02 12:48:52 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -204,14 +204,36 @@ struct redraw_scene {
|
|||||||
u_int oy;
|
u_int oy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* A damaged rectangle in a window. */
|
||||||
|
struct redraw_damage {
|
||||||
|
u_int x;
|
||||||
|
u_int y;
|
||||||
|
u_int sx;
|
||||||
|
u_int sy;
|
||||||
|
|
||||||
|
TAILQ_ENTRY(redraw_damage) entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there are more damage rectangles than this, they are collapsed into
|
||||||
|
* one.
|
||||||
|
*/
|
||||||
|
#define REDRAW_DAMAGE_MAX 16
|
||||||
|
|
||||||
/* Cell for building the scene. */
|
/* Cell for building the scene. */
|
||||||
struct redraw_build_cell {
|
struct redraw_build_cell {
|
||||||
struct redraw_span_data data;
|
struct redraw_span_data data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct redraw_build_cell *redraw_cells;
|
static struct redraw_build_cell *redraw_cells;
|
||||||
static size_t redraw_ncells;
|
static size_t redraw_ncells;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can reuse the same pane status lines during one damage redraw, but when
|
||||||
|
* we enter a new one, the client or format variables may have changed, so we
|
||||||
|
* need to make them again. The generation is increased so this happens.
|
||||||
|
*/
|
||||||
|
static u_int redraw_status_generation;
|
||||||
|
|
||||||
/* Context for building the scene. */
|
/* Context for building the scene. */
|
||||||
struct redraw_build_ctx {
|
struct redraw_build_ctx {
|
||||||
struct client *c;
|
struct client *c;
|
||||||
@@ -1054,6 +1076,13 @@ redraw_free_scene(struct redraw_scene *scene)
|
|||||||
free(scene);
|
free(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Does a client's cached scene show this window? */
|
||||||
|
int
|
||||||
|
redraw_client_has_window(struct client *c, struct window *w)
|
||||||
|
{
|
||||||
|
return (c->redraw_scene != NULL && c->redraw_scene->w == w);
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark a window's cached redraw scenes as out of date. */
|
/* Mark a window's cached redraw scenes as out of date. */
|
||||||
void
|
void
|
||||||
redraw_invalidate_scene(struct window *w)
|
redraw_invalidate_scene(struct window *w)
|
||||||
@@ -1061,6 +1090,104 @@ redraw_invalidate_scene(struct window *w)
|
|||||||
w->redraw_scene_generation++;
|
w->redraw_scene_generation++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free all pending damage for a window. */
|
||||||
|
void
|
||||||
|
redraw_free_damage(struct window *w)
|
||||||
|
{
|
||||||
|
struct redraw_damage *rd, *rd1;
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(rd, &w->damage, entry, rd1) {
|
||||||
|
TAILQ_REMOVE(&w->damage, rd, entry);
|
||||||
|
free(rd);
|
||||||
|
}
|
||||||
|
w->damage_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collapse all pending damage for a window into one rectangle. */
|
||||||
|
static void
|
||||||
|
redraw_collapse_damage(struct window *w)
|
||||||
|
{
|
||||||
|
struct redraw_damage *rd, *rd1, *first;
|
||||||
|
u_int x0, y0, x1, y1;
|
||||||
|
|
||||||
|
first = TAILQ_FIRST(&w->damage);
|
||||||
|
if (first == NULL)
|
||||||
|
return;
|
||||||
|
x0 = first->x;
|
||||||
|
y0 = first->y;
|
||||||
|
x1 = first->x + first->sx;
|
||||||
|
y1 = first->y + first->sy;
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(rd, &w->damage, entry, rd1) {
|
||||||
|
if (rd->x < x0)
|
||||||
|
x0 = rd->x;
|
||||||
|
if (rd->y < y0)
|
||||||
|
y0 = rd->y;
|
||||||
|
if (rd->x + rd->sx > x1)
|
||||||
|
x1 = rd->x + rd->sx;
|
||||||
|
if (rd->y + rd->sy > y1)
|
||||||
|
y1 = rd->y + rd->sy;
|
||||||
|
if (rd != first) {
|
||||||
|
TAILQ_REMOVE(&w->damage, rd, entry);
|
||||||
|
free(rd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
first->x = x0;
|
||||||
|
first->y = y0;
|
||||||
|
first->sx = x1 - x0;
|
||||||
|
first->sy = y1 - y0;
|
||||||
|
w->damage_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record window damage, merging nearby rectangles and limiting the count. */
|
||||||
|
void
|
||||||
|
redraw_damage_window(struct window *w, u_int x, u_int y, u_int sx, u_int sy)
|
||||||
|
{
|
||||||
|
struct redraw_damage *rd;
|
||||||
|
u_int x0, y0, x1, y1, area, union_area;
|
||||||
|
|
||||||
|
if (x >= w->sx || y >= w->sy)
|
||||||
|
return;
|
||||||
|
if (x + sx > w->sx)
|
||||||
|
sx = w->sx - x;
|
||||||
|
if (y + sy > w->sy)
|
||||||
|
sy = w->sy - y;
|
||||||
|
if (sx == 0 || sy == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(rd, &w->damage, entry) {
|
||||||
|
if (x > rd->x + rd->sx || rd->x > x + sx ||
|
||||||
|
y > rd->y + rd->sy || rd->y > y + sy)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
x0 = (x < rd->x) ? x : rd->x;
|
||||||
|
y0 = (y < rd->y) ? y : rd->y;
|
||||||
|
x1 = (x + sx > rd->x + rd->sx) ? x + sx : rd->x + rd->sx;
|
||||||
|
y1 = (y + sy > rd->y + rd->sy) ? y + sy : rd->y + rd->sy;
|
||||||
|
|
||||||
|
area = sx * sy + rd->sx * rd->sy;
|
||||||
|
union_area = (x1 - x0) * (y1 - y0);
|
||||||
|
if (union_area > 2 * area)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rd->x = x0;
|
||||||
|
rd->y = y0;
|
||||||
|
rd->sx = x1 - x0;
|
||||||
|
rd->sy = y1 - y0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rd = xcalloc(1, sizeof *rd);
|
||||||
|
rd->x = x;
|
||||||
|
rd->y = y;
|
||||||
|
rd->sx = sx;
|
||||||
|
rd->sy = sy;
|
||||||
|
TAILQ_INSERT_TAIL(&w->damage, rd, entry);
|
||||||
|
if (++w->damage_count > REDRAW_DAMAGE_MAX)
|
||||||
|
redraw_collapse_damage(w);
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark all cached redraw scenes as out of date. */
|
/* Mark all cached redraw scenes as out of date. */
|
||||||
void
|
void
|
||||||
redraw_invalidate_all_scenes(void)
|
redraw_invalidate_all_scenes(void)
|
||||||
@@ -1603,6 +1730,24 @@ redraw_set_draw_context(struct redraw_draw_ctx *dctx,
|
|||||||
dctx->flags |= REDRAW_ISOLATES;
|
dctx->flags |= REDRAW_ISOLATES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Build a pane prompt. */
|
||||||
|
static void
|
||||||
|
redraw_make_pane_prompt(struct window_pane *wp, struct screen *screen)
|
||||||
|
{
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
struct prompt_draw_data pdd;
|
||||||
|
|
||||||
|
screen_init(screen, wp->sx, 1, 0);
|
||||||
|
screen_write_start(&ctx, screen);
|
||||||
|
pdd.ctx = &ctx;
|
||||||
|
pdd.cursor_x = &wp->prompt_cx;
|
||||||
|
pdd.area_x = 0;
|
||||||
|
pdd.area_width = wp->sx;
|
||||||
|
pdd.prompt_line = 0;
|
||||||
|
prompt_draw(wp->prompt, &pdd);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/* Draw a pane's prompt over its content. */
|
/* Draw a pane's prompt over its content. */
|
||||||
static void
|
static void
|
||||||
redraw_draw_pane_prompt(struct redraw_draw_ctx *dctx, struct window_pane *wp)
|
redraw_draw_pane_prompt(struct redraw_draw_ctx *dctx, struct window_pane *wp)
|
||||||
@@ -1611,8 +1756,6 @@ redraw_draw_pane_prompt(struct redraw_draw_ctx *dctx, struct window_pane *wp)
|
|||||||
struct client *c = scene->c;
|
struct client *c = scene->c;
|
||||||
struct tty *tty = &c->tty;
|
struct tty *tty = &c->tty;
|
||||||
struct screen screen;
|
struct screen screen;
|
||||||
struct screen_write_ctx ctx;
|
|
||||||
struct prompt_draw_data pdd;
|
|
||||||
int ox = scene->ox, oy = scene->oy;
|
int ox = scene->ox, oy = scene->oy;
|
||||||
int sx = scene->sx, sy = scene->sy;
|
int sx = scene->sx, sy = scene->sy;
|
||||||
int line, cy, px, offset, width, wy;
|
int line, cy, px, offset, width, wy;
|
||||||
@@ -1645,16 +1788,7 @@ redraw_draw_pane_prompt(struct redraw_draw_ctx *dctx, struct window_pane *wp)
|
|||||||
if (px + width > sx)
|
if (px + width > sx)
|
||||||
width = sx - px;
|
width = sx - px;
|
||||||
|
|
||||||
screen_init(&screen, wp->sx, 1, 0);
|
redraw_make_pane_prompt(wp, &screen);
|
||||||
screen_write_start(&ctx, &screen);
|
|
||||||
pdd.ctx = &ctx;
|
|
||||||
pdd.cursor_x = &wp->prompt_cx;
|
|
||||||
pdd.area_x = 0;
|
|
||||||
pdd.area_width = wp->sx;
|
|
||||||
pdd.prompt_line = 0;
|
|
||||||
prompt_draw(wp->prompt, &pdd);
|
|
||||||
screen_write_stop(&ctx);
|
|
||||||
|
|
||||||
tty_draw_line(tty, &screen, offset, 0, width, px, cy, NULL);
|
tty_draw_line(tty, &screen, offset, 0, width, px, cy, NULL);
|
||||||
screen_free(&screen);
|
screen_free(&screen);
|
||||||
}
|
}
|
||||||
@@ -1684,7 +1818,9 @@ redraw_draw(struct client *c, struct window_pane *wp, int flags)
|
|||||||
redraw = status_prompt_redraw(c);
|
redraw = status_prompt_redraw(c);
|
||||||
else
|
else
|
||||||
redraw = status_redraw(c);
|
redraw = status_redraw(c);
|
||||||
if (!redraw && !REDRAW_IS_ALL(flags)) {
|
if (!redraw &&
|
||||||
|
(~c->flags & CLIENT_REDRAWSTATUSALWAYS) &&
|
||||||
|
!REDRAW_IS_ALL(flags)) {
|
||||||
flags &= ~REDRAW_STATUS;
|
flags &= ~REDRAW_STATUS;
|
||||||
if (flags == 0)
|
if (flags == 0)
|
||||||
return;
|
return;
|
||||||
@@ -1834,7 +1970,7 @@ redraw_screen(struct client *c)
|
|||||||
else {
|
else {
|
||||||
if (c->flags & CLIENT_REDRAWBORDERS)
|
if (c->flags & CLIENT_REDRAWBORDERS)
|
||||||
flags |= (REDRAW_PANE_BORDER|REDRAW_PANE_STATUS);
|
flags |= (REDRAW_PANE_BORDER|REDRAW_PANE_STATUS);
|
||||||
if (c->flags & CLIENT_REDRAWSTATUS)
|
if (c->flags & (CLIENT_REDRAWSTATUS|CLIENT_REDRAWSTATUSALWAYS))
|
||||||
flags |= (REDRAW_STATUS|REDRAW_PANE_STATUS);
|
flags |= (REDRAW_STATUS|REDRAW_PANE_STATUS);
|
||||||
if (c->flags & CLIENT_REDRAWMENU)
|
if (c->flags & CLIENT_REDRAWMENU)
|
||||||
flags |= REDRAW_MENU;
|
flags |= REDRAW_MENU;
|
||||||
@@ -1860,3 +1996,138 @@ redraw_pane_scrollbar(struct client *c, struct window_pane *wp)
|
|||||||
{
|
{
|
||||||
redraw_draw(c, wp, REDRAW_PANE_SCROLLBAR);
|
redraw_draw(c, wp, REDRAW_PANE_SCROLLBAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Rebuild damaged pane status. */
|
||||||
|
static void
|
||||||
|
redraw_damage_refresh_status(struct redraw_draw_ctx *dctx,
|
||||||
|
struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct redraw_span *first;
|
||||||
|
u_int g = wp->status_generation, width;
|
||||||
|
|
||||||
|
if ((wp->flags & PANE_NEWSTATUS) && g == redraw_status_generation)
|
||||||
|
return;
|
||||||
|
width = redraw_pane_status_width(dctx, wp, &first);
|
||||||
|
if (width != 0) {
|
||||||
|
window_make_pane_status(wp, dctx->scene->c, width, first);
|
||||||
|
wp->flags |= PANE_NEWSTATUS;
|
||||||
|
wp->status_generation = redraw_status_generation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw a pane's prompt over a damaged span. */
|
||||||
|
static void
|
||||||
|
redraw_damage_draw_pane_prompt(struct redraw_draw_ctx *dctx,
|
||||||
|
struct redraw_span *span, u_int y)
|
||||||
|
{
|
||||||
|
struct redraw_scene *scene = dctx->scene;
|
||||||
|
struct window_pane *wp = span->data.p.wp;
|
||||||
|
struct tty *tty = &scene->c->tty;
|
||||||
|
struct screen screen;
|
||||||
|
u_int px = span->data.p.px, width, prompt_y;
|
||||||
|
|
||||||
|
if (wp->prompt == NULL || wp->sx == 0 || wp->sy == 0)
|
||||||
|
return;
|
||||||
|
if (dctx->flags & REDRAW_STATUS_TOP)
|
||||||
|
prompt_y = 0;
|
||||||
|
else
|
||||||
|
prompt_y = wp->sy - 1;
|
||||||
|
if (span->data.p.py != prompt_y)
|
||||||
|
return;
|
||||||
|
redraw_make_pane_prompt(wp, &screen);
|
||||||
|
if (px < screen_size_x(&screen)) {
|
||||||
|
width = span->width;
|
||||||
|
if (width > screen_size_x(&screen) - px)
|
||||||
|
width = screen_size_x(&screen) - px;
|
||||||
|
tty_draw_line(tty, &screen, px, 0, width, span->x, y, NULL);
|
||||||
|
}
|
||||||
|
screen_free(&screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw the spans intersecting a damaged rectangle. */
|
||||||
|
static void
|
||||||
|
redraw_draw_damage_rectangle(struct redraw_draw_ctx *dctx, u_int x, u_int y,
|
||||||
|
u_int sx, u_int sy)
|
||||||
|
{
|
||||||
|
struct redraw_scene *scene = dctx->scene;
|
||||||
|
struct redraw_line *line;
|
||||||
|
struct redraw_spans *spans;
|
||||||
|
struct redraw_span *span;
|
||||||
|
u_int cy, yy, type;
|
||||||
|
|
||||||
|
if (x >= scene->sx || y >= scene->sy)
|
||||||
|
return;
|
||||||
|
if (x + sx > scene->sx)
|
||||||
|
sx = scene->sx - x;
|
||||||
|
if (y + sy > scene->sy)
|
||||||
|
sy = scene->sy - y;
|
||||||
|
if (sx == 0 || sy == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (yy = y; yy < y + sy; yy++) {
|
||||||
|
line = &scene->lines[yy];
|
||||||
|
if (dctx->flags & REDRAW_STATUS_TOP)
|
||||||
|
cy = dctx->status_lines + yy;
|
||||||
|
else
|
||||||
|
cy = yy;
|
||||||
|
for (type = 0; type < REDRAW_SPAN_TYPES; type++) {
|
||||||
|
spans = &line->spans[type];
|
||||||
|
TAILQ_FOREACH(span, spans, entry) {
|
||||||
|
if (span->x >= x + sx)
|
||||||
|
continue;
|
||||||
|
if (span->x + span->width <= x)
|
||||||
|
continue;
|
||||||
|
if (type == REDRAW_SPAN_STATUS) {
|
||||||
|
redraw_damage_refresh_status(dctx,
|
||||||
|
span->data.st.wp);
|
||||||
|
}
|
||||||
|
redraw_draw_span(dctx, span, cy);
|
||||||
|
if (type == REDRAW_SPAN_PANE) {
|
||||||
|
redraw_damage_draw_pane_prompt(dctx,
|
||||||
|
span, cy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw pending window damage on this client. */
|
||||||
|
void
|
||||||
|
redraw_client_damage(struct client *c)
|
||||||
|
{
|
||||||
|
struct window *w = c->session->curw->window;
|
||||||
|
struct window_pane *wp;
|
||||||
|
struct redraw_scene *scene;
|
||||||
|
struct redraw_draw_ctx dctx;
|
||||||
|
struct redraw_damage *rd;
|
||||||
|
u_int ox, oy, sx, sy, x0, y0, x1, y1;
|
||||||
|
|
||||||
|
if (TAILQ_EMPTY(&w->damage))
|
||||||
|
return;
|
||||||
|
redraw_status_generation++;
|
||||||
|
|
||||||
|
scene = redraw_get_scene(c);
|
||||||
|
if (scene == NULL)
|
||||||
|
return;
|
||||||
|
redraw_set_draw_context(&dctx, scene);
|
||||||
|
redraw_get_window_offset(c, &ox, &oy, &sx, &sy);
|
||||||
|
|
||||||
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
|
wp->border_gc_set = 0;
|
||||||
|
wp->active_border_gc_set = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_sync_start(&c->tty);
|
||||||
|
tty_update_mode(&c->tty, c->tty.mode & ~CURSOR_MODES, NULL);
|
||||||
|
|
||||||
|
TAILQ_FOREACH(rd, &w->damage, entry) {
|
||||||
|
x0 = (rd->x > ox) ? rd->x : ox;
|
||||||
|
y0 = (rd->y > oy) ? rd->y : oy;
|
||||||
|
x1 = (rd->x + rd->sx < ox + sx) ? rd->x + rd->sx : ox + sx;
|
||||||
|
y1 = (rd->y + rd->sy < oy + sy) ? rd->y + rd->sy : oy + sy;
|
||||||
|
if (x0 < x1 && y0 < y1) {
|
||||||
|
redraw_draw_damage_rectangle(&dctx, x0 - ox, y0 - oy,
|
||||||
|
x1 - x0, y1 - y0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: screen-write.c,v 1.294 2026/09/28 10:10:16 nicm Exp $ */
|
/* $OpenBSD: screen-write.c,v 1.295 2026/10/02 12:48:52 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -122,14 +122,26 @@ screen_write_set_cursor(struct screen_write_ctx *ctx, int cx, int cy)
|
|||||||
evtimer_add(&w->offset_timer, &tv);
|
evtimer_add(&w->offset_timer, &tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do a full redraw. */
|
/* Redraw lines. */
|
||||||
static void
|
static void
|
||||||
screen_write_redraw_cb(const struct tty_ctx *ttyctx)
|
screen_write_redraw_cb(const struct tty_ctx *ttyctx, u_int py, u_int ny)
|
||||||
{
|
{
|
||||||
struct window_pane *wp = ttyctx->arg;
|
struct window_pane *wp = ttyctx->arg;
|
||||||
|
int x0, y0, x1, y1;
|
||||||
|
|
||||||
if (wp != NULL)
|
if (wp == NULL)
|
||||||
wp->flags |= PANE_REDRAW;
|
return;
|
||||||
|
|
||||||
|
x0 = wp->xoff;
|
||||||
|
y0 = wp->yoff + (int)py;
|
||||||
|
x1 = x0 + (int)wp->sx;
|
||||||
|
y1 = y0 + (int)ny;
|
||||||
|
if (x0 < 0)
|
||||||
|
x0 = 0;
|
||||||
|
if (y0 < 0)
|
||||||
|
y0 = 0;
|
||||||
|
if (x1 > x0 && y1 > y0)
|
||||||
|
redraw_damage_window(wp->window, x0, y0, x1 - x0, y1 - y0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update context for client. */
|
/* Update context for client. */
|
||||||
@@ -2185,7 +2197,7 @@ screen_write_fullredraw(struct screen_write_ctx *ctx)
|
|||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 1, 0);
|
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, 0, ttyctx.sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Trim collected items. */
|
/* Trim collected items. */
|
||||||
@@ -3138,7 +3150,7 @@ screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
|||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 1, 0);
|
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, 0, ttyctx.sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Turn alternate screen off. */
|
/* Turn alternate screen off. */
|
||||||
@@ -3163,5 +3175,5 @@ screen_write_alternateoff(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
|||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 1, 0);
|
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, 0, ttyctx.sy);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: server-client.c,v 1.516 2026/10/02 12:28:07 nicm Exp $ */
|
/* $OpenBSD: server-client.c,v 1.517 2026/10/02 12:48:52 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -361,7 +361,13 @@ server_client_set_session(struct client *c, struct session *s)
|
|||||||
tty_update_client_offset(c);
|
tty_update_client_offset(c);
|
||||||
status_timer_start(c);
|
status_timer_start(c);
|
||||||
server_client_fire_session_changed(c, old);
|
server_client_fire_session_changed(c, old);
|
||||||
server_redraw_client(c);
|
|
||||||
|
/*
|
||||||
|
* Redraw if the session or displayed window changed. Use the
|
||||||
|
* cached scene because the session's current window is already set.
|
||||||
|
*/
|
||||||
|
if (old != s || !redraw_client_has_window(c, s->curw->window))
|
||||||
|
server_redraw_client(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
server_check_unattached();
|
server_check_unattached();
|
||||||
@@ -1353,10 +1359,11 @@ server_client_key_callback(struct cmdq_item *item, void *data)
|
|||||||
m->key = key;
|
m->key = key;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mouse drag is in progress, so fire the callback (now that
|
* Synchronize direct drag output with the later damage redraw
|
||||||
* the mouse event is valid).
|
* before invoking the drag callback.
|
||||||
*/
|
*/
|
||||||
if ((key & KEYC_MASK_KEY) == KEYC_DRAGGING) {
|
if ((key & KEYC_MASK_KEY) == KEYC_DRAGGING) {
|
||||||
|
tty_sync_start(&c->tty);
|
||||||
c->tty.mouse_drag_update(c, m);
|
c->tty.mouse_drag_update(c, m);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1783,8 +1790,8 @@ server_client_loop(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Any windows will have been redrawn as part of clients, so clear
|
* Clear window redraw state after processing all clients. Deferred
|
||||||
* their flags now.
|
* redraws are preserved in client flags.
|
||||||
*/
|
*/
|
||||||
RB_FOREACH(w, windows, &windows) {
|
RB_FOREACH(w, windows, &windows) {
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
@@ -1795,6 +1802,8 @@ server_client_loop(void)
|
|||||||
wp->flags &= ~(PANE_REDRAW|PANE_REDRAWSCROLLBAR|
|
wp->flags &= ~(PANE_REDRAW|PANE_REDRAWSCROLLBAR|
|
||||||
PANE_ACTIVITY);
|
PANE_ACTIVITY);
|
||||||
}
|
}
|
||||||
|
redraw_free_damage(w);
|
||||||
|
|
||||||
check_window_name(w);
|
check_window_name(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2340,6 +2349,8 @@ server_client_any_pane_redraw(struct client *c)
|
|||||||
|
|
||||||
if (c->flags & CLIENT_REDRAWWINDOW)
|
if (c->flags & CLIENT_REDRAWWINDOW)
|
||||||
return (1);
|
return (1);
|
||||||
|
if (!TAILQ_EMPTY(&w->damage))
|
||||||
|
return (1);
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
if (wp->flags & (PANE_REDRAW|PANE_REDRAWSCROLLBAR))
|
if (wp->flags & (PANE_REDRAW|PANE_REDRAWSCROLLBAR))
|
||||||
return (1);
|
return (1);
|
||||||
@@ -2356,6 +2367,7 @@ server_client_check_redraw(struct client *c)
|
|||||||
struct window *w = s->curw->window;
|
struct window *w = s->curw->window;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
int needed, tflags, mode = tty->mode;
|
int needed, tflags, mode = tty->mode;
|
||||||
|
int damaged = !TAILQ_EMPTY(&w->damage);
|
||||||
struct timeval tv = { .tv_usec = 1000 };
|
struct timeval tv = { .tv_usec = 1000 };
|
||||||
static struct event ev;
|
static struct event ev;
|
||||||
size_t n;
|
size_t n;
|
||||||
@@ -2381,12 +2393,12 @@ server_client_check_redraw(struct client *c)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Ignore output queued within the current synchronized frame. */
|
||||||
* If there is outstanding data, defer the redraw until it has been
|
|
||||||
* consumed. We can just add a timer to get out of the event loop and
|
|
||||||
* end up back here.
|
|
||||||
*/
|
|
||||||
n = EVBUFFER_LENGTH(tty->out);
|
n = EVBUFFER_LENGTH(tty->out);
|
||||||
|
if ((tty->flags & TTY_SYNCING) && n > tty->sync_offset)
|
||||||
|
n = tty->sync_offset;
|
||||||
|
|
||||||
|
/* Defer until output drains, preserving damage in client flags. */
|
||||||
if (n != 0 || (tty->flags & TTY_BLOCK)) {
|
if (n != 0 || (tty->flags & TTY_BLOCK)) {
|
||||||
if (n != 0)
|
if (n != 0)
|
||||||
log_debug("%s: redraw deferred (%zu left)", c->name, n);
|
log_debug("%s: redraw deferred (%zu left)", c->name, n);
|
||||||
@@ -2398,6 +2410,10 @@ server_client_check_redraw(struct client *c)
|
|||||||
log_debug("redraw timer started");
|
log_debug("redraw timer started");
|
||||||
evtimer_add(&ev, &tv);
|
evtimer_add(&ev, &tv);
|
||||||
}
|
}
|
||||||
|
if (damaged) {
|
||||||
|
c->flags |= CLIENT_REDRAWWINDOW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
if (wp->flags & PANE_REDRAW) {
|
if (wp->flags & PANE_REDRAW) {
|
||||||
c->flags |= CLIENT_REDRAWWINDOW;
|
c->flags |= CLIENT_REDRAWWINDOW;
|
||||||
@@ -2431,6 +2447,10 @@ server_client_check_redraw(struct client *c)
|
|||||||
redraw_pane_scrollbar(c, wp);
|
redraw_pane_scrollbar(c, wp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Draw damage here if no client redraw flags will handle it. */
|
||||||
|
if (damaged && (c->flags & CLIENT_ALLREDRAWFLAGS) == 0)
|
||||||
|
redraw_client_damage(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2444,6 +2464,7 @@ server_client_check_redraw(struct client *c)
|
|||||||
}
|
}
|
||||||
server_client_set_progress_bar(c);
|
server_client_set_progress_bar(c);
|
||||||
redraw_screen(c);
|
redraw_screen(c);
|
||||||
|
redraw_client_damage(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put the tty back how it was. */
|
/* Put the tty back how it was. */
|
||||||
|
|||||||
18
tmux.h
18
tmux.h
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: tmux.h,v 1.1450 2026/10/02 12:28:07 nicm Exp $ */
|
/* $OpenBSD: tmux.h,v 1.1451 2026/10/02 12:48:52 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -68,6 +68,7 @@ struct options_array_item;
|
|||||||
struct options_entry;
|
struct options_entry;
|
||||||
struct prompt;
|
struct prompt;
|
||||||
struct window_pane_prompt;
|
struct window_pane_prompt;
|
||||||
|
struct redraw_damage;
|
||||||
struct redraw_scene;
|
struct redraw_scene;
|
||||||
struct redraw_span;
|
struct redraw_span;
|
||||||
struct screen_write_citem;
|
struct screen_write_citem;
|
||||||
@@ -1372,6 +1373,7 @@ struct window_pane {
|
|||||||
struct screen base;
|
struct screen base;
|
||||||
|
|
||||||
struct screen status_screen;
|
struct screen status_screen;
|
||||||
|
u_int status_generation;
|
||||||
|
|
||||||
TAILQ_HEAD(, window_mode_entry) modes;
|
TAILQ_HEAD(, window_mode_entry) modes;
|
||||||
|
|
||||||
@@ -1402,6 +1404,7 @@ struct window_pane {
|
|||||||
TAILQ_HEAD(window_panes, window_pane);
|
TAILQ_HEAD(window_panes, window_pane);
|
||||||
TAILQ_HEAD(window_panes_zindex, window_pane);
|
TAILQ_HEAD(window_panes_zindex, window_pane);
|
||||||
RB_HEAD(window_pane_tree, window_pane);
|
RB_HEAD(window_pane_tree, window_pane);
|
||||||
|
TAILQ_HEAD(redraw_damages, redraw_damage);
|
||||||
|
|
||||||
/* Window structure. */
|
/* Window structure. */
|
||||||
struct window {
|
struct window {
|
||||||
@@ -1445,6 +1448,9 @@ struct window {
|
|||||||
|
|
||||||
uint64_t redraw_scene_generation;
|
uint64_t redraw_scene_generation;
|
||||||
|
|
||||||
|
struct redraw_damages damage;
|
||||||
|
u_int damage_count;
|
||||||
|
|
||||||
struct menu_data *menu;
|
struct menu_data *menu;
|
||||||
u_int menu_last_px;
|
u_int menu_last_px;
|
||||||
u_int menu_last_py;
|
u_int menu_last_py;
|
||||||
@@ -1767,6 +1773,8 @@ struct tty {
|
|||||||
struct event timer;
|
struct event timer;
|
||||||
size_t discarded;
|
size_t discarded;
|
||||||
|
|
||||||
|
size_t sync_offset;
|
||||||
|
|
||||||
struct termios tio;
|
struct termios tio;
|
||||||
|
|
||||||
struct grid_cell cell;
|
struct grid_cell cell;
|
||||||
@@ -1814,7 +1822,7 @@ struct tty {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Terminal command context. */
|
/* Terminal command context. */
|
||||||
typedef void (*tty_ctx_redraw_cb)(const struct tty_ctx *);
|
typedef void (*tty_ctx_redraw_cb)(const struct tty_ctx *, u_int, u_int);
|
||||||
typedef int (*tty_ctx_set_client_cb)(struct tty_ctx *, struct client *);
|
typedef int (*tty_ctx_set_client_cb)(struct tty_ctx *, struct client *);
|
||||||
struct tty_ctx {
|
struct tty_ctx {
|
||||||
struct screen *s;
|
struct screen *s;
|
||||||
@@ -3589,8 +3597,12 @@ void redraw_screen(struct client *);
|
|||||||
void redraw_pane(struct client *, struct window_pane *);
|
void redraw_pane(struct client *, struct window_pane *);
|
||||||
void redraw_pane_scrollbar(struct client *, struct window_pane *);
|
void redraw_pane_scrollbar(struct client *, struct window_pane *);
|
||||||
void redraw_free_scene(struct redraw_scene *);
|
void redraw_free_scene(struct redraw_scene *);
|
||||||
|
int redraw_client_has_window(struct client *, struct window *);
|
||||||
void redraw_invalidate_scene(struct window *);
|
void redraw_invalidate_scene(struct window *);
|
||||||
void redraw_invalidate_all_scenes(void);
|
void redraw_invalidate_all_scenes(void);
|
||||||
|
void redraw_damage_window(struct window *, u_int, u_int, u_int, u_int);
|
||||||
|
void redraw_free_damage(struct window *);
|
||||||
|
void redraw_client_damage(struct client *);
|
||||||
int redraw_get_status_border_cell_type(struct redraw_span **, u_int);
|
int redraw_get_status_border_cell_type(struct redraw_span **, u_int);
|
||||||
|
|
||||||
/* screen.c */
|
/* screen.c */
|
||||||
@@ -3767,6 +3779,8 @@ struct style_range *window_pane_status_get_range(struct window_pane *, u_int,
|
|||||||
u_int);
|
u_int);
|
||||||
int window_pane_is_floating(struct window_pane *);
|
int window_pane_is_floating(struct window_pane *);
|
||||||
int window_pane_is_floating_with_hidden(struct window_pane *);
|
int window_pane_is_floating_with_hidden(struct window_pane *);
|
||||||
|
void window_redraw_floating_pane(struct window_pane *, int, int,
|
||||||
|
int, int);
|
||||||
|
|
||||||
/* window-border.c */
|
/* window-border.c */
|
||||||
void window_set_fill_cells(struct window *);
|
void window_set_fill_cells(struct window *);
|
||||||
|
|||||||
9
tty.c
9
tty.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: tty.c,v 1.482 2026/09/22 06:58:06 nicm Exp $ */
|
/* $OpenBSD: tty.c,v 1.483 2026/10/02 12:48:52 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -1110,7 +1110,7 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
*/
|
*/
|
||||||
if (tty_large_region(tty, ctx) || ctx->flags & TTY_CTX_PANE_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, ctx->orupper, ctx->orlower - ctx->orupper + 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1458,6 +1458,7 @@ tty_sync_start(struct tty *tty)
|
|||||||
if (tty->flags & TTY_SYNCING)
|
if (tty->flags & TTY_SYNCING)
|
||||||
return;
|
return;
|
||||||
tty->flags |= TTY_SYNCING;
|
tty->flags |= TTY_SYNCING;
|
||||||
|
tty->sync_offset = EVBUFFER_LENGTH(tty->out);
|
||||||
|
|
||||||
if (tty_term_has(tty->term, TTYC_SYNC)) {
|
if (tty_term_has(tty->term, TTYC_SYNC)) {
|
||||||
log_debug("%s sync start", tty->client->name);
|
log_debug("%s sync start", tty->client->name);
|
||||||
@@ -1851,7 +1852,7 @@ tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
u_int i, j;
|
u_int i, j;
|
||||||
|
|
||||||
if (ctx->flags & TTY_CTX_WINDOW_BIGGER) {
|
if (ctx->flags & TTY_CTX_WINDOW_BIGGER) {
|
||||||
ctx->redraw_cb(ctx);
|
ctx->redraw_cb(ctx, 0, ctx->sy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1910,7 +1911,7 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
tty->cy == tty->rlower)
|
tty->cy == tty->rlower)
|
||||||
tty_draw_pane(tty, ctx, ctx->ocy);
|
tty_draw_pane(tty, ctx, ctx->ocy);
|
||||||
else
|
else
|
||||||
ctx->redraw_cb(ctx);
|
ctx->redraw_cb(ctx, ctx->ocy, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: window-copy.c,v 1.431 2026/09/21 10:43:37 nicm Exp $ */
|
/* $OpenBSD: window-copy.c,v 1.432 2026/10/02 12:48:52 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -768,6 +768,7 @@ window_copy_scroll(struct window_pane *wp, int sl_mpos, u_int my,
|
|||||||
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
|
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
|
||||||
|
|
||||||
if (wme != NULL) {
|
if (wme != NULL) {
|
||||||
|
window_redraw_active_switch(wp->window, wp);
|
||||||
window_set_active_pane(wp->window, wp, 0);
|
window_set_active_pane(wp->window, wp, 0);
|
||||||
window_copy_scroll1(wme, wp, sl_mpos, my, tty_oy, scroll_exit);
|
window_copy_scroll1(wme, wp, sl_mpos, my, tty_oy, scroll_exit);
|
||||||
}
|
}
|
||||||
|
|||||||
59
window.c
59
window.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: window.c,v 1.383 2026/09/28 10:42:01 nicm Exp $ */
|
/* $OpenBSD: window.c,v 1.384 2026/10/02 12:48:52 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -425,6 +425,7 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel)
|
|||||||
TAILQ_INIT(&w->panes);
|
TAILQ_INIT(&w->panes);
|
||||||
TAILQ_INIT(&w->z_index);
|
TAILQ_INIT(&w->z_index);
|
||||||
TAILQ_INIT(&w->last_panes);
|
TAILQ_INIT(&w->last_panes);
|
||||||
|
TAILQ_INIT(&w->damage);
|
||||||
w->active = NULL;
|
w->active = NULL;
|
||||||
|
|
||||||
w->lastlayout = -1;
|
w->lastlayout = -1;
|
||||||
@@ -478,6 +479,7 @@ window_destroy(struct window *w)
|
|||||||
|
|
||||||
menu_destroy(w);
|
menu_destroy(w);
|
||||||
window_destroy_panes(w);
|
window_destroy_panes(w);
|
||||||
|
redraw_free_damage(w);
|
||||||
|
|
||||||
if (event_initialized(&w->name_event))
|
if (event_initialized(&w->name_event))
|
||||||
evtimer_del(&w->name_event);
|
evtimer_del(&w->name_event);
|
||||||
@@ -747,6 +749,7 @@ int
|
|||||||
window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
||||||
{
|
{
|
||||||
struct window_pane *lastwp;
|
struct window_pane *lastwp;
|
||||||
|
int unzoomed;
|
||||||
|
|
||||||
log_debug("%s: pane %%%u", __func__, wp->id);
|
log_debug("%s: pane %%%u", __func__, wp->id);
|
||||||
|
|
||||||
@@ -754,7 +757,8 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
|||||||
return (0);
|
return (0);
|
||||||
if (w->modal != NULL && wp != w->modal)
|
if (w->modal != NULL && wp != w->modal)
|
||||||
return (0);
|
return (0);
|
||||||
if ((w->flags & WINDOW_ZOOMED) && !window_pane_is_visible(wp))
|
unzoomed = (w->flags & WINDOW_ZOOMED) && !window_pane_is_visible(wp);
|
||||||
|
if (unzoomed)
|
||||||
window_unzoom(w, 1);
|
window_unzoom(w, 1);
|
||||||
lastwp = w->active;
|
lastwp = w->active;
|
||||||
|
|
||||||
@@ -771,7 +775,19 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tty_update_window_offset(w);
|
tty_update_window_offset(w);
|
||||||
server_redraw_window(w);
|
|
||||||
|
/*
|
||||||
|
* Unzooming changes every pane's geometry and needs a full window
|
||||||
|
* redraw. Otherwise, only the previous and new active pane's border
|
||||||
|
* and status appearance changed, so avoid redrawing unaffected pane
|
||||||
|
* content.
|
||||||
|
*/
|
||||||
|
if (unzoomed)
|
||||||
|
server_redraw_window(w);
|
||||||
|
else {
|
||||||
|
server_redraw_window_borders(w);
|
||||||
|
server_status_window(w);
|
||||||
|
}
|
||||||
|
|
||||||
if (notify)
|
if (notify)
|
||||||
window_fire_pane_changed(w, w->active, lastwp);
|
window_fire_pane_changed(w, w->active, lastwp);
|
||||||
@@ -2960,3 +2976,40 @@ window_pane_is_floating_with_hidden(struct window_pane *wp)
|
|||||||
return (0);
|
return (0);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Report damage for a floating pane, including its border and scrollbar. */
|
||||||
|
static void
|
||||||
|
window_damage_floating_pane(struct window_pane *wp, int xoff, int yoff,
|
||||||
|
int sx, int sy)
|
||||||
|
{
|
||||||
|
struct window *w = wp->window;
|
||||||
|
int x0, x1, y0, y1, sb_left = 0, sb_right = 0;
|
||||||
|
struct style *sb_sy = &wp->scrollbar_style;
|
||||||
|
|
||||||
|
if (window_pane_scrollbar_reserve(wp)) {
|
||||||
|
if (w->sb_pos == PANE_SCROLLBARS_LEFT)
|
||||||
|
sb_left = sb_sy->width + sb_sy->pad;
|
||||||
|
else
|
||||||
|
sb_right = sb_sy->width + sb_sy->pad;
|
||||||
|
}
|
||||||
|
x0 = xoff - 1 - sb_left;
|
||||||
|
x1 = xoff + sx + sb_right;
|
||||||
|
y0 = yoff - 1;
|
||||||
|
y1 = yoff + sy;
|
||||||
|
if (x0 < 0)
|
||||||
|
x0 = 0;
|
||||||
|
if (y0 < 0)
|
||||||
|
y0 = 0;
|
||||||
|
if (x1 >= x0 && y1 >= y0)
|
||||||
|
redraw_damage_window(w, x0, y0, x1 - x0 + 1U, y1 - y0 + 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Report damage for a floating pane's old and new areas. */
|
||||||
|
void
|
||||||
|
window_redraw_floating_pane(struct window_pane *wp, int oxoff, int oyoff,
|
||||||
|
int osx, int osy)
|
||||||
|
{
|
||||||
|
window_damage_floating_pane(wp, oxoff, oyoff, osx, osy);
|
||||||
|
window_damage_floating_pane(wp, wp->xoff, wp->yoff, wp->sx, wp->sy);
|
||||||
|
server_status_window(wp->window);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user