[RFC] Floating windows in TUI and Remote UI#6619
Conversation
|
hi, will this PR be merged? or, still wip? |
|
Is still WIP, many window commands can easily segfault, and the mouse is broken. Also we need a better redrawing strategy than "redraw the float everytime anything else is redrawn". Probabaly should use some buffering logic from #5686 |
|
Good to know that. I am waiting for it. |
|
Update: replaced fnew with api command: mode supports anchor modes (will be relevant for UIs with different grid sizes in floats) as well making the window "unfocusable". It is still possible to make it current with api or number, but the user selecting it "by accident" with mouse or Also added very basic mouse support. |
|
I'd suggest "new" as the standard verb for creating things. Also in API functions we always spell "window" as |
|
|
|
|
|
My point was primarily about operation strength, not grammar. Opening/Creating a new window or buffer (or channel) is a lot heavier than adding a new line (we call it [o]pen only because [n] was taken for [n]ext) or highlight, or allocating a new object in "many programming languages". These are all different verbs for a reason. (and if we're discussing common languages, |
|
Added |
|
This PR is awesome, and I have a question about the floating window, I just see the doc what dese |
|
|
||
| Window nvim_open_floating_window(Buffer buffer, | ||
| Integer x, Integer y, Integer w, Integer h, | ||
| Integer mode, Boolean enter, Error *err) |
Here "new" as the verb makes sense to me: |
|
The buffer list most definitely not an implementation detail: it is well known and used vim functionality that a buffer can be "listed" without actually being "opened". The API functions current operation is only to add/return a number in the buffer list, but "add" might not be the best either, as it can return an existing buffer. However, that is not necessarily the best operation, we could have a function that only creates a new (unnamed) buffer and fully allocates it (this special case might not need to make it temporarily displayed, as there is no swapfile, encoding errors, and probably we want no autocmds either) The current behavior makes sense in the "floating window" case given that it will immediately opened in a window anyway, at which point all the vim stuff happens. |
|
I have a suggestion: either make Or do the other thing: /// Open floating window
///
/// @param[in] buffer Buffer to display in that window.
/// @param[in] position Window position, pair of two integers which may be
/// negative.
/// @param[in] options Additional options:
/// Option | Type | Description
/// ------ | ---- | -----------
/// anchor | String | Make position be relative to the
/// | | given anchor: "type-pos" where "type"
/// | | is one of "screen", "editor_area",
/// | | "wm_window" and "pos" is one of "NW",
/// | | "NE", "SW" or "SE"; additionally
/// | | "cursor" position is supported.
/// | |
/// | | Defaults to "cursor".
/// | |
/// | | TUI only supports "editor_area-…" and
/// | | "cursor".
/// dimensions | pair of Integers | Dimensions in screen
/// | | cells, width x height.
/// | |
/// | | Defaults to either just
/// | | enough to show the
/// | | whole buffer contents
/// | | (not updated when
/// | | buffer contents
/// | | changes, call
/// | | `nvim_reconfigure_floating_window({dimensions: NIL})`
/// | | then), or just enough
/// | | to occupy all available
/// | | space, whichever is
/// | | lesser.
/// standalone | Boolean | Make window standalone.
/// | |
/// | | Defaults to false, may be
/// | | ignored in TUI.
/// focusable | Boolean | Make window not focusable, and
/// | | also ignore mouse events.
/// | |
/// | | Defaults to false.
/// position_type | String | Position type: either "cells"
/// | | (position in display cells) or
/// | | "pixels".
/// | |
/// | | Defaults to "cells" for
/// | | "editor_area-*" and "cursor"
/// | | anchors, "pixels" otherwise.
Window nvim_open_floating_window(Buffer buffer, ArrayOf(Integer) position,
Dictionary options, Error *const err)
/// Reconfigure floating window
///
/// @param[in] window Window to reconfigure.
/// @param[in] options @see nvim_open_floating_window()
/// Missing values mean “do not change option”, use NIL to
/// force defaults.
void nvim_reconfigure_floating_window(Window window, Dictionary options,
Error *const err) |
It's an irrelevant detail in the context of the API. When one creates a buffer one does not think "I want to add a buffer to the buffer list", only "I want a new buffer". |
|
Again, the name describes what the function does right now, which was the simplest thing to implement. The relevant change would be to change what the function actually does (fully allocate a buffer), which will be more involved but probably worth it in the long run. |
Wouldn't this be the first dict option? What's wrong with using the canonical comma-separated, colon-delimited format for other complex options? Typing a dict for an option is going to be error-prone, since people are likely to want to insert whitespace but that's not allowed (without going |
Doesn't matter too much in this context, unless it turns out to be easier to implement. Anyways, let's save that discussion for later. |
There is a z-index internally, but it is not updated for anything yet. Bringing focused float to front makes sense to start with, I will add it right away.
This means that the plugin has to use string interpolation to configure the float, rather than construct the dict using the native language construct i e [1] Unless it already exists some option like that, wouldn't surprise me anymore. |
That's true, window layout is not a "window option". Though it could be viewed as a "tab option" (where "option" is understood as Vim-parlance for "property"). But it may be awkward to force "layout" it into the "options" model, and it shouldn't block this. At the very least I hope we can avoid treating "floating windows", "flex windows", etc., as different classes of things, and instead stick with just windows which have layout properties. So Does this seem feasible? |
|
Yes, general |
| /// See documentation at |nvim_open_float_win|, for the meaning of parameters. | ||
| /// | ||
| /// When reconfiuring an existing float, absent option keys will not be | ||
| /// changed. The following restriction apply though: `x`, `y` and `relative` |
There was a problem hiding this comment.
There is row and col instead of x, y at documentation of nvim_open_float_win, so what should be used?
There was a problem hiding this comment.
row, col. I'm in the process of updating it
|
Can't move floating window without change content of buffer: let s:buf = nvim_create_buf(1)
let s:win = nvim_open_float_win(s:buf, v:false, 5, 5, {
\ 'col': 10,
\ 'row': 1,
\ 'unfocusable': v:true,
\ 'standalone': v:true,
\})
call nvim_buf_set_lines(s:buf, 0, -1, v:false, ['a', 'b', 'c', 'd', 'e'])
call setwinvar(s:win, '&signcolumn', 'no')
call setwinvar(s:win, '&number', 0)
call setwinvar(s:win, '&relativenumber', 0)
call setwinvar(s:win, '&winhl', 'NormalNC:Pmenu')
function! s:config()
"call nvim_buf_set_lines(s:buf, 0, -1, v:false, ['a', 'b', 'c', '', ''])
call nvim_win_config_float(s:win, 5, 5, {
\ 'col': 11,
\ 'row': 1,
\})
endfunction
call timer_start(1000, {-> s:config()})source these script with |
|
@chemzqm Thanks for testing! Redrawing is still a bit unreliable, I probably messed up something in latest rebase. Hopefully I will have some time in the weekend to patch things up. |
|
Updated the API (and docs) to use non-float specific names. Added 'window' relative positioning, which is needed for multigrid support. The end goal is to support lnum+col positioning, though that looks a bit messy, so it will be a follow up PR. For now Tests now use proper multigrid representation. Still a few failures due to leaks and missing checks (external window should only be valid with multigrid). |
| /// Exactly one of `external` and `relative` must be specified. | ||
| /// | ||
| /// @param buffer handle of buffer to be displayed in the window | ||
| /// @param enter whether the window should be entered (made the current window) |
There was a problem hiding this comment.
focus (used in FocusGained/Lost)is more common.
There was a problem hiding this comment.
focus as opposed to what? "current" is our jargon for current window (nvim_get/set_current_xx). "enter" is our jargon for entering a window/buffer (BufEnter / WinEnter).
| /// "SW" south-west | ||
| /// "SE" south-east | ||
| /// `unfocusable`: The window will not be focused by wincmds and | ||
| /// mouse events. It can still be made current by API calls. |
There was a problem hiding this comment.
Negative logic is confusing, so focusable is a better name. It's ok if the default is true.
It can still be made current by API calls.
Does "made current" mean "focused"?
There was a problem hiding this comment.
"made current" means "made the current window", "entered" would be established verb for this. "focused" means entered due to user input being directed towards the window, i e by clicking inside the window.
| /// floating and external windows (including changing a split window to these | ||
| /// types). | ||
| /// | ||
| /// See documentation at |nvim_open_window|, for the meaning of parameters. |
There was a problem hiding this comment.
tag |nvim_open_window| won't exist, should be |nvim_open_window()|
There was a problem hiding this comment.
| /// See documentation at |nvim_open_window|, for the meaning of parameters. | |
| /// See documentation at |nvim_open_win()|, for the meaning of parameters. |
s/window/win/
|
|
||
| FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { | ||
| if (wp->w_redr_type == CLEAR && wp->w_floating && wp->w_grid.chars) { | ||
| // TODO(bfredl): this is overly expensive. The solution is to CLEAR less |
There was a problem hiding this comment.
could add a field to g_stats so we have a counter of CLEARs which could be (eventually) tested.
There was a problem hiding this comment.
It could be this TODO was from before the clearmaggedon. Now basically only resize and user intervention should lead to a clear.
| assert(method == 'redraw') | ||
| for _, update in ipairs(args) do | ||
| print(require('inspect')(update)) | ||
| if update[1] ~= "mode_info_set" then |
There was a problem hiding this comment.
is this because mode_info_set is noisy? Would be good to add a comment.
|
Floating window support is here in denite.nvim. |
|
I will also add floating windows support in flygrep :), but the api seems has been changed. |
|
Could floating window support optional border? |
|
Yes, but that would be a follow-up PR. |
|
Implemented basic z-order: if float becomes current window, it will be put on top, with the exception of popupmenu which always is on top if shown. It can be made more fancy later on. |
|
I think a function for close preview window or close window without focus is needed. I can close the preview window by |
|
|
|
Working on the last issues, ci build is aalmost passing now. I plan to merge this today or tomorrow. It is usable enough as a MVP (as demonstrated by plugins adding support already). The API/functionality (and tests with them) can be expanded in follow-up PRs. |
Co-Author: Dongdong Zhou <dzhou121@gmail.com>
|
Merged. Sorry for taking so long. I will lock this thread, as dealing with overlong github threads is a mess. Requests for additions/improvements (or bugs too minor to deserve their own issue) can be in #9421. Feel free to repeat stuff that is hidden somewhere in the middle of this thread and still are a concern. |
From the drawer of very naive and crazy stuff (one does not simply mess with window positioning and expect stuff to work). Partially based on @dzhou121 external ui stuff (crazy/naiveness mine)
do this in a script: