From f31db30975479cb6b57247f124a65f4362f80bfe Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 30 Jun 2022 13:26:31 +0600 Subject: feat(lua): vim.ui_attach to get ui events from lua Co-authored-by: Famiu Haque --- src/nvim/ui_compositor.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) (limited to 'src/nvim/ui_compositor.c') diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c index 2216e25db9..5167f291c3 100644 --- a/src/nvim/ui_compositor.c +++ b/src/nvim/ui_compositor.c @@ -20,6 +20,7 @@ #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, { + xfree(event_cb); + }) + pmap_destroy(uint32_t)(&ui_event_cbs); +} + void ui_comp_syn_init(void) { dbghl_normal = syn_check_group(S_LEN("RedrawDebugNormal")); @@ -676,3 +692,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_schedule_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_schedule_refresh(); +} -- cgit From db2e5f46f5aa5a6300395eaa9c4923835683c770 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 1 Sep 2022 16:37:29 +0800 Subject: fix(lua): make ui_attach()/ui_detach() take effect immediately (#20037) --- src/nvim/ui_compositor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/ui_compositor.c') diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c index 5167f291c3..b8c7834e2b 100644 --- a/src/nvim/ui_compositor.c +++ b/src/nvim/ui_compositor.c @@ -749,7 +749,7 @@ void ui_comp_add_cb(uint32_t ns_id, LuaRef cb, bool *ext_widgets) *item = event_cb; ui_comp_update_ext(); - ui_schedule_refresh(); + ui_refresh(); } void ui_comp_remove_cb(uint32_t ns_id) @@ -759,5 +759,5 @@ void ui_comp_remove_cb(uint32_t ns_id) pmap_del(uint32_t)(&ui_event_cbs, ns_id); } ui_comp_update_ext(); - ui_schedule_refresh(); + ui_refresh(); } -- cgit From 2dd55f81f736d5fe9697cd0e15c96f763eb90458 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Fri, 2 Sep 2022 17:44:14 +0600 Subject: fix(ui): ui compositor does not correctly free event callbacks Prior to this PR, when freeing event callbacks, UI compositor did not free the luarefs which could cause potential memory leaks. This PR fixes that by freeing the luarefs properly. --- src/nvim/ui_compositor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/ui_compositor.c') diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c index b8c7834e2b..2fb70eae8a 100644 --- a/src/nvim/ui_compositor.c +++ b/src/nvim/ui_compositor.c @@ -98,7 +98,7 @@ void ui_comp_free_all_mem(void) { UIEventCallback *event_cb; map_foreach_value(&ui_event_cbs, event_cb, { - xfree(event_cb); + free_ui_event_callback(event_cb); }) pmap_destroy(uint32_t)(&ui_event_cbs); } -- cgit