mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #21605 from bfredl/uidvp
The UI Devirtualization Project
This commit is contained in:
commit
85eb564bac
@ -36,7 +36,6 @@ set(HEADER_GENERATOR ${GENERATOR_DIR}/gen_declarations.lua)
|
||||
set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include)
|
||||
set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch_wrappers.generated.h)
|
||||
set(GENERATED_FUNCS_METADATA ${GENERATED_DIR}/api/private/funcs_metadata.generated.h)
|
||||
set(GENERATED_UI_EVENTS ${GENERATED_DIR}/ui_events.generated.h)
|
||||
set(GENERATED_UI_EVENTS_CALL ${GENERATED_DIR}/ui_events_call.generated.h)
|
||||
set(GENERATED_UI_EVENTS_REMOTE ${GENERATED_DIR}/ui_events_remote.generated.h)
|
||||
set(GENERATED_UI_EVENTS_CLIENT ${GENERATED_DIR}/ui_events_client.generated.h)
|
||||
@ -310,14 +309,12 @@ list(APPEND NVIM_GENERATED_SOURCES
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${GENERATED_UI_EVENTS}
|
||||
${GENERATED_UI_EVENTS_CALL}
|
||||
OUTPUT ${GENERATED_UI_EVENTS_CALL}
|
||||
${GENERATED_UI_EVENTS_REMOTE}
|
||||
${GENERATED_UI_EVENTS_METADATA}
|
||||
${GENERATED_UI_EVENTS_CLIENT}
|
||||
COMMAND ${LUA_PRG} ${API_UI_EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h
|
||||
${GENERATED_UI_EVENTS}
|
||||
${GENERATED_UI_EVENTS_CALL}
|
||||
${GENERATED_UI_EVENTS_REMOTE}
|
||||
${GENERATED_UI_EVENTS_METADATA}
|
||||
|
@ -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));
|
||||
|
@ -5,8 +5,10 @@
|
||||
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/map.h"
|
||||
#include "nvim/ui.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "api/ui.h.generated.h"
|
||||
# include "ui_events_remote.h.generated.h"
|
||||
#endif
|
||||
#endif // NVIM_API_UI_H
|
||||
|
@ -37,7 +37,7 @@ void set_title(String title)
|
||||
void set_icon(String icon)
|
||||
FUNC_API_SINCE(3);
|
||||
void screenshot(String path)
|
||||
FUNC_API_SINCE(7) FUNC_API_REMOTE_IMPL;
|
||||
FUNC_API_SINCE(7);
|
||||
void option_set(String name, Object value)
|
||||
FUNC_API_SINCE(4);
|
||||
// Stop event is not exported as such, represented by EOF in the msgpack stream.
|
||||
@ -75,7 +75,7 @@ void default_colors_set(Integer rgb_fg, Integer rgb_bg, Integer rgb_sp, Integer
|
||||
void hl_attr_define(Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs, Array info)
|
||||
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL;
|
||||
void hl_group_set(String name, Integer id)
|
||||
FUNC_API_SINCE(6);
|
||||
FUNC_API_SINCE(6) FUNC_API_CLIENT_IGNORE;
|
||||
void grid_resize(Integer grid, Integer width, Integer height)
|
||||
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL FUNC_API_CLIENT_IMPL;
|
||||
void grid_clear(Integer grid)
|
||||
@ -97,9 +97,6 @@ void raw_line(Integer grid, Integer row, Integer startcol, Integer endcol, Integ
|
||||
Integer clearattr, LineFlags flags, const schar_T *chunk, const sattr_T *attrs)
|
||||
FUNC_API_NOEXPORT FUNC_API_COMPOSITOR_IMPL;
|
||||
|
||||
void event(char *name, Array args)
|
||||
FUNC_API_NOEXPORT FUNC_API_COMPOSITOR_IMPL;
|
||||
|
||||
void win_pos(Integer grid, Window win, Integer startrow, Integer startcol, Integer width,
|
||||
Integer height)
|
||||
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
|
||||
@ -114,11 +111,11 @@ void win_close(Integer grid)
|
||||
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
|
||||
|
||||
void msg_set_pos(Integer grid, Integer row, Boolean scrolled, String sep_char)
|
||||
FUNC_API_SINCE(6) FUNC_API_COMPOSITOR_IMPL;
|
||||
FUNC_API_SINCE(6) FUNC_API_COMPOSITOR_IMPL FUNC_API_CLIENT_IGNORE;
|
||||
|
||||
void win_viewport(Integer grid, Window win, Integer topline, Integer botline, Integer curline,
|
||||
Integer curcol, Integer line_count)
|
||||
FUNC_API_SINCE(7) FUNC_API_BRIDGE_IMPL;
|
||||
FUNC_API_SINCE(7) FUNC_API_CLIENT_IGNORE;
|
||||
|
||||
void win_extmark(Integer grid, Window win, Integer ns_id, Integer mark_id, Integer row, Integer col)
|
||||
FUNC_API_SINCE(10) FUNC_API_REMOTE_ONLY;
|
||||
@ -150,11 +147,11 @@ void cmdline_block_hide(void)
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
|
||||
|
||||
void wildmenu_show(Array items)
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL;
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
|
||||
void wildmenu_select(Integer selected)
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL;
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
|
||||
void wildmenu_hide(void)
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL;
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
|
||||
|
||||
void msg_show(String kind, Array content, Boolean replace_last)
|
||||
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
|
||||
|
@ -49,9 +49,9 @@ local c_proto = Ct(
|
||||
(fill * Cg((P('FUNC_API_LUA_ONLY') * Cc(true)), 'lua_only') ^ -1) *
|
||||
(fill * Cg((P('FUNC_API_CHECK_TEXTLOCK') * Cc(true)), 'check_textlock') ^ -1) *
|
||||
(fill * Cg((P('FUNC_API_REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1) *
|
||||
(fill * Cg((P('FUNC_API_BRIDGE_IMPL') * Cc(true)), 'bridge_impl') ^ -1) *
|
||||
(fill * Cg((P('FUNC_API_COMPOSITOR_IMPL') * Cc(true)), 'compositor_impl') ^ -1) *
|
||||
(fill * Cg((P('FUNC_API_CLIENT_IMPL') * Cc(true)), 'client_impl') ^ -1) *
|
||||
(fill * Cg((P('FUNC_API_CLIENT_IGNORE') * Cc(true)), 'client_ignore') ^ -1) *
|
||||
fill * P(';')
|
||||
)
|
||||
|
||||
|
@ -3,13 +3,12 @@ local mpack = require('mpack')
|
||||
local nvimdir = arg[1]
|
||||
package.path = nvimdir .. '/?.lua;' .. package.path
|
||||
|
||||
assert(#arg == 7)
|
||||
assert(#arg == 6)
|
||||
local input = io.open(arg[2], 'rb')
|
||||
local proto_output = io.open(arg[3], 'wb')
|
||||
local call_output = io.open(arg[4], 'wb')
|
||||
local remote_output = io.open(arg[5], 'wb')
|
||||
local metadata_output = io.open(arg[6], 'wb')
|
||||
local client_output = io.open(arg[7], 'wb')
|
||||
local call_output = io.open(arg[3], 'wb')
|
||||
local remote_output = io.open(arg[4], 'wb')
|
||||
local metadata_output = io.open(arg[5], 'wb')
|
||||
local client_output = io.open(arg[6], 'wb')
|
||||
|
||||
local c_grammar = require('generators.c_grammar')
|
||||
local events = c_grammar.grammar:match(input:read('*all'))
|
||||
@ -81,12 +80,9 @@ local function call_ui_event_method(output, ev)
|
||||
end
|
||||
end
|
||||
|
||||
output:write(' ui_call_'..ev.name..'(')
|
||||
output:write(' tui_'..ev.name..'(tui')
|
||||
for j = 1, #ev.parameters do
|
||||
output:write('arg_'..j)
|
||||
if j ~= #ev.parameters then
|
||||
output:write(', ')
|
||||
end
|
||||
output:write(', arg_'..j)
|
||||
end
|
||||
output:write(');\n')
|
||||
|
||||
@ -104,12 +100,9 @@ for i = 1, #events do
|
||||
ev.since = tonumber(ev.since)
|
||||
|
||||
if not ev.remote_only then
|
||||
proto_output:write(' void (*'..ev.name..')')
|
||||
write_signature(proto_output, ev, 'UI *ui')
|
||||
proto_output:write(';\n')
|
||||
|
||||
if not ev.remote_impl and not ev.noexport then
|
||||
remote_output:write('static void remote_ui_'..ev.name)
|
||||
remote_output:write('void remote_ui_'..ev.name)
|
||||
write_signature(remote_output, ev, 'UI *ui')
|
||||
remote_output:write('\n{\n')
|
||||
remote_output:write(' UIData *data = ui->data;\n')
|
||||
@ -130,6 +123,9 @@ for i = 1, #events do
|
||||
call_output:write(' UI_LOG('..ev.name..');\n')
|
||||
call_output:write(' ui_call_event("'..ev.name..'", args);\n')
|
||||
elseif ev.compositor_impl then
|
||||
call_output:write(' ui_comp_'..ev.name)
|
||||
write_signature(call_output, ev, '', true)
|
||||
call_output:write(";\n")
|
||||
call_output:write(' UI_CALL')
|
||||
write_signature(call_output, ev, '!ui->composed, '..ev.name..', ui', true)
|
||||
call_output:write(";\n")
|
||||
@ -151,14 +147,14 @@ for i = 1, #events do
|
||||
call_output:write("}\n\n")
|
||||
end
|
||||
|
||||
if (not ev.remote_only) and (not ev.noexport) and (not ev.client_impl) then
|
||||
if (not ev.remote_only) and (not ev.noexport) and (not ev.client_impl) and (not ev.client_ignore) then
|
||||
call_ui_event_method(client_output, ev)
|
||||
end
|
||||
end
|
||||
|
||||
local client_events = {}
|
||||
for _,ev in ipairs(events) do
|
||||
if (not ev.noexport) and ((not ev.remote_only) or ev.client_impl) then
|
||||
if (not ev.noexport) and ((not ev.remote_only) or ev.client_impl) and (not ev.client_ignore) then
|
||||
client_events[ev.name] = ev
|
||||
end
|
||||
end
|
||||
@ -176,7 +172,6 @@ end
|
||||
client_output:write('\n};\n\n')
|
||||
client_output:write(hashfun)
|
||||
|
||||
proto_output:close()
|
||||
call_output:close()
|
||||
remote_output:close()
|
||||
client_output:close()
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "lauxlib.h"
|
||||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/api/ui.h"
|
||||
#include "nvim/decoration_provider.h"
|
||||
#include "nvim/drawscreen.h"
|
||||
#include "nvim/gettext.h"
|
||||
@ -128,19 +129,15 @@ static int get_attr_entry(HlEntry entry)
|
||||
/// When a UI connects, we need to send it the table of highlights used so far.
|
||||
void ui_send_all_hls(UI *ui)
|
||||
{
|
||||
if (ui->hl_attr_define) {
|
||||
for (size_t i = 1; i < kv_size(attr_entries); i++) {
|
||||
Array inspect = hl_inspect((int)i);
|
||||
ui->hl_attr_define(ui, (Integer)i, kv_A(attr_entries, i).attr,
|
||||
kv_A(attr_entries, i).attr, inspect);
|
||||
api_free_array(inspect);
|
||||
}
|
||||
for (size_t i = 1; i < kv_size(attr_entries); i++) {
|
||||
Array inspect = hl_inspect((int)i);
|
||||
remote_ui_hl_attr_define(ui, (Integer)i, kv_A(attr_entries, i).attr,
|
||||
kv_A(attr_entries, i).attr, inspect);
|
||||
api_free_array(inspect);
|
||||
}
|
||||
if (ui->hl_group_set) {
|
||||
for (size_t hlf = 0; hlf < HLF_COUNT; hlf++) {
|
||||
ui->hl_group_set(ui, cstr_as_string((char *)hlf_names[hlf]),
|
||||
highlight_attr[hlf]);
|
||||
}
|
||||
for (size_t hlf = 0; hlf < HLF_COUNT; hlf++) {
|
||||
remote_ui_hl_group_set(ui, cstr_as_string((char *)hlf_names[hlf]),
|
||||
highlight_attr[hlf]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -653,7 +653,7 @@ ok:
|
||||
}
|
||||
|
||||
LuaRef ui_event_cb = nlua_ref_global(lstate, 3);
|
||||
ui_comp_add_cb(ns_id, ui_event_cb, ext_widgets);
|
||||
ui_add_cb(ns_id, ui_event_cb, ext_widgets);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -667,7 +667,7 @@ static int nlua_ui_detach(lua_State *lstate)
|
||||
return luaL_error(lstate, "invalid ns_id");
|
||||
}
|
||||
|
||||
ui_comp_remove_cb(ns_id);
|
||||
ui_remove_cb(ns_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -627,11 +627,13 @@ void os_exit(int r)
|
||||
{
|
||||
exiting = true;
|
||||
|
||||
if (!ui_client_channel_id) {
|
||||
if (ui_client_channel_id) {
|
||||
ui_client_stop();
|
||||
} else {
|
||||
ui_flush();
|
||||
ui_call_stop();
|
||||
ml_close_all(true); // remove all memfiles
|
||||
}
|
||||
ui_call_stop();
|
||||
ml_close_all(true); // remove all memfiles
|
||||
|
||||
if (!event_teardown() && r == 0) {
|
||||
r = 1; // Exit with error if main_loop did not teardown gracefully.
|
||||
|
@ -834,7 +834,6 @@ void free_all_mem(void)
|
||||
decor_free_all_mem();
|
||||
|
||||
ui_free_all_mem();
|
||||
ui_comp_free_all_mem();
|
||||
nlua_free_all_mem();
|
||||
|
||||
// should be last, in case earlier free functions deallocates arenas
|
||||
|
1461
src/nvim/tui/tui.c
1461
src/nvim/tui/tui.c
File diff suppressed because it is too large
Load Diff
168
src/nvim/ui.c
168
src/nvim/ui.c
@ -11,6 +11,7 @@
|
||||
#include "auto/config.h"
|
||||
#include "klib/kvec.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/api/ui.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/autocmd.h"
|
||||
#include "nvim/buffer_defs.h"
|
||||
@ -25,6 +26,7 @@
|
||||
#include "nvim/highlight.h"
|
||||
#include "nvim/highlight_defs.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/lua/executor.h"
|
||||
#include "nvim/main.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/message.h"
|
||||
@ -55,6 +57,9 @@ static bool pending_mode_info_update = false;
|
||||
static bool pending_mode_update = false;
|
||||
static handle_T cursor_grid_handle = DEFAULT_GRID_HANDLE;
|
||||
|
||||
static PMap(uint32_t) ui_event_cbs = MAP_INIT;
|
||||
bool ui_cb_ext[kUIExtCount]; ///< Internalized UI capabilities.
|
||||
|
||||
static bool has_mouse = false;
|
||||
static int pending_has_mouse = -1;
|
||||
|
||||
@ -96,8 +101,8 @@ static char uilog_last_event[1024] = { 0 };
|
||||
bool any_call = false; \
|
||||
for (size_t i = 0; i < ui_count; i++) { \
|
||||
UI *ui = uis[i]; \
|
||||
if (ui->funname && (cond)) { \
|
||||
ui->funname(__VA_ARGS__); \
|
||||
if ((cond)) { \
|
||||
remote_ui_##funname(__VA_ARGS__); \
|
||||
any_call = true; \
|
||||
} \
|
||||
} \
|
||||
@ -122,36 +127,25 @@ void ui_init(void)
|
||||
kv_ensure_space(call_buf, 16);
|
||||
}
|
||||
|
||||
static UI *builtin_ui = NULL;
|
||||
|
||||
#ifdef EXITFREE
|
||||
void ui_free_all_mem(void)
|
||||
{
|
||||
kv_destroy(call_buf);
|
||||
if (builtin_ui) {
|
||||
tui_free_all_mem(builtin_ui);
|
||||
builtin_ui = NULL;
|
||||
}
|
||||
|
||||
UIEventCallback *event_cb;
|
||||
map_foreach_value(&ui_event_cbs, event_cb, {
|
||||
free_ui_event_callback(event_cb);
|
||||
})
|
||||
pmap_destroy(uint32_t)(&ui_event_cbs);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ui_builtin_start(void)
|
||||
{
|
||||
builtin_ui = tui_start();
|
||||
}
|
||||
|
||||
UI *ui_get_by_index(int idx)
|
||||
{
|
||||
assert(idx < 16);
|
||||
return uis[idx];
|
||||
}
|
||||
|
||||
bool ui_rgb_attached(void)
|
||||
{
|
||||
if (!headless_mode && p_tgc) {
|
||||
return true;
|
||||
}
|
||||
for (size_t i = 1; i < ui_count; i++) {
|
||||
for (size_t i = 0; i < ui_count; i++) {
|
||||
if (uis[i]->rgb) {
|
||||
return true;
|
||||
}
|
||||
@ -162,7 +156,7 @@ bool ui_rgb_attached(void)
|
||||
/// Returns true if any UI requested `override=true`.
|
||||
bool ui_override(void)
|
||||
{
|
||||
for (size_t i = 1; i < ui_count; i++) {
|
||||
for (size_t i = 0; i < ui_count; i++) {
|
||||
if (uis[i]->override) {
|
||||
return true;
|
||||
}
|
||||
@ -172,11 +166,15 @@ bool ui_override(void)
|
||||
|
||||
bool ui_active(void)
|
||||
{
|
||||
return ui_count > 1;
|
||||
return ui_count > 0;
|
||||
}
|
||||
|
||||
void ui_refresh(void)
|
||||
{
|
||||
if (ui_client_channel_id) {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!ui_active()) {
|
||||
return;
|
||||
}
|
||||
@ -192,16 +190,13 @@ void ui_refresh(void)
|
||||
ext_widgets[i] = true;
|
||||
}
|
||||
|
||||
UI *compositor = uis[0];
|
||||
|
||||
bool inclusive = ui_override();
|
||||
for (size_t i = 1; i < ui_count; i++) {
|
||||
for (size_t i = 0; i < ui_count; i++) {
|
||||
UI *ui = uis[i];
|
||||
width = MIN(ui->width, width);
|
||||
height = MIN(ui->height, height);
|
||||
for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
|
||||
bool in_compositor = (ui->composed || j < kUIGlobalCount) && compositor->ui_ext[j];
|
||||
ext_widgets[j] &= (ui->ui_ext[j] || in_compositor || inclusive);
|
||||
ext_widgets[j] &= (ui->ui_ext[j] || inclusive);
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,6 +204,9 @@ void ui_refresh(void)
|
||||
pending_cursor_update = true;
|
||||
|
||||
for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
|
||||
if (i < kUIGlobalCount) {
|
||||
ext_widgets[i] |= ui_cb_ext[i];
|
||||
}
|
||||
ui_ext[i] = ext_widgets[i];
|
||||
if (i < kUIGlobalCount) {
|
||||
ui_call_option_set(cstr_as_string((char *)ui_ext_names[i]),
|
||||
@ -218,27 +216,10 @@ void ui_refresh(void)
|
||||
|
||||
ui_default_colors_set();
|
||||
|
||||
if (!ui_client_channel_id) {
|
||||
int save_p_lz = p_lz;
|
||||
p_lz = false; // convince redrawing() to return true ...
|
||||
screen_resize(width, height);
|
||||
p_lz = save_p_lz;
|
||||
} else {
|
||||
if (ui_client_attached) {
|
||||
// TODO(bfredl): ui_refresh() should only be used on the server
|
||||
// we are in the client process. forward the resize
|
||||
MAXSIZE_TEMP_ARRAY(args, 2);
|
||||
ADD_C(args, INTEGER_OBJ((int)width));
|
||||
ADD_C(args, INTEGER_OBJ((int)height));
|
||||
rpc_send_event(ui_client_channel_id, "nvim_ui_try_resize", args);
|
||||
} else {
|
||||
/// TODO(bfredl): Messy! The screen does not yet exist, but we need to
|
||||
/// communicate its size from the TUI to the client. Clean this up
|
||||
/// in The UI Devirtualization Project.
|
||||
Rows = height;
|
||||
Columns = width;
|
||||
}
|
||||
}
|
||||
int save_p_lz = p_lz;
|
||||
p_lz = false; // convince redrawing() to return true ...
|
||||
screen_resize(width, height);
|
||||
p_lz = save_p_lz;
|
||||
|
||||
if (ext_widgets[kUIMessages]) {
|
||||
set_option_value("cmdheight", 0L, NULL, 0);
|
||||
@ -253,7 +234,7 @@ void ui_refresh(void)
|
||||
int ui_pum_get_height(void)
|
||||
{
|
||||
int pum_height = 0;
|
||||
for (size_t i = 1; i < ui_count; i++) {
|
||||
for (size_t i = 0; i < ui_count; i++) {
|
||||
int ui_pum_height = uis[i]->pum_nlines;
|
||||
if (ui_pum_height) {
|
||||
pum_height =
|
||||
@ -265,7 +246,7 @@ int ui_pum_get_height(void)
|
||||
|
||||
bool ui_pum_get_pos(double *pwidth, double *pheight, double *prow, double *pcol)
|
||||
{
|
||||
for (size_t i = 1; i < ui_count; i++) {
|
||||
for (size_t i = 0; i < ui_count; i++) {
|
||||
if (!uis[i]->pum_pos) {
|
||||
continue;
|
||||
}
|
||||
@ -372,10 +353,7 @@ void ui_attach_impl(UI *ui, uint64_t chanid)
|
||||
}
|
||||
ui_refresh();
|
||||
|
||||
bool is_compositor = (ui == uis[0]);
|
||||
if (!is_compositor) {
|
||||
do_autocmd_uienter(chanid, true);
|
||||
}
|
||||
do_autocmd_uienter(chanid, true);
|
||||
}
|
||||
|
||||
void ui_detach_impl(UI *ui, uint64_t chanid)
|
||||
@ -420,9 +398,9 @@ void ui_set_ext_option(UI *ui, UIExtension ext, bool active)
|
||||
ui_refresh();
|
||||
return;
|
||||
}
|
||||
if (ui->option_set && (ui_ext_names[ext][0] != '_' || active)) {
|
||||
ui->option_set(ui, cstr_as_string((char *)ui_ext_names[ext]),
|
||||
BOOLEAN_OBJ(active));
|
||||
if (ui_ext_names[ext][0] != '_' || active) {
|
||||
remote_ui_option_set(ui, cstr_as_string((char *)ui_ext_names[ext]),
|
||||
BOOLEAN_OBJ(active));
|
||||
}
|
||||
if (ext == kUITermColors) {
|
||||
ui_default_colors_set();
|
||||
@ -618,7 +596,7 @@ bool ui_has(UIExtension ext)
|
||||
Array ui_array(void)
|
||||
{
|
||||
Array all_uis = ARRAY_DICT_INIT;
|
||||
for (size_t i = 1; i < ui_count; i++) {
|
||||
for (size_t i = 0; i < ui_count; i++) {
|
||||
UI *ui = uis[i];
|
||||
Dictionary info = ARRAY_DICT_INIT;
|
||||
PUT(info, "width", INTEGER_OBJ(ui->width));
|
||||
@ -630,7 +608,7 @@ Array ui_array(void)
|
||||
PUT(info, ui_ext_names[j], BOOLEAN_OBJ(ui->ui_ext[j]));
|
||||
}
|
||||
}
|
||||
ui->inspect(ui, &info);
|
||||
remote_ui_inspect(ui, &info);
|
||||
ADD(all_uis, DICTIONARY_OBJ(info));
|
||||
}
|
||||
return all_uis;
|
||||
@ -663,3 +641,75 @@ void ui_grid_resize(handle_T grid_handle, int width, int height, Error *error)
|
||||
win_set_inner_size(wp, true);
|
||||
}
|
||||
}
|
||||
|
||||
void ui_call_event(char *name, Array args)
|
||||
{
|
||||
UIEventCallback *event_cb;
|
||||
bool handled = false;
|
||||
map_foreach_value(&ui_event_cbs, event_cb, {
|
||||
Error err = ERROR_INIT;
|
||||
Object res = nlua_call_ref(event_cb->cb, name, args, false, &err);
|
||||
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
|
||||
handled = true;
|
||||
}
|
||||
if (ERROR_SET(&err)) {
|
||||
ELOG("Error while executing ui_comp_event callback: %s", err.msg);
|
||||
}
|
||||
api_clear_error(&err);
|
||||
})
|
||||
|
||||
if (!handled) {
|
||||
UI_CALL(true, event, ui, name, args);
|
||||
}
|
||||
}
|
||||
|
||||
void ui_cb_update_ext(void)
|
||||
{
|
||||
memset(ui_cb_ext, 0, ARRAY_SIZE(ui_cb_ext));
|
||||
|
||||
for (size_t i = 0; i < kUIGlobalCount; i++) {
|
||||
UIEventCallback *event_cb;
|
||||
|
||||
map_foreach_value(&ui_event_cbs, event_cb, {
|
||||
if (event_cb->ext_widgets[i]) {
|
||||
ui_cb_ext[i] = true;
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
void free_ui_event_callback(UIEventCallback *event_cb)
|
||||
{
|
||||
api_free_luaref(event_cb->cb);
|
||||
xfree(event_cb);
|
||||
}
|
||||
|
||||
void ui_add_cb(uint32_t ns_id, LuaRef cb, bool *ext_widgets)
|
||||
{
|
||||
UIEventCallback *event_cb = xcalloc(1, sizeof(UIEventCallback));
|
||||
event_cb->cb = cb;
|
||||
memcpy(event_cb->ext_widgets, ext_widgets, ARRAY_SIZE(event_cb->ext_widgets));
|
||||
if (event_cb->ext_widgets[kUIMessages]) {
|
||||
event_cb->ext_widgets[kUICmdline] = true;
|
||||
}
|
||||
|
||||
UIEventCallback **item = (UIEventCallback **)pmap_ref(uint32_t)(&ui_event_cbs, ns_id, true);
|
||||
if (*item) {
|
||||
free_ui_event_callback(*item);
|
||||
}
|
||||
*item = event_cb;
|
||||
|
||||
ui_cb_update_ext();
|
||||
ui_refresh();
|
||||
}
|
||||
|
||||
void ui_remove_cb(uint32_t ns_id)
|
||||
{
|
||||
if (pmap_has(uint32_t)(&ui_event_cbs, ns_id)) {
|
||||
free_ui_event_callback(pmap_get(uint32_t)(&ui_event_cbs, ns_id));
|
||||
pmap_del(uint32_t)(&ui_event_cbs, ns_id);
|
||||
}
|
||||
ui_cb_update_ext();
|
||||
ui_refresh();
|
||||
}
|
||||
|
@ -52,6 +52,41 @@ enum {
|
||||
|
||||
typedef int LineFlags;
|
||||
|
||||
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;
|
||||
|
||||
struct ui_t {
|
||||
bool rgb;
|
||||
bool override; ///< Force highest-requested UI capabilities.
|
||||
@ -65,13 +100,9 @@ struct ui_t {
|
||||
double pum_col;
|
||||
double pum_height;
|
||||
double pum_width;
|
||||
void *data;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "ui_events.generated.h"
|
||||
#endif
|
||||
|
||||
void (*inspect)(UI *ui, Dictionary *info);
|
||||
// TODO(bfredl): integrate into struct!
|
||||
UIData data[1];
|
||||
};
|
||||
|
||||
typedef struct ui_event_callback {
|
||||
|
@ -15,15 +15,19 @@
|
||||
#include "nvim/main.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/msgpack_rpc/channel.h"
|
||||
#include "nvim/tui/tui.h"
|
||||
#include "nvim/ui.h"
|
||||
#include "nvim/ui_client.h"
|
||||
|
||||
static TUIData *tui = NULL;
|
||||
|
||||
// uncrustify:off
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "ui_client.c.generated.h"
|
||||
# include "ui_events_client.generated.h"
|
||||
#endif
|
||||
// uncrustify:on
|
||||
//
|
||||
|
||||
uint64_t ui_client_start_server(int argc, char **argv)
|
||||
{
|
||||
@ -52,20 +56,20 @@ uint64_t ui_client_start_server(int argc, char **argv)
|
||||
void ui_client_run(bool remote_ui)
|
||||
FUNC_ATTR_NORETURN
|
||||
{
|
||||
ui_builtin_start();
|
||||
|
||||
loop_poll_events(&main_loop, 1);
|
||||
int width, height;
|
||||
char *term;
|
||||
tui = tui_start(&width, &height, &term);
|
||||
|
||||
MAXSIZE_TEMP_ARRAY(args, 3);
|
||||
ADD_C(args, INTEGER_OBJ(Columns));
|
||||
ADD_C(args, INTEGER_OBJ(Rows));
|
||||
ADD_C(args, INTEGER_OBJ(width));
|
||||
ADD_C(args, INTEGER_OBJ(height));
|
||||
|
||||
MAXSIZE_TEMP_DICT(opts, 9);
|
||||
PUT_C(opts, "rgb", BOOLEAN_OBJ(true));
|
||||
PUT_C(opts, "ext_linegrid", BOOLEAN_OBJ(true));
|
||||
PUT_C(opts, "ext_termcolors", BOOLEAN_OBJ(true));
|
||||
if (ui_client_termname) {
|
||||
PUT_C(opts, "term_name", STRING_OBJ(cstr_as_string(ui_client_termname)));
|
||||
if (term) {
|
||||
PUT(opts, "term_name", STRING_OBJ(cstr_to_string(term)));
|
||||
}
|
||||
if (ui_client_bg_respose != kNone) {
|
||||
bool is_dark = (ui_client_bg_respose == kTrue);
|
||||
@ -80,6 +84,7 @@ void ui_client_run(bool remote_ui)
|
||||
}
|
||||
}
|
||||
ADD_C(args, DICTIONARY_OBJ(opts));
|
||||
|
||||
rpc_send_event(ui_client_channel_id, "nvim_ui_attach", args);
|
||||
ui_client_attached = true;
|
||||
|
||||
@ -89,6 +94,22 @@ void ui_client_run(bool remote_ui)
|
||||
}
|
||||
}
|
||||
|
||||
void ui_client_stop(void)
|
||||
{
|
||||
tui_stop(tui);
|
||||
}
|
||||
|
||||
void ui_client_set_size(int width, int height)
|
||||
{
|
||||
// The currently known size will be sent when attaching
|
||||
if (ui_client_attached) {
|
||||
MAXSIZE_TEMP_ARRAY(args, 2);
|
||||
ADD_C(args, INTEGER_OBJ((int)width));
|
||||
ADD_C(args, INTEGER_OBJ((int)height));
|
||||
rpc_send_event(ui_client_channel_id, "nvim_ui_try_resize", args);
|
||||
}
|
||||
}
|
||||
|
||||
UIClientHandler ui_client_get_redraw_handler(const char *name, size_t name_len, Error *error)
|
||||
{
|
||||
int hash = ui_client_handler_hash(name, name_len);
|
||||
@ -133,7 +154,7 @@ void ui_client_event_grid_resize(Array args)
|
||||
Integer grid = args.items[0].data.integer;
|
||||
Integer width = args.items[1].data.integer;
|
||||
Integer height = args.items[2].data.integer;
|
||||
ui_call_grid_resize(grid, width, height);
|
||||
tui_grid_resize(tui, grid, width, height);
|
||||
|
||||
if (grid_line_buf_size < (size_t)width) {
|
||||
xfree(grid_line_buf_char);
|
||||
@ -159,6 +180,6 @@ void ui_client_event_raw_line(GridLineEvent *g)
|
||||
// TODO(hlpr98): Accommodate other LineFlags when included in grid_line
|
||||
LineFlags lineflags = 0;
|
||||
|
||||
ui_call_raw_line(grid, row, startcol, endcol, clearcol, g->cur_attr, lineflags,
|
||||
(const schar_T *)grid_line_buf_char, grid_line_buf_attr);
|
||||
tui_raw_line(tui, grid, row, startcol, endcol, clearcol, g->cur_attr, lineflags,
|
||||
(const schar_T *)grid_line_buf_char, grid_line_buf_attr);
|
||||
}
|
||||
|
@ -34,8 +34,6 @@ EXTERN TriState ui_client_bg_respose INIT(= kNone);
|
||||
/// by convention, this uses fd=3 (next free number after stdio)
|
||||
EXTERN bool ui_client_forward_stdin INIT(= false);
|
||||
|
||||
EXTERN char *ui_client_termname INIT(= NULL);
|
||||
|
||||
#define UI_CLIENT_STDIN_FD 3
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "ui_client.h.generated.h"
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "nvim/highlight.h"
|
||||
#include "nvim/highlight_group.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/lua/executor.h"
|
||||
#include "nvim/macros.h"
|
||||
#include "nvim/map.h"
|
||||
#include "nvim/memory.h"
|
||||
@ -39,7 +38,6 @@
|
||||
# include "ui_compositor.c.generated.h"
|
||||
#endif
|
||||
|
||||
static UI *compositor = NULL;
|
||||
static int composed_uis = 0;
|
||||
kvec_t(ScreenGrid *) layers = KV_INITIAL_VALUE;
|
||||
|
||||
@ -60,52 +58,12 @@ static bool msg_was_scrolled = false;
|
||||
static int msg_sep_row = -1;
|
||||
static schar_T msg_sep_char = { ' ', NUL };
|
||||
|
||||
static PMap(uint32_t) ui_event_cbs = MAP_INIT;
|
||||
|
||||
static int dbghl_normal, dbghl_clear, dbghl_composed, dbghl_recompose;
|
||||
|
||||
void ui_comp_init(void)
|
||||
{
|
||||
if (compositor != NULL) {
|
||||
return;
|
||||
}
|
||||
compositor = xcalloc(1, sizeof(UI));
|
||||
|
||||
compositor->rgb = true;
|
||||
compositor->grid_resize = ui_comp_grid_resize;
|
||||
compositor->grid_scroll = ui_comp_grid_scroll;
|
||||
compositor->grid_cursor_goto = ui_comp_grid_cursor_goto;
|
||||
compositor->raw_line = ui_comp_raw_line;
|
||||
compositor->msg_set_pos = ui_comp_msg_set_pos;
|
||||
compositor->event = ui_comp_event;
|
||||
|
||||
// Be unopinionated: will be attached together with a "real" ui anyway
|
||||
compositor->width = INT_MAX;
|
||||
compositor->height = INT_MAX;
|
||||
for (UIExtension i = kUIGlobalCount; (int)i < kUIExtCount; i++) {
|
||||
compositor->ui_ext[i] = true;
|
||||
}
|
||||
|
||||
// TODO(bfredl): one day. in the future.
|
||||
compositor->ui_ext[kUIMultigrid] = false;
|
||||
|
||||
// TODO(bfredl): this will be more complicated if we implement
|
||||
// hlstate per UI (i e reduce hl ids for non-hlstate UIs)
|
||||
compositor->ui_ext[kUIHlState] = false;
|
||||
|
||||
kv_push(layers, &default_grid);
|
||||
curgrid = &default_grid;
|
||||
|
||||
ui_attach_impl(compositor, 0);
|
||||
}
|
||||
|
||||
void ui_comp_free_all_mem(void)
|
||||
{
|
||||
UIEventCallback *event_cb;
|
||||
map_foreach_value(&ui_event_cbs, event_cb, {
|
||||
free_ui_event_callback(event_cb);
|
||||
})
|
||||
pmap_destroy(uint32_t)(&ui_event_cbs);
|
||||
}
|
||||
|
||||
void ui_comp_syn_init(void)
|
||||
@ -258,7 +216,7 @@ bool ui_comp_set_grid(handle_T handle)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ui_comp_raise_grid(ScreenGrid *grid, size_t new_index)
|
||||
void ui_comp_raise_grid(ScreenGrid *grid, size_t new_index)
|
||||
{
|
||||
size_t old_index = grid->comp_index;
|
||||
for (size_t i = old_index; i < new_index; i++) {
|
||||
@ -278,7 +236,7 @@ static void ui_comp_raise_grid(ScreenGrid *grid, size_t new_index)
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_comp_grid_cursor_goto(UI *ui, Integer grid_handle, Integer r, Integer c)
|
||||
void ui_comp_grid_cursor_goto(Integer grid_handle, Integer r, Integer c)
|
||||
{
|
||||
if (!ui_comp_should_draw() || !ui_comp_set_grid((int)grid_handle)) {
|
||||
return;
|
||||
@ -538,9 +496,9 @@ void ui_comp_compose_grid(ScreenGrid *grid)
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_comp_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 ui_comp_raw_line(Integer grid, Integer row, Integer startcol, Integer endcol, Integer clearcol,
|
||||
Integer clearattr, LineFlags flags, const schar_T *chunk,
|
||||
const sattr_T *attrs)
|
||||
{
|
||||
if (!ui_comp_should_draw() || !ui_comp_set_grid((int)grid)) {
|
||||
return;
|
||||
@ -605,8 +563,7 @@ bool ui_comp_set_screen_valid(bool valid)
|
||||
return old_val;
|
||||
}
|
||||
|
||||
static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row, Boolean scrolled,
|
||||
String sep_char)
|
||||
void ui_comp_msg_set_pos(Integer grid, Integer row, Boolean scrolled, String sep_char)
|
||||
{
|
||||
msg_grid.comp_row = (int)row;
|
||||
if (scrolled && row > 0) {
|
||||
@ -650,8 +607,8 @@ static bool curgrid_covered_above(int row)
|
||||
return kv_size(layers) - (above_msg?1:0) > curgrid->comp_index + 1;
|
||||
}
|
||||
|
||||
static void ui_comp_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left,
|
||||
Integer right, Integer rows, Integer cols)
|
||||
void ui_comp_grid_scroll(Integer grid, Integer top, Integer bot, Integer left, Integer right,
|
||||
Integer rows, Integer cols)
|
||||
{
|
||||
if (!ui_comp_should_draw() || !ui_comp_set_grid((int)grid)) {
|
||||
return;
|
||||
@ -685,7 +642,7 @@ static void ui_comp_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot,
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_comp_grid_resize(UI *ui, Integer grid, Integer width, Integer height)
|
||||
void ui_comp_grid_resize(Integer grid, Integer width, Integer height)
|
||||
{
|
||||
if (grid == 1) {
|
||||
ui_composed_call_grid_resize(1, width, height);
|
||||
@ -703,75 +660,3 @@ static void ui_comp_grid_resize(UI *ui, Integer grid, Integer width, Integer hei
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_comp_event(UI *ui, char *name, Array args)
|
||||
{
|
||||
UIEventCallback *event_cb;
|
||||
bool handled = false;
|
||||
map_foreach_value(&ui_event_cbs, event_cb, {
|
||||
Error err = ERROR_INIT;
|
||||
Object res = nlua_call_ref(event_cb->cb, name, args, false, &err);
|
||||
if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
|
||||
handled = true;
|
||||
}
|
||||
if (ERROR_SET(&err)) {
|
||||
ELOG("Error while executing ui_comp_event callback: %s", err.msg);
|
||||
}
|
||||
api_clear_error(&err);
|
||||
})
|
||||
|
||||
if (!handled) {
|
||||
ui_composed_call_event(name, args);
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_comp_update_ext(void)
|
||||
{
|
||||
memset(compositor->ui_ext, 0, ARRAY_SIZE(compositor->ui_ext));
|
||||
|
||||
for (size_t i = 0; i < kUIGlobalCount; i++) {
|
||||
UIEventCallback *event_cb;
|
||||
|
||||
map_foreach_value(&ui_event_cbs, event_cb, {
|
||||
if (event_cb->ext_widgets[i]) {
|
||||
compositor->ui_ext[i] = true;
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
void free_ui_event_callback(UIEventCallback *event_cb)
|
||||
{
|
||||
api_free_luaref(event_cb->cb);
|
||||
xfree(event_cb);
|
||||
}
|
||||
|
||||
void ui_comp_add_cb(uint32_t ns_id, LuaRef cb, bool *ext_widgets)
|
||||
{
|
||||
UIEventCallback *event_cb = xcalloc(1, sizeof(UIEventCallback));
|
||||
event_cb->cb = cb;
|
||||
memcpy(event_cb->ext_widgets, ext_widgets, ARRAY_SIZE(event_cb->ext_widgets));
|
||||
if (event_cb->ext_widgets[kUIMessages]) {
|
||||
event_cb->ext_widgets[kUICmdline] = true;
|
||||
}
|
||||
|
||||
UIEventCallback **item = (UIEventCallback **)pmap_ref(uint32_t)(&ui_event_cbs, ns_id, true);
|
||||
if (*item) {
|
||||
free_ui_event_callback(*item);
|
||||
}
|
||||
*item = event_cb;
|
||||
|
||||
ui_comp_update_ext();
|
||||
ui_refresh();
|
||||
}
|
||||
|
||||
void ui_comp_remove_cb(uint32_t ns_id)
|
||||
{
|
||||
if (pmap_has(uint32_t)(&ui_event_cbs, ns_id)) {
|
||||
free_ui_event_callback(pmap_get(uint32_t)(&ui_event_cbs, ns_id));
|
||||
pmap_del(uint32_t)(&ui_event_cbs, ns_id);
|
||||
}
|
||||
ui_comp_update_ext();
|
||||
ui_refresh();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user