mirror of
https://github.com/neovim/neovim.git
synced 2025-09-17 08:48:16 +00:00
UI: add "compositor" layer to merge grids for TUI use in a correct way
Initially we will use this for the popupmenu, floating windows will follow soon NB: writedelay + compositor is weird, we need more flexible redraw introspection.
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
#include "nvim/popupmnu.h"
|
||||
#include "nvim/screen.h"
|
||||
#include "nvim/highlight.h"
|
||||
#include "nvim/ui_compositor.h"
|
||||
#include "nvim/window.h"
|
||||
#include "nvim/cursor_shape.h"
|
||||
#ifdef FEAT_TUI
|
||||
@@ -60,11 +61,11 @@ static bool pending_mode_update = false;
|
||||
static handle_T cursor_grid_handle = DEFAULT_GRID_HANDLE;
|
||||
|
||||
#if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL
|
||||
# define UI_LOG(funname, ...)
|
||||
# define UI_LOG(funname)
|
||||
#else
|
||||
static size_t uilog_seen = 0;
|
||||
static char uilog_last_event[1024] = { 0 };
|
||||
# define UI_LOG(funname, ...) \
|
||||
# define UI_LOG(funname) \
|
||||
do { \
|
||||
if (strequal(uilog_last_event, STR(funname))) { \
|
||||
uilog_seen++; \
|
||||
@@ -80,42 +81,34 @@ static char uilog_last_event[1024] = { 0 };
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
// UI_CALL invokes a function on all registered UI instances. The functions can
|
||||
// have 0-10 arguments (configurable by SELECT_NTH).
|
||||
//
|
||||
// See http://stackoverflow.com/a/11172679 for how it works.
|
||||
#ifdef _MSC_VER
|
||||
# define UI_CALL(funname, ...) \
|
||||
do { \
|
||||
UI_LOG(funname, 0); \
|
||||
for (size_t i = 0; i < ui_count; i++) { \
|
||||
UI *ui = uis[i]; \
|
||||
UI_CALL_MORE(funname, __VA_ARGS__); \
|
||||
// UI_CALL invokes a function on all registered UI instances.
|
||||
// This is called by code generated by generators/gen_api_ui_events.lua
|
||||
// C code should use ui_call_{funname} instead.
|
||||
# define UI_CALL(cond, funname, ...) \
|
||||
do { \
|
||||
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__); \
|
||||
any_call = true; \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
# define UI_CALL(...) \
|
||||
do { \
|
||||
UI_LOG(__VA_ARGS__, 0); \
|
||||
for (size_t i = 0; i < ui_count; i++) { \
|
||||
UI *ui = uis[i]; \
|
||||
UI_CALL_HELPER(CNT(__VA_ARGS__), __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
#define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, MORE, MORE, \
|
||||
MORE, MORE, MORE, MORE, ZERO, ignore)
|
||||
#define SELECT_NTH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, ...) a11
|
||||
#define UI_CALL_HELPER(c, ...) UI_CALL_HELPER2(c, __VA_ARGS__)
|
||||
// Resolves to UI_CALL_MORE or UI_CALL_ZERO.
|
||||
#define UI_CALL_HELPER2(c, ...) UI_CALL_##c(__VA_ARGS__)
|
||||
#define UI_CALL_MORE(method, ...) if (ui->method) ui->method(ui, __VA_ARGS__)
|
||||
#define UI_CALL_ZERO(method) if (ui->method) ui->method(ui)
|
||||
} \
|
||||
if (any_call) { \
|
||||
UI_LOG(funname); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "ui_events_call.generated.h"
|
||||
#endif
|
||||
|
||||
void ui_init(void)
|
||||
{
|
||||
default_grid.handle = 1;
|
||||
ui_comp_init();
|
||||
}
|
||||
|
||||
void ui_builtin_start(void)
|
||||
{
|
||||
#ifdef FEAT_TUI
|
||||
@@ -135,17 +128,12 @@ void ui_builtin_start(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void ui_builtin_stop(void)
|
||||
{
|
||||
UI_CALL(stop);
|
||||
}
|
||||
|
||||
bool ui_rgb_attached(void)
|
||||
{
|
||||
if (!headless_mode && p_tgc) {
|
||||
return true;
|
||||
}
|
||||
for (size_t i = 0; i < ui_count; i++) {
|
||||
for (size_t i = 1; i < ui_count; i++) {
|
||||
if (uis[i]->rgb) {
|
||||
return true;
|
||||
}
|
||||
@@ -155,13 +143,13 @@ bool ui_rgb_attached(void)
|
||||
|
||||
bool ui_active(void)
|
||||
{
|
||||
return ui_count != 0;
|
||||
return ui_count > 1;
|
||||
}
|
||||
|
||||
void ui_event(char *name, Array args)
|
||||
{
|
||||
bool args_consumed = false;
|
||||
UI_CALL(event, name, args, &args_consumed);
|
||||
ui_call_event(name, args, &args_consumed);
|
||||
if (!args_consumed) {
|
||||
api_free_array(args);
|
||||
}
|
||||
@@ -257,6 +245,9 @@ void ui_attach_impl(UI *ui)
|
||||
if (ui_count == MAX_UI_COUNT) {
|
||||
abort();
|
||||
}
|
||||
if (!ui->ui_ext[kUIMultigrid]) {
|
||||
ui_comp_attach(ui);
|
||||
}
|
||||
|
||||
uis[ui_count++] = ui;
|
||||
ui_refresh_options();
|
||||
@@ -303,6 +294,10 @@ void ui_detach_impl(UI *ui)
|
||||
&& !exiting) {
|
||||
ui_schedule_refresh();
|
||||
}
|
||||
|
||||
if (!ui->ui_ext[kUIMultigrid]) {
|
||||
ui_comp_detach(ui);
|
||||
}
|
||||
}
|
||||
|
||||
void ui_set_ext_option(UI *ui, UIExtension ext, bool active)
|
||||
@@ -322,9 +317,9 @@ void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol,
|
||||
{
|
||||
size_t off = grid->line_offset[row] + (size_t)startcol;
|
||||
|
||||
UI_CALL(raw_line, grid->handle, row, startcol, endcol, clearcol, clearattr,
|
||||
wrap, (const schar_T *)grid->chars + off,
|
||||
(const sattr_T *)grid->attrs + off);
|
||||
ui_call_raw_line(grid->handle, row, startcol, endcol,
|
||||
clearcol, clearattr, wrap, (const schar_T *)grid->chars + off,
|
||||
(const sattr_T *)grid->attrs + off);
|
||||
|
||||
if (p_wd) { // 'writedelay': flush & delay each time.
|
||||
int old_row = cursor_row, old_col = cursor_col;
|
||||
@@ -421,7 +416,7 @@ bool ui_is_external(UIExtension widget)
|
||||
Array ui_array(void)
|
||||
{
|
||||
Array all_uis = ARRAY_DICT_INIT;
|
||||
for (size_t i = 0; i < ui_count; i++) {
|
||||
for (size_t i = 1; i < ui_count; i++) {
|
||||
UI *ui = uis[i];
|
||||
Dictionary info = ARRAY_DICT_INIT;
|
||||
PUT(info, "width", INTEGER_OBJ(ui->width));
|
||||
|
Reference in New Issue
Block a user