Instead of fixing with the cursor position when the copied screen is

created, resize it and let the resize/reflow code fix it up and return
it. Solves various problems with cursor position and resizing when in
copy mode. With Anindya Mukherjee.
pull/2172/head
nicm 2020-04-15 17:50:02 +00:00
parent 1e72f5ea43
commit 53a29a2ffa
3 changed files with 88 additions and 62 deletions

View File

@ -48,9 +48,8 @@ struct screen_title_entry {
}; };
TAILQ_HEAD(screen_titles, screen_title_entry); TAILQ_HEAD(screen_titles, screen_title_entry);
static void screen_resize_y(struct screen *, u_int); static void screen_resize_y(struct screen *, u_int, int);
static void screen_reflow(struct screen *, u_int, u_int *, u_int *);
static void screen_reflow(struct screen *, u_int);
/* Free titles stack. */ /* Free titles stack. */
static void static void
@ -216,10 +215,23 @@ screen_pop_title(struct screen *s)
} }
} }
/* Resize screen. */ /* Resize screen and return cursor position. */
void void
screen_resize(struct screen *s, u_int sx, u_int sy, int reflow) screen_resize_cursor(struct screen *s, u_int sx, u_int sy, int reflow,
int eat_empty, u_int *cx, u_int *cy)
{ {
u_int tcx, tcy;
if (cx == NULL)
cx = &tcx;
*cx = s->cx;
if (cy == NULL)
cy = т
*cy = s->grid->hsize + s->cy;
log_debug("%s: start %u,%u (%u,%u)", __func__, s->cx, s->cy, *cx, *cy);
if (sx < 1) if (sx < 1)
sx = 1; sx = 1;
if (sy < 1) if (sy < 1)
@ -232,14 +244,30 @@ screen_resize(struct screen *s, u_int sx, u_int sy, int reflow)
reflow = 0; reflow = 0;
if (sy != screen_size_y(s)) if (sy != screen_size_y(s))
screen_resize_y(s, sy); screen_resize_y(s, sy, eat_empty);
if (reflow) if (reflow)
screen_reflow(s, sx); screen_reflow(s, sx, cx, cy);
if (*cy >= s->grid->hsize) {
s->cx = *cx;
s->cy = (*cy) - s->grid->hsize;
} else {
s->cx = 0;
s->cy = 0;
}
log_debug("%s: finish %u,%u (%u,%u)", __func__, s->cx, s->cy, *cx, *cy);
}
/* Resize screen. */
void
screen_resize(struct screen *s, u_int sx, u_int sy, int reflow)
{
screen_resize_cursor(s, sx, sy, reflow, 1, NULL, NULL);
} }
static void static void
screen_resize_y(struct screen *s, u_int sy) screen_resize_y(struct screen *s, u_int sy, int eat_empty)
{ {
struct grid *gd = s->grid; struct grid *gd = s->grid;
u_int needed, available, oldy, i; u_int needed, available, oldy, i;
@ -264,14 +292,16 @@ screen_resize_y(struct screen *s, u_int sy)
needed = oldy - sy; needed = oldy - sy;
/* Delete as many lines as possible from the bottom. */ /* Delete as many lines as possible from the bottom. */
available = oldy - 1 - s->cy; if (eat_empty) {
if (available > 0) { available = oldy - 1 - s->cy;
if (available > needed) if (available > 0) {
available = needed; if (available > needed)
grid_view_delete_lines(gd, oldy - available, available, available = needed;
8); grid_view_delete_lines(gd, oldy - available,
available, 8);
}
needed -= available;
} }
needed -= available;
/* /*
* Now just increase the history size, if possible, to take * Now just increase the history size, if possible, to take
@ -287,7 +317,6 @@ screen_resize_y(struct screen *s, u_int sy)
available = needed; available = needed;
grid_view_delete_lines(gd, 0, available, 8); grid_view_delete_lines(gd, 0, available, 8);
} }
s->cy -= needed;
} }
/* Resize line array. */ /* Resize line array. */
@ -307,7 +336,6 @@ screen_resize_y(struct screen *s, u_int sy)
available = needed; available = needed;
gd->hscrolled -= available; gd->hscrolled -= available;
gd->hsize -= available; gd->hsize -= available;
s->cy += available;
} else } else
available = 0; available = 0;
needed -= available; needed -= available;
@ -482,25 +510,17 @@ screen_select_cell(struct screen *s, struct grid_cell *dst,
/* Reflow wrapped lines. */ /* Reflow wrapped lines. */
static void static void
screen_reflow(struct screen *s, u_int new_x) screen_reflow(struct screen *s, u_int new_x, u_int *cx, u_int *cy)
{ {
u_int cx = s->cx, cy = s->grid->hsize + s->cy, wx, wy; u_int wx, wy;
grid_wrap_position(s->grid, cx, cy, &wx, &wy); grid_wrap_position(s->grid, *cx, *cy, &wx, &wy);
log_debug("%s: cursor %u,%u is %u,%u", __func__, cx, cy, wx, wy); log_debug("%s: cursor %u,%u is %u,%u", __func__, *cx, *cy, wx, wy);
grid_reflow(s->grid, new_x); grid_reflow(s->grid, new_x);
grid_unwrap_position(s->grid, &cx, &cy, wx, wy); grid_unwrap_position(s->grid, cx, cy, wx, wy);
log_debug("%s: new cursor is %u,%u", __func__, cx, cy); log_debug("%s: new cursor is %u,%u", __func__, *cx,* cy);
if (cy >= s->grid->hsize) {
s->cx = cx;
s->cy = cy - s->grid->hsize;
} else {
s->cx = 0;
s->cy = 0;
}
} }
/* /*

2
tmux.h
View File

@ -2437,6 +2437,8 @@ void screen_set_path(struct screen *, const char *);
void screen_push_title(struct screen *); void screen_push_title(struct screen *);
void screen_pop_title(struct screen *); void screen_pop_title(struct screen *);
void screen_resize(struct screen *, u_int, u_int, int); void screen_resize(struct screen *, u_int, u_int, int);
void screen_resize_cursor(struct screen *, u_int, u_int, int, int, u_int *,
u_int *);
void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int, void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int,
u_int, int, struct grid_cell *); u_int, int, struct grid_cell *);
void screen_clear_selection(struct screen *); void screen_clear_selection(struct screen *);

View File

@ -298,30 +298,33 @@ window_copy_scroll_timer(__unused int fd, __unused short events, void *arg)
} }
static struct screen * static struct screen *
window_copy_clone_screen(struct screen *src, struct screen *hint) window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx,
u_int *cy)
{ {
struct screen *dst; struct screen *dst;
struct screen_write_ctx ctx; u_int sy;
u_int dy, sy; const struct grid_line *gl;
dst = xcalloc(1, sizeof *dst); dst = xcalloc(1, sizeof *dst);
sy = screen_hsize(src) + screen_size_y(src); sy = screen_hsize(src) + screen_size_y(src);
if (screen_size_y(hint) > sy) while (sy > screen_hsize(src)) {
dy = screen_size_y(hint); gl = grid_peek_line(src->grid, sy - 1);
else if (gl->cellused != 0)
dy = sy; break;
screen_init(dst, screen_size_x(src), dy, src->grid->hlimit); sy--;
grid_duplicate_lines(dst->grid, 0, src->grid, 0, sy);
if (screen_size_y(hint) < sy) {
dst->grid->sy = screen_size_y(hint);
dst->grid->hsize = sy - screen_size_y(hint);
} }
screen_init(dst, screen_size_x(src), sy, screen_hlimit(src));
grid_duplicate_lines(dst->grid, 0, src->grid, 0, sy);
screen_write_start(&ctx, NULL, dst); dst->grid->sy = sy - screen_hsize(src);
screen_write_cursormove(&ctx, 0, dst->grid->sy + sy - dy - 1, 0); dst->grid->hsize = screen_hsize(src);
screen_write_stop(&ctx); dst->grid->hscrolled = src->grid->hscrolled;
dst->cx = src->cx;
dst->cy = src->cy;
screen_resize_cursor(dst, screen_size_x(hint), screen_size_y(hint), 1,
0, cx, cy);
return (dst); return (dst);
} }
@ -370,22 +373,22 @@ window_copy_init(struct window_mode_entry *wme,
{ {
struct window_pane *wp = wme->swp; struct window_pane *wp = wme->swp;
struct window_copy_mode_data *data; struct window_copy_mode_data *data;
struct screen *base = &wp->base;
struct screen_write_ctx ctx; struct screen_write_ctx ctx;
u_int i; u_int i, cx, cy;
data = window_copy_common_init(wme); data = window_copy_common_init(wme);
data->backing = window_copy_clone_screen(&wp->base, &data->screen); data->backing = window_copy_clone_screen(base, &data->screen, &cx, &cy);
data->cx = wp->base.cx; if (cy < screen_hsize(data->backing)) {
if (data->cx > screen_size_x(&data->screen) - 1) data->cx = cx;
data->cx = screen_size_x(&data->screen) - 1;
data->cy = screen_hsize(&wp->base) + wp->base.cy;
if (data->cy < screen_hsize(data->backing)) {
data->oy = screen_hsize(data->backing) - data->cy;
data->cy = 0; data->cy = 0;
} else data->oy = screen_hsize(data->backing) - cy;
data->cy -= screen_hsize(data->backing); } else {
data->cx = data->backing->cx;
data->cy = data->backing->cy;
data->oy = 0;
}
data->scroll_exit = args_has(args, 'e'); data->scroll_exit = args_has(args, 'e');
data->hide_position = args_has(args, 'H'); data->hide_position = args_has(args, 'H');
@ -697,8 +700,8 @@ window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
struct screen_write_ctx ctx; struct screen_write_ctx ctx;
int search; int search;
screen_resize(s, sx, sy, 1); screen_resize(s, sx, sy, 0);
screen_resize(data->backing, sx, sy, 1); screen_resize_cursor(data->backing, sx, sy, 1, 0, NULL, NULL);
if (data->cy > sy - 1) if (data->cy > sy - 1)
data->cy = sy - 1; data->cy = sy - 1;
@ -2024,7 +2027,8 @@ window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs)
screen_free(data->backing); screen_free(data->backing);
free(data->backing); free(data->backing);
data->backing = window_copy_clone_screen(&wp->base, &data->screen); data->backing = window_copy_clone_screen(&wp->base, &data->screen, NULL,
NULL);
return (WINDOW_COPY_CMD_REDRAW); return (WINDOW_COPY_CMD_REDRAW);
} }