Neovide: How to get neovim's default buffer?

Created on 3 May 2021  路  7Comments  路  Source: Kethku/neovide

Neovide seems to open a scratch file by default instead of the help screen in vim/neovim. How do you change this?

bug good first issue

Most helpful comment

I would like to offer my help with this issue.

At first glance, the issue seems to be that the screen is redrawn before anything is input by the user (e.g because of a resize or something).
nvim's :h :into tells us that:

When Vim starts without a file name, an introductory message is displayed (for
those who don't know what Vim is).  It is removed as soon as the display is
redrawn in any way.  To see the message again, use the ":intro" command (if
there is not enough room, you will see only part of it).

I will now investigate if my suspicion is correct and if startup-redraws can be avoided.

Edit 1:
I logged all rpc-calls to nvim and will now dig through the docs to see which one could cause a redraw. nvim_ui_try_resize is a Probable Candidate.

Edit 2:
I commented out the content of the following match in src/bridge/ui_command.rs:UiCommand.execute

            UiCommand::Resize { width, height } => {
                nvim
                .ui_try_resize(width.max(10) as i64, height.max(3) as i64)
                .await
                .expect("Resize failed")
            }

and the welcome screen started showing - but of the wrong size of course.
Now the great question is how to avoid calling resize at startup and still get a correctly sized nvim

~~Edit 3:
It seems that the initial resize happens as expected at system start at src/window/sdl2/mod.rs:Sdl2WindowWrapper.draw_frame. There the window is resized from some weird initial size to the actual size. Let's see where the initial size comes from, if we can correct it and if we can plug it directly into the bridge.

Edit 4:
I am wondering if maybe the best way would be to actually wait in src/bridge/mod.rs:start_neovim_runtime until this initial resize has already happened... Feels hacky tho

Edit 5:
Oh I just noticed that the resize-ui-commands actually are dispatched in a thread which is started in src/bridge/mod.rs:start_neovim_runtime:286 which is nice, because that's where our search started. When I tap into the match

            match ui_command_receiver.recv().await {
                Ok(ui_command) => {
                    if let UiCommand::Resize { width, height } = ui_command {
                        println!("== Resize would just have happened")
                    } else {
                        let input_nvim = input_nvim.clone();
                        tokio::spawn(async move {
                            ui_command.execute(&input_nvim).await;
                        });
                    }
                }
                Err(_) => {
...

then the redraw is prevented and therefore the vim-intro-message is shown.

Edit 6:
When starting neovide on my system three things happen. First of all nvim.ui_attach is called with (100x50) which are the INITIAL_DIMENSION. That means that window_geometry returns Err. Then a UiCommand::Resize is dispatched with (68x29) and afterwards another one is dispatched with (68,33).

In my opinion the best way to proceed would be to

  1. Check why there are two UiCommand::Resizes (this may be caused by some i3 madness on my system only).
  2. When dispatching a resize event, check if the window dimensions are actually different from before (this may be obsolete because nvim itself may check that and do not redraw if that is the case)
  3. Change something to let window_geometry_or_default() inside start_neovim_runtime return the actual window dimensions and not the default values. This way nvim.ui_attach is called with the correct window size and future resizes are obsolete.

At this point I will finish my investigations for today.

All 7 comments

Thats a good question. I suspect this is a bug in the init logic.

Shouldn't be hard to fix. THe relevant code is in the bridge mod.rs file

I would like to offer my help with this issue.

At first glance, the issue seems to be that the screen is redrawn before anything is input by the user (e.g because of a resize or something).
nvim's :h :into tells us that:

When Vim starts without a file name, an introductory message is displayed (for
those who don't know what Vim is).  It is removed as soon as the display is
redrawn in any way.  To see the message again, use the ":intro" command (if
there is not enough room, you will see only part of it).

I will now investigate if my suspicion is correct and if startup-redraws can be avoided.

Edit 1:
I logged all rpc-calls to nvim and will now dig through the docs to see which one could cause a redraw. nvim_ui_try_resize is a Probable Candidate.

Edit 2:
I commented out the content of the following match in src/bridge/ui_command.rs:UiCommand.execute

            UiCommand::Resize { width, height } => {
                nvim
                .ui_try_resize(width.max(10) as i64, height.max(3) as i64)
                .await
                .expect("Resize failed")
            }

and the welcome screen started showing - but of the wrong size of course.
Now the great question is how to avoid calling resize at startup and still get a correctly sized nvim

~~Edit 3:
It seems that the initial resize happens as expected at system start at src/window/sdl2/mod.rs:Sdl2WindowWrapper.draw_frame. There the window is resized from some weird initial size to the actual size. Let's see where the initial size comes from, if we can correct it and if we can plug it directly into the bridge.

Edit 4:
I am wondering if maybe the best way would be to actually wait in src/bridge/mod.rs:start_neovim_runtime until this initial resize has already happened... Feels hacky tho

Edit 5:
Oh I just noticed that the resize-ui-commands actually are dispatched in a thread which is started in src/bridge/mod.rs:start_neovim_runtime:286 which is nice, because that's where our search started. When I tap into the match

            match ui_command_receiver.recv().await {
                Ok(ui_command) => {
                    if let UiCommand::Resize { width, height } = ui_command {
                        println!("== Resize would just have happened")
                    } else {
                        let input_nvim = input_nvim.clone();
                        tokio::spawn(async move {
                            ui_command.execute(&input_nvim).await;
                        });
                    }
                }
                Err(_) => {
...

then the redraw is prevented and therefore the vim-intro-message is shown.

Edit 6:
When starting neovide on my system three things happen. First of all nvim.ui_attach is called with (100x50) which are the INITIAL_DIMENSION. That means that window_geometry returns Err. Then a UiCommand::Resize is dispatched with (68x29) and afterwards another one is dispatched with (68,33).

In my opinion the best way to proceed would be to

  1. Check why there are two UiCommand::Resizes (this may be caused by some i3 madness on my system only).
  2. When dispatching a resize event, check if the window dimensions are actually different from before (this may be obsolete because nvim itself may check that and do not redraw if that is the case)
  3. Change something to let window_geometry_or_default() inside start_neovim_runtime return the actual window dimensions and not the default values. This way nvim.ui_attach is called with the correct window size and future resizes are obsolete.

At this point I will finish my investigations for today.

Wow thanks so much for the in depth investigation. This is super useful. As a side note: did you find logging the rpc calls to slow down the system? I wonder if we should change the --log function to do this all the time. For bonus points we could also have it log every command between the different neovide threads. That would turn it into a truly useful log rather than the hit or miss experience it is today.

As for the issue at hand, I suspect that the two resizes happen because we resize the screen when we get the font from neovim. I don't remember for sure, but I think its possible that the window tries to preserve the current size as close as possible when the font changes. So we start with the default font at a given size, and then on receiving the configured font, resize again to match the new font dimensions.

I did not notice any slowdowns while logging. However this isn't pretty representative, because first I didn't do much more than starting it up, look if the intro is shown and then :quitting instantly and second I just used a println! for the sake of brevity and third my system's pretty beefy.

I simply inserted a println!("Method CALL: {} {:?}", method, args); as the first line in nvim-rs/src/neovim.rs:Neovim.call.

I did however notice that there weren't that many RPC calls at all so maybe a simple trace! call wouldn't be a problem. Maybe that call would even get removed in release builds. I can draft up a PR to your nvim-rs repo if you deem it useful.


The resize after font change sounds like a bit of a problem for our issue here, as that one probably depends on nvim up and running and we probably cannot delay starting nvim to after we know the font. Maybe we can delay the call to nvim.ui_attach to after the font is known. I will take a look at that.

Edit 1:
As I see it both of the resizes originates in src/window/sdl2/mod.rs:draw_frame.
The first time handle_new_grid_size is called is directly at system startup (because the initial self.previous_size has a funny value, coming from: ) - Yet it only gets dispatched after nvim.ui_attach(100,50) is called as the dispatcher loop is started then.
The second time handle_new_grid_size is called is, as you said when the font is loaded.

I now naively tried to just delay nvim.ui_attach until two resize commands are received and noticed, that the second "font" resize does not happen until nvim.ui_attach was called. (In fact, no DrawCommands are handled at all). This means that such a change would be non-trivial and probably overkill for a simple thing like the intro screen.

My next idea would be to avoid useless resizes by starting the UI attachment with the correct size in the first place. Then we would have to do some kind of magic with knowing right font size. If I'm right there are some font-related issues going on in the OpenGL branch.
Would it maybe make more sense to postpone solving this issue until possible changes to the font rendering have stabilized?

I am still thinking about this. I think it makes sense to me to delay creation of the window until we get an official font from the vim config. That way we can set the font size correct rather than resizing a couple times. But I don't know exactly yet what the best way is to go about that. If you have ideas, I'm all ears.

As a side note, I added hooks to the message channels between the neovim threads so that when in logging mode, every message is logged out to file. I also took the opportunity to clean up some pretty useless traces we had lying around. Overall I think the log feature is way better for diagnostic purposes now. Thanks for the idea!

I think solving this issue beautifully is not as trivial as it may initially seem. I'll get a bit more comfortable with the OpenGL branch for now and maybe inspiration strikes me. We probably just need one good idea and then everything falls into place XD

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Kethku picture Kethku  路  87Comments

khalidchawtany picture khalidchawtany  路  23Comments

aj3423 picture aj3423  路  45Comments

ssxwcz picture ssxwcz  路  50Comments

mdudzinski picture mdudzinski  路  60Comments