diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/ui.c | 58 | ||||
-rw-r--r-- | src/nvim/eval/typval.c | 22 | ||||
-rw-r--r-- | src/nvim/generators/gen_api_dispatch.lua | 6 | ||||
-rw-r--r-- | src/nvim/popupmnu.c | 15 | ||||
-rw-r--r-- | src/nvim/testdir/test_popup.vim | 14 | ||||
-rw-r--r-- | src/nvim/ui.c | 17 | ||||
-rw-r--r-- | src/nvim/ui.h | 7 |
7 files changed, 124 insertions, 15 deletions
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 75ee05761b..717713b948 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -109,7 +109,12 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, UI *ui = xcalloc(1, sizeof(UI)); ui->width = (int)width; ui->height = (int)height; - ui->pum_height = 0; + ui->pum_nlines = 0; + ui->pum_pos = false; + ui->pum_width = 0.0; + ui->pum_height = 0.0; + ui->pum_row = -1.0; + ui->pum_col = -1.0; ui->rgb = true; ui->override = false; ui->grid_resize = remote_ui_grid_resize; @@ -340,7 +345,56 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err) "It must support the ext_popupmenu option"); return; } - ui->pum_height = (int)height; + + ui->pum_nlines = (int)height; +} + +/// Tells Nvim the geometry of the popumenu, to align floating windows with an +/// external popup menu. +/// +/// Note that this method is not to be confused with |nvim_ui_pum_set_height()|, +/// which sets the number of visible items in the popup menu, while this +/// function sets the bounding box of the popup menu, including visual +/// decorations such as boarders and sliders. Floats need not use the same font +/// size, nor be anchored to exact grid corners, so one can set floating-point +/// numbers to the popup menu geometry. +/// +/// @param channel_id +/// @param width Popupmenu width. +/// @param height Popupmenu height. +/// @param row Popupmenu row. +/// @param col Popupmenu height. +/// @param[out] err Error details, if any. +void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, + Float row, Float col, Error *err) + FUNC_API_SINCE(7) FUNC_API_REMOTE_ONLY +{ + if (!pmap_has(uint64_t)(connected_uis, channel_id)) { + api_set_error(err, kErrorTypeException, + "UI not attached to channel: %" PRId64, channel_id); + return; + } + + UI *ui = pmap_get(uint64_t)(connected_uis, channel_id); + if (!ui->ui_ext[kUIPopupmenu]) { + api_set_error(err, kErrorTypeValidation, + "UI must support the ext_popupmenu option"); + return; + } + + if (width <= 0) { + api_set_error(err, kErrorTypeValidation, "Expected width > 0"); + return; + } else if (height <= 0) { + api_set_error(err, kErrorTypeValidation, "Expected height > 0"); + return; + } + + ui->pum_row = (double)row; + ui->pum_col = (double)col; + ui->pum_width = (double)width; + ui->pum_height = (double)height; + ui->pum_pos = true; } /// Pushes data into UI.UIData, to be consumed later by remote_ui_flush(). diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index c8b5fc294c..773e493d0b 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1634,6 +1634,28 @@ int tv_dict_add_nr(dict_T *const d, const char *const key, return OK; } +/// Add a floating point number entry to dictionary +/// +/// @param[out] d Dictionary to add entry to. +/// @param[in] key Key to add. +/// @param[in] key_len Key length. +/// @param[in] nr Floating point number to add. +/// +/// @return OK in case of success, FAIL when key already exists. +int tv_dict_add_float(dict_T *const d, const char *const key, + const size_t key_len, const float_T nr) +{ + dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); + + item->di_tv.v_type = VAR_FLOAT; + item->di_tv.vval.v_float = nr; + if (tv_dict_add(d, item) == FAIL) { + tv_dict_item_free(item); + return FAIL; + } + return OK; +} + /// Add a special entry to dictionary /// /// @param[out] d Dictionary to add entry to. diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index e861cfda35..6e80ad0e5c 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -237,6 +237,12 @@ for i = 1, #functions do (j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer >= 0) {') output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') end + if rt:match('^Float$') then + -- accept integers for Floats + output:write('\n } else if (args.items['.. + (j - 1)..'].type == kObjectTypeInteger) {') + output:write('\n '..converted..' = (Float)args.items['..(j - 1)..'].data.integer;') + end -- accept empty lua tables as empty dictionarys if rt:match('^Dictionary') then output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeArray && args.items['..(j - 1)..'].data.array.size == 0) {') --luacheck: ignore 631 diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index da34d85c00..532bf68190 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -908,10 +908,17 @@ void pum_set_event_info(dict_T *dict) if (!pum_visible()) { return; } - tv_dict_add_nr(dict, S_LEN("height"), pum_height); - tv_dict_add_nr(dict, S_LEN("width"), pum_width); - tv_dict_add_nr(dict, S_LEN("row"), pum_row); - tv_dict_add_nr(dict, S_LEN("col"), pum_col); + double w, h, r, c; + if (!ui_pum_get_pos(&w, &h, &r, &c)) { + w = (double)pum_width; + h = (double)pum_height; + r = (double)pum_row; + c = (double)pum_col; + } + tv_dict_add_float(dict, S_LEN("height"), h); + tv_dict_add_float(dict, S_LEN("width"), w); + tv_dict_add_float(dict, S_LEN("row"), r); + tv_dict_add_float(dict, S_LEN("col"), c); tv_dict_add_nr(dict, S_LEN("size"), pum_size); tv_dict_add_special(dict, S_LEN("scrollbar"), pum_scrollbar ? kSpecialVarTrue : kSpecialVarFalse); diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim index e5696f4cbb..bb0ed6e00c 100644 --- a/src/nvim/testdir/test_popup.vim +++ b/src/nvim/testdir/test_popup.vim @@ -979,9 +979,9 @@ func Test_CompleteChanged() call cursor(4, 1) call feedkeys("Sf\<C-N>", 'tx') - call assert_equal({'completed_item': {}, 'width': 15, - \ 'height': 2, 'size': 2, - \ 'col': 0, 'row': 4, 'scrollbar': v:false}, g:event) + call assert_equal({'completed_item': {}, 'width': 15.0, + \ 'height': 2.0, 'size': 2, + \ 'col': 0.0, 'row': 4.0, 'scrollbar': v:false}, g:event) call feedkeys("a\<C-N>\<C-N>\<C-E>", 'tx') call assert_equal('foo', g:word) call feedkeys("a\<C-N>\<C-N>\<C-N>\<C-E>", 'tx') @@ -1009,10 +1009,10 @@ func Test_pum_getpos() setlocal completefunc=UserDefinedComplete let d = { - \ 'height': 5, - \ 'width': 15, - \ 'row': 1, - \ 'col': 0, + \ 'height': 5.0, + \ 'width': 15.0, + \ 'row': 1.0, + \ 'col': 0.0, \ 'size': 5, \ 'scrollbar': v:false, \ } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 3a5aa95ad3..685da77b39 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -226,7 +226,7 @@ int ui_pum_get_height(void) { int pum_height = 0; for (size_t i = 1; i < ui_count; i++) { - int ui_pum_height = uis[i]->pum_height; + int ui_pum_height = uis[i]->pum_nlines; if (ui_pum_height) { pum_height = pum_height != 0 ? MIN(pum_height, ui_pum_height) : ui_pum_height; @@ -235,6 +235,21 @@ int ui_pum_get_height(void) return pum_height; } +bool ui_pum_get_pos(double *pwidth, double *pheight, double *prow, double *pcol) +{ + for (size_t i = 1; i < ui_count; i++) { + if (!uis[i]->pum_pos) { + continue; + } + *pwidth = uis[i]->pum_width; + *pheight = uis[i]->pum_height; + *prow = uis[i]->pum_row; + *pcol = uis[i]->pum_col; + return true; + } + return false; +} + static void ui_refresh_event(void **argv) { ui_refresh(); diff --git a/src/nvim/ui.h b/src/nvim/ui.h index 8867b5ee24..d00243d35f 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -53,7 +53,12 @@ struct ui_t { bool ui_ext[kUIExtCount]; ///< Externalized UI capabilities. int width; int height; - int pum_height; + int pum_nlines; /// actual nr. lines shown in PUM + bool pum_pos; /// UI reports back pum position? + double pum_row; + double pum_col; + double pum_height; + double pum_width; void *data; #ifdef INCLUDE_GENERATED_DECLARATIONS |