aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ui_compositor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/ui_compositor.c')
-rw-r--r--src/nvim/ui_compositor.c101
1 files changed, 96 insertions, 5 deletions
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index 2216e25db9..47c83b8ed1 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -11,15 +11,16 @@
#include <stdbool.h>
#include <stdio.h>
+#include "klib/kvec.h"
#include "nvim/api/private/helpers.h"
#include "nvim/ascii.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
-#include "nvim/lib/kvec.h"
#include "nvim/log.h"
#include "nvim/lua/executor.h"
#include "nvim/main.h"
+#include "nvim/map.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/os/os.h"
@@ -54,6 +55,8 @@ 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)
@@ -69,14 +72,18 @@ void ui_comp_init(void)
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 = 0; (int)i < kUIExtCount; i++) {
+ 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;
@@ -87,6 +94,15 @@ void ui_comp_init(void)
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)
{
dbghl_normal = syn_check_group(S_LEN("RedrawDebugNormal"));
@@ -122,7 +138,7 @@ bool ui_comp_should_draw(void)
///
/// TODO(bfredl): later on the compositor should just use win_float_pos events,
/// though that will require slight event order adjustment: emit the win_pos
-/// events in the beginning of update_screen(0), rather than in ui_flush()
+/// events in the beginning of update_screen(), rather than in ui_flush()
bool ui_comp_put_grid(ScreenGrid *grid, int row, int col, int height, int width, bool valid,
bool on_top)
{
@@ -469,6 +485,10 @@ static void compose_debug(Integer startrow, Integer endrow, Integer startcol, In
endcol = MIN(endcol, default_grid.cols);
int attr = syn_id2attr(syn_id);
+ if (delay) {
+ debug_delay(endrow - startrow);
+ }
+
for (int row = (int)startrow; row < endrow; row++) {
ui_composed_call_raw_line(1, row, startcol, startcol, endcol, attr, false,
(const schar_T *)linebuf,
@@ -570,12 +590,14 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row, Integer startcol
/// The screen is invalid and will soon be cleared
///
/// Don't redraw floats until screen is cleared
-void ui_comp_set_screen_valid(bool valid)
+bool ui_comp_set_screen_valid(bool valid)
{
+ bool old_val = valid_screen;
valid_screen = valid;
if (!valid) {
msg_sep_row = -1;
}
+ return old_val;
}
static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row, Boolean scrolled,
@@ -594,7 +616,7 @@ static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row, Boolean scrol
if (row > msg_current_row && ui_comp_should_draw()) {
compose_area(MAX(msg_current_row - 1, 0), row, 0, default_grid.cols);
} else if (row < msg_current_row && ui_comp_should_draw()
- && msg_current_row < Rows) {
+ && (msg_current_row < Rows || (scrolled && !msg_was_scrolled))) {
int delta = msg_current_row - (int)row;
if (msg_grid.blending) {
int first_row = MAX((int)row - (scrolled?1:0), 0);
@@ -676,3 +698,72 @@ 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)
+{
+ Error err = ERROR_INIT;
+ UIEventCallback *event_cb;
+ bool handled = false;
+
+ map_foreach_value(&ui_event_cbs, event_cb, {
+ Object res = nlua_call_ref(event_cb->cb, name, args, false, &err);
+ if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
+ handled = true;
+ }
+ })
+
+ 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();
+}