aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ui.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-01-25 18:31:31 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-01-25 18:31:31 +0000
commit9243becbedbb6a1592208051f8fa2b090dcc5e7d (patch)
tree607c2a862ec3f4399b8766383f6f8e04c4aa43b4 /src/nvim/ui.c
parent9e40b6e9e1bc67f2d856adb837ee64dd0e25b717 (diff)
parent3c48d3c83fc21dbc0841f9210f04bdb073d73cd1 (diff)
downloadrneovim-9243becbedbb6a1592208051f8fa2b090dcc5e7d.tar.gz
rneovim-9243becbedbb6a1592208051f8fa2b090dcc5e7d.tar.bz2
rneovim-9243becbedbb6a1592208051f8fa2b090dcc5e7d.zip
Merge remote-tracking branch 'upstream/master' into usermarksusermarks
Diffstat (limited to 'src/nvim/ui.c')
-rw-r--r--src/nvim/ui.c266
1 files changed, 154 insertions, 112 deletions
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index da671a3ad1..9f1cb87eb0 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -2,47 +2,40 @@
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <assert.h>
-#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
#include <string.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/charset.h"
-#include "nvim/cursor.h"
+#include "nvim/buffer_defs.h"
#include "nvim/cursor_shape.h"
-#include "nvim/diff.h"
#include "nvim/drawscreen.h"
-#include "nvim/event/loop.h"
#include "nvim/ex_getln.h"
-#include "nvim/fold.h"
-#include "nvim/garray.h"
+#include "nvim/gettext.h"
+#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/log.h"
-#include "nvim/main.h"
-#include "nvim/mbyte.h"
+#include "nvim/lua/executor.h"
+#include "nvim/map.h"
#include "nvim/memory.h"
-#include "nvim/move.h"
-#include "nvim/msgpack_rpc/channel.h"
-#include "nvim/normal.h"
+#include "nvim/message.h"
#include "nvim/option.h"
-#include "nvim/os/input.h"
-#include "nvim/os/signal.h"
#include "nvim/os/time.h"
-#include "nvim/os_unix.h"
-#include "nvim/popupmenu.h"
+#include "nvim/strings.h"
#include "nvim/ui.h"
+#include "nvim/ui_client.h"
#include "nvim/ui_compositor.h"
#include "nvim/vim.h"
#include "nvim/window.h"
-#ifdef FEAT_TUI
-# include "nvim/tui/tui.h"
-#else
-# include "nvim/msgpack_rpc/server.h"
-#endif
-#include "nvim/api/private/helpers.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui.c.generated.h"
@@ -61,6 +54,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;
@@ -102,8 +98,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; \
} \
} \
@@ -116,10 +112,6 @@ static char uilog_last_event[1024] = { 0 };
# include "ui_events_call.generated.h"
#endif
-#ifndef EXITFREE
-# undef entered_free_all_mem
-#endif
-
void ui_init(void)
{
default_grid.handle = 1;
@@ -128,36 +120,25 @@ void ui_init(void)
kv_ensure_space(call_buf, 16);
}
+#ifdef EXITFREE
void ui_free_all_mem(void)
{
kv_destroy(call_buf);
-}
-void ui_builtin_start(void)
-{
-#ifdef FEAT_TUI
- tui_start();
-#else
- fprintf(stderr, "Nvim headless-mode started.\n");
- size_t len;
- char **addrs = server_address_list(&len);
- if (addrs != NULL) {
- fprintf(stderr, "Listening on:\n");
- for (size_t i = 0; i < len; i++) {
- fprintf(stderr, "\t%s\n", addrs[i]);
- }
- xfree(addrs);
- }
- fprintf(stderr, "Press CTRL+C to exit.\n");
-#endif
+ 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
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;
}
@@ -168,7 +149,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;
}
@@ -178,17 +159,21 @@ 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;
}
if (updating_screen) {
- deferred_refresh_event(NULL);
+ ui_schedule_refresh();
return;
}
@@ -212,6 +197,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]),
@@ -221,20 +209,13 @@ 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 {
- Array args = ARRAY_DICT_INIT;
- ADD(args, INTEGER_OBJ((int)width));
- ADD(args, INTEGER_OBJ((int)height));
- rpc_send_event(ui_client_channel_id, "nvim_ui_try_resize", args);
- }
+ 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]) {
- p_ch = 0;
+ set_option_value("cmdheight", 0L, NULL, 0);
command_height();
}
ui_mode_info_set();
@@ -246,7 +227,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 =
@@ -258,7 +239,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;
}
@@ -278,10 +259,6 @@ static void ui_refresh_event(void **argv)
void ui_schedule_refresh(void)
{
- loop_schedule_fast(&main_loop, event_create(deferred_refresh_event, 0));
-}
-static void deferred_refresh_event(void **argv)
-{
multiqueue_put(resize_events, ui_refresh_event, 0);
}
@@ -312,34 +289,36 @@ void vim_beep(unsigned val)
{
called_vim_beep = true;
- if (emsg_silent == 0) {
- if (!((bo_flags & val) || (bo_flags & BO_ALL))) {
- static int beeps = 0;
- static uint64_t start_time = 0;
+ if (emsg_silent != 0 || in_assert_fails) {
+ return;
+ }
- // Only beep up to three times per half a second,
- // otherwise a sequence of beeps would freeze Vim.
- if (start_time == 0 || os_hrtime() - start_time > 500000000u) {
- beeps = 0;
- start_time = os_hrtime();
- }
- beeps++;
- if (beeps <= 3) {
- if (p_vb) {
- ui_call_visual_bell();
- } else {
- ui_call_bell();
- }
+ if (!((bo_flags & val) || (bo_flags & BO_ALL))) {
+ static int beeps = 0;
+ static uint64_t start_time = 0;
+
+ // Only beep up to three times per half a second,
+ // otherwise a sequence of beeps would freeze Vim.
+ if (start_time == 0 || os_hrtime() - start_time > 500000000U) {
+ beeps = 0;
+ start_time = os_hrtime();
+ }
+ beeps++;
+ if (beeps <= 3) {
+ if (p_vb) {
+ ui_call_visual_bell();
+ } else {
+ ui_call_bell();
}
}
+ }
- // When 'debug' contains "beep" produce a message. If we are sourcing
- // a script or executing a function give the user a hint where the beep
- // comes from.
- if (vim_strchr((char *)p_debug, 'e') != NULL) {
- msg_source(HL_ATTR(HLF_W));
- msg_attr(_("Beep!"), HL_ATTR(HLF_W));
- }
+ // When 'debug' contains "beep" produce a message. If we are sourcing
+ // a script or executing a function give the user a hint where the beep
+ // comes from.
+ if (vim_strchr(p_debug, 'e') != NULL) {
+ msg_source(HL_ATTR(HLF_W));
+ msg_attr(_("Beep!"), HL_ATTR(HLF_W));
}
}
@@ -369,10 +348,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)
@@ -417,9 +393,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();
@@ -449,7 +425,7 @@ void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol,
MIN(clearcol, (int)grid->cols - 1));
ui_call_flush();
uint64_t wd = (uint64_t)labs(p_wd);
- os_microdelay(wd * 1000u, true);
+ os_microdelay(wd * 1000U, true);
pending_cursor_update = true; // restore the cursor later
}
}
@@ -503,11 +479,12 @@ handle_T ui_cursor_grid(void)
void ui_flush(void)
{
+ assert(!ui_client_channel_id);
if (!ui_active()) {
return;
}
cmdline_ui_flush();
- win_ui_flush();
+ win_ui_flush(false);
msg_ext_ui_flush();
msg_scroll_flush();
@@ -517,11 +494,10 @@ void ui_flush(void)
}
if (pending_mode_info_update) {
Arena arena = ARENA_EMPTY;
- arena_start(&arena, &ui_ext_fixblk);
Array style = mode_style_array(&arena);
bool enabled = (*p_guicursor != NUL);
ui_call_mode_info_set(enabled, style);
- arena_mem_free(arena_finish(&arena), &ui_ext_fixblk);
+ arena_mem_free(arena_finish(&arena));
pending_mode_info_update = false;
}
if (pending_mode_update && !starting) {
@@ -566,7 +542,7 @@ void ui_check_mouse(void)
// - 'a' is in 'mouse' and "c" is in MOUSE_A, or
// - the current buffer is a help file and 'h' is in 'mouse' and we are in a
// normal editing mode (not at hit-return message).
- for (char_u *p = p_mouse; *p; p++) {
+ for (char *p = p_mouse; *p; p++) {
switch (*p) {
case 'a':
if (vim_strchr(MOUSE_A, checkfor) != NULL) {
@@ -612,16 +588,10 @@ bool ui_has(UIExtension ext)
return ui_ext[ext];
}
-/// Returns true if the UI has messages area.
-bool ui_has_messages(void)
-{
- return p_ch > 0 || ui_has(kUIMessages);
-}
-
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));
@@ -633,7 +603,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;
@@ -666,3 +636,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();
+}