API/UI: Allow UI to set PUM position and size, and pass the position to CompleteChanged

This commit is contained in:
Yatao Li 2020-02-24 16:40:58 +08:00
parent d90a92bcd3
commit 630ec6cfb8
5 changed files with 126 additions and 4 deletions

View File

@ -2341,6 +2341,22 @@ nvim_ui_pum_set_height({height}) *nvim_ui_pum_set_height()*
Parameters: ~
{height} Popupmenu height, must be greater than zero.
*nvim_ui_pum_set_bounds()*
nvim_ui_pum_set_bounds({width}, {height}, {row}, {col})
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.
Parameters: ~
{width} Popupmenu width, must be greater than zero.
{height} Popupmenu height, must be greater than zero.
{row} Popupmenu row, must be greater or equal to zero.
{height} Popupmenu height, must be greater or equal to zero.
nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()*
TODO: Documentation

View File

@ -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_nlines = 0;
ui->pum_pos = false;
ui->pum_width = 0;
ui->pum_height = 0;
ui->pum_row = -1;
ui->pum_col = -1;
ui->rgb = true;
ui->override = false;
ui->grid_resize = remote_ui_grid_resize;
@ -340,7 +345,69 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err)
"It must support the ext_popupmenu option");
return;
}
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.
///
/// @param channel_id
/// @param width Popupmenu width, must be greater than zero.
/// @param height Popupmenu height, must be greater than zero.
/// @param row Popupmenu row, must be greater or equal to zero.
/// @param col Popupmenu height, must be greater or equal to zero.
/// @param[out] err Error details, if any. On error, suspend pum position reporting for the current UI.
void nvim_ui_pum_set_bounds(uint64_t channel_id, Integer width, Integer height,
Integer row, Integer col, Error *err)
FUNC_API_SINCE(6) 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,
"It must support the ext_popupmenu option");
return;
}
if (row < 0) {
api_set_error(err, kErrorTypeValidation, "Expected pumpos row >= 0");
ui->pum_pos = false;
return;
}
if (col < 0) {
api_set_error(err, kErrorTypeValidation, "Expected pumpos col >= 0");
ui->pum_pos = false;
return;
}
if (width <= 0) {
api_set_error(err, kErrorTypeValidation, "Expected pumpos width > 0");
ui->pum_pos = false;
return;
}
if (height <= 0) {
api_set_error(err, kErrorTypeValidation, "Expected pumpos height > 0");
ui->pum_pos = false;
return;
}
ui->pum_row = (int)row;
ui->pum_col = (int)col;
ui->pum_width = (int)width;
ui->pum_height = (int)height;
ui->pum_pos = true;
}
/// Pushes data into UI.UIData, to be consumed later by remote_ui_flush().

View File

@ -908,10 +908,18 @@ void pum_set_event_info(dict_T *dict)
if (!pum_visible()) {
return;
}
int w,h,r,c;
if (!ui_pum_get_pos(&w, &h, &r, &c)){
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);
} else {
tv_dict_add_nr(dict, S_LEN("height"), h);
tv_dict_add_nr(dict, S_LEN("width"), w);
tv_dict_add_nr(dict, S_LEN("row"), r);
tv_dict_add_nr(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);

View File

@ -235,6 +235,32 @@ int ui_pum_get_height(void)
return pum_height;
}
bool ui_pum_get_pos(int* pwidth, int *pheight, int* prow, int* pcol)
{
int w=0,h=0,r=-1,c=-1;
bool found = false;
for (size_t i = 1; i < ui_count; i++) {
if (!uis[i]->pum_pos) continue;
if (!found) {
w = uis[i]->pum_width;
h = uis[i]->pum_height;
r = uis[i]->pum_row;
c = uis[i]->pum_col;
found = true;
} else {
w = MIN(uis[i]->pum_width, w);
h = MIN(uis[i]->pum_height, h);
r = MIN(uis[i]->pum_row, r);
c = MIN(uis[i]->pum_col, c);
}
}
*pwidth = w;
*pheight = h;
*prow = r;
*pcol = c;
return found;
}
static void ui_refresh_event(void **argv)
{
ui_refresh();

View File

@ -53,7 +53,12 @@ struct ui_t {
bool ui_ext[kUIExtCount]; ///< Externalized UI capabilities.
int width;
int height;
int pum_nlines; /// actual nr. lines shown in PUM
bool pum_pos; /// UI reports back pum position?
int pum_row;
int pum_col;
int pum_height;
int pum_width;
void *data;
#ifdef INCLUDE_GENERATED_DECLARATIONS