aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2021-05-01 13:29:34 +0200
committerBjörn Linse <bjorn.linse@gmail.com>2021-05-15 13:56:27 +0200
commitedb5864a29ec0d1049c4674afb75c8279301446c (patch)
tree2ced0985bb7d20d64a42d927323c1e4878f6cdd1 /src
parent7d82ea01025b6981e0233ca9a5e7ee62c8b5bcad (diff)
downloadrneovim-edb5864a29ec0d1049c4674afb75c8279301446c.tar.gz
rneovim-edb5864a29ec0d1049c4674afb75c8279301446c.tar.bz2
rneovim-edb5864a29ec0d1049c4674afb75c8279301446c.zip
floats: z-index
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/private/helpers.c10
-rw-r--r--src/nvim/api/ui_events.in.h3
-rw-r--r--src/nvim/api/vim.c9
-rw-r--r--src/nvim/buffer_defs.h2
-rw-r--r--src/nvim/grid_defs.h14
-rw-r--r--src/nvim/message.c1
-rw-r--r--src/nvim/popupmnu.c6
-rw-r--r--src/nvim/ui_compositor.c22
-rw-r--r--src/nvim/window.c5
9 files changed, 51 insertions, 21 deletions
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 24ba6110c4..0f7008e150 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -1909,7 +1909,7 @@ bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf,
} else if (strequal(key, "height")) {
has_height = true;
if (val.type == kObjectTypeInteger && val.data.integer > 0) {
- fconfig->height= (int)val.data.integer;
+ fconfig->height = (int)val.data.integer;
} else {
api_set_error(err, kErrorTypeValidation,
"'height' key must be a positive Integer");
@@ -1983,6 +1983,14 @@ bool parse_float_config(Dictionary config, FloatConfig *fconfig, bool reconf,
"'focusable' key must be Boolean");
return false;
}
+ } else if (strequal(key, "zindex")) {
+ if (val.type == kObjectTypeInteger && val.data.integer > 0) {
+ fconfig->zindex = (int)val.data.integer;
+ } else {
+ api_set_error(err, kErrorTypeValidation,
+ "'zindex' key must be a positive Integer");
+ return false;
+ }
} else if (!strcmp(key, "border")) {
parse_border_style(val, fconfig, err);
if (ERROR_SET(err)) {
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index e934d5dc92..11e21a88ea 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -106,7 +106,8 @@ void win_pos(Integer grid, Window win, Integer startrow,
Integer startcol, Integer width, Integer height)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
void win_float_pos(Integer grid, Window win, String anchor, Integer anchor_grid,
- Float anchor_row, Float anchor_col, Boolean focusable)
+ Float anchor_row, Float anchor_col, Boolean focusable,
+ Integer zindex)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
void win_external_pos(Integer grid, Window win)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index e0eebd079f..e9a0b0df2e 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -1417,6 +1417,15 @@ void nvim_chan_send(Integer chan, String data, Error *err)
/// - `external`: GUI should display the window as an external
/// top-level window. Currently accepts no other positioning
/// configuration together with this.
+/// - `zindex`: Stacking order. floats with higher `zindex` go on top on
+/// floats with lower indices. Must be larger than zero. The
+/// following screen elements have hard-coded z-indices:
+/// - 100: insert completion popupmenu
+/// - 200: message scrollback
+/// - 250: cmdline completion popupmenu (when wildoptions+=pum)
+/// The default value for floats are 50. In general, values below 100 are
+/// recommended, unless there is a good reason to overshadow builtin
+/// elements.
/// - `style`: Configure the appearance of the window. Currently only takes
/// one non-empty value:
/// - "minimal" Nvim will display the window with many UI options
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index dd24db910e..0c839ba12a 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -1083,6 +1083,7 @@ typedef struct {
FloatRelative relative;
bool external;
bool focusable;
+ int zindex;
WinStyle style;
bool border;
bool shadow;
@@ -1096,6 +1097,7 @@ typedef struct {
.row = 0, .col = 0, .anchor = 0, \
.relative = 0, .external = false, \
.focusable = true, \
+ .zindex = kZIndexFloatDefault, \
.style = kWinStyleUnused })
// Structure to store last cursor position and topline. Used by check_lnums()
diff --git a/src/nvim/grid_defs.h b/src/nvim/grid_defs.h
index 3b34af46e4..724363674c 100644
--- a/src/nvim/grid_defs.h
+++ b/src/nvim/grid_defs.h
@@ -13,6 +13,15 @@
typedef char_u schar_T[(MAX_MCO+1) * 4 + 1];
typedef int sattr_T;
+enum {
+ kZIndexDefaultGrid = 0,
+ kZIndexFloatDefault = 50,
+ kZIndexPopupMenu = 100,
+ kZIndexMessages = 200,
+ kZIndexCmdlinePopupMenu = 250,
+};
+
+
/// ScreenGrid represents a resizable rectuangular grid displayed by UI clients.
///
/// chars[] contains the UTF-8 text that is currently displayed on the grid.
@@ -73,6 +82,9 @@ struct ScreenGrid {
// whether the grid can be focused with mouse clicks.
bool focusable;
+ // z-index: the order in the stack of grids.
+ int zindex;
+
// Below is state owned by the compositor. Should generally not be set/read
// outside this module, except for specific compatibilty hacks
@@ -96,7 +108,7 @@ struct ScreenGrid {
};
#define SCREEN_GRID_INIT { 0, NULL, NULL, NULL, NULL, NULL, 0, 0, false, \
- false, 0, 0, NULL, false, true, \
+ false, 0, 0, NULL, false, true, 0, \
0, 0, 0, 0, 0, false }
#endif // NVIM_GRID_DEFS_H
diff --git a/src/nvim/message.c b/src/nvim/message.c
index a34b895033..ec5dabbbc0 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -165,6 +165,7 @@ void msg_grid_validate(void)
// TODO(bfredl): eventually should be set to "invalid". I e all callers
// will use the grid including clear to EOS if necessary.
grid_alloc(&msg_grid, Rows, Columns, false, true);
+ msg_grid.zindex = kZIndexMessages;
xfree(msg_grid.dirty_col);
msg_grid.dirty_col = xcalloc(Rows, sizeof(*msg_grid.dirty_col));
diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c
index 32c9750628..7d452d6797 100644
--- a/src/nvim/popupmnu.c
+++ b/src/nvim/popupmnu.c
@@ -421,6 +421,10 @@ void pum_redraw(void)
}
grid_assign_handle(&pum_grid);
+
+ pum_grid.zindex = ((State == CMDLINE)
+ ? kZIndexCmdlinePopupMenu : kZIndexPopupMenu);
+
bool moved = ui_comp_put_grid(&pum_grid, pum_row, pum_col-col_off,
pum_height, grid_width, false, true);
bool invalid_grid = moved || pum_invalid;
@@ -439,7 +443,7 @@ void pum_redraw(void)
int row_off = pum_above ? pum_height : 0;
ui_call_win_float_pos(pum_grid.handle, -1, cstr_to_string(anchor),
pum_anchor_grid, pum_row-row_off, pum_col-col_off,
- false);
+ false, pum_grid.zindex);
}
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index c1e4a40ef2..1ec5189795 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -165,22 +165,13 @@ bool ui_comp_put_grid(ScreenGrid *grid, int row, int col, int height, int width,
}
#endif
- // TODO(bfredl): this is pretty ad-hoc, add a proper z-order/priority
- // scheme. For now:
- // - msg_grid is always on top.
- // - pum_grid is on top of all windows but not msg_grid. Except for when
- // wildoptions=pum, and completing the cmdline with scrolled messages,
- // then the pum has to be drawn over the scrolled messages.
size_t insert_at = kv_size(layers);
- bool cmd_completion = (grid == &pum_grid && (State & CMDLINE)
- && (wop_flags & WOP_PUM));
- if (kv_A(layers, insert_at-1) == &msg_grid && !cmd_completion) {
- insert_at--;
- }
- if (kv_A(layers, insert_at-1) == &pum_grid && (grid != &msg_grid)) {
+ while (insert_at > 0 && kv_A(layers, insert_at-1)->zindex > grid->zindex) {
insert_at--;
}
+
if (curwin && kv_A(layers, insert_at-1) == &curwin->w_grid_alloc
+ && kv_A(layers, insert_at-1)->zindex == grid->zindex
&& !on_top) {
insert_at--;
}
@@ -279,12 +270,11 @@ static void ui_comp_grid_cursor_goto(UI *ui, Integer grid_handle,
// should configure all grids before entering win_update()
if (curgrid != &default_grid) {
size_t new_index = kv_size(layers)-1;
- if (kv_A(layers, new_index) == &msg_grid) {
- new_index--;
- }
- if (kv_A(layers, new_index) == &pum_grid) {
+
+ while (new_index > 1 && kv_A(layers, new_index)->zindex > curgrid->zindex) {
new_index--;
}
+
if (curgrid->comp_index < new_index) {
ui_comp_raise_grid(curgrid, new_index);
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
index d4d00c0a71..0b28e8aa76 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -763,10 +763,13 @@ void ui_ext_win_position(win_T *wp)
}
api_clear_error(&dummy);
}
+
+ wp->w_grid_alloc.zindex = wp->w_float_config.zindex;
if (ui_has(kUIMultigrid)) {
String anchor = cstr_to_string(float_anchor_str[c.anchor]);
ui_call_win_float_pos(wp->w_grid_alloc.handle, wp->handle, anchor,
- grid->handle, row, col, c.focusable);
+ grid->handle, row, col, c.focusable,
+ wp->w_grid_alloc.zindex);
} else {
// TODO(bfredl): ideally, compositor should work like any multigrid UI
// and use standard win_pos events.