mirror of
https://github.com/neovim/neovim.git
synced 2025-09-20 10:18:18 +00:00
refactor(ui): devirtualize the ui layer
- The defined interface for the UI is only the RPC protocol. The original UI interface as an array of function pointers fill no function. - On the server, all the UI:s are all RPC channels. - ui.c is only used on the server. - The compositor is a preprocessing step for single-grid UI:s - on the client, ui_client and tui talk directly to each other - we still do module separation, as ui_client.c could form the basis of a libnvim client module later. Items for later PR:s - vim.ui_attach is still an unhappy child, reconsider based on plugin experience. - the flags in ui_events.in.h are still a mess. Can be simplified now. - UX for remote attachment needs more work. - startup for client can be simplified further (think of the millisecs we can save)
This commit is contained in:
@@ -29,41 +29,6 @@
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/window.h"
|
||||
|
||||
typedef struct {
|
||||
uint64_t channel_id;
|
||||
|
||||
#define UI_BUF_SIZE 4096 ///< total buffer size for pending msgpack data.
|
||||
/// guaranteed size available for each new event (so packing of simple events
|
||||
/// and the header of grid_line will never fail)
|
||||
#define EVENT_BUF_SIZE 256
|
||||
char buf[UI_BUF_SIZE]; ///< buffer of packed but not yet sent msgpack data
|
||||
char *buf_wptr; ///< write head of buffer
|
||||
const char *cur_event; ///< name of current event (might get multiple arglists)
|
||||
Array call_buf; ///< buffer for constructing a single arg list (max 16 elements!)
|
||||
|
||||
// state for write_cb, while packing a single arglist to msgpack. This
|
||||
// might fail due to buffer overflow.
|
||||
size_t pack_totlen;
|
||||
bool buf_overflow;
|
||||
char *temp_buf;
|
||||
|
||||
// We start packing the two outermost msgpack arrays before knowing the total
|
||||
// number of elements. Thus track the location where array size will need
|
||||
// to be written in the msgpack buffer, once the specific array is finished.
|
||||
char *nevents_pos;
|
||||
char *ncalls_pos;
|
||||
uint32_t nevents; ///< number of distinct events (top-level args to "redraw"
|
||||
uint32_t ncalls; ///< number of calls made to the current event (plus one for the name!)
|
||||
bool flushed_events; ///< events where sent to client without "flush" event
|
||||
|
||||
int hl_id; // Current highlight for legacy put event.
|
||||
Integer cursor_row, cursor_col; // Intended visible cursor position.
|
||||
|
||||
// Position of legacy cursor, used both for drawing and visible user cursor.
|
||||
Integer client_row, client_col;
|
||||
bool wildmenu_active;
|
||||
} UIData;
|
||||
|
||||
#define BUF_POS(data) ((size_t)((data)->buf_wptr - (data)->buf))
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
@@ -143,8 +108,6 @@ void remote_ui_disconnect(uint64_t channel_id)
|
||||
UIData *data = ui->data;
|
||||
kv_destroy(data->call_buf);
|
||||
pmap_del(uint64_t)(&connected_uis, channel_id);
|
||||
xfree(data);
|
||||
ui->data = NULL; // Flag UI as "stopped".
|
||||
ui_detach_impl(ui, channel_id);
|
||||
xfree(ui);
|
||||
}
|
||||
@@ -204,32 +167,6 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
|
||||
ui->pum_col = -1.0;
|
||||
ui->rgb = true;
|
||||
ui->override = false;
|
||||
ui->grid_resize = remote_ui_grid_resize;
|
||||
ui->grid_clear = remote_ui_grid_clear;
|
||||
ui->grid_cursor_goto = remote_ui_grid_cursor_goto;
|
||||
ui->mode_info_set = remote_ui_mode_info_set;
|
||||
ui->update_menu = remote_ui_update_menu;
|
||||
ui->busy_start = remote_ui_busy_start;
|
||||
ui->busy_stop = remote_ui_busy_stop;
|
||||
ui->mouse_on = remote_ui_mouse_on;
|
||||
ui->mouse_off = remote_ui_mouse_off;
|
||||
ui->mode_change = remote_ui_mode_change;
|
||||
ui->grid_scroll = remote_ui_grid_scroll;
|
||||
ui->hl_attr_define = remote_ui_hl_attr_define;
|
||||
ui->hl_group_set = remote_ui_hl_group_set;
|
||||
ui->raw_line = remote_ui_raw_line;
|
||||
ui->bell = remote_ui_bell;
|
||||
ui->visual_bell = remote_ui_visual_bell;
|
||||
ui->default_colors_set = remote_ui_default_colors_set;
|
||||
ui->flush = remote_ui_flush;
|
||||
ui->suspend = remote_ui_suspend;
|
||||
ui->set_title = remote_ui_set_title;
|
||||
ui->set_icon = remote_ui_set_icon;
|
||||
ui->option_set = remote_ui_option_set;
|
||||
ui->msg_set_pos = remote_ui_msg_set_pos;
|
||||
ui->event = remote_ui_event;
|
||||
ui->inspect = remote_ui_inspect;
|
||||
ui->win_viewport = remote_ui_win_viewport;
|
||||
|
||||
CLEAR_FIELD(ui->ui_ext);
|
||||
|
||||
@@ -252,7 +189,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
|
||||
ui->ui_ext[kUICmdline] = true;
|
||||
}
|
||||
|
||||
UIData *data = xmalloc(sizeof(UIData));
|
||||
UIData *data = ui->data;
|
||||
data->channel_id = channel_id;
|
||||
data->cur_event = NULL;
|
||||
data->hl_id = 0;
|
||||
@@ -267,7 +204,6 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
|
||||
data->wildmenu_active = false;
|
||||
data->call_buf = (Array)ARRAY_DICT_INIT;
|
||||
kv_ensure_space(data->call_buf, 16);
|
||||
ui->data = data;
|
||||
|
||||
pmap_put(uint64_t)(&connected_uis, channel_id, ui);
|
||||
ui_attach_impl(ui, channel_id);
|
||||
@@ -313,6 +249,10 @@ void nvim_ui_detach(uint64_t channel_id, Error *err)
|
||||
remote_ui_disconnect(channel_id);
|
||||
}
|
||||
|
||||
// TODO(bfredl): use me to detach a specifc ui from the server
|
||||
void remote_ui_stop(UI *ui)
|
||||
{}
|
||||
|
||||
void nvim_ui_try_resize(uint64_t channel_id, Integer width, Integer height, Error *err)
|
||||
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
|
||||
{
|
||||
@@ -684,7 +624,7 @@ static void push_call(UI *ui, const char *name, Array args)
|
||||
data->ncalls++;
|
||||
}
|
||||
|
||||
static void remote_ui_grid_clear(UI *ui, Integer grid)
|
||||
void remote_ui_grid_clear(UI *ui, Integer grid)
|
||||
{
|
||||
UIData *data = ui->data;
|
||||
Array args = data->call_buf;
|
||||
@@ -695,7 +635,7 @@ static void remote_ui_grid_clear(UI *ui, Integer grid)
|
||||
push_call(ui, name, args);
|
||||
}
|
||||
|
||||
static void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height)
|
||||
void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height)
|
||||
{
|
||||
UIData *data = ui->data;
|
||||
Array args = data->call_buf;
|
||||
@@ -708,8 +648,8 @@ static void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer h
|
||||
push_call(ui, name, args);
|
||||
}
|
||||
|
||||
static void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left,
|
||||
Integer right, Integer rows, Integer cols)
|
||||
void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left,
|
||||
Integer right, Integer rows, Integer cols)
|
||||
{
|
||||
UIData *data = ui->data;
|
||||
if (ui->ui_ext[kUILinegrid]) {
|
||||
@@ -745,8 +685,8 @@ static void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot
|
||||
}
|
||||
}
|
||||
|
||||
static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp,
|
||||
Integer cterm_fg, Integer cterm_bg)
|
||||
void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp,
|
||||
Integer cterm_fg, Integer cterm_bg)
|
||||
{
|
||||
if (!ui->ui_ext[kUITermColors]) {
|
||||
HL_SET_DEFAULT_COLORS(rgb_fg, rgb_bg, rgb_sp);
|
||||
@@ -776,8 +716,8 @@ static void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg,
|
||||
}
|
||||
}
|
||||
|
||||
static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs,
|
||||
Array info)
|
||||
void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs,
|
||||
Array info)
|
||||
{
|
||||
if (!ui->ui_ext[kUILinegrid]) {
|
||||
return;
|
||||
@@ -802,7 +742,7 @@ static void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAt
|
||||
push_call(ui, "hl_attr_define", args);
|
||||
}
|
||||
|
||||
static void remote_ui_highlight_set(UI *ui, int id)
|
||||
void remote_ui_highlight_set(UI *ui, int id)
|
||||
{
|
||||
UIData *data = ui->data;
|
||||
Array args = data->call_buf;
|
||||
@@ -818,7 +758,7 @@ static void remote_ui_highlight_set(UI *ui, int id)
|
||||
}
|
||||
|
||||
/// "true" cursor used only for input focus
|
||||
static void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col)
|
||||
void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col)
|
||||
{
|
||||
if (ui->ui_ext[kUILinegrid]) {
|
||||
UIData *data = ui->data;
|
||||
@@ -836,7 +776,7 @@ static void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Intege
|
||||
}
|
||||
|
||||
/// emulated cursor used both for drawing and for input focus
|
||||
static void remote_ui_cursor_goto(UI *ui, Integer row, Integer col)
|
||||
void remote_ui_cursor_goto(UI *ui, Integer row, Integer col)
|
||||
{
|
||||
UIData *data = ui->data;
|
||||
if (data->client_row == row && data->client_col == col) {
|
||||
@@ -850,7 +790,7 @@ static void remote_ui_cursor_goto(UI *ui, Integer row, Integer col)
|
||||
push_call(ui, "cursor_goto", args);
|
||||
}
|
||||
|
||||
static void remote_ui_put(UI *ui, const char *cell)
|
||||
void remote_ui_put(UI *ui, const char *cell)
|
||||
{
|
||||
UIData *data = ui->data;
|
||||
data->client_col++;
|
||||
@@ -859,9 +799,9 @@ static void remote_ui_put(UI *ui, const char *cell)
|
||||
push_call(ui, "put", args);
|
||||
}
|
||||
|
||||
static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol,
|
||||
Integer clearcol, Integer clearattr, LineFlags flags,
|
||||
const schar_T *chunk, const sattr_T *attrs)
|
||||
void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol,
|
||||
Integer clearcol, Integer clearattr, LineFlags flags, const schar_T *chunk,
|
||||
const sattr_T *attrs)
|
||||
{
|
||||
UIData *data = ui->data;
|
||||
if (ui->ui_ext[kUILinegrid]) {
|
||||
@@ -953,7 +893,7 @@ static void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startc
|
||||
///
|
||||
/// This might happen multiple times before the actual ui_flush, if the
|
||||
/// total redraw size is large!
|
||||
static void remote_ui_flush_buf(UI *ui)
|
||||
void remote_ui_flush_buf(UI *ui)
|
||||
{
|
||||
UIData *data = ui->data;
|
||||
if (!data->nevents_pos) {
|
||||
@@ -980,7 +920,7 @@ static void remote_ui_flush_buf(UI *ui)
|
||||
///
|
||||
/// Clients can know this happened by a final "flush" event at the end of the
|
||||
/// "redraw" batch.
|
||||
static void remote_ui_flush(UI *ui)
|
||||
void remote_ui_flush(UI *ui)
|
||||
{
|
||||
UIData *data = ui->data;
|
||||
if (data->nevents > 0 || data->flushed_events) {
|
||||
@@ -1025,7 +965,7 @@ static Array translate_firstarg(UI *ui, Array args, Arena *arena)
|
||||
return new_args;
|
||||
}
|
||||
|
||||
static void remote_ui_event(UI *ui, char *name, Array args)
|
||||
void remote_ui_event(UI *ui, char *name, Array args)
|
||||
{
|
||||
Arena arena = ARENA_EMPTY;
|
||||
UIData *data = ui->data;
|
||||
@@ -1092,7 +1032,7 @@ free_ret:
|
||||
arena_mem_free(arena_finish(&arena));
|
||||
}
|
||||
|
||||
static void remote_ui_inspect(UI *ui, Dictionary *info)
|
||||
void remote_ui_inspect(UI *ui, Dictionary *info)
|
||||
{
|
||||
UIData *data = ui->data;
|
||||
PUT(*info, "chan", INTEGER_OBJ((Integer)data->channel_id));
|
||||
|
Reference in New Issue
Block a user