Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

neovide does not focus on launch from terminal (macOS, iTerm2) #2330

Closed
halostatue opened this issue Jan 31, 2024 · 34 comments · Fixed by #2562 or #2799
Closed

neovide does not focus on launch from terminal (macOS, iTerm2) #2330

halostatue opened this issue Jan 31, 2024 · 34 comments · Fixed by #2562 or #2799
Labels
bug Something isn't working macos Specific to macOS and not investigable on other platforms

Comments

@halostatue
Copy link

Describe the bug

I launched neovide from iTerm2 and it launched behind the iTerm2 window and all the way at the end of the app switcher. (I had been doing something where I had set neovide to be on the right side of the screen the same as my typical iTerm2 window, and I kept it here because it shows the behaviour fairly well.)

Even adding vim.cmd("NeovideFocus") to the end of init.lua is not fixing the issue.

To Reproduce

Steps to reproduce the behavior:

  1. Type neovide in iTerm2 (this probably happens with Terminal.app as well, but I currently use iTerm2).
  2. Observe that the window opens behind the iTerm2 window.
  3. Observe on ⌘-Tab that Neovide's icon is at the end of the app switcher.

Expected behavior

Neovide should take focus (especially if vim.cmd("NeovideFocus") is in init.lua or NeovideFocus is in init.vim) from iTerm2 and be positioned in front of iTerm2.

Screenshots

CleanShot 2024-01-30 at 23 41 08@2x

Desktop (please complete the following information):

  • OS: macOS 14.3 23D56 arm64
  • Neovide 0.12.2
  • Neovim 0.9.5

Please run neovide --log and paste the contents of the .log file created in the current directory here:

neovide_rCURRENT.log

Additional context
Add any other context about the problem here.

n/a

@halostatue halostatue added the bug Something isn't working label Jan 31, 2024
@D00mch
Copy link

D00mch commented Jan 31, 2024

related #2324

@wSedlacek
Copy link

wSedlacek commented Mar 10, 2024

I noticed this issue start to occur after updating when using Raycast.
https://www.raycast.com/

After updating Neovide when Neovide is launch from Raycast it starts in the background.
I did not notice this behavior on prior versions.

I am able to work around this by including this in my init.lua

  vim.schedule(function()
    vim.cmd "NeovideFocus"
  end)

@thraizz
Copy link

thraizz commented Mar 11, 2024

For me, this is also the case. Launching from Finder results in the same behavior, even with all plugins disabled. Scheduling NeovideFocus event does not help for me sadly.

EDIT: Launching from kitty / Terminal.app works just fine!

@brnt
Copy link

brnt commented Mar 14, 2024

Seeing same behavior from iTerm2 as described above.

Also note that when launching from Spotlight, the neovide window is focused, but is appended to the end of the cmd-tab switcher (same as described above when launching from a terminal), which is the opposite of most macOS applications. The focus+stacking issue is likely separate from the cmd-tab issue.

@nazriel
Copy link
Contributor

nazriel commented Mar 25, 2024

I can reproduce it as well.

It gets focused properly when launched from Raycast or Launchpad (after symlinking from /opt/homebrew/Cellar/neovide/* to $HOME/Applications) but doesn't focus up when starting from WezTerm nor iTerm2

UPDATE1:
Isn't an issue anymore on HEAD but on HEAD there are other issues like not playing well with Yabai

UPDATE2:
I got confused.

It has something to do with how macOS handles CLI binaries vs Neovide.app files.

Launching
./target/debug/bundle/osx/Neovide.app/Contents/MacOS/neovide [1]
yields different result than
./target/debug/neovide [2]

  1. Doesn't get focused but plays well with Window manager like yabai
  2. Gets focused by doesn't play well with yabai and starts with weird size and position

@nazriel
Copy link
Contributor

nazriel commented Mar 25, 2024

I did some digging about this and looks like it is general macOS problem/default behaviour.

For example when launching wezterm from terminal it behaves the same way as neovide does.
On other hand kitty somehow works around it.

My current workaround for it:

alias nv="open -n -a Neovide --args "

@brnt
Copy link

brnt commented Apr 7, 2024

FWIW, adding a delay before calling NeovideFocus from .vimrc seems to do the trick. Here's the command for adding a 20ms delay:

if exists('g:neovide')
  autocmd VimEnter * call timer_start(20, {tid -> execute('NeovideFocus')})
endif

This seems like a fairly effective workaround while the application itself doesn't currently request focus on startup.

@nazriel
Copy link
Contributor

nazriel commented Apr 12, 2024

FWIW, adding a delay before calling NeovideFocus from .vimrc seems to do the trick. Here's the command for adding a 20ms delay:

if exists('g:neovide')
  autocmd VimEnter * call timer_start(20, {tid -> execute('NeovideFocus')})
endif

This seems like a fairly effective workaround while the application itself doesn't currently request focus on startup.

Works great!

Here is Lua version:

if vim.g.neovide then
  vim.defer_fn(function()
    vim.cmd("NeovideFocus")
  end, 25)
end

@fredizzimo fredizzimo added the macos Specific to macOS and not investigable on other platforms label May 17, 2024
@fredizzimo
Copy link
Member

fredizzimo commented May 18, 2024

I have a potential fix for this here:

It would be good if someone could test it.

@AThePeanut4
Copy link
Contributor

@fredizzimo I'm unfortunately still seeing this after #2562, with a locally built neovide.

I'm also seeing the same behaviour as @nazriel, the issue only happens when running target/release/bundle/osx/Neovide.app/Contents/MacOS/neovide, and not target/release/neovide.

If it helps, Alacritty doesn't have this problem and they're also using winit afaik.

@fredizzimo
Copy link
Member

Ok, I will re-open this. The list bugs that PR fixed was more of a wishlist than scientific proof, based on the winit documentation:

Winit has an OS requirement of macOS 10.11 or higher (same as Rust itself), and is regularly tested on macOS 10.14.

A lot of functionality expects the application to be ready before you start doing anything; this includes creating windows, fetching monitors, drawing, and so on, see issues #2238, #2051 and #2087.

If you encounter problems, you should try doing your initialization inside Event::Resumed.

@fredizzimo fredizzimo reopened this May 19, 2024
@ruibinx
Copy link

ruibinx commented Aug 5, 2024

For anyone interested, I solved this by disabling secure keyboard in iTerm2.

See this also: https://groups.google.com/g/iterm2-discuss/c/Fg6jOm-PrHo

@fboundp
Copy link
Contributor

fboundp commented Aug 21, 2024

The workaround (scheduling NeovideFocus) doesn’t work for me, sadly. I get the “started but not focused” in Terminal.app, iTerm2, and when launching an additional instance from Neovide itself. When launching via Finder or with open -a, Neovide does get focus.

@fredizzimo
Copy link
Member

Are you all using homebrew version of Neovide? There's a chance that there's some issue with the recipe there.

The recipe is also not updated with our new way of packaging https://github.com/neovide/neovide/tree/main/macos-builder

This is what the recipe does: https://github.com/Homebrew/homebrew-core/blob/552d255be9d93db38f7c602345e3a9d0bc3e30db/Formula/n/neovide.rb#L40

@fboundp
Copy link
Contributor

fboundp commented Aug 23, 2024

I am. However, I just uninstalled the Homebrew version and downloaded the Github release and get the same behavior when using the neovide command.

@fredizzimo
Copy link
Member

How did you run the neovide command, since our releases don't provide any? You would have to use open to launch it, or something like /Applications/Neovide.app/Contents/MacOS/neovide. At least I think so, I'm not a macOS users, so I'm mostly going on what I have heard and seen here.

@fboundp
Copy link
Contributor

fboundp commented Aug 23, 2024

Exactly, using /Applications/Neovide.app/Contents/MacOS/neovide …

@fboundp
Copy link
Contributor

fboundp commented Aug 23, 2024

Additional data point: If I build Neovide locally using the macOS instructions at https://neovide.dev/installation.html, then:

  • Running the resulting ~/.cargo/bin/neovide (from e.g. iTerm2) launches Neovide and brings its window frontmost.
  • Running the resulting Neovide.app/Contents/MacOS/neovide launches Neovide but does not bring its window frontmost.

@fredizzimo
Copy link
Member

@fredizzimo
Copy link
Member

fredizzimo commented Aug 23, 2024

Actually, this is probably not something we can fix:

Q: When I use open the app's window doesn't come to the foreground.

A: This is a security feature of macOS when Secure Keyboard Entry is enabled. It prevents an app from stealing keyboard focus while you're entering sensitive text. Disable the menu item iTerm2 > Secure Keyboard Entry to resolve the issue

Source: https://iterm2.com/faq.html, and various forum posts and this post #2330 (comment), by @ruibinx

@fboundp
Copy link
Contributor

fboundp commented Aug 23, 2024

I believe that is just a distraction:

  • I do not have Secure Keyboard Entry enabled.
  • Other similar applications such as mvim (MacVIM) or bbedit do not exhibit this problem.
  • neovide itself does not exhibit this problem in the one case I mentioned above.

@fboundp
Copy link
Contributor

fboundp commented Aug 23, 2024

or possibly the parameters to create-dmg here https://github.com/neovide/neovide/blob/main/macos-builder/run

I do not think create-dmg involved when following the instructions on https://neovide.dev/installation.html, so I think that can be ruled out.

@AThePeanut4
Copy link
Contributor

This isn't a Secure Keyboard issue - I get the same behaviour of neovide opening behind the terminal window when using Alacritty (what I normally use), iTerm with Secure Keyboard enabled or disabled, or the default Terminal app.

As I mentioned in #2330 (comment), and as mentioned by a few others, this only happens when running the binary inside the .app produced by cargo bundle (i.e. Neovide.app/Contents/MacOS/neovide), and not when running the binary produced by cargo build or cargo install. So the issue could maybe be with the way cargo-bundle builds/packages the binary.

When running the binary from cargo build, a few things break, like the app icon in the Dock and the "About neovide" page, so "just don't run the binary in the .app directly" is an okay workaround but wouldn't be a good permanent solution. I imagine these drawbacks are the reason why the Homebrew formula for neovide adds the binary in the .app to $PATH rather than the one produced by cargo install.

Also what I meant by "Alacritty doesn't have this problem" in #2330 (comment) is that the Alacritty app itself opens in the foreground when launched from a terminal, even when running the binary inside the .app. From what I can tell, they don't use cargo-bundle at all and do the .app packaging themselves in the Makefile - perhaps that could be the solution.

@AThePeanut4
Copy link
Contributor

Ah I see now that the new macos-builder script doesn't use cargo-bundle - but I've just tested the .app it produces and unfortunately the issue still persists. If I simply mv the binary outside of the .app the issue magically goes away.

So I imagine the problem is probably with the Info.plist, or perhaps some kind of "app-specific" behaviour where programs launched as part of .apps start minimized and then need to focus themselves somehow.

Also since the macos-builder script doesn't use cargo-bundle, I don't think the macOS build from source instructions on the docs should recommend using cargo-bundle anymore.

What would be great is if there was a script that only builds the .app and doesn't package it into a dmg - essentially macos-builder/run but without the create-dmg command. This would make it easy to build from source locally, and presumably also make it easier for homebrew to package it correctly.

@fredizzimo
Copy link
Member

As mentioned several times, we don't use cargo bundle anymore, instead https://github.com/create-dmg/create-dmg is used, which does pretty much the same as Alacritty, building it using hdiutil.

Even, if you don't have secure input enabled in the terminal, some other application might enable it, here's a script for detecting that https://alexwlchan.net/2021/secure-input/

I suspect because our images are not signed https://developer.apple.com/documentation/security/notarizing-macos-software-before-distribution, it's automatically threated as a potential key logger. This is the only actual technical documentation, I have found, but it's way out of date https://developer.apple.com/library/archive/technotes/tn2150/_index.html.

I still think this is the most likely explanation, since it's a well documented behaviour, and @ruibinx reported that it fixed the problem for them.

Some other links, with inconstent behaviour, all fixed by disabling secure input
https://apple.stackexchange.com/questions/435954/why-does-terminal-retain-focus-stay-in-the-foreground-when-i-open-other-apps
https://apple.stackexchange.com/questions/439347/why-is-terminal-app-weird-about-stealing-keyboard-focus-on-monterey
https://apple.stackexchange.com/questions/469420/how-to-switch-foreground-app-focus-while-using-terminal-with-secure-keyboard
https://apple.stackexchange.com/questions/472674/starting-an-app-often-doesnt-bring-the-window-forward
https://apple.stackexchange.com/questions/183047/os-x-terminal-open-command-and-keeping-focus-on-the-command-line
https://apple.stackexchange.com/questions/472847/open-launches-certain-apps-and-certain-files-in-background-without-g-option

@AThePeanut4
Copy link
Contributor

Well I've just run the find_processes_using_secure_input script, and it returned nothing both before and after running neovide in Alacritty (and having it open into the background). If I enable Secure Keyboard Entry in iTerm then iTerm does show up in the script output, so it is actually working.

So I still don't think Secure Input is the problem, but who knows. Either way, "disabling secure input" doesn't fix the issue, and the problem occurs when using Alacritty which doesn't support Secure Input at all. Secure Input is not a system-wide setting, it's a function that "provide[s] a secure means for a process to protect keyboard input to a custom data entry field".

It could be related to the app not being signed/notarised though - I have come across annoying issues similar to this in an app I was working on that appeared to occur simply because the app wasn't properly signed. However in that case everything worked fine when I built the app locally, and the issues only appeared when building the app somewhere else and copying it over. Here the issue happens every time, no matter where/how the app is built.

I've also just built Alacritty locally to test, i.e. signing the app with an ad-hoc certificate and not notarising, and running the binary inside the produced .app correctly opens in the foreground. The commands run to create the .app in the Alacritty Makefile are identical to those in macos-builder/run. On the other hand, building neovide locally and running those same commands to create and sign the .app causes neovide to open in the background.

Also just to be clear, I don't really ever run neovide from the terminal, so this doesn't actually affect me. I just use a Mac so I'm trying to help troubleshoot and find the root cause of the problem.

@fredizzimo
Copy link
Member

Since, @falcucci mentioned that macVim also has the issue, I found this macvim-dev/macvim#1456

And then further this https://developer.apple.com/documentation/appkit/nsapplication/passing_control_from_one_app_to_another_with_cooperative_activation

So, it seems like the terminal need to cooporate and focus the launched app.

@fboundp
Copy link
Contributor

fboundp commented Sep 14, 2024

To be clear, launching MacVim from iTerm or Terminal on macOS does result in MacVim being in the foreground. (Tested on macOS 14 and macOS 15.)

@falcucci
Copy link
Member

To be clear, launching MacVim from iTerm or Terminal on macOS does result in MacVim being in the foreground. (Tested on macOS 14 and macOS 15.)

To be clear, if you launch neovide from the bundle binary one, you will have this behavior as the same as MacVim, and I do believe that people are installing neovide using this alias. That's what @fredizzimo is mentioning.

For example if you launch MacVim using /Applications/MacVim.app/Contents/MacOS/MacVim

that's the behavior https://share.cleanshot.com/zrjHrD7b

If you launch neovide from the build binary tho, you will have always a new instance in the foreground but many instances to manage and neohub comes into action, (at least for now)

let's consider here all the facts @fredizzimo has putted.

@fboundp
Copy link
Contributor

fboundp commented Sep 14, 2024

But launching …/MacOS/MacVim is not typical usage. Rather, one uses the wrapper script mvim which launches …/MacOS/Vim -g. That results in a new MacVim window in the foreground.

@AThePeanut4
Copy link
Contributor

AThePeanut4 commented Sep 15, 2024

I don't think it's going to possible to get around having to bundle some kind of wrapper script like MacVim does (a la mvim).

That script can then call yieldActivation to allow Neovide to "activate" before running the neovide binary, as described in https://developer.apple.com/documentation/appkit/nsapplication/passing_control_from_one_app_to_another_with_cooperative_activation.

This seems to work, but as a disclaimer, an hour ago my Swift knowledge was exactly zero...

#!/usr/bin/env swift

import Cocoa

let bundleId = "com.neovide.neovide"

func main() {
    guard let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleId) else {
        print("Application with bundle identifier '\(bundleId)' not found")
        return
    }
    let path = Bundle.init(url: url)!.executablePath!

    NSApplication.shared.yieldActivation(toApplicationWithBundleIdentifier: bundleId)

    var args = CommandLine.arguments
    if args.count > 0 {
        args.removeFirst()
    }
    args.insert(path, at: 0)

    let cargs = args.map { strdup($0) } + [nil]

    execv(path, cargs)
}

main()

It can be run directly as a script (after a chmod +x), but it should probably be compiled to a binary with swiftc -o launch launch.swift. Not sure what the best name for it would be, just neovide probably makes the most sense but idk if that would conflict with the actual neovide binary in some way.

The difference between this and mvim is of course that it doesn't fork by default, for that you need to use --fork. Discussion on that at #2147 and #2512.

@fboundp
Copy link
Contributor

fboundp commented Sep 15, 2024

Nice, that’s fairly promising! Perhaps MacVim is doing something similar, where the Vim binary (as opposed to MacVim) appears to be a relatively small wrapper.

@AThePeanut4
Copy link
Contributor

Nice, that’s fairly promising! Perhaps MacVim is doing something similar, where the Vim binary (as opposed to MacVim) appears to be a relatively small wrapper.

At least on my system, in /Applications/MacVim.app/Contents/MacOS, the Vim binary is definitely not just a wrapper (it's 10MB), and it's also much larger than the MacVim binary which is 1MB.

In macvim-dev/macvim#1456, they say that the reason why MacVim doesn't have this whole foregrounding issue is because they're using the deprecated activateIgnoringOtherApps API, which doesn't need the previous app to "yield activation" and just focuses the app unconditionally. I assume Neovide/winit/whoever is using the replacement activate API, which does need the previous app to "yield activation".

@fboundp
Copy link
Contributor

fboundp commented Sep 20, 2024

Following the leads from @AThePeanut4 (thank you!), I’ve analyzed two approaches to this problem: (a) using a wrapper for neovide as suggested, and (b) activating Neovide on startup.

The wrapper approach can be viewed at https://github.com/fboundp/neovide-start. It works pretty well, but I am not excited about it for a few reasons. First, I just generally believe a wrapper should be avoided unless there is no other good way to solve this problem. Additionally, a couple of hacks are necessary for the wrapper to work well. It must do its own processing of the --fork option, so that it can wait on the spawned neovide to propagate and report on exit status. Activating the application once it has been spawned is awkward, requiring the wrapper to wait around until neovide fully initializes. And if the --fork behavior is specified, then we need to wait around a bit in case neovide exits shortly after launching so we can report on that.

The activate approach is given in PR #2799, using the deprecated -[NSApplication activateIgnoringOtherApps:] API. This seems to solve the issue nicely, and is the same approach as used by MacVim, emacs, and a number of other applications that can be launched from terminal. Yes, the API is deprecated, but it is not forbidden nor removed; and I don’t believe it ever will be. I do have a concern with my PR: It is not clear to me that I’ve identified the “right” place to make this call. I think this should be invoked in the -[NSApplicationDelegate applicationDidFinishLaunching:] message, but I couldn’t figure how to accomplish that within winit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working macos Specific to macOS and not investigable on other platforms
Projects
None yet