From 46401030b7de77f7f03121107316acfcf3642cc2 Mon Sep 17 00:00:00 2001 From: glepnir Date: Wed, 4 Sep 2024 15:40:27 +0800 Subject: [PATCH] fix(float): re-sort layers when grid zindex changed Problem: when change the zindex in vim.schedule the zindex sort in layers not changed. Solution: resort layers when zindex changed. --- src/nvim/ui_compositor.c | 17 +++++ src/nvim/window.c | 5 ++ test/functional/ui/float_spec.lua | 101 ++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+) diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c index 6e89894e0b..5c70f64f13 100644 --- a/src/nvim/ui_compositor.c +++ b/src/nvim/ui_compositor.c @@ -101,6 +101,23 @@ bool ui_comp_should_draw(void) return composed_uis != 0 && valid_screen; } +static int compare_zindex(const void *a, const void *b) +{ + int za = (*(ScreenGrid **)a)->zindex; + int zb = (*(ScreenGrid **)b)->zindex; + size_t ia = (*(ScreenGrid **)a)->comp_index; + size_t ib = (*(ScreenGrid **)b)->comp_index; + return za == zb ? (ia == ib ? 0 : (ia < ib ? -1 : 1)) : (za < zb ? -1 : 1); +} + +void ui_sort_layers_by_zindex(void) +{ + qsort(layers.items, layers.size, sizeof(ScreenGrid *), compare_zindex); + for (size_t i = 0; i < kv_size(layers); i++) { + kv_A(layers, i)->comp_index = i; + } +} + /// Places `grid` at (col,row) position with (width * height) size. /// Adds `grid` as the top layer if it is a new layer. /// diff --git a/src/nvim/window.c b/src/nvim/window.c index f61485ccb3..d2aaa6d90c 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -839,7 +839,12 @@ void ui_ext_win_position(win_T *wp, bool validate) } } + bool resort = wp->w_grid_alloc.comp_index != 0 + && wp->w_grid_alloc.zindex != wp->w_config.zindex; wp->w_grid_alloc.zindex = wp->w_config.zindex; + if (resort) { + ui_sort_layers_by_zindex(); + } if (ui_has(kUIMultigrid)) { String anchor = cstr_as_string(float_anchor_str[c.anchor]); if (!c.hide) { diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 754f0772f6..072b450524 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -8434,6 +8434,107 @@ describe('float window', function() | ]]} end + command('fclose') + exec_lua([[ + local win1, win3 = ... + vim.api.nvim_win_set_config(win1, { zindex = 400, title = 'win_400', title_pos = 'center', border = 'double' }) + vim.api.nvim_win_set_config(win3, { zindex = 300, title = 'win_300', title_pos = 'center', border = 'single' }) + ]], win1, win3) + if multigrid then + screen:expect({ + grid = [[ + ## grid 1 + [2:----------------------------------------]|*6 + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }|*5 + ## grid 3 + | + ## grid 4 + {5:╔══════}{11:win_400}{5:═══════╗}| + {5:║}{7: }{5:║}| + {5:║}{7:~ }{5:║}|*2 + {5:╚════════════════════╝}| + ## grid 6 + {5:┌──────}{11:win_300}{5:───────┐}| + {5:│}{8: }{5:│}| + {5:│}{8:~ }{5:│}|*2 + {5:└────────────────────┘}| + ]], float_pos={ + [4] = {1001, "NW", 1, 1, 5, true, 400}; + [6] = {1003, "NW", 1, 3, 7, true, 300}; + }, win_viewport={ + [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [6] = {win = 1003, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = { bottom = 0, left = 0, right = 0, top = 0, win = 1000 }, + [4] = { bottom = 1, left = 1, right = 1, top = 1, win = 1001 }, + [6] = { bottom = 1, left = 1, right = 1, top = 1, win = 1003 } + }}) + else + screen:expect({ + grid = [[ + ^ | + {0:~ }{5:╔══════}{11:win_400}{5:═══════╗}{0: }| + {0:~ }{5:║}{7: }{5:║─┐}{0: }| + {0:~ }{5:║}{7:~ }{5:║}{8: }{5:│}{0: }|*2 + {0:~ }{5:╚════════════════════╝}{8: }{5:│}{0: }| + {5:└────────────────────┘} | + ]] + }) + end + exec_lua([[ + local win1, win3 = ... + vim.api.nvim_win_set_config(win1, { zindex = 100, title='win_100' }) + vim.api.nvim_win_set_config(win3, { zindex = 150, title='win_150' }) + ]], win1, win3) + if multigrid then + screen:expect({ + grid = [[ + ## grid 1 + [2:----------------------------------------]|*6 + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }|*5 + ## grid 3 + | + ## grid 4 + {5:╔}{11:win_100}{5:═════════════╗}| + {5:║}{7: }{5:║}| + {5:║}{7:~ }{5:║}|*2 + {5:╚════════════════════╝}| + ## grid 6 + {5:┌}{11:win_150}{5:─────────────┐}| + {5:│}{8: }{5:│}| + {5:│}{8:~ }{5:│}|*2 + {5:└────────────────────┘}| + ]], float_pos={ + [4] = {1001, "NW", 1, 1, 5, true, 100}; + [6] = {1003, "NW", 1, 3, 7, true, 150}; + }, win_viewport={ + [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [6] = {win = 1003, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = { bottom = 0, left = 0, right = 0, top = 0, win = 1000 }, + [4] = { bottom = 1, left = 1, right = 1, top = 1, win = 1001 }, + [6] = { bottom = 1, left = 1, right = 1, top = 1, win = 1003 } + }}) + else + screen:expect({ + grid = [[ + ^ | + {0:~ }{5:╔}{11:w}{5:┌}{11:win_150}{5:─────────────┐}{0: }| + {0:~ }{5:║}{7: }{5:│}{8: }{5:│}{0: }| + {0:~ }{5:║}{7:~}{5:│}{8:~ }{5:│}{0: }|*2 + {0:~ }{5:╚═└────────────────────┘}{0: }| + | + ]] + }) + end end) it('can use winbar', function()