fix(ui): propagate line wrapping state on grid_line events

This fixes the TUI's line-wrapping behavior, which was broken with the
migration to the msgpack-based UI protocol (see
https://github.com/neovim/neovim/issues/7369#issuecomment-1571812273).
This commit is contained in:
Ricky Zhou 2023-06-01 02:15:14 -07:00
parent 780ab11b90
commit 981acc2922
6 changed files with 38 additions and 19 deletions

View File

@ -78,14 +78,14 @@ Example of a typical "redraw" batch in a single RPC notification: >
[ [
['grid_resize', [2, 77, 36]], ['grid_resize', [2, 77, 36]],
['grid_line', ['grid_line',
[2, 0, 0, [[' ' , 0, 77]]], [2, 0, 0, [[' ' , 0, 77]], false],
[2, 1, 0, [['~', 7], [' ', 7, 76]]], [2, 1, 0, [['~', 7], [' ', 7, 76]], false],
[2, 9, 0, [['~', 7], [' ', 7, 76]]], [2, 9, 0, [['~', 7], [' ', 7, 76]], false],
... ...
[2, 35, 0, [['~', 7], [' ', 7, 76]]], [2, 35, 0, [['~', 7], [' ', 7, 76]], false],
[1, 36, 0, [['[', 9], ['N'], ['o'], [' '], ['N'], ['a'], ['m'], ['e'], [']']]], [1, 36, 0, [['[', 9], ['N'], ['o'], [' '], ['N'], ['a'], ['m'], ['e'], [']']], false],
[1, 36, 9, [[' ', 9, 50]]], [1, 36, 9, [[' ', 9, 50]], false],
[1, 36, 59, [['0', 9], [','], ['0'], ['-' ], ['1'], [' ', 9, 10], ['A'], ['l', 9, 2]]] [1, 36, 59, [['0', 9], [','], ['0'], ['-' ], ['1'], [' ', 9, 10], ['A'], ['l', 9, 2]], false]
], ],
['msg_showmode', [[]]], ['msg_showmode', [[]]],
['win_pos', [2, 1000, 0, 0, 77, 36]], ['win_pos', [2, 1000, 0, 0, 77, 36]],
@ -360,7 +360,7 @@ numerical highlight ids to the actual attributes.
use the |hl-Pmenu| family of builtin highlights. use the |hl-Pmenu| family of builtin highlights.
*ui-event-grid_line* *ui-event-grid_line*
["grid_line", grid, row, col_start, cells] ~ ["grid_line", grid, row, col_start, cells, wrap] ~
Redraw a continuous part of a `row` on a `grid`, starting at the column Redraw a continuous part of a `row` on a `grid`, starting at the column
`col_start`. `cells` is an array of arrays each with 1 to 3 items: `col_start`. `cells` is an array of arrays each with 1 to 3 items:
`[text(, hl_id, repeat)]` . `text` is the UTF-8 text that should be put in `[text(, hl_id, repeat)]` . `text` is the UTF-8 text that should be put in
@ -379,6 +379,12 @@ numerical highlight ids to the actual attributes.
enough to cover the remaining line, will be sent when the rest of the enough to cover the remaining line, will be sent when the rest of the
line should be cleared. line should be cleared.
`wrap` is a boolean indicating that this line wraps to the next row.
When redrawing a line which wraps to the next row, Nvim will emit a
`grid_line` event covering the last column of the line with `wrap` set
to true, followed immediately by a `grid_line` event starting at the
first column of the next row.
["grid_clear", grid] ~ ["grid_clear", grid] ~
Clear a `grid`. Clear a `grid`.

View File

@ -73,6 +73,11 @@ static void mpack_uint(char **buf, uint32_t val)
} }
} }
static void mpack_bool(char **buf, bool val)
{
mpack_w(buf, 0xc2 | val);
}
static void mpack_array(char **buf, uint32_t len) static void mpack_array(char **buf, uint32_t len)
{ {
if (len < 0x10) { if (len < 0x10) {
@ -809,7 +814,7 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
data->ncalls++; data->ncalls++;
char **buf = &data->buf_wptr; char **buf = &data->buf_wptr;
mpack_array(buf, 4); mpack_array(buf, 5);
mpack_uint(buf, (uint32_t)grid); mpack_uint(buf, (uint32_t)grid);
mpack_uint(buf, (uint32_t)row); mpack_uint(buf, (uint32_t)row);
mpack_uint(buf, (uint32_t)startcol); mpack_uint(buf, (uint32_t)startcol);
@ -823,17 +828,20 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
repeat++; repeat++;
if (i == ncells - 1 || attrs[i] != attrs[i + 1] if (i == ncells - 1 || attrs[i] != attrs[i + 1]
|| strcmp(chunk[i], chunk[i + 1]) != 0) { || strcmp(chunk[i], chunk[i + 1]) != 0) {
if (UI_BUF_SIZE - BUF_POS(data) < 2 * (1 + 2 + sizeof(schar_T) + 5 + 5)) { if (UI_BUF_SIZE - BUF_POS(data) < 2 * (1 + 2 + sizeof(schar_T) + 5 + 5) + 1) {
// close to overflowing the redraw buffer. finish this event, // close to overflowing the redraw buffer. finish this event,
// flush, and start a new "grid_line" event at the current position. // flush, and start a new "grid_line" event at the current position.
// For simplicity leave place for the final "clear" element // For simplicity leave place for the final "clear" element
// as well, hence the factor of 2 in the check. // as well, hence the factor of 2 in the check.
mpack_w2(&lenpos, nelem); mpack_w2(&lenpos, nelem);
// We only ever set the wrap field on the final "grid_line" event for the line.
mpack_bool(buf, false);
remote_ui_flush_buf(ui); remote_ui_flush_buf(ui);
prepare_call(ui, "grid_line"); prepare_call(ui, "grid_line");
data->ncalls++; data->ncalls++;
mpack_array(buf, 4); mpack_array(buf, 5);
mpack_uint(buf, (uint32_t)grid); mpack_uint(buf, (uint32_t)grid);
mpack_uint(buf, (uint32_t)row); mpack_uint(buf, (uint32_t)row);
mpack_uint(buf, (uint32_t)startcol + (uint32_t)i - repeat + 1); mpack_uint(buf, (uint32_t)startcol + (uint32_t)i - repeat + 1);
@ -865,9 +873,10 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
mpack_uint(buf, (uint32_t)(clearcol - endcol)); mpack_uint(buf, (uint32_t)(clearcol - endcol));
} }
mpack_w2(&lenpos, nelem); mpack_w2(&lenpos, nelem);
mpack_bool(buf, flags & kLineFlagWrap);
if (data->ncells_pending > 500) { if (data->ncells_pending > 500) {
// pass of cells to UI to let it start processing them // pass off cells to UI to let it start processing them
remote_ui_flush_buf(ui); remote_ui_flush_buf(ui);
} }
} else { } else {

View File

@ -82,7 +82,7 @@ void grid_clear(Integer grid)
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL; FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL;
void grid_cursor_goto(Integer grid, Integer row, Integer col) void grid_cursor_goto(Integer grid, Integer row, Integer col)
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL; FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL;
void grid_line(Integer grid, Integer row, Integer col_start, Array data) void grid_line(Integer grid, Integer row, Integer col_start, Array data, Boolean wrap)
FUNC_API_SINCE(5) FUNC_API_REMOTE_ONLY FUNC_API_CLIENT_IMPL; FUNC_API_SINCE(5) FUNC_API_REMOTE_ONLY FUNC_API_CLIENT_IMPL;
void grid_scroll(Integer grid, Integer top, Integer bot, Integer left, Integer right, Integer rows, void grid_scroll(Integer grid, Integer top, Integer bot, Integer left, Integer right, Integer rows,
Integer cols) Integer cols)

View File

@ -117,6 +117,7 @@ typedef struct {
int coloff; int coloff;
int cur_attr; int cur_attr;
int clear_width; int clear_width;
bool wrap;
} GridLineEvent; } GridLineEvent;
#endif // NVIM_GRID_DEFS_H #endif // NVIM_GRID_DEFS_H

View File

@ -441,7 +441,7 @@ redo:
case 14: case 14:
NEXT_TYPE(tok, MPACK_TOKEN_ARRAY); NEXT_TYPE(tok, MPACK_TOKEN_ARRAY);
int eventarrsize = (int)tok.length; int eventarrsize = (int)tok.length;
if (eventarrsize != 4) { if (eventarrsize != 5) {
p->state = -1; p->state = -1;
return false; return false;
} }
@ -509,11 +509,16 @@ redo:
} }
g->icell++; g->icell++;
p->read_ptr = data;
p->read_size = size;
if (g->icell == g->ncells) { if (g->icell == g->ncells) {
NEXT_TYPE(tok, MPACK_TOKEN_BOOLEAN);
g->wrap = mpack_unpack_boolean(tok);
p->read_ptr = data;
p->read_size = size;
return true; return true;
} }
p->read_ptr = data;
p->read_size = size;
goto redo; goto redo;
case 12: case 12:

View File

@ -210,9 +210,7 @@ void ui_client_event_raw_line(GridLineEvent *g)
int grid = g->args[0], row = g->args[1], startcol = g->args[2]; int grid = g->args[0], row = g->args[1], startcol = g->args[2];
Integer endcol = startcol + g->coloff; Integer endcol = startcol + g->coloff;
Integer clearcol = endcol + g->clear_width; Integer clearcol = endcol + g->clear_width;
LineFlags lineflags = g->wrap ? kLineFlagWrap : 0;
// TODO(hlpr98): Accommodate other LineFlags when included in grid_line
LineFlags lineflags = 0;
tui_raw_line(tui, grid, row, startcol, endcol, clearcol, g->cur_attr, lineflags, tui_raw_line(tui, grid, row, startcol, endcol, clearcol, g->cur_attr, lineflags,
(const schar_T *)grid_line_buf_char, grid_line_buf_attr); (const schar_T *)grid_line_buf_char, grid_line_buf_attr);