[discuss] Popup Window API design.

This is not an issue, but I have no idea how to attach images in vim_dev group. So forgive me create this post in the issues and it can be closed immediately.
The human readable page is here:
https://github.com/skywind3000/vim-proposal/blob/master/popup_window.md

Popup Window API Proposal
Problem
Vim has already got some builtin popup-widgets for certain usage, like completion menu or balloon. But users and plugin authors are still asking for more:

3379: Support Floating Window
2948: balloon_show doesn't display the balloon
2352: Call to balloon_show() doesn't show the balloon in the terminal
3811: Feature Request: Trigger balloon via keyboard at cursor position
0234: Implement argument completion/hints
2718: Display function prototype in the cmdline
RFC: Signature help/argument hints in a second popup menu

In Vim conf 2018, Bram claimed that he has plan for this already:

Popup Windows:
Use for a notification:

Asynchronously show window with text “build done”.
Remove after a few seconds.

Use for picking an item:

Show window where each line is an item
Let user pick an item
A bit like confirm() but much nicer

Summary, there are two types of popup window: interactive and non-interactive.
For non-interactive popup windows, people want to use them to:

Display the documentation for a function:

Display linting errors or warnings:

Preview a portion of file (can be used to preview grep results in quickfix):

Display funny help for newbies (like paperclip assistent in office 2000):

For interactive popup windows, people want to use them to:

pick an item:

display a nice popup menu:

cmd line completion:

use fuzzy finder in a popup window:

There are too many popup-related widgets for certain usage, designing one by one is nearly impossible.
Implementing a neovim's floating window will take too much time (it is working in progress for almost 2-years and still not merge to master).
Can we implement the popup window in a simple and adaptive way ? Is this possible to unify all their needs and simplify API design ?
The following parts of this article will introduce an overlay mechanism similar to Emacs's text overlay which is the backend of various popup windows in Emacs.
API Scope
Popup windows will draw into an overlay layer, A popup will remain after creation  until an erase function is called. Everything in the overlay will not interfere vim's  states, people can continue editing or using vim commands no matter there is a popup window  or not.
So, the APIs are only designed for drawing a popup window and has nothing to do with user input. Dialogs like yes/no box and confirm box require user input, can be simulated with following steps:
function! Dialog_YesNo(...)
    while not_quit
       draw/update the popup window
       get input from getchar()
    endwhile
    erase the popup window
endfunc

Popup window APIs is not responsible for any interactive functionalities. Instead of implementing a complex widget/event system (which is too complex), it is sane to let user to handle the input by getchar().
There can be a popup.vim script contains some predefined popup windows/dialogs and will be shipped with vim itself. User can use the primitive APIs and getchar() to implement other complex dialogs like a popup fuzzy finder or a command line history completion box.
Overlay Buffer
The overlay buffer is a character matrix with the same size of the screen:
|\     |\
| \    | \
|  \   |  \
|   \  |   \
|   |  |   |
| 1 |  | 2 |   <---- Observer
|   |  |   |
|   /  |   /
|  /   |  /
| /    | /
|/     |/

^      ^
|      |
|   Overlay Buffer (M rows and N columns)
|
Ground Vim UI (M rows and N columns)

Similar to Video Buffer (0xb8000) in x86's text mode, the overlay buffer is a 2D array of characters and attributes. Change the content of the 2D array will change the text in the screen.
The overlay buffer is invisible by default and can be enabled by:
set guioptions+=o

Every existent text rendering code in both Vim & GVim needs to be updated to support this overlay buffer, once it finished, we can use it to build powerful popup windows.
There are also some basic APIs for overlay buffer:

add a text string with position and attribute.
erase a rectangle of text.
command redrawoverlay to update the overlay (it uses double buffer to prevent flicker).

With these primitive APIs, user can draw what ever they like on the overlay buffer.
Overlay Panes
Overlay panes is an abstraction of the popup windows, it consists of:

position and size
z order (for overlapping calculation)
background color
border styles
lines of text and text-properties

There can be multiple panes at the same time, the panes can be manipulated by:
pane_create(int row, int col, int width, int height, ...);
pane_destroy(int pane_id);
pane_update(int pane_id, ...);
pane_move(int pane_id, int new_row, int new_col, int new_width, int new_height);
pane_show(int pane_id, bool show_hide);

(PS: they are provided as both C-apis and vim functions).
The life cycle of a pane is between pane_create and pane_destroy.
The (row, col) is using screen coordinate system, and there can be some functions to convert window based coordinate system to screen coordinate system. If you want to display a popup balloon right above your cursor, you can use them to calculate the position.
Finally, there is a function to render the pane list into the overlay buffer:
pane_flush();

If you create some panes, the overlay buffer will not change until pane_flush().
Popup Windows
All the common popup windows are implemented in popup.vim script, they will use panes to display a popup window and getchar() to provide interactive functionalities.
There are some predefined popup windows:

Popup_Message(): display a "build complete" message and hide after a few seconds.
Popup_LinterHint(): display a message right above cursor and hide if cursor moves outside current <cword>.
Popup_Menu(): display a menu (use getchar() to receive user input) and quit after user select an item.
Popup_YesNo(): display a yes/no box and return the result after user made a selection.
...
and so on.

User or plugin authors can use the high level APIs provided by popup.vim or design their own popup window by utilizing lower level pane APIs or overlay APIs.
Summary
It is complex to design an event system or NeoVim's floating window, and nearly impossible to implement every type of popup window for certain usage.
To unify and simplify the interface, this proposal suggests to provide an overlay mechanism with some primitive APIs to:

render a popup window (pane)
erase a popup window
update a popup window

And let user handle input themself by getchar(). At last, makes it possible to enable users to create various popup windows with different styles and functionalities.
--
2019/3/2 edit: floating window got merged to master.

Few more things I would like to add.

It would also be good to see if we can come up with a different richer ui for GUI. For example embedding bold, italic, images and markdown texts, hr would be useful. Might be allow the user to set html and use the OS webview?
As for flush would be good to have an api that allows us to optimize re-renders. I'm working on creating a fast async quickpick with vimscript only that can support fuzzy finder and to make it look responsive I need to draw a spinner which only takes one char but because I'm calling redraw everything is getting redrawn. (If anyone knows how too force redraw statusline only let me know, that would also solve this issue).

@skywind3000: you may correct this statement:

it is working in progress for almost 2-years and still not merge to master

Possible implementation for GVim and Vim:
For Windows, create a layered child window on the top of textarea. Layered Window can use a color key to control transparent area. No need to update most of GVim code.
For terminal, ncurses has overlapping windows and panels. I don't know if they can be used because I haven't programmed in ncurses.

Currently, nvim support floating window!
Vim need some features against it.

It would also be good to see if we can come up with a different richer ui for GUI. For example embedding bold, italic, images and markdown texts, hr would be useful. Might be allow the user to set html and use the OS webview?

webview is crazy great

@iamcco @prabirshrestha Webview is too big for vim, GVim needs to include at least 20MB dynamic libraries to support webview. You can check the binary size of cef or electron.
The webview can be implemented in a separated process, and attach to GVim's main window.

By webview I mean the OS default browser that is for Mac it would be safari and windows IE. Not sure about Linux. But if it isn’t portable then not worth it. Or if one could make a markdown renderer that would also be great.

I think it is very important that the implementation is super simple (KISS) and NOT super feature rich. We need only the basic overlay with just the proposed controls and new highlight groups and then the users are free to use it for various stuff. There will be many new ideas, you'll see.

Prefer text ui, not webview.
neovim's floating window is awesome feature!

For the plugin writers' sanity sake, we should really try to make our implementation's API as close to neovim's as possible. Though, that's a little hard at the moment, considering that neovim's documentation isn't available just yet.

@bstaletic I'm working on it here https://github.com/neovim/neovim/pull/9669/files, though I need adjust the script to show the indented text in nvim_open_win() correctly, so currently that part can be read here.

Found another RFC by @puremourning：
RFC: Signature help/argument hints in a second popup menu

That RFC has been updated in my vim fork: https://github.com/bstaletic/vim/tree/current_argument_update

Highlight support is great, like this:

One of reasons that I don't like balloon is that doesn't allow highlight.

As part of https://github.com/myitcv/govim I'd like to see development in this area. govim is backed by gopls, an LSP server. So we have lots of rich information some users might like to be surfaced.
One of the key use cases is signature help. That is, when the user is in the middle of typing an expression that represents a function/method call, signature help reminds them of the function/method's signature, which parameter they are currently providing etc.
Some users will prefer this sort of detail in the status line.
Others, particularly those perhaps more used to things like VSCode, will appreciate the option of a balloon-like presentation of the signature help immediately above/below the relevant position.
Highlighting support would be a bonus, not least because it can be used to show the current parameter. (Highlighting support in balloons would also be useful too)
@brammool - what are your thoughts on this space in general?

@myitcv reminder that you have all that available in neovim master/nightly, with coc.nvim making use of it for quite a while already. I find the govim's approach regarding adopting Vim8-only late remote API instead of NeoVim's one (and producing/using a wrapper over it for Vim8) kinda... strange. Is it worth it? I see even @Shougo preferring the latest approach with his plugins, even despite he being the original author of Vim's remote API implementation, if I recall correctly.
I think the remote API feature is one hard-to-borrow idea if you simply dismiss implementing it in a compatible way, and since NeoVim took the lead, I've seen many authors leveraging its remote API before Vim came with its own, unrelated one, that's of no use for the already existing remote plugins in NeoVim-land. Reason why I hardly see any Vim8-only remote plugin around.

@oblitum - I'd be happy to continue the conversation about govim, Neovim vs Vim8, different APIs etc in an issue over at https://github.com/myitcv/govim. I don't think this thread is the best place for that discussion.

I have added a detailed design in patch 8.1.1329.  Feel free to comment.

Regarding the API, i'm a strong believer in "write the usage code first", i.e. you can't really know if the API works without some practical code which uses it. Bram, if you have a toy or POC implementation of the proposed API, i am more than willing to rewrite our my RFC demo to use it and let you know how it goes ? But on the face of it, your proposed API  does seem to be a superset of what i proposed in that RFC.
In my original proposal i said this(;
hint_pum_set( {arg} ) = set the contents of the hint menu

For some reason i recall that i wanted to set the text, then display it separately. Maybe this was just implementation convenience, but perhaps it would make sense to allow popup_create which does all of what popup_show does, but doesn't actually show it ? This might be YAGNI, though.

@puremourning

For some reason i recall that i wanted to set the text, then display it separately.

I guess that was your idea at some point, but you also scrapped it and didn't end up using it in the actual code for the RFC mentioned, because you also had:
hint_pum_show( {arg} ) = set the contents and show the hint menu

Your branch didn't use hint_pum_set() at all by the time I took over the branch to rebase it onto, at the time, latest changes to the upstream vim.

OK then, carry on... :)

Your paperclip design is awesome!

I was wondering about mouse clicks.  We can probably do this:
A mouse click arrives as .  The coordinates are in
v:mouse_popup_col and v:mouse_popup_row.  The top-left screen cell of the
popup is col 1, row 1 (not counting the border).

See a discussion about using a buffer instead of a List of lines: https://groups.google.com/forum/#!topic/vim_dev/6RXkRnhpMNM

I think, it's better to merge floating window feature from neovim.
Floating window is more generic than popup.

@epheien I am afraid that merging is nearly impossible, because the ui backends is totally different between vim and neovim. If vim wants to merge neovim's floating window, the detachable ui mechanism in neovim must get merged first, which equivalent to merge entire neovim to vim.
Nearly impossible.

https://github.com/vim/vim/blob/957f85d54ebd5a3bd0d930de9603190f0876f977/runtime/doc/popup.txt
This is totally beyond my expectation, cool.
The only question I really care about is: is it possible to block all the vim's event loop while a popup is visible ??
Like a dialog box in Win32, when a dialog box is created, the parent window will be paused until the dialog box get closed. It is useful while waiting user to make some choice or settings (like open a file).
There is a filter-callback in the api document, If create a dialog box in INSERT mode, I don't want to user input any text to current buffer while the dialog box is visible, can I use the filter-callback to achieve this ??

I think, it's better to merge floating window feature from neovim.
Floating window is more generic than popup.

Where is that documented?  I only found one snippet, and it looked like
it supports fewer features than what the proposal for the popup window
currently has.
--
I learned the customs and mannerisms of engineers by observing them, much the
way Jane Goodall learned about the great apes, but without the hassle of
grooming.
(Scott Adams - The Dilbert principle)
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

https://github.com/vim/vim/blob/957f85d54ebd5a3bd0d930de9603190f0876f977/runtime/doc/popup.txt
This is totally beyond my expectation, cool.
The only question I really care about is: is it possible to block all the vim's event loop while a popup is visible ??
Like a dialog box in Win32, when a dialog box is created, the parent
window will be paused until the dialog box get closed. It is useful
while waiting user to make some choice or settings (like open a file).
There is a filter-callback in the api document, If create a dialog
box in INSERT mode, I don't want to user input any text to current
buffer while the dialog box is visible, can I use the
filter-callback to achieve this ??

The filter can consume all keyboard events, thus: yes.
--
It's totally unfair to suggest - as many have - that engineers are socially
inept.  Engineers simply have different objectives when it comes to social
interaction.
(Scott Adams - The Dilbert principle)
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

@brammool

I think, it's better to merge floating window feature from neovim. Floating window is more generic than popup.

Where is that documented?

https://github.com/neovim/neovim/pull/9722/files

I think, it's better to merge floating window feature from neovim. Floating window is more generic than popup.

Where is that documented?

https://github.com/neovim/neovim/pull/9722/files

That's what I already found.  It doesn't say much specific, esp. all the
arguments for nvim_open_win().  Where is that?
It also mentions "reconfigure a normal window into a float".  Where is
explained how that happens?
Can the floating window be moved by the user?  Can it extend (hidden)
outside of the Vim window?   Or does it get smaller and text wraps?
What happens if there is more than one floating window?  Is that even
possible?  If yes, can I create a hundred of them?  How are they all
positioned then?
--
A consultant is a person who takes your money and annoys your employees while
tirelessly searching for the best way to extend the consulting contract.
(Scott Adams - The Dilbert principle)
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

I guess @bfredl should know.

I wrote:

I think, it's better to merge floating window feature from neovim. Floating window is more generic than popup.

Where is that documented?

https://github.com/neovim/neovim/pull/9722/files

That's what I already found.  It doesn't say much specific, esp. all the
arguments for nvim_open_win().  Where is that?

It's actually in the same file: https://neovim.io/doc/user/api.html
At about 1/3 of the file.

It also mentions "reconfigure a normal window into a float".  Where is
explained how that happens?

Looks like this actually isn't supported.

Can the floating window be moved by the user?  Can it extend (hidden)
outside of the Vim window?   Or does it get smaller and text wraps?

Apparently the window is truncated.  Unless it's an external window,
which only works with the GUI.

What happens if there is more than one floating window?  Is that even
possible?  If yes, can I create a hundred of them?  How are they all
positioned then?

Strangely there is no priority argument, thus when two windows overlap
one can't control which one goes on top.
Apparently the floating window behaves like a normal window, one can put
focus in it and edit the text.  That's not really what we want with a
popup.  It will trigger creeping featurism to add a window manager...
--
hundred-and-one symptoms of being an internet addict:

You actually wore a blue ribbon to protest the Communications Decency Act.

/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

@brammool

It also mentions "reconfigure a normal window into a float". Where is explained how that happens? Looks like this actually isn't supported.

This is supported and done by nvim_win_set_config function. It detaches the window from the split layout and displays it as a float.

Apparently the window is truncated.

Depends what "truncated" means. The floating window will be reduced in size to fit the size of the screen, and remain fully functional (unless the screen is really small, so normal windows doesn't render properly anyway).

Strangely there is no priority argument, thus when two windows overlap one can't control which one goes on top.

Yeah this is something we need to add. There is an ordering mechanism internally, but it is not exposed by the API. Currently order can only be changed by focusing the window.

Apparently the floating window behaves like a normal window, one can put focus in it and edit the text. That's not really what we want with a popup. It will trigger creeping featurism to add a window manager...

The rationale for us was rather to reduce the need for special API:s for float features. Text and highlighting can be set with the same mechanisms as for an ordinary window (including preview windows). Existing plugin code that uses a split window to display info (or show a menu, fuzzy search prompt etc) can be extended to support floating windows.  Also, it is possible to disable focus support on a per-float basis. I understand if you prefer a different design though.

It also mentions "reconfigure a normal window into a float". Where
is explained how that happens? Looks like this actually isn't
supported.

This is supported and done by nvim_win_set_config function. It
detaches the window from the split layout and displays it as a float.

Aha.  Can it also be put back?

Apparently the window is truncated.

Depends what "truncated" means. The floating window will be reduced in
size to fit the size of the screen, and remain fully functional
(unless the screen is really small, so normal windows doesn't render
properly anyway).

That's what I meant with truncated.  "sized to fit" would be a better
description, no text it lost or hidden.

Strangely there is no priority argument, thus when two windows
overlap one can't control which one goes on top.

Yeah this is something we need to add. There is an ordering mechanism
internally, but it is not exposed by the API. Currently order can only
be changed by focusing the window.

Apparently the floating window behaves like a normal window, one can
put focus in it and edit the text. That's not really what we want
with a popup. It will trigger creeping featurism to add a window
manager...

The rationale for us was rather to reduce the need for special API:s
for float features. Text and highlighting can be set with the same
mechanisms as for an ordinary window (including preview windows).
Existing plugin code that uses a split window to display info (or show
a menu, fuzzy search prompt etc) can be extended to support floating
windows.  Also, it is possible to disable focus support on a per-float
basis. I understand if you prefer a different design though.

If it's possible to put focus in a floating window this triggers all
kinds of questions, and probably many commands will need to behave
differently.  E.g., what does "split" do?  If it actually splits inside
the floating window it's like the floating window is a tabpage.
What does CTRL-W CTRL-W do?  It's easy to think of more.  Not putting
focus in the floating/popup window makes it easier (but there will still
be lots of things to check, e.g. how options are used).
It's clear that many plugin authors need popup windows, but focusing
them is not needed, and even undesired.  So that's what I want to build
(at least now).
A small group of users would like floating windows for editing, toplevel
GUI windows, non-tiling window layout, etc.  I think this is what Neovim
is intending to provide, and have popup windows as a side effect.
--
When a fly lands on the ceiling, does it do a half roll or
a half loop?
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

Aha. Can it also be put back?

Yes. <c-w>J and such works.

E.g., what does "split" do? If it actually splits inside the floating window it's like the floating window is a tabpage. What does CTRL-W CTRL-W do? It's e

No. Splits in floats are not allowed, that would be too complex. If split command is invoked, the split will go to the edge of the main screen instead. The floating windows are last in the window list, so <c-w><c-w> will cycle through first all split windows and then all focusable floats.

A small group of users would like floating windows for editing, toplevel GUI windows, non-tiling window layout, etc. I think this is what Neovim is intending to provide, and have popup windows as a side effect.

What nvim currently provides is a low-level but generic API for plugins to use as they see fit. Most plugin use so far use them as temporary popup windows or menus, some by re-purposing existing special spilt windows, as mentioned. It is possible we will add higher level API:s to more conveniently support popular usecases (which in part can determined by observing how the current implementation is used by the community). To say that it is "intended" for the small-group usecases specifically while popular usecases are a "side effect" doesn't make any sense.

Implementation has started and the design is now in runtime/doc/popup.txt.
Let's close this issue now.  If you have ideas or comments regarding popup windows, please open a new issue.

In case anyone is interested, here's a prototype implementation of YouCompleteMe using this new API for argument hints. Very much a work in progress:

The backend completer clangd.

@puremourning awesome !!
Maybe a distinguished background color would be better, It is hard to tell if a text line belongs to ground window or popup window.

@brammool I want to simulate a menu bar with popup window:

They are hide by default, and then:

press SPACE: display the top menu bar
press f: display the file menu (select an item in menu bar)
press s: to save current file (select an item in the file menu)
or press ESC to hide them all.

Questions are:

can we still have borders ??
can I reuse buffer id's for them ??

I can answer the buffer reuse question myself now, it is totally unnecessary, just use hide/show, during the life cycle, the buffer is always there.

two minor issues:
the number isn't disabled in the popup window by default:
let winid = popup_create(["Hello, World !!", "line2", "line3"], {})

see the line number makes calculating width/height incorrectly. and the first line get wrapped and the third line are not displayed.
Unless I call:
call setwinvar(winid, '&number', 0)

after creation, and it works as expected:

It should be disable by default.
The tilde is visible in non-text area:

reproduct:
let winid = popup_create(["Hello, World !!", "line2", "line3"], {"minheight": 10})

If a popup is created with a minheight larger than the actual size, the annoying tilde sign is visible and the background color is incorrect.

@puremourning awesome !!
Maybe a distinguished background color would be better, It is hard to tell if a text line belongs to ground window or popup window.

Well yes. It’s very simple, but UI is all placeholder right now. There are some other options we might want to Disable like ‘signcolumn’. But I will raise or fix those separately

@puremourning , there is a work around:
call setwinvar(winid, '&number', 0)
call setwinvar(winid, '&signcolumn', "no")

@skywind3000 You forgot &relativenumber and there might be more.

@puremourning - that demo looks fantastic, excellent proof of concept to start with with the signature help. Are you prototyping this on a branch of YCM?

@myitcv
YCM - https://github.com/puremourning/YouCompleteMe/tree/signature-help
ycmd - https://github.com/puremourning/ycmd-1/tree/signature-help

@skywind3000 I know
@myitcv yeah, though the branch has other stuff from my fork, you can the relevant changes in my 'signature-help' YCM branch here: https://github.com/puremourning/YouCompleteMe/compare/yaml...puremourning:signature-help and here: https://github.com/puremourning/ycmd-1/compare/yaml...puremourning:signature-help

two minor issues:
the number isn't disabled in the popup window by default:
let winid = popup_create(["Hello, World !!", "line2", "line3"], {})

see the line number makes calculating width/height incorrectly. and the first line get wrapped and the third line are not displayed.
Unless I call:
call setwinvar(winid, '&number', 0)

after creation, and it works as expected:

It should be disable by default.

Currently it copies the window options of the current window.  I tried
not doing that, but then it crashes (because options are not
initialized).  I suppose for popup windows re-using the options of the
current window doesn't work well.  Better to start with Vim default
values.

The tilde is visible in non-text area:

reproduct:
let winid = popup_create(["Hello, World !!", "line2", "line3"], {"minheight": 10})

If a popup is created with a minheight larger than the actual size, the annoying tilde sign is visible and the background color is incorrect.

I recently fixed the background color (there is a screendump test for
that).   So perhaps in a popup window the tilde should just not be used?
Alternatively you can add some empty lines in the buffer.  But I suppose
the tilde is not really useful anyway.
--
I started out with nothing, and I still have most of it.
-- Michael Davis -- "Tonight Show"
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

Minor drawing issue: When scrolling a non-current window (i e by using mouse scrollwheel), and popup is displayed on top of it, artefacts of the popup window is visible in the scrolled window. (scrolling current window is not affected).

Thanks, since the popup window is local to the current tabpage, is the winid an unique id across tabpages ?
I am simulating a popup menu, text in popup can be changed by setbufline but how to change highlighting ?? When the menu indicator jump from one position to another (press UP/DOWN, CTRL+N/P), highlighting requires to be changed.
Any API for this ??
Now a popup window uses a traditional buffer, how can I apply traditional syntax highlighting on it ??

Another issue: if a popup window covers a statusline, then statusline will sometimes be drawn on top of the popup window (very frequent with statusline plugin like lightline, with NORC it seems to happen on switching windows).

Thanks, since the popup window is local to the current tabpage, is the
winid an unique id across tabpages ?

Yes, ":help window-ID".
Popup windows can also be global, they hang around when going through
tab pages.

I am simulating a popup menu, text in popup can be changed by
setbufline but how to change highlighting ?? When the menu indicator
jump from one position to another (press UP/DOWN, CTRL+N/P),
highlighting requires to be changed.

Use text properties.

Any API for this ??
Now a popup window uses a traditional buffer, how can I apply
traditional syntax highlighting on it ??

Not implemented yet:
call win_execute(winid, 'syntax enable')
--
hundred-and-one symptoms of being an internet addict:
39. You move into a new house and decide to Netscape before you landscape.
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

Another issue: if a popup window covers a statusline, then statusline
will sometimes be drawn on top of the popup window (very frequent with
statusline plugin like lightline, with NORC it seems to happen on
switching windows).

The drawing of popup windows is a very rough implementation currently.
Still needs quite a bit of work.
--
The future isn't what it used to be.
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

@brammool I want to simulate a menu bar with popup window:

They are hide by default, and then:

press SPACE: display the top menu bar
press f: display the file menu (select an item in menu bar)
press s: to save current file (select an item in the file menu)
or press ESC to hide them all.

The first trigger would need to be a mapping.  The rest can be done with
the popup window filter.

Questions are:

can we still have borders ??
can I reuse buffer id's for them ??

Borders are planned, although I wonder if we should only support
something simple.  It's easy to go crazy with this.
The separators need to be part of the buffer text, using text properties
for the highlighting.  Once you do this, you could probably also draw
the borders that way, if you want something different from the default.
--
Light travels faster than sound.  This is why some people
appear bright until you hear them speak
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

@skywind3000. Aren't menus already supported?  E.g. in the termdebug plugin?

@brammool

Now a popup window uses a traditional buffer, how can I apply traditional syntax highlighting on it ??

Not implemented yet:
call win_execute(winid, 'syntax enable')

and then ?? how to define the syntax ?? sourcing a syntax file ??
call win_execute(winid, "source /path/to/my_popup_syntax.vim")

or just source a built-in syntax file for snippets ??:
call win_execute(winid, "source /usr/local/share/vim/vim81/syntax/cpp.vim")

I wrote a test for applying traditional syntax highlighting in a popup window:
let winid = popup_create([
                        \ "#include <stdio.h>",
                        \ "int main(void)",
                        \ "{",
                        \ "    printf(123);",
                        \ "}"],
                        \ {"minheight": 10,
                        \ "line": 3, "col": 45})

call setwinvar(winid, '&number', 0)
call setwinvar(winid, "&wincolor", "NonText")

redraw
echo getchar()

call win_execute(winid, "syntax enable")
call win_execute(winid, "source /usr/local/opt/share/vim/vim81/syntax/cpp.vim")

redraw
echo getchar()
call popup_close(winid)

It works, but my LineNr (modified in my .vimrc) has been changed by cpp.vim:
before sourcing cpp.vim:

after sourcing cpp.vim:

What is unexpected is that the highlighting group of LineNr has been reset, you can see the line number color changed from gray to yellow.
I am using desert256 color scheme, LineNr is yellow by default, and I changed it to gray in my .vimrc:
" tune line numbers
highlight LineNr term=bold cterm=NONE ctermfg=DarkGrey ctermbg=NONE
	\ gui=NONE guifg=#585858 guibg=NONE

But after sourcing "cpp.vim", it seems to be reseted to the origin yellow in desert256 colors cheme.
What I can confirm is that desert256.vim has been called by cpp.vim:
see the output of :scriptnames:
140: ~/.vim/bundles/vim-colorschemes/colors/desert256.vim
141: /usr/local/opt/share/vim/vim81/syntax/cpp.vim
142: /usr/local/opt/share/vim/vim81/syntax/c.vim
143: ~/.vim/bundles/vim-cpp-enhanced-highlight/after/syntax/c.vim

This is what happenning after:
call win_execute(winid, "source /usr/local/share/vim/vim81/syntax/cpp.vim")

I have no idea why "cpp.vim" will resourcing my current color scheme  ??
Any work around to prevent this ?

For someone who care about highlighting, I wrote another test to demostrate  textprop + popup:

but using textprop on popup is trivial, every time I need change the highlighting, it requires:

calculate new highlighting rules and call prop_clear and prop_add in a function
call that function in win_execute

It would be convenience if there are some functions like setbufline can enable me change the text properties within the popup window directly (without define a function and call it from win_execute).

The old syntax highlighting is much easier for me than text properties:

let winid = popup_create([
                        \ "+----------+",
                        \ "| item (1) |",
                        \ "| item (2) |",
                        \ "+----------+",
                        \ "| item (3) |",
                        \ "+----------+",
                        \ ],
                        \ {"line": 3, "col": 45})

call setwinvar(winid, '&number', 0)
call setwinvar(winid, "&wincolor", "Pmenu")

hi link popupSelect PmenuSel
hi link popupKey PreProc

call win_execute(winid, 'syn region PmenuSel start=/\%2l\%2v/ end=/\%2l\%12v/')
call win_execute(winid, 'syn match popupKey /\d/')

redraw
echo getchar()

call popup_close(winid)

Code is very simple. It is good to choose old syntax highlighting over textprop for a popup window.

It also mentions "reconfigure a normal window into a float". Where > is explained how that happens? Looks like this actually isn't > supported. This is supported and done by nvim_win_set_config function. It detaches the window from the split layout and displays it as a float.

Aha. Can it also be put back?

Apparently the window is truncated. Depends what "truncated" means. The floating window will be reduced in size to fit the size of the screen, and remain fully functional (unless the screen is really small, so normal windows doesn't render properly anyway).

That's what I meant with truncated. "sized to fit" would be a better description, no text it lost or hidden.

Strangely there is no priority argument, thus when two windows > overlap one can't control which one goes on top. Yeah this is something we need to add. There is an ordering mechanism internally, but it is not exposed by the API. Currently order can only be changed by focusing the window. > Apparently the floating window behaves like a normal window, one can > put focus in it and edit the text. That's not really what we want > with a popup. It will trigger creeping featurism to add a window > manager... The rationale for us was rather to reduce the need for special API:s for float features. Text and highlighting can be set with the same mechanisms as for an ordinary window (including preview windows). Existing plugin code that uses a split window to display info (or show a menu, fuzzy search prompt etc) can be extended to support floating windows. Also, it is possible to disable focus support on a per-float basis. I understand if you prefer a different design though.

If it's possible to put focus in a floating window this triggers all kinds of questions, and probably many commands will need to behave differently. E.g., what does "split" do? If it actually splits inside the floating window it's like the floating window is a tabpage. What does CTRL-W CTRL-W do? It's easy to think of more. Not putting focus in the floating/popup window makes it easier (but there will still be lots of things to check, e.g. how options are used).
It's clear that many plugin authors need popup windows, but focusing them is not needed, and even undesired. So that's what I want to build (at least now).
A small group of users would like floating windows for editing, toplevel GUI windows, non-tiling window layout, etc. I think this is what Neovim is intending to provide, and have popup windows as a side effect.

Focusable popup window is much desirable for me.  I want to extend my fuzzy finder plugin LeaderF to support popup window, but it seems impossible without focusing, because LeaderF has two modes, when it is in normal mode, it should work as in normal window/buffer.  However I can easily extend LeaderF to support float window on neovim. The scope of usage is too narrow for popup window if it can only be used to display something.
So can an option be added to specify whether to support focusing?

but it seems impossible without focusing

please explain why you need focusing.

but it seems impossible without focusing

please explain why you need focusing.

If you have a try my plugin LeaderF, you will know why. It has a normal mode, for example, if you run command: Leaderf function, then press <tab>, it will switch to normal mode, you can use j, k to navigate the result, and even you can copy something from the result using the copy command.

Focusing popup seems already possible, though only with a hack:
split
let wid = popup_create("text", {'minwidth': 15, 'minheight': 5})
call win_execute(wid, winnr()."close")

Editing and redrawing works just fine, but wincmds do not (need win_gotoid() to leave the popup window).

Focusing popup seems already possible, though only with a hack:
split
let wid = popup_create("text", {'minwidth': 15, 'minheight': 5})
call win_execute(wid, winnr()."close")

Editing and redrawing works just fine, but wincmds do not (need win_gotoid() to leave the popup window).

The hack has some issues, for example, :qa can not quit from vim. If the focus leave the popup window, it can not get back again.
It is best that vim can support focusing.

Indeed, the point was to show that the design is compatible with focusing, but the wincmd issues would need to be fixed for real usage.
Similarly displaying and interacting with a terminal buffer in a popup window also sort-of works (like neovim float), but there are some drawing glitches and crashes. I think because some of the code checks for "popup" buffer type instead of popup window, which creates issues with special buffer types.

I worry that focussable pop ups is the tip of a scope creep iceberg. There were very specific use cases in the original request/rfc and in the plugin author survey.
Overlaying entire windows with complex interactions seems beyond that scope IMO.
E.g. for such things, what makes pop ups better than say splits?

For someone who care about highlighting, I wrote another test to
demostrate  textprop + popup:

but using textprop on popup is trivial, every time I need change
the highlighting, it requires:

calculate new highlighting rules and call prop_clear and
prop_add in a function
call that function in win_execute

It would be convenience if there are some functions like setbufline
can enable me change the text properties within the popup window
directly (without define a function and call it from win_execute).

You should get the buffer number of the popup with winbufnr() and pass
it to the "bufnr" argument of prop_add().
--
hundred-and-one symptoms of being an internet addict:
56. You leave the modem speaker on after connecting because you think it
sounds like the ocean wind...the perfect soundtrack for "surfing the net".
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

Now a popup window uses a traditional buffer, how can I apply traditional syntax highlighting on it ??

Not implemented yet:
call win_execute(winid, 'syntax enable')

and then ?? how to define the syntax ?? sourcing a syntax file ??
call win_execute(winid, "source /path/to/my_popup_syntax.vim")

or just source a built-in syntax file for snippets ??:
call win_execute(winid, "source /usr/local/share/vim/vim81/syntax/cpp.vim")

I played around with this a bit and realized that using setwinvar() for
'syntax' does not work, because setwinvar() blocks autocommands, and
setting up syntax highligting needs autocommands.  So the best way is:
call win_execute(winid, "set syntax=python")

I added test for that.  And fixed that an unintended side effect was
that 'buftype' got reset.
--
Be thankful to be in a traffic jam, because it means you own a car.
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

The old syntax highlighting is much easier for me than text properties:

let winid = popup_create([
                        \ "+----------+",
                        \ "| item (1) |",
                        \ "| item (2) |",
                        \ "+----------+",
                        \ "| item (3) |",
                        \ "+----------+",
                        \ ],
                        \ {"line": 3, "col": 45})

call setwinvar(winid, '&number', 0)
call setwinvar(winid, "&wincolor", "Pmenu")

hi link popupSelect PmenuSel
hi link popupKey PreProc

call win_execute(winid, 'syn region PmenuSel start=/\%2l\%2v/ end=/\%2l\%12v/')
call win_execute(winid, 'syn match popupKey /\d/')

redraw
echo getchar()

call popup_close(winid)

Code is very simple. It is good to choose old syntax highlighting over textprop for a popup window.

Whether you use syntax highlighting or text properties in a popup window
is completely up to you.  You can also mix them.
--
"I don’t know how to make a screenshot" - Richard Stallman, July 2002
(when asked to send a screenshot of his desktop for unix.se)
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

but it seems impossible without focusing

please explain why you need focusing.

If you have a try my plugin
LeaderF, you will know why.

I do not just try out random plugins to see what they do.  I assume
others also prefer reading some text you write, perhaps look at a
screenshot or recording, instead of taking the effort and risk of
installing a plugin.

It has a normal mode, for example, if you run command: Leaderf function, then press <tab>, it will switch to normal mode, you can
use j, k to navigate the result, and even you can copy something
from the result using the copy command.

Anything you cannot do with a popup window filter?  It's not implemented
yet, but you can read the docs for the planned functionality:
:help popup-filter
--
hundred-and-one symptoms of being an internet addict:
59. Your wife says communication is important in a marriage...so you buy
another computer and install a second phone line so the two of you can
chat.
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

Anything you cannot do with a popup window filter? It's not implemented yet, but you can read the docs for the planned functionality: :help popup-filter

I have already read all the docs about popup window, and have tried writing some little tests. I think I can  understand what popup-filter will do. Unfortunately it can't meet my requirement. It can only work like fzf, which has only one mode.
Anyway, thanks for your great work.

Bjorn Linse wrote:

Focusing popup seems already possible, though only with a hack:
split
let wid = popup_create("text", {'minwidth': 15, 'minheight': 5})
call win_execute(wid, winnr()."close")

Editing and redrawing works just fine, but wincmds do not (need
win_gotoid() to leave the popup window).

And eventually leads to a crash.  Thanks for catching that, I sent out a
fix.
Please watch out for other problems, introducing a new type of window
means having to check all places where the difference might matter.
--
hundred-and-one symptoms of being an internet addict:
60. As your car crashes through the guardrail on a mountain road, your first
instinct is to search for the "back" button.
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

@brammool I think there still will be issues from that a lot of "interactive" features can be activated indirectly via commands, like :normal , feedkeys(), :wincmd and so on. A quick example, call win_execute(popup, "wincmd s") generates weird behavior.

@brammool I think there still will be issues from that a lot of
"interactive" features can be activated indirectly via commands, like
:normal , feedkeys(), :wincmd and so on. A quick example, call win_execute(popup, "wincmd s") generates weird behavior.

Yes, well, weird behavior is up to the user (or plugin author) to avoid.
You can also mess up a normal window.  But Vim should not crash or get
into a bad state.  Perhaps CTRL-W commands and feedkeys() should be
disabled, I can't think of a useful application of these in a popup
window.  Another way would be to whitelist commands to use in a popup
window, but that's going to be quite a bit of work, since we do want to
allow for useful things.
--
hundred-and-one symptoms of being an internet addict:
61. Your best friends know your e-mail address, but neither your phone number
nor the address where you live.
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

@puremourning - how are you finding popup windows for providing signature help?
I'm toying with the idea of adding support to https://github.com/myitcv/govim; wondering whether the ideas you were exploring in https://github.com/puremourning/YouCompleteMe/tree/signature-help are still current?
Thanks

@Yggdroo you can implement with filter. This is confirm dialog when open new buffer.

https://github.com/mattn/vimgon-quest-menu

@puremourning - how are you finding popup windows for providing signature help?

It's brilliant. I'm already using it every day pretty much.
I susepect that now ycmd uses gopls it would just work with go. I haven't tried it though.

Great to hear. It looks like your changes haven't been merged yet, so I assume you're still working off that branch?

Yes I am dogfooding.

@myitcv as mentioned, YCM just works with gopls (though gopls seems to have a bug identifying the current argument):

@puremourning - that looks fantastic!

@puremourning: though gopls seems to have a bug identifying the current argument

This issue doesn't happen when snippet is expanded, which just adds an empty () but leaves the cursor inside. The server doesn't seem prepared to handle signatureHelp with an open parenthesis without a closing one following.
There was a previous relevant issue on https://github.com/saibing/bingo/issues/20, whose development stopped in favor of gopls.

@Yggdroot you can implement with filter. This is confirm dialog when open new buffer.

https://github.com/mattn/vimgon-quest-menu

I know, this is easy to implement, however, what I need is a window that can get focusing just like neovim's floating window.

@Yggdroot If using filter, you can make prompt in the popup window.

someone would write a readline library for popups？

Here is another example where we needed to focus popup in order to be able to scroll.
https://github.com/prabirshrestha/vim-lsp/pull/395

It is using :LspHover to get information of the symbol under the cursor. But the language server provides quite a lot of doc so impossible for me to read the entire docs. There could also be cases where I would actually like to even copy some of the sample docs in popup and paste it in my file.
Let me know if we want to create a new issue for this.

Scroll your content by
call win_execute("normal \<c-e>")
call win_execute("normal \<c-y>")

??

This is not an issue, but I have no idea how to attach images in vim_dev group. So forgive me create this post in the issues and it can be closed immediately.
The human readable page is here:
https://github.com/skywind3000/vim-proposal/blob/master/popup_window.md
Popup Window API Proposal
Problem
Vim has already got some builtin popup-widgets for certain usage, like completion menu or balloon. But users and plugin authors are still asking for more:
* 3379: [Support Floating Window](https://github.com/vim/vim/issues/3379)

* 2948: [balloon_show doesn't display the balloon](https://github.com/vim/vim/issues/2948)

* 2352: [Call to balloon_show() doesn't show the balloon in the terminal](https://github.com/vim/vim/issues/2352)

* 3811: [Feature Request: Trigger balloon via keyboard at cursor position](https://github.com/vim/vim/issues/3811)

* 0234: [Implement argument completion/hints](https://github.com/Valloric/YouCompleteMe/issues/234)

* 2718: [Display function prototype in the cmdline](https://github.com/Valloric/YouCompleteMe/issues/2718)

* [RFC: Signature help/argument hints in a second popup menu](https://groups.google.com/forum/#!searchin/vim_dev/argument$20hints%7Csort:date/vim_dev/YntCTlqdVyc/Me8uwfBpAgAJ)

In Vim conf 2018, Bram claimed that he has plan for this already:

Popup Windows:
Use for a notification:

Asynchronously show window with text “build done”.
Remove after a few seconds.

Use for picking an item:

Show window where each line is an item
Let user pick an item
A bit like confirm() but much nicer

Summary, there are two types of popup window: interactive and non-interactive.
For non-interactive popup windows, people want to use them to:
* Display the documentation for a function:

* Display linting errors or warnings:

* Preview a portion of file (can be used to preview grep results in quickfix):

* Display funny help for newbies (like paperclip assistent in office 2000):

For interactive popup windows, people want to use them to:
* pick an item:

* display a nice popup menu:

* cmd line completion:

* use fuzzy finder in a popup window:

There are too many popup-related widgets for certain usage, designing one by one is nearly impossible.
Implementing a neovim's floating window will take too much time (it is working in progress for almost 2-years and still not merge to master).
Can we implement the popup window in a simple and adaptive way ? Is this possible to unify all their needs and simplify API design ?
The following parts of this article will introduce an overlay mechanism similar to Emacs's text overlay which is the backend of various popup windows in Emacs.
API Scope
Popup windows will draw into an overlay layer, A popup will remain after creation until an erase function is called. Everything in the overlay will not interfere vim's states, people can continue editing or using vim commands no matter there is a popup window or not.
So, the APIs are only designed for drawing a popup window and has nothing to do with user input. Dialogs like yes/no box and confirm box require user input, can be simulated with following steps:
function! Dialog_YesNo(...)
    while not_quit
       draw/update the popup window
       get input from getchar()
    endwhile
    erase the popup window
endfunc

Popup window APIs is not responsible for any interactive functionalities. Instead of implementing a complex widget/event system (which is too complex), it is sane to let user to handle the input by getchar().
There can be a popup.vim script contains some predefined popup windows/dialogs and will be shipped with vim itself. User can use the primitive APIs and getchar() to implement other complex dialogs like a popup fuzzy finder or a command line history completion box.
Overlay Buffer
The overlay buffer is a character matrix with the same size of the screen:
|\     |\
| \    | \
|  \   |  \
|   \  |   \
|   |  |   |
| 1 |  | 2 |   <---- Observer
|   |  |   |
|   /  |   /
|  /   |  /
| /    | /
|/     |/

^      ^
|      |
|   Overlay Buffer (M rows and N columns)
|
Ground Vim UI (M rows and N columns)

Similar to Video Buffer (0xb8000) in x86's text mode, the overlay buffer is a 2D array of characters and attributes. Change the content of the 2D array will change the text in the screen.
The overlay buffer is invisible by default and can be enabled by:
set guioptions+=o

Every existent text rendering code in both Vim & GVim needs to be updated to support this overlay buffer, once it finished, we can use it to build powerful popup windows.
There are also some basic APIs for overlay buffer:
* add a text string with position and attribute.

* erase a rectangle of text.

* command `redrawoverlay` to update the overlay (it uses double buffer to prevent flicker).

With these primitive APIs, user can draw what ever they like on the overlay buffer.
Overlay Panes
Overlay panes is an abstraction of the popup windows, it consists of:
* position and size

* z order (for overlapping calculation)

* background color

* border styles

* lines of text and text-properties

There can be multiple panes at the same time, the panes can be manipulated by:
pane_create(int row, int col, int width, int height, ...);
pane_destroy(int pane_id);
pane_update(int pane_id, ...);
pane_move(int pane_id, int new_row, int new_col, int new_width, int new_height);
pane_show(int pane_id, bool show_hide);

(PS: they are provided as both C-apis and vim functions).
The life cycle of a pane is between pane_create and pane_destroy.
The (row, col) is using screen coordinate system, and there can be some functions to convert window based coordinate system to screen coordinate system. If you want to display a popup balloon right above your cursor, you can use them to calculate the position.
Finally, there is a function to render the pane list into the overlay buffer:
pane_flush();

If you create some panes, the overlay buffer will not change until pane_flush().
Popup Windows
All the common popup windows are implemented in popup.vim script, they will use panes to display a popup window and getchar() to provide interactive functionalities.
There are some predefined popup windows:
* Popup_Message(): display a "build complete" message and hide after a few seconds.

* Popup_LinterHint(): display a message right above cursor and hide if cursor moves outside current `<cword>`.

* Popup_Menu(): display a menu (use `getchar()` to receive user input) and quit after user select an item.

* Popup_YesNo(): display a `yes/no` box and return the result after user made a selection.

* ...

* and so on.

User or plugin authors can use the high level APIs provided by popup.vim or design their own popup window by utilizing lower level pane APIs or overlay APIs.
Summary
It is complex to design an event system or NeoVim's floating window, and nearly impossible to implement every type of popup window for certain usage.
To unify and simplify the interface, this proposal suggests to provide an overlay mechanism with some primitive APIs to:
* render a popup window (pane)

* erase a popup window

* update a popup window

And let user handle input themself by getchar(). At last, makes it possible to enable users to create various popup windows with different styles and functionalities.
--
2019/3/2 edit: floating window got merged to master.

Are we able to have a foating fuzzyfinder (FZF) or grep. Can't seen to figure it out.
e.g https://github.com/junegunn/fzf.vim/issues/786

This you have to ask junegunn. It has nothing to do with the popup window implementation

Are we able to have a foating fuzzyfinder (FZF) or grep. Can't seem to figure it out.

Well the infrastructure for that is available. Needs a plugin writer for that, if there is none available yet.

@chrisbra It seems not possible to implement since vim's popup_menu is not a normal buffer.

so what exactly are you missing? that is not possible currently. Please be specific.

@chrisbra what missing is opening terminal in popup_menu

and you need the terminal in a popup window because?

@chrisbra Using fzf in popup_menu. Latest fzf can use terminal feature in vim to have the same behavior like in terminal.

that makes it sound like it should be possible without terminal feature. So the question remains: Why do you need the terminal in the popup window? Can't you filter the popup window using other means?

@chrisbra I just want to have the same behavior like in terminal!

@iamcco I think you can display the terminal in a popup now (because a popup can load any buffer now), but such a terminal cannot use terminal mode (because a popup window still cannot be entered). You might be able to fake the latter by using getchar() plus term_sendkeys() in a loop, though it is of course not as convenient (and won't support :tmap etc, not sure if fzf plugin uses that).

@chrisbra It seems not possible to implement since vim's popup_menu is
not a normal buffer.

You can create a popup window with any existing buffer.
--
Not too long ago, a program was something you watched on TV...
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

@chrisbra I just want to have the same behavior like in terminal!

Please be more specific about what that is needed for.  This sequence of
one-liners is not really helpful.
Running a terminal window in a popup seems like a total hack.  No idea
why anyone would want to do that.
--
Q:  Why do ducks have flat feet?
A:  To stamp out forest fires.
Q:  Why do elephants have flat feet?
A:  To stamp out flaming ducks.
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

@bfredl It's good to know that, will have a try to see if it can use with fzf.
@brammool it's really worth if it can focus cursor on popup window since it can use existing buffer.

@bfredl It's good to know that, will have a try to see if it can use with fzf.
@brammool it's really worth if it can focus cursor on popup window
since it can use existing buffer.

Those are unrelated.  You can open a popup window with an existing
buffer:
popup_create({what}, {options})				popup_create()
Open a popup window showing {what}, which is either:
- a buffer number
- a string
- a list of strings
- a list of text lines with text properties
--
FIRST GUARD: Ah!  Now ... we're not allowed to ...
SIR LAUNCELOT runs him through,  grabs his spear and stabs the other
guard who collapses in a heap.  Hiccoughs quietly.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

@bfredl what would be the VIM equivalent of:
let g:fzf_layout = { 'window': 'call FloatingFZF()' }
function! FloatingFZF()
let buf = nvim_create_buf(v:false, v:true)
call setbufvar(buf, '&signcolumn', 'no')
let height = &lines - 3
let width = float2nr(&columns - (&columns * 2 / 10))
let col = float2nr((&columns - width) / 2)
let opts = {
\ 'relative': 'editor',
\ 'row': 1,
\ 'col': col,
\ 'width': width,
\ 'height': height
\ }
call nvim_open_win(buf, v:true, opts)
endfunction

@blayz3r as alluded to earlier use  popup_create with the bufnr of the vim terminal. The position arguments should map to the ones documented at :help popup_create-arguments.

@blayz3r @bfredl You can't open a terminal window with a running job in a popup window. It will crash your Vim session. Running a fuzzy-searcher in a Vim popup window doesn't work.
Popup windows do not have a cursor. When you open a popup window, the focus and the cursor stay on the window it was called from. The way to interact with a popup window is through popup-filter.
Opening a shell in a popup window will result in a crash:
let ptybuf = term_start(&shell, #{hidden: 1})
let winnr = popup_create(ptybuf, #{
        \ close: 'button',
        \ padding: [1,1,1,1],
        \ border: [0,0,0,0],
        \ minwidth: 70,
        \ maxwidth: 70,
        \ minheight: 20,
        \ maxheight: 20
        \ })

Removing the #{hidden: 1} option will open the terminal in a new split. Now the content can be displayed in a popup window, partially. You have to execute each line separately. Running :source % will result in a crash (adding a term_wait(ptybuf, 200) in-between the two lines doesn't help either).
The popup window will display the content of the terminal buffer but only as long as it stays visible in a window. There are also other issues with scrolling the popup window and redrawing.
Using a popup-filter with term_sendkeys() is weird because it will insert keys into the terminal window but you won't see a cursor. It also won't update the popup window as you type.
let ptybuf = term_start(&shell, #{hidden: 0})

function! s:popup_filter(winid, key) abort
    call term_sendkeys(winbufnr(a:winid), a:key)
    redraw
    return v:true
endfunction

let winnr = popup_create(ptybuf, #{
        \ close: 'button',
        \ padding: [1,1,1,1],
        \ border: [0,0,0,0],
        \ minwidth: 70,
        \ maxwidth: 70,
        \ minheight: 20,
        \ maxheight: 20,
        \ mapping: 0,
        \ filter: function('s:popup_filter')
        \ })

Displaying the content of a terminal buffer with a finished job in a popup window seems to work better. The following works but as above each line needs to be executed separately (:source % will crash for some reasons):
let ptybuf = term_start([&shell, &shellcmdflag, 'ls'], #{hidden: 1})
let winnr = popup_create(ptybuf, #{
        \ close: 'button',
        \ padding: [1,1,1,1],
        \ border: [0,0,0,0],
        \ minwidth: 70,
        \ maxwidth: 70,
        \ minheight: 20,
        \ maxheight: 20
        \ })

Using a popup-filter with term_sendkeys() is weird because it will insert keys into the terminal window but you won't see a cursor. It also won't update the popup window as you type.

Even if it is hacky and weird I would have expected redraw to still work, perhaps this cause of this is related to the crashes (i e the redraw code path from libvterm updates does not work with popups).

@blayz3r @bfredl You can't open a terminal window with a running job in a
popup window. It will crash your Vim session. Running a fuzzy-searcher in a
Vim popup window doesn't work.
Popup windows do not have a cursor. When you open a popup window, the focus
and the cursor stay on the window it was called from. The way to interact
with a popup window is through popup-filter.
Opening a shell in a popup window will result in a crash:

I'll check out why it crashes.  Probably we need to forbid doing this.
Why are you trying to run a terminal window in a popup window?  It smells like
you want to show the result of some external command.  Using channel functions
for this is probably a better solution.  Or use a hidden terminal window and
copy the text to the popup window (the terminal debugger does this).
--
Q: How does a UNIX Guru do Sex ?
A: unzip;strip;touch;finger;mount;fsck;more;yes;umount;sleep
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

Why are you trying to run a terminal window in a popup window?

Hi @brammool, let me chime in on this. They are running TUI programs using the terminal buffer. i.e. They are not just interested in the result of the program; they need to interact with the program.
For example, fzf is not a native Vim plugin but an external TUI program you can run on your shell and the Vim plugin for fzf is a just thin wrapper that starts an fzf process in a terminal buffer and lets the users "interact" with the program. It usually looks like this:

(You are looking at a TUI program with its own interface running inside a terminal buffer)
If it's possible to open a terminal buffer that allows user interaction in a popup window, we can start the program in the center of the screen without affecting the window layout. The floating window of Neovim supports that, and this is how it looks:

So, this is a file selection dialog.  And that preview of travis.yml is put in the terminal window by that fzf program?  Looks like it has its own popup mechanism.
OK, this looks like a valid use case.  I would think if we have a terminal window in a popup it would always get keyboard focus (like using a filter that always returns true).

@brammool Thank you for the quick response.

And that preview of travis.yml is put in the terminal window by that fzf program?

Yes, the whole section of the screen is drawn by fzf. It's a generic text filter with --preview functionality.

What about a new ! command ? for example !!, which will execute command in a dedicated popup window and returns after command exit.
Not flexible I know, but enough for tools like fzf.

What about a new ! command ? for example !!, which will execute
command in a dedicated popup window and returns after command exit.
Not flexible I know, but enough for tools like fzf.

That starts looking like something you should do with a new terminal,
not inside Vim:
:!xterm -c "your command"&
I was only thinking of the use case of a dialog to select a file, where
the dialog can have keyboard focus until it's closed.  Popup windows are
intended for that, but so far excluding using a terminal window.
--
This is an airconditioned room, do not open Windows.
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

What about a new ! command ? for example !!, which will execute command in a dedicated popup window and returns after command exit. Not flexible I know, but enough for tools like fzf.
That starts looking like something you should do with a new terminal, not inside Vim: :!xterm -c "your command"& I was only thinking of the use case of a dialog to select a file, where the dialog can have keyboard focus until it's closed. Popup windows are intended for that, but so far excluding using a terminal window.
…
-- This is an airconditioned room, do not open Windows. /// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net \\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\ \\ an exciting new programming language -- http://www.Zimbu.org /// \\ help me help AIDS victims -- http://ICCF-Holland.org ///

This would be great to have!

If we have this topmost terminal popup window, maybe we can get keywordprg running in it.
much convenient.

Hi @brammool thanks for Vim!
Just to +1 @junegunn comment above, I need some way to use a :terminal inside your new popup window feature. Here's an example of how I'm using Neovim 'floating' window to call fzf and display output:

I absolutely love the API you've designed with popup. This would be a very useful addition for us I think.
Happy new year!

@brammool , I am trying to simulate this, by calling term_sendkeys from a popup filter:
function! PopupBuffer(bid)
	let opts = {'mapping':0, 'close':'button'}
	let opts.filter = 'PopupFilter'
	let opts.title = ' POPUP '
	let opts.border = [1,1,1,1,1,1,1,1,1]
	let winid = popup_create(a:bid, opts)
	let opts = {"minwidth":20, "minheight":5, "maxwidth":20, "maxheight":5}
	call popup_move(winid, opts)
	call popup_show(winid)
endfunc

function! PopupFilter(winid, key)
	let bid = winbufnr(a:winid)
	if a:key == "\<c-x>"
		call popup_close(a:winid, 0)
		return 1
	endif
	echo "key: ".a:key
	call term_sendkeys(bid, a:key)
	return 1
endfunc

term
let bid = bufnr('')
wincmd p
call PopupBuffer(bid)

But it displays:
E278: Cannont put a terminal buffer in a popup window.

Can we just remove this restriction ? and I can send keys to a hidden terminal from my popup filter.

It is now possible to run a terminal in a popup window.  First create the terminal buffer hidden, then create a popup for that buffer.
It is quite brittle, making a popup window the current window is unexpected and can cause many problems.  I have found some things that can go wrong, there probably are several more.

@brammool , I tried it but the popup can not be closed when terminal job finished:

let w = 80
let h = 24
let opts = {'hidden': 1, 'term_rows':h, 'term_cols':w}
let opts.term_kill = 'term'
let opts.norestore = 1
let bid = term_start(['bash'], opts)

let opts = {'maxwidth':w, 'maxheight':h, 'minwidth':w, 'minheight':h}
let opts.wrap = 0
let opts.mapping = 0
let opts.title = 'popup-terminal'
let opts.close = 'button'
let opts.border = [1,1,1,1,1,1,1,1,1]
let opts.drag = 1
let opts.resize = 0
let winid = popup_create(bid, opts)

save this to test.vim and so test.vim in vim 8.2.0200, than type exit in the popup terminal.
the terminal popup should be closed, but it remains there.

@brammool use close in the exit_cb function can close the terminal.

When I create a terminal in a popup window, &buftype is set to terminal (consider autocmd WinEnter * echom 'WinEnter: ' . &buftype). Should it be popup-terminal or something)? How can we detect popup windows (including a terminal in popup) since there're many limitations in the popup window.

FWIW, I inspect the output of popup_getoptions(win_getid()).
I consider the current window as a popup window if and only if it's not empty.
The downside is that – in addition to evaluating to an empty dictionary – it raises E993 in a non-popup window.  So, I use silent!.  So far, it seems to work as expected.
But I like your suggestion of setting &buftype to popup-terminal; it would make the code a little less verbose and a little more readable.

diff --git a/src/popupwin.c b/src/popupwin.c
index 714f457fe..32adb7935 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -1826,6 +1826,11 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
 	win_init_popup_win(wp, buf);
 	set_local_options_default(wp, FALSE);
 	buffer_ensure_loaded(buf);
+#ifdef FEAT_TERMINAL
+	if (buf->b_term != NULL)
+	    set_string_option_direct_in_buf(buf, (char_u *)"buftype", -1,
+		    (char_u *)"popup-terminal", OPT_FREE|OPT_LOCAL, 0);
+#endif
     }
     else
     {

I've noticed that TerminalOpen is triggered when a terminal buffer is created even without a window.  I know it's not a bug since it's documented:

This event is triggered even if the buffer is created
without a window, with the ++hidden option.

But I had some issues because of it; some of my terminal-specific configurations were applied to regular buffers, because I didn't think it was necessary to inspect &buftype.  I fixed my issues by wrapping all commands executed from TerminalOpen inside an if &bt is# 'terminal'.

Don't use &buftype to detect popup window, a buffer may be display in a normal window and in a popup window at the same time. Assume that you are editing a.c, and use popup window to preview symbol definitions in a.c. How to set the buftype in this situation ?

@brammool , I tried it but the popup can not be closed when terminal job finished:

let w = 80
let h = 24
let opts = {'hidden': 1, 'term_rows':h, 'term_cols':w}
let opts.term_kill = 'term'
let opts.norestore = 1

Add term_finish "close" here.

let bid = term_start(['bash'], opts)
let opts = {'maxwidth':w, 'maxheight':h, 'minwidth':w, 'minheight':h}
let opts.wrap = 0
let opts.mapping = 0
let opts.title = 'popup-terminal'
let opts.close = 'button'
let opts.border = [1,1,1,1,1,1,1,1,1]
let opts.drag = 1
let opts.resize = 0
let winid = popup_create(bid, opts)

save this to `test.vim` and `so test.vim` in vim 8.2.0200, than type `exit` in the popup terminal.

the terminal popup should be closed, but it remains there.

Typing ":quit" works, right?
--
How To Keep A Healthy Level Of Insanity:
8. Don't use any punctuation marks.
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

Don't use &buftype to detect popup window, a buffer may be displayed in a normal window and in a popup window at the same time.

Okay, got it. So what's the correct way to detect a popup window after all? I think I just want to expose WIN_IS_POPUP(wp) to Vim script. Maybe &wintype or is_popup_win({nr})?  I think empty(popup_getoptions(win_getid())) is too long and allocates unnecessary dictionary.

But I had some issues because of it; some of my terminal-specific configurations were applied to regular buffers, because I didn't think it was necessary to inspect &buftype. I fixed my issues by wrapping all commands executed from TerminalOpen inside an if &bt is# 'terminal'.

Can't you simply use a TerminalWinOpen autocommand instead?

@brammool , yes, use a close or quit in terminal's exit_cb can close the popup window:
let w = 80
let h = 24
let opts = {'hidden': 1, 'term_rows':h, 'term_cols':w}
let opts.term_kill = 'term'
let opts.norestore = 1
let opts.exit_cb = 'OnTermExit'
let bid = term_start(['bash'], opts)

function! OnTermExit(job, message)
    close
    " TODO: add some code to confirm that current window is a popup.
    " TODO: prevent close other window by accident.
endfunction

let opts = {'maxwidth':w, 'maxheight':h, 'minwidth':w, 'minheight':h}
let opts.wrap = 0
let opts.mapping = 0
let opts.title = 'popup-terminal'
let opts.close = 'button'
let opts.border = [1,1,1,1,1,1,1,1,1]
let opts.drag = 1
let opts.resize = 0
let winid = popup_create(bid, opts)

It works as expected now.

Can't you simply use a TerminalWinOpen autocommand instead?

@chrisbra For some reason, I didn't notice the patch 8.1.2219; you're right, I should listen to this event instead of TerminalOpen.  Thank you very much, it will make my autocmds less verbose, and more reliable, since the configurations will be applied even for a hidden terminal buffer once it's displayed in a window.

This also works:
let opts.term_finish = 'close'

But I cannot get the exit code. using a exit_cb can get the exit code.

Okay, got it. So what's the correct way to detect a popup window after all? I think I just want to expose WIN_IS_POPUP(wp) to Vim script. Maybe &wintype or is_popup_win({nr})? I think empty(popup_getoptions(win_getid())) is too long and allocates unnecessary dictionary.

FWIW, I would go with win_ispopup() and/or add the entry popup in getwininfo().

When I create a terminal in a popup window, &buftype is set to
terminal (consider autocmd WinEnter * echom 'WinEnter: ' . &buftype). Should it be popup-terminal or something)? How can we
detect popup windows (including a terminal in popup) since there're
many limitations in the popup window.

Adding a 'wintype' option would pair with 'buftype', but since it's not
an option you can set, would give the wrong idea.
Adding win_ispopup() would work, but perhaps it's better to use
win_type() and return "popup".  We can then use it for other types as
well.  But we don't need to duplicate what is already in 'buftype.
One that comes to mind is the command line window, which is another
specialy one.
So if 'buftype' is "terminal" and win_type() returns "popup" you have a
terminal running in a popup window.  Makes sense?
--
How To Keep A Healthy Level Of Insanity:
16. Have your coworkers address you by your wrestling name, Rock Hard Kim.
/// Bram Moolenaar --<EMAIL_ADDRESS>-- http://www.Moolenaar.net   \
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \
\\  an exciting new programming language -- http://www.Zimbu.org        ///
\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

@brammool, the popup_hide() and popup_close are not allowed in the popup terminal, can we allow one of them ??
The popup terminal can be more useful if it can be temporary hidden or shown. (or the relative popup window can be closed and recreated).
A efficient workflow will be possible if so:

When I need to use the shell, I can press <c-F12> to open a popup terminal, unlike split terminal, it will not change my window layout and will not disturb me.

The shell job is not finished, now I want to edit, I don't have to exit the terminal, just press <c-F12>  to hide it.

Then, I finish my editing I can use <c-f12> again to bring the popup terminal back and continue my previous works in the shell.

It can make me really productive if the terminal popup can be toggled on/off swiftly by <c-f12> .  I even don't need the tmux pane any more if I can use this.
But sadly, I found both popup_hide() and popup_close() are disabled in an unfinished terminal popup. Can we enable one of them ??

This issue was closed, please create a new issue for new items to discuss.