mirror of
https://github.com/tmux/tmux.git
synced 2026-06-20 17:25:57 +00:00
Merge branch 'obsd-master'
This commit is contained in:
11
grid.c
11
grid.c
@@ -292,7 +292,7 @@ grid_free_line(struct grid *gd, u_int py)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Free several lines. */
|
/* Free several lines. */
|
||||||
static void
|
void
|
||||||
grid_free_lines(struct grid *gd, u_int py, u_int ny)
|
grid_free_lines(struct grid *gd, u_int py, u_int ny)
|
||||||
{
|
{
|
||||||
u_int yy;
|
u_int yy;
|
||||||
@@ -320,6 +320,10 @@ grid_create(u_int sx, u_int sy, u_int hlimit)
|
|||||||
gd->hsize = 0;
|
gd->hsize = 0;
|
||||||
gd->hlimit = hlimit;
|
gd->hlimit = hlimit;
|
||||||
|
|
||||||
|
gd->scroll_added = 0;
|
||||||
|
gd->scroll_collected = 0;
|
||||||
|
gd->scroll_generation = 0;
|
||||||
|
|
||||||
if (gd->sy != 0)
|
if (gd->sy != 0)
|
||||||
gd->linedata = xcalloc(gd->sy, sizeof *gd->linedata);
|
gd->linedata = xcalloc(gd->sy, sizeof *gd->linedata);
|
||||||
else
|
else
|
||||||
@@ -405,6 +409,7 @@ grid_collect_history(struct grid *gd, int all)
|
|||||||
grid_trim_history(gd, ny);
|
grid_trim_history(gd, ny);
|
||||||
|
|
||||||
gd->hsize -= ny;
|
gd->hsize -= ny;
|
||||||
|
gd->scroll_collected += ny;
|
||||||
if (gd->hscrolled > gd->hsize)
|
if (gd->hscrolled > gd->hsize)
|
||||||
gd->hscrolled = gd->hsize;
|
gd->hscrolled = gd->hsize;
|
||||||
}
|
}
|
||||||
@@ -442,6 +447,7 @@ grid_scroll_history(struct grid *gd, u_int bg)
|
|||||||
grid_compact_line(&gd->linedata[gd->hsize]);
|
grid_compact_line(&gd->linedata[gd->hsize]);
|
||||||
gd->linedata[gd->hsize].time = current_time;
|
gd->linedata[gd->hsize].time = current_time;
|
||||||
gd->hsize++;
|
gd->hsize++;
|
||||||
|
gd->scroll_added++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the history. */
|
/* Clear the history. */
|
||||||
@@ -452,6 +458,7 @@ grid_clear_history(struct grid *gd)
|
|||||||
|
|
||||||
gd->hscrolled = 0;
|
gd->hscrolled = 0;
|
||||||
gd->hsize = 0;
|
gd->hsize = 0;
|
||||||
|
gd->scroll_generation++;
|
||||||
|
|
||||||
gd->linedata = xreallocarray(gd->linedata, gd->sy,
|
gd->linedata = xreallocarray(gd->linedata, gd->sy,
|
||||||
sizeof *gd->linedata);
|
sizeof *gd->linedata);
|
||||||
@@ -489,6 +496,7 @@ grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower, u_int bg)
|
|||||||
/* Move the history offset down over the line. */
|
/* Move the history offset down over the line. */
|
||||||
gd->hscrolled++;
|
gd->hscrolled++;
|
||||||
gd->hsize++;
|
gd->hsize++;
|
||||||
|
gd->scroll_added++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expand line to fit to cell. */
|
/* Expand line to fit to cell. */
|
||||||
@@ -1510,6 +1518,7 @@ grid_reflow(struct grid *gd, u_int sx)
|
|||||||
free(gd->linedata);
|
free(gd->linedata);
|
||||||
gd->linedata = target->linedata;
|
gd->linedata = target->linedata;
|
||||||
free(target);
|
free(target);
|
||||||
|
gd->scroll_generation++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert to position based on wrapped lines. */
|
/* Convert to position based on wrapped lines. */
|
||||||
|
|||||||
@@ -530,7 +530,7 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode g { command-prompt -p'(goto line)' { send -X goto-line -- '%%' } }",
|
"bind -Tcopy-mode g { command-prompt -p'(goto line)' { send -X goto-line -- '%%' } }",
|
||||||
"bind -Tcopy-mode n { send -X search-again }",
|
"bind -Tcopy-mode n { send -X search-again }",
|
||||||
"bind -Tcopy-mode q { send -X cancel }",
|
"bind -Tcopy-mode q { send -X cancel }",
|
||||||
"bind -Tcopy-mode r { send -X refresh-from-pane }",
|
"bind -Tcopy-mode r { send -X refresh-toggle }",
|
||||||
"bind -Tcopy-mode t { command-prompt -1p'(jump to forward)' { send -X jump-to-forward -- '%%' } }",
|
"bind -Tcopy-mode t { command-prompt -1p'(jump to forward)' { send -X jump-to-forward -- '%%' } }",
|
||||||
"bind -Tcopy-mode Home { send -X start-of-line }",
|
"bind -Tcopy-mode Home { send -X start-of-line }",
|
||||||
"bind -Tcopy-mode End { send -X end-of-line }",
|
"bind -Tcopy-mode End { send -X end-of-line }",
|
||||||
@@ -638,7 +638,7 @@ key_bindings_init(void)
|
|||||||
"bind -Tcopy-mode-vi n { send -X search-again }",
|
"bind -Tcopy-mode-vi n { send -X search-again }",
|
||||||
"bind -Tcopy-mode-vi o { send -X other-end }",
|
"bind -Tcopy-mode-vi o { send -X other-end }",
|
||||||
"bind -Tcopy-mode-vi q { send -X cancel }",
|
"bind -Tcopy-mode-vi q { send -X cancel }",
|
||||||
"bind -Tcopy-mode-vi r { send -X refresh-from-pane }",
|
"bind -Tcopy-mode-vi r { send -X refresh-toggle }",
|
||||||
"bind -Tcopy-mode-vi t { command-prompt -1p'(jump to forward)' { send -X jump-to-forward -- '%%' } }",
|
"bind -Tcopy-mode-vi t { command-prompt -1p'(jump to forward)' { send -X jump-to-forward -- '%%' } }",
|
||||||
"bind -Tcopy-mode-vi v { send -X rectangle-toggle }",
|
"bind -Tcopy-mode-vi v { send -X rectangle-toggle }",
|
||||||
"bind -Tcopy-mode-vi w { send -X next-word }",
|
"bind -Tcopy-mode-vi w { send -X next-word }",
|
||||||
|
|||||||
15
tmux.1
15
tmux.1
@@ -2295,11 +2295,22 @@ Toggle rectangle selection mode.
|
|||||||
.Xc
|
.Xc
|
||||||
Cycles the current line between centre, top, and bottom.
|
Cycles the current line between centre, top, and bottom.
|
||||||
.It Xo
|
.It Xo
|
||||||
.Ic refresh\-from\-pane
|
.Ic refresh\-on
|
||||||
|
.Xc
|
||||||
|
Turn on automatic refresh of the content from the pane, so that new output
|
||||||
|
appears while in copy mode.
|
||||||
|
Automatic refresh is off by default; it will scroll only while the cursor is at
|
||||||
|
the bottom and is paused while a selection is in progress.
|
||||||
|
.It Xo
|
||||||
|
.Ic refresh\-off
|
||||||
|
.Xc
|
||||||
|
Turn off automatic refresh of the content from the pane.
|
||||||
|
.It Xo
|
||||||
|
.Ic refresh\-toggle
|
||||||
(vi: r)
|
(vi: r)
|
||||||
(emacs: r)
|
(emacs: r)
|
||||||
.Xc
|
.Xc
|
||||||
Refresh the content from the pane.
|
Toggle automatic refresh of the content from the pane.
|
||||||
.It Xo
|
.It Xo
|
||||||
.Ic scroll\-bottom
|
.Ic scroll\-bottom
|
||||||
.Xc
|
.Xc
|
||||||
|
|||||||
5
tmux.h
5
tmux.h
@@ -871,6 +871,10 @@ struct grid {
|
|||||||
u_int hsize;
|
u_int hsize;
|
||||||
u_int hlimit;
|
u_int hlimit;
|
||||||
|
|
||||||
|
u_int scroll_added;
|
||||||
|
u_int scroll_collected;
|
||||||
|
u_int scroll_generation;
|
||||||
|
|
||||||
struct grid_line *linedata;
|
struct grid_line *linedata;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3213,6 +3217,7 @@ int grid_cells_look_equal(const struct grid_cell *,
|
|||||||
const struct grid_cell *);
|
const struct grid_cell *);
|
||||||
struct grid *grid_create(u_int, u_int, u_int);
|
struct grid *grid_create(u_int, u_int, u_int);
|
||||||
void grid_destroy(struct grid *);
|
void grid_destroy(struct grid *);
|
||||||
|
void grid_free_lines(struct grid *, u_int, u_int);
|
||||||
int grid_compare(struct grid *, struct grid *);
|
int grid_compare(struct grid *, struct grid *);
|
||||||
void grid_collect_history(struct grid *, int);
|
void grid_collect_history(struct grid *, int);
|
||||||
void grid_remove_history(struct grid *, u_int );
|
void grid_remove_history(struct grid *, u_int );
|
||||||
|
|||||||
268
window-copy.c
268
window-copy.c
@@ -51,6 +51,11 @@ static void window_copy_redraw_selection(struct window_mode_entry *, u_int);
|
|||||||
static void window_copy_redraw_lines(struct window_mode_entry *, u_int,
|
static void window_copy_redraw_lines(struct window_mode_entry *, u_int,
|
||||||
u_int);
|
u_int);
|
||||||
static void window_copy_redraw_screen(struct window_mode_entry *);
|
static void window_copy_redraw_screen(struct window_mode_entry *);
|
||||||
|
static void window_copy_do_refresh(struct window_mode_entry *, int);
|
||||||
|
static void window_copy_refresh_timer(int, short, void *);
|
||||||
|
static void window_copy_refresh_arm(struct window_mode_entry *);
|
||||||
|
static void window_copy_refresh_start(struct window_mode_entry *);
|
||||||
|
static void window_copy_refresh_stop(struct window_mode_entry *);
|
||||||
static void window_copy_style_changed(struct window_mode_entry *);
|
static void window_copy_style_changed(struct window_mode_entry *);
|
||||||
static int window_copy_line_number_mode(struct window_mode_entry *);
|
static int window_copy_line_number_mode(struct window_mode_entry *);
|
||||||
static int window_copy_line_number_is_absolute(struct window_mode_entry *);
|
static int window_copy_line_number_is_absolute(struct window_mode_entry *);
|
||||||
@@ -255,6 +260,10 @@ struct window_copy_mode_data {
|
|||||||
int backing_written; /* backing display started */
|
int backing_written; /* backing display started */
|
||||||
struct input_ctx *ictx;
|
struct input_ctx *ictx;
|
||||||
|
|
||||||
|
u_int sync_added; /* snapshot of backing grid counters */
|
||||||
|
u_int sync_collected;
|
||||||
|
u_int sync_generation;
|
||||||
|
|
||||||
int viewmode; /* view mode entered */
|
int viewmode; /* view mode entered */
|
||||||
|
|
||||||
u_int oy; /* number of lines scrolled up */
|
u_int oy; /* number of lines scrolled up */
|
||||||
@@ -338,6 +347,10 @@ struct window_copy_mode_data {
|
|||||||
|
|
||||||
struct event dragtimer;
|
struct event dragtimer;
|
||||||
#define WINDOW_COPY_DRAG_REPEAT_TIME 50000
|
#define WINDOW_COPY_DRAG_REPEAT_TIME 50000
|
||||||
|
|
||||||
|
struct event refresh_timer;
|
||||||
|
#define WINDOW_COPY_REFRESH_INTERVAL 50000
|
||||||
|
int refresh_active;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -424,6 +437,116 @@ window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx,
|
|||||||
return (dst);
|
return (dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Snapshot the source grid's monotonic scroll counters so the next incremental
|
||||||
|
* sync can tell how much history was added or collected since this point.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
window_copy_sync_snapshot(struct window_copy_mode_data *data, struct grid *src)
|
||||||
|
{
|
||||||
|
data->sync_added = src->scroll_added;
|
||||||
|
data->sync_collected = src->scroll_collected;
|
||||||
|
data->sync_generation = src->scroll_generation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reconcile the backing screen with the live pane grid in place, copying only
|
||||||
|
* the history that scrolled in or was collected since the last snapshot rather
|
||||||
|
* than cloning the whole scrollback. The result is identical to a fresh
|
||||||
|
* window_copy_clone_screen, so the caller repositions and redraws the same way
|
||||||
|
* for both paths. Returns 1 on success, or 0 if the caller must fall back to a
|
||||||
|
* full clone (different source pane, geometry or generation change, or counter
|
||||||
|
* deltas that do not add up).
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
window_copy_sync_backing(struct window_mode_entry *wme)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
struct window_pane *wp = wme->swp;
|
||||||
|
struct screen *src = &wp->base;
|
||||||
|
struct screen *dst = data->backing;
|
||||||
|
struct grid *sg = src->grid;
|
||||||
|
struct grid *dg = dst->grid;
|
||||||
|
u_int sy = sg->sy;
|
||||||
|
u_int old_hsize = dg->hsize;
|
||||||
|
u_int new_hsize = sg->hsize;
|
||||||
|
u_int added, collected, kept;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only a pane's own live grid is tracked incrementally. A different
|
||||||
|
* source pane (copy-mode -s) goes through clone_screen, which also
|
||||||
|
* trims trailing blank lines that this path does not.
|
||||||
|
*/
|
||||||
|
if (data->viewmode || wme->swp != wme->wp)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/* Indices only line up at the same size and generation. */
|
||||||
|
if (sg->sx != dg->sx || sg->sy != dg->sy ||
|
||||||
|
sg->scroll_generation != data->sync_generation)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
added = sg->scroll_added - data->sync_added;
|
||||||
|
collected = sg->scroll_collected - data->sync_collected;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reject anything that does not balance: counter wrap, a history-limit
|
||||||
|
* change that collected past the snapshot, or arithmetic that does not
|
||||||
|
* reproduce the new history size.
|
||||||
|
*/
|
||||||
|
if (added > (u_int)INT_MAX || collected > (u_int)INT_MAX ||
|
||||||
|
collected > old_hsize || old_hsize + added < collected ||
|
||||||
|
old_hsize + added - collected != new_hsize)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
kept = old_hsize - collected;
|
||||||
|
|
||||||
|
if (added == 0 && collected == 0) {
|
||||||
|
/* History is unchanged; only the viewport can have mutated. */
|
||||||
|
grid_duplicate_lines(dg, dg->hsize, sg, sg->hsize, sy);
|
||||||
|
} else {
|
||||||
|
/* Drop the oldest lines and shift the rest down. */
|
||||||
|
if (collected > 0) {
|
||||||
|
grid_free_lines(dg, 0, collected);
|
||||||
|
memmove(&dg->linedata[0], &dg->linedata[collected],
|
||||||
|
(old_hsize + sy - collected) * sizeof *dg->linedata);
|
||||||
|
memset(&dg->linedata[old_hsize + sy - collected], 0,
|
||||||
|
collected * sizeof *dg->linedata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resize linedata to the new history plus viewport. */
|
||||||
|
if (new_hsize + sy != old_hsize + sy - collected) {
|
||||||
|
dg->linedata = xreallocarray(dg->linedata,
|
||||||
|
new_hsize + sy, sizeof *dg->linedata);
|
||||||
|
memset(&dg->linedata[old_hsize + sy - collected], 0,
|
||||||
|
(new_hsize - kept) * sizeof *dg->linedata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set hsize before copying so grid_duplicate_lines does not
|
||||||
|
* clamp the count to the old, smaller grid size.
|
||||||
|
*/
|
||||||
|
dg->hsize = new_hsize;
|
||||||
|
|
||||||
|
/* Copy the newly scrolled history, then refresh the viewport. */
|
||||||
|
if (added > 0)
|
||||||
|
grid_duplicate_lines(dg, kept, sg, kept, added);
|
||||||
|
grid_duplicate_lines(dg, new_hsize, sg, new_hsize, sy);
|
||||||
|
}
|
||||||
|
|
||||||
|
dg->hscrolled = sg->hscrolled;
|
||||||
|
|
||||||
|
/* Match clone_screen's backing cursor placement. */
|
||||||
|
if (src->cy > dg->sy - 1) {
|
||||||
|
dst->cx = 0;
|
||||||
|
dst->cy = dg->sy - 1;
|
||||||
|
} else {
|
||||||
|
dst->cx = src->cx;
|
||||||
|
dst->cy = src->cy;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
static struct window_copy_mode_data *
|
static struct window_copy_mode_data *
|
||||||
window_copy_common_init(struct window_mode_entry *wme)
|
window_copy_common_init(struct window_mode_entry *wme)
|
||||||
{
|
{
|
||||||
@@ -458,6 +581,7 @@ window_copy_common_init(struct window_mode_entry *wme)
|
|||||||
data->modekeys = options_get_number(wp->window->options, "mode-keys");
|
data->modekeys = options_get_number(wp->window->options, "mode-keys");
|
||||||
|
|
||||||
evtimer_set(&data->dragtimer, window_copy_scroll_timer, wme);
|
evtimer_set(&data->dragtimer, window_copy_scroll_timer, wme);
|
||||||
|
evtimer_set(&data->refresh_timer, window_copy_refresh_timer, wme);
|
||||||
|
|
||||||
return (data);
|
return (data);
|
||||||
}
|
}
|
||||||
@@ -475,6 +599,7 @@ window_copy_init(struct window_mode_entry *wme,
|
|||||||
data = window_copy_common_init(wme);
|
data = window_copy_common_init(wme);
|
||||||
data->backing = window_copy_clone_screen(base, &data->screen, &cx, &cy,
|
data->backing = window_copy_clone_screen(base, &data->screen, &cx, &cy,
|
||||||
wme->swp != wme->wp);
|
wme->swp != wme->wp);
|
||||||
|
window_copy_sync_snapshot(data, base->grid);
|
||||||
|
|
||||||
data->cx = cx;
|
data->cx = cx;
|
||||||
if (cy < screen_hsize(data->backing)) {
|
if (cy < screen_hsize(data->backing)) {
|
||||||
@@ -541,6 +666,7 @@ window_copy_free(struct window_mode_entry *wme)
|
|||||||
struct window_copy_mode_data *data = wme->data;
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
|
||||||
evtimer_del(&data->dragtimer);
|
evtimer_del(&data->dragtimer);
|
||||||
|
evtimer_del(&data->refresh_timer);
|
||||||
|
|
||||||
free(data->searchmark);
|
free(data->searchmark);
|
||||||
free(data->searchstr);
|
free(data->searchstr);
|
||||||
@@ -2781,34 +2907,136 @@ window_copy_cmd_search_forward_incremental(struct window_copy_cmd_state *cs)
|
|||||||
return (action);
|
return (action);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum window_copy_cmd_action
|
/*
|
||||||
window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs)
|
* Reconcile the backing screen with the live pane, incrementally if possible
|
||||||
|
* and otherwise by recloning, then reposition the view. When following, jump
|
||||||
|
* to the bottom so new output stays visible; otherwise keep the same lines on
|
||||||
|
* screen. Driven by the automatic refresh timer.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
window_copy_do_refresh(struct window_mode_entry *wme, int follow)
|
||||||
{
|
{
|
||||||
struct window_mode_entry *wme = cs->wme;
|
|
||||||
struct window_pane *wp = wme->swp;
|
struct window_pane *wp = wme->swp;
|
||||||
struct window_copy_mode_data *data = wme->data;
|
struct window_copy_mode_data *data = wme->data;
|
||||||
u_int oy_from_top;
|
u_int oy_from_top;
|
||||||
|
|
||||||
if (data->viewmode)
|
|
||||||
return (WINDOW_COPY_CMD_NOTHING);
|
|
||||||
if (data->oy > screen_hsize(data->backing))
|
if (data->oy > screen_hsize(data->backing))
|
||||||
data->oy = screen_hsize(data->backing);
|
data->oy = screen_hsize(data->backing);
|
||||||
oy_from_top = screen_hsize(data->backing) - data->oy;
|
oy_from_top = screen_hsize(data->backing) - data->oy;
|
||||||
|
|
||||||
screen_free(data->backing);
|
if (!window_copy_sync_backing(wme)) {
|
||||||
free(data->backing);
|
screen_free(data->backing);
|
||||||
data->backing = window_copy_clone_screen(&wp->base, &data->screen, NULL,
|
free(data->backing);
|
||||||
NULL, wme->swp != wme->wp);
|
data->backing = window_copy_clone_screen(&wp->base,
|
||||||
|
&data->screen, NULL, NULL, wme->swp != wme->wp);
|
||||||
|
}
|
||||||
|
|
||||||
if (oy_from_top <= screen_hsize(data->backing))
|
if (follow) {
|
||||||
|
data->cy = screen_size_y(&data->screen) - 1;
|
||||||
|
data->cx = window_copy_cursor_limit(wme,
|
||||||
|
screen_hsize(data->backing) + data->cy, 0);
|
||||||
|
data->oy = 0;
|
||||||
|
} else if (oy_from_top <= screen_hsize(data->backing))
|
||||||
data->oy = screen_hsize(data->backing) - oy_from_top;
|
data->oy = screen_hsize(data->backing) - oy_from_top;
|
||||||
else {
|
else {
|
||||||
data->cy = 0;
|
data->cy = 0;
|
||||||
data->oy = screen_hsize(data->backing);
|
data->oy = screen_hsize(data->backing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window_copy_sync_snapshot(data, wp->base.grid);
|
||||||
window_copy_size_changed(wme);
|
window_copy_size_changed(wme);
|
||||||
return (WINDOW_COPY_CMD_REDRAW);
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_copy_refresh_arm(struct window_mode_entry *wme)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
struct timeval tv = {
|
||||||
|
.tv_sec = WINDOW_COPY_REFRESH_INTERVAL / 1000000,
|
||||||
|
.tv_usec = WINDOW_COPY_REFRESH_INTERVAL % 1000000
|
||||||
|
};
|
||||||
|
|
||||||
|
if (data->refresh_active)
|
||||||
|
evtimer_add(&data->refresh_timer, &tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_copy_refresh_timer(__unused int fd, __unused short events, void *arg)
|
||||||
|
{
|
||||||
|
struct window_mode_entry *wme = arg;
|
||||||
|
struct window_pane *wp = wme->wp;
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
int follow;
|
||||||
|
|
||||||
|
if (TAILQ_FIRST(&wp->modes) != wme || !data->refresh_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip the refresh while a selection is being made, otherwise it would
|
||||||
|
* move; only follow new output if the cursor is still at the bottom.
|
||||||
|
*/
|
||||||
|
if ((wp->flags & PANE_UNSEENCHANGES) && data->screen.sel == NULL &&
|
||||||
|
data->cursordrag == CURSORDRAG_NONE) {
|
||||||
|
follow = (data->oy == 0 &&
|
||||||
|
data->cy == screen_size_y(&data->screen) - 1);
|
||||||
|
window_copy_do_refresh(wme, follow);
|
||||||
|
window_copy_redraw_screen(wme);
|
||||||
|
/* The timer runs outside key handling, so force a repaint. */
|
||||||
|
wp->flags |= PANE_REDRAW;
|
||||||
|
wp->flags &= ~PANE_UNSEENCHANGES;
|
||||||
|
}
|
||||||
|
|
||||||
|
window_copy_refresh_arm(wme);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_copy_refresh_start(struct window_mode_entry *wme)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not refresh a view of another pane (copy-mode -s): the source may
|
||||||
|
* disappear and changes are not tracked on this pane.
|
||||||
|
*/
|
||||||
|
if (data->viewmode || wme->swp != wme->wp || data->refresh_active)
|
||||||
|
return;
|
||||||
|
data->refresh_active = 1;
|
||||||
|
window_copy_refresh_arm(wme);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_copy_refresh_stop(struct window_mode_entry *wme)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
|
||||||
|
data->refresh_active = 0;
|
||||||
|
evtimer_del(&data->refresh_timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_refresh_on(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
window_copy_refresh_start(cs->wme);
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_refresh_off(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
window_copy_refresh_stop(cs->wme);
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_refresh_toggle(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = cs->wme->data;
|
||||||
|
|
||||||
|
if (data->refresh_active)
|
||||||
|
window_copy_refresh_stop(cs->wme);
|
||||||
|
else
|
||||||
|
window_copy_refresh_start(cs->wme);
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum window_copy_cmd_action
|
static enum window_copy_cmd_action
|
||||||
@@ -3275,11 +3503,23 @@ static const struct {
|
|||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_rectangle_toggle
|
.f = window_copy_cmd_rectangle_toggle
|
||||||
},
|
},
|
||||||
{ .command = "refresh-from-pane",
|
{ .command = "refresh-on",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
||||||
.f = window_copy_cmd_refresh_from_pane
|
.f = window_copy_cmd_refresh_on
|
||||||
|
},
|
||||||
|
{ .command = "refresh-off",
|
||||||
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
||||||
|
.f = window_copy_cmd_refresh_off
|
||||||
|
},
|
||||||
|
{ .command = "refresh-toggle",
|
||||||
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
||||||
|
.f = window_copy_cmd_refresh_toggle
|
||||||
},
|
},
|
||||||
{ .command = "scroll-bottom",
|
{ .command = "scroll-bottom",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
|||||||
Reference in New Issue
Block a user