neovim / neovim

Vim-fork focused on extensibility and usability
https://neovim.io
Other
83.7k stars 5.72k forks source link

UI protocol: expose floatwin composition order (comp_index) to UIs #30586

Open fredizzimo opened 2 months ago

fredizzimo commented 2 months ago

Problem

Neovim uses a hidden internal composition order, which determines the order the floating windows with the same z-index are drawn. Many UIs, including the very widespread telecope relies on this order to build the UIs. In particular, a there's no alpha blending between the windows of the same z-index, the last window in the index will always be used.

A GUI like, Neovide, need to respect this order and do the same type of rendering, or things will look wrong. So that's in fact what we are doing right now, I reverse engineered the algorithm and duplicated it in Neovide here. But it only works when the UI is connected from the start, and we receive absolutely all the events. It's also very fragile.

Expected behavior

The internal composition order is exposed in the UI protocol.

NOTE: Another solution would be to require the whole plugin world to stop using overlapping z-indices. But this does still not work correctly in Neovide, because then we need a way to control the shadow casting and blur. Threating the whole z-index as one layer, is much easier to understand and does not require plugin authors to add additional Neovide specific annotations.

justinmk commented 1 month ago

Expected behavior: composition order is exposed in the UI protocol.

What would this look like? An extra property in a UI event (which one)?

In :help ui-events I don't see any explicit mention of z-index. win_float_pos is documented as:

["win_float_pos", grid, win, anchor, anchor_grid, anchor_row, anchor_col, focusable] ~

... The window should be displayed above another grid anchor_grid at the specified position ...

Do "floating windows with the same z-index" currently have the same anchor_grid? Perhaps that should be changed, so the internal composition order is reflected in anchor_grid?

fredizzimo commented 1 month ago

Hm, I see this in my help, and this is on the website as well https://neovim.io/doc/user/ui.html#ui-multigrid ["win_float_pos", grid, win, anchor, anchor_grid, anchor_row, anchor_col, focusable, zindex]

So, yes, another numerical property after zindex would be ideal. And it should be the same as the comp_index But, note that it's currently not updated when multgrid is enabled. https://github.com/neovim/neovim/blob/20251be15a4ad3f6e7016450ca3338d52b2f0951/src/nvim/grid_defs.h#L104

I think that anchor_grid should remain an independent property, which, that should only affect the position. For example, you might want to render two windows side by side, and on top of some kind of frame window. So, you use anchor for position them next to each other, and the order to draw on top of the other window.

Another thing to note, is that the whole comp_index is unspecified and dependent on the implementation. But many plugins rely on the current implementation. And at least this PR, will change a bit how it works https://github.com/neovim/neovim/pull/30259

justinmk commented 1 month ago

another numerical property after zindex would be ideal. And it should be the same as the comp_index

Is it actually ideal, or would it make sense to adjust the zindex in the UI event? Though maybe that's complicated to implement in Nvim.

fredizzimo commented 1 month ago

Yes, currently we need both. Z-index to group shadows and blur. And the composition order to decide which window, or part of it, should actually be rendered within the same index. Remember the assumption that Neovim makes, is that the blend always blends through everything, even if a floating window underneath has a solid cell. In Neovide we extend this slightly, so that each z-index can see a z-index underneath it, and cast shadows on top of it.

Of course, this could also be done some other way, like introducing window groups, or additional window properties, but our current model is simple, and out of the box compatible with most plugins. And when it isn't easy to fix like this https://github.com/MunifTanjim/nui.nvim/pull/373.

justinmk commented 1 month ago

Yes, currently we need both. Z-index to group shadows and blur. And the composition order to decide which window, or part of it, should actually be rendered within the same index. Remember the assumption that Neovim makes, is that the blend always blends through everything, even if a floating window underneath has a solid cell. In Neovide we extend this slightly, so that each z-index can see a z-index underneath it, and cast shadows on top of it.

This is great info to include in the docs for the new field.