Store and restore cursor position when copy mode is resized, from

Anindya Mukherjee.
pull/2219/head
nicm 2020-05-16 15:49:20 +00:00
parent daa95810b5
commit 6ea6d46d0a
4 changed files with 70 additions and 40 deletions

2
grid.c
View File

@ -1285,7 +1285,7 @@ grid_reflow(struct grid *gd, u_int sx)
/* /*
* If the line is exactly right or the first character is wider * If the line is exactly right or the first character is wider
* than the targe width, just move it across unchanged. * than the target width, just move it across unchanged.
*/ */
if (width == sx || first > sx) { if (width == sx || first > sx) {
grid_reflow_move(target, gl); grid_reflow_move(target, gl);

View File

@ -49,7 +49,7 @@ 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, int, u_int *); static void screen_resize_y(struct screen *, u_int, int, u_int *);
static void screen_reflow(struct screen *, u_int, u_int *, u_int *); static void screen_reflow(struct screen *, u_int, u_int *, u_int *, int);
/* Free titles stack. */ /* Free titles stack. */
static void static void
@ -220,27 +220,19 @@ screen_pop_title(struct screen *s)
} }
} }
/* Resize screen and return cursor position. */ /* Resize screen with options. */
void void
screen_resize_cursor(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) int eat_empty, int cursor)
{ {
u_int tcx, tcy; u_int cx = s->cx, cy = s->grid->hsize + s->cy;
if (s->write_list != NULL) if (s->write_list != NULL)
screen_write_free_list(s); screen_write_free_list(s);
if (cx == NULL)
cx = &tcx;
*cx = s->cx;
if (cy == NULL)
cy = т
*cy = s->grid->hsize + s->cy;
log_debug("%s: new size %ux%u, now %ux%u (cursor %u,%u = %u,%u)", log_debug("%s: new size %ux%u, now %ux%u (cursor %u,%u = %u,%u)",
__func__, sx, sy, screen_size_x(s), screen_size_y(s), s->cx, s->cy, __func__, sx, sy, screen_size_x(s), screen_size_y(s), s->cx, s->cy,
*cx, *cy); cx, cy);
if (sx < 1) if (sx < 1)
sx = 1; sx = 1;
@ -254,20 +246,21 @@ screen_resize_cursor(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, eat_empty, cy); screen_resize_y(s, sy, eat_empty, &cy);
if (reflow) if (reflow)
screen_reflow(s, sx, cx, cy); screen_reflow(s, sx, &cx, &cy, cursor);
if (*cy >= s->grid->hsize) { if (cy >= s->grid->hsize) {
s->cx = *cx; s->cx = cx;
s->cy = (*cy) - s->grid->hsize; s->cy = cy - s->grid->hsize;
} else { } else {
s->cx = 0; s->cx = 0;
s->cy = 0; s->cy = 0;
} }
log_debug("%s: cursor finished at %u,%u = %u,%u", __func__, s->cx, log_debug("%s: cursor finished at %u,%u = %u,%u", __func__, s->cx,
s->cy, *cx, *cy); s->cy, cx, cy);
if (s->write_list != NULL) if (s->write_list != NULL)
screen_write_make_list(s); screen_write_make_list(s);
@ -277,7 +270,7 @@ screen_resize_cursor(struct screen *s, u_int sx, u_int sy, int reflow,
void void
screen_resize(struct screen *s, u_int sx, u_int sy, int reflow) screen_resize(struct screen *s, u_int sx, u_int sy, int reflow)
{ {
screen_resize_cursor(s, sx, sy, reflow, 1, NULL, NULL); screen_resize_cursor(s, sx, sy, reflow, 1, 1);
} }
static void static void
@ -525,17 +518,26 @@ 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, u_int *cx, u_int *cy) screen_reflow(struct screen *s, u_int new_x, u_int *cx, u_int *cy, int cursor)
{ {
u_int wx, wy; u_int wx, wy;
grid_wrap_position(s->grid, *cx, *cy, &wx, &wy); if (cursor) {
log_debug("%s: cursor %u,%u is %u,%u", __func__, *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);
}
grid_reflow(s->grid, new_x); grid_reflow(s->grid, new_x);
grid_unwrap_position(s->grid, cx, cy, wx, wy); if (cursor) {
log_debug("%s: new cursor is %u,%u", __func__, *cx,* cy); grid_unwrap_position(s->grid, cx, cy, wx, wy);
log_debug("%s: new cursor is %u,%u", __func__, *cx, *cy);
}
else {
*cx = 0;
*cy = s->grid->hsize;
}
} }
/* /*

3
tmux.h
View File

@ -2529,8 +2529,7 @@ 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 *, void screen_resize_cursor(struct screen *, u_int, u_int, int, int, 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

@ -306,8 +306,9 @@ window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx,
u_int *cy, int trim) u_int *cy, int trim)
{ {
struct screen *dst; struct screen *dst;
u_int sy;
const struct grid_line *gl; const struct grid_line *gl;
u_int sy, wx, wy;
int reflow;
dst = xcalloc(1, sizeof *dst); dst = xcalloc(1, sizeof *dst);
@ -324,6 +325,12 @@ window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx,
screen_size_x(src), sy, screen_size_x(hint), screen_size_x(src), sy, screen_size_x(hint),
screen_hsize(src) + screen_size_y(src)); screen_hsize(src) + screen_size_y(src));
screen_init(dst, screen_size_x(src), sy, screen_hlimit(src)); screen_init(dst, screen_size_x(src), sy, screen_hlimit(src));
/*
* Ensure history is on for the backing grid so lines are not deleted
* during resizing.
*/
dst->grid->flags |= GRID_HISTORY;
grid_duplicate_lines(dst->grid, 0, src->grid, 0, sy); grid_duplicate_lines(dst->grid, 0, src->grid, 0, sy);
dst->grid->sy = sy - screen_hsize(src); dst->grid->sy = sy - screen_hsize(src);
@ -337,8 +344,19 @@ window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx,
dst->cy = src->cy; dst->cy = src->cy;
} }
if (cx != NULL && cy != NULL) {
*cx = dst->cx;
*cy = screen_hsize(dst) + dst->cy;
reflow = (screen_size_x(hint) != screen_size_x(dst));
}
else
reflow = 0;
if (reflow)
grid_wrap_position(dst->grid, *cx, *cy, &wx, &wy);
screen_resize_cursor(dst, screen_size_x(hint), screen_size_y(hint), 1, screen_resize_cursor(dst, screen_size_x(hint), screen_size_y(hint), 1,
0, cx, cy); 0, 0);
if (reflow)
grid_unwrap_position(dst->grid, cx, cy, wx, wy);
return (dst); return (dst);
} }
@ -392,13 +410,12 @@ window_copy_init(struct window_mode_entry *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);
data->cx = cx;
if (cy < screen_hsize(data->backing)) { if (cy < screen_hsize(data->backing)) {
data->cx = cx;
data->cy = 0; data->cy = 0;
data->oy = screen_hsize(data->backing) - cy; data->oy = screen_hsize(data->backing) - cy;
} else { } else {
data->cx = data->backing->cx; data->cy = cy - screen_hsize(data->backing);
data->cy = data->backing->cy;
data->oy = 0; data->oy = 0;
} }
@ -731,16 +748,28 @@ window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
{ {
struct window_copy_mode_data *data = wme->data; struct window_copy_mode_data *data = wme->data;
struct screen *s = &data->screen; struct screen *s = &data->screen;
struct grid *gd = data->backing->grid;
u_int cx, cy, wx, wy;
int reflow;
screen_resize(s, sx, sy, 0); screen_resize(s, sx, sy, 0);
screen_resize_cursor(data->backing, sx, sy, 1, 0, NULL, NULL); cx = data->cx;
cy = gd->hsize + data->cy - data->oy;
reflow = (gd->sx != sx);
if (reflow)
grid_wrap_position(gd, cx, cy, &wx, &wy);
screen_resize_cursor(data->backing, sx, sy, 1, 0, 0);
if (reflow)
grid_unwrap_position(gd, &cx, &cy, wx, wy);
if (data->cy > sy - 1) data->cx = cx;
data->cy = sy - 1; if (cy < gd->hsize) {
if (data->cx > sx) data->cy = 0;
data->cx = sx; data->oy = gd->hsize - cy;
if (data->oy > screen_hsize(data->backing)) } else {
data->oy = screen_hsize(data->backing); data->cy = cy - gd->hsize;
data->oy = 0;
}
window_copy_size_changed(wme); window_copy_size_changed(wme);
window_copy_redraw_screen(wme); window_copy_redraw_screen(wme);