diff --git a/layout.c b/layout.c index 1eb36477..494d758e 100644 --- a/layout.c +++ b/layout.c @@ -453,6 +453,7 @@ layout_fix_panes(struct window *w, struct window_pane *skip) window_pane_resize(wp, sx, sy); } + screen_redraw_invalidate_scene(w); } /* Count the number of available cells in a layout. */ @@ -777,6 +778,7 @@ layout_resize_floating_pane_to(struct window_pane *wp, enum layout_type type, lc->sy = size; else lc->sx = size; + screen_redraw_invalidate_scene(wp->window); } /* Resize a floating pane relative to its current size. */ @@ -811,6 +813,7 @@ layout_resize_floating_pane(struct window_pane *wp, enum layout_type type, if (opposite) lc->xoff -= change; } + screen_redraw_invalidate_scene(wp->window); } /* Resize a layout cell. */ diff --git a/options.c b/options.c index a847ad9c..fd849150 100644 --- a/options.c +++ b/options.c @@ -1219,6 +1219,15 @@ options_push_changes(const char *name) if (strcmp(name, "status") == 0 || strcmp(name, "status-interval") == 0) status_timer_start_all(); + if (strcmp(name, "status") == 0 || + strcmp(name, "status-position") == 0 || + strcmp(name, "pane-border-indicators") == 0 || + strcmp(name, "pane-border-lines") == 0 || + strcmp(name, "pane-border-status") == 0 || + strcmp(name, "pane-scrollbars") == 0 || + strcmp(name, "pane-scrollbars-position") == 0 || + strcmp(name, "pane-scrollbars-style") == 0) + screen_redraw_invalidate_all_scenes(); if (strcmp(name, "monitor-silence") == 0) alerts_reset_all(); if (strcmp(name, "window-style") == 0 || diff --git a/screen-redraw.c b/screen-redraw.c index fa1080f5..a165f891 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -149,6 +149,8 @@ struct redraw_scene { struct client *c; struct window *w; + uint64_t generation; + u_int sx; u_int sy; u_int ox; @@ -818,6 +820,7 @@ screen_redraw_make_scene(struct client *c) scene = xcalloc(1, sizeof *scene); scene->c = c; scene->w = bctx.w; + scene->generation = bctx.w->redraw_scene_generation; scene->sx = bctx.sx; scene->sy = bctx.sy; scene->ox = bctx.ox; @@ -851,13 +854,16 @@ screen_redraw_make_scene(struct client *c) } /* Free a scene. */ -static void +void screen_redraw_free_scene(struct redraw_scene *scene) { struct redraw_spans *spans; struct redraw_span *span, *span1; u_int y, type; + if (scene == NULL) + return; + for (y = 0; y < scene->sy; y++) { for (type = 0; type < REDRAW_SPAN_TYPES; type++) { spans = &scene->lines[y].spans[type]; @@ -871,6 +877,46 @@ screen_redraw_free_scene(struct redraw_scene *scene) free(scene); } +/* Mark a window's cached redraw scenes as out of date. */ +void +screen_redraw_invalidate_scene(struct window *w) +{ + w->redraw_scene_generation++; +} + +/* Mark all cached redraw scenes as out of date. */ +void +screen_redraw_invalidate_all_scenes(void) +{ + struct window *w; + + RB_FOREACH(w, windows, &windows) + screen_redraw_invalidate_scene(w); +} + +/* Get the cached redraw scene, rebuilding it if needed. */ +static struct redraw_scene * +screen_redraw_get_scene(struct client *c) +{ + struct redraw_scene *scene = c->redraw_scene; + struct window *w = c->session->curw->window; + u_int ox, oy, sx, sy; + + tty_window_offset(&c->tty, &ox, &oy, &sx, &sy); + if (scene == NULL || + scene->w != w || + scene->generation != w->redraw_scene_generation || + scene->ox != ox || + scene->oy != oy || + scene->sx != sx || + scene->sy != sy) { + screen_redraw_free_scene(scene); + scene = screen_redraw_make_scene(c); + c->redraw_scene = scene; + } + return (scene); +} + /* Is this span adjacent to this pane? */ static int screen_redraw_span_has_pane(struct redraw_span *span, struct window_pane *wp) @@ -1379,7 +1425,9 @@ screen_redraw_draw(struct client *c, struct window_pane *wp, int flags) } } - scene = screen_redraw_make_scene(c); //XXX + scene = screen_redraw_get_scene(c); + if (scene == NULL) + return; if (scene == NULL) return; screen_redraw_set_draw_context(&dctx, scene); @@ -1411,10 +1459,8 @@ screen_redraw_draw(struct client *c, struct window_pane *wp, int flags) } if (!redraw && !REDRAW_IS_ALL(flags)) { flags &= ~REDRAW_PANE_STATUS; - if (flags == 0) { - screen_redraw_free_scene(scene); + if (flags == 0) return; - } } } @@ -1457,7 +1503,6 @@ screen_redraw_draw(struct client *c, struct window_pane *wp, int flags) tty_reset(tty); tty_sync_end(tty); - screen_redraw_free_scene(scene); //XXX } /* Get cell type for offset from span. */ diff --git a/server-client.c b/server-client.c index 11ea4b5e..77b7c67a 100644 --- a/server-client.c +++ b/server-client.c @@ -530,6 +530,7 @@ server_client_free(__unused int fd, __unused short events, void *arg) log_debug("free client %p (%d references)", c, c->references); + screen_redraw_free_scene(c->redraw_scene); cmdq_free(c->queue); if (c->references == 0) { diff --git a/tmux.h b/tmux.h index ce55b724..6e797f17 100644 --- a/tmux.h +++ b/tmux.h @@ -63,6 +63,7 @@ struct mouse_event; struct options; struct options_array_item; struct options_entry; +struct redraw_scene; struct redraw_span; struct screen_write_citem; struct screen_write_cline; @@ -1380,6 +1381,8 @@ struct window { u_int new_xpixel; u_int new_ypixel; + uint64_t redraw_scene_generation; + u_int last_new_pane_x; u_int last_new_pane_y; @@ -2073,6 +2076,8 @@ struct client { size_t discarded; size_t redraw; + struct redraw_scene *redraw_scene; + struct event repeat_timer; struct event click_timer; @@ -3367,6 +3372,9 @@ void screen_write_alternateoff(struct screen_write_ctx *, void screen_redraw_screen(struct client *); void screen_redraw_pane(struct client *, struct window_pane *); void screen_redraw_pane_scrollbar(struct client *, struct window_pane *); +void screen_redraw_free_scene(struct redraw_scene *); +void screen_redraw_invalidate_scene(struct window *); +void screen_redraw_invalidate_all_scenes(void); int screen_redraw_get_span_cell_type(struct redraw_span **, u_int); /* screen.c */ diff --git a/window.c b/window.c index 33ac6e1f..3b7d78ca 100644 --- a/window.c +++ b/window.c @@ -758,6 +758,7 @@ window_zoom(struct window_pane *wp) w->flags |= WINDOW_ZOOMED; notify_window("window-layout-changed", w); + screen_redraw_invalidate_scene(w); return (0); } @@ -784,6 +785,7 @@ window_unzoom(struct window *w, int notify) if (notify) notify_window("window-layout-changed", w); + screen_redraw_invalidate_scene(w); return (0); } @@ -840,6 +842,7 @@ window_add_pane(struct window *w, struct window_pane *other, u_int hlimit, else { TAILQ_INSERT_HEAD(&w->z_index, wp, zentry); } + screen_redraw_invalidate_scene(w); return (wp); } @@ -866,6 +869,7 @@ window_lost_pane(struct window *w, struct window_pane *wp) window_update_focus(w); } } + screen_redraw_invalidate_scene(w); } void @@ -874,6 +878,7 @@ window_remove_pane(struct window *w, struct window_pane *wp) window_lost_pane(w, wp); TAILQ_REMOVE(&w->panes, wp, entry); TAILQ_REMOVE(&w->z_index, wp, zentry); + screen_redraw_invalidate_scene(w); window_pane_destroy(wp); }