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

feat(macos): expose set_activation_policy #2258

Closed
srsholmes opened this issue Jul 20, 2021 · 11 comments
Closed

feat(macos): expose set_activation_policy #2258

srsholmes opened this issue Jul 20, 2021 · 11 comments

Comments

@srsholmes
Copy link

srsholmes commented Jul 20, 2021

Is your feature request related to a problem? Please describe.

I would like to make a launcher / spotlight / alfred type application. Currently tauri apps have a menu and a dock icon, which isn't really compatible with this use case.

Describe the solution you'd like

Ideally, we would have the ability to create NSPanel type windows, as described here. This would allow the apps to hide and show and not steal focus when they come to the foreground.

In conjuction with the hide window functionality, this would also solve https://github.com/tauri-apps/tauri/issues/2063

However, after doing some exploration I couldn't find any reference to NSPanel in the cocoa bindings that wry depends on, so this might not be possible without multiple PR's and potentially a lot of work.

Describe alternatives you've considered

tao has the ability to create applications without a dock menu item and menu bar, which can be seen in this example here.

As wry exposes taos functionality, this should be possible in tauri, but it is not exposed in the public api.

I think if this were to be expose by the public tauri api we could create similar apps to an NSPanel window, when used in combination with a sidecar application to manage window focus.

Additional context

Some more info on NSPanel:
https://developer.apple.com/documentation/appkit/nspanel
https://www.markusbodner.com/til/2021/02/08/create-a-spotlight/alfred-like-window-on-macos-with-swiftui/
https://stackoverflow.com/questions/54054473/create-spotlight-like-window-in-swift-4

What an NSPanel window would look like:

image

@srsholmes srsholmes changed the title Enable the ability to make apps with system tray only and no menu / dock item. Feature request : enable the ability to make apps with system tray only and no menu / dock item. Jul 21, 2021
@srsholmes
Copy link
Author

After doing a bit of digging on this, I have managed to build an app using a local version of tauri without a menu bar and only a system tray icon by changing this line to the following

    let mut event_loop = EventLoop::<Message>::with_user_event();
    let proxy = event_loop.create_proxy();
    event_loop.set_activation_policy(ActivationPolicy::Accessory);

and changing the import of the EventLoopExtMacOS to the following...

#[cfg(target_os = "macos")]
use wry::application::platform::macos::{ActivationPolicy, EventLoopExtMacOS};

I would like to contribute this as a PR to tauri-runtime-wry, based on some config / passed in user variable (possibly in the tauri.conf.json?), but unfortunately my rust skills are not at a level where I feel confident in doing so.

I hope that this attempt helps other people in the meantime.

@amrbashir amrbashir changed the title Feature request : enable the ability to make apps with system tray only and no menu / dock item. feat: expose set_activation_policy for macOS Aug 11, 2021
@probablykasper
Copy link
Member

probablykasper commented Aug 11, 2021

Some questions/concerns I have about using ActivationPolicy::Accessory for Spotlight-like windows:

  1. Behavior with multiple spaces/monitors. Spotlight's behavior seems to be to open in the current space, and close whenever the user switches spaces (don't know how it deals with multiple monitors).
  2. Does it show over fullscreen apps?
  3. Does it take away focus from the active window?

@amrbashir
Copy link
Member

One question I have is how ActivationPolicy::Accessory behaves with multiple spaces/monitors. Spotlight's behavior seems to be to open in the current space,

In order to do something like this you would need to do.

  1. get the monitor nearest the cursor (would need a feature request at Tao then Tauri can expose it)
  2. position your window according to the info of the monitor.

and close whenever the user switches spaces (don't know how it deals with multiple monitors).

I think switching to another space will make the window lose focus, and would trigger blur event, and so you'd call window.hide()

@srsholmes
Copy link
Author

srsholmes commented Aug 12, 2021

Regarding the spaces, currently with activation policy, it will switch space when the user activates the app (back to the space the app was on).

This can be overcome by adding the following to tao in src/platform_impl/macos/window.rs line 195.

      ns_window.setCollectionBehavior_(NSWindowCollectionBehavior::NSWindowCollectionBehaviorCanJoinAllSpaces);
      ns_window.setCollectionBehavior_(NSWindowCollectionBehavior::NSWindowCollectionBehaviorMoveToActiveSpace);
       // TODO: get a real level?
      ns_window.setLevel_(10000);

and building tauri against this. This allows the app to pop up on whatever space is currently active, without switching the user back to the original space.

It also allows the app to be viewed over full screen apps.

More info here

and here

With multiple monitors, It only pops up the app on the monitor it was previously on (ie it doesnt follow active monitor). I havn't figured out how to do that yet.

It doesnt not however deal with the window gaining and losing focus. I have had to build a small sidecard app to do this in swift which shifts window focus on blur / whenever the keyboard shortcut is pressed.

This has been quite difficult to achieve the same sort of functionality that the NSPanel provides.

@probablykasper is right to have concerns about this approach, it doesn't offer the same experience as the NSPanel and is a slightly hacky way around the problem.

The main issue is giving focus back to the previous window, once the tauri app is hidden. Without an NSPanel window, this needs to be done by a separate process to handle window focus.

As i understand it, a NSPanel does not steal focus away from the original app, so when an NSPanel app hides focus is still on the original window. The NSPanel receives 'focus' whilst it is active, but immediately loses it when the window is hidden, and restores focus automatically to the previous app.

I would have liked to contribute the changes to Tao / Tauri to make them configurable, but my knowledge of rust is not that great to be honest, so I've just put them in my local copy and build against that. I'm happy to help in any way that i can though, please just let me know or ask.

@amrbashir
Copy link
Member

amrbashir commented Aug 12, 2021

@srsholmes Thanks for the detailed explanation.

There is a project called Ueli which is a spotlight-like app built in electron and I don't think it is using any activation policy, if you don't mind can you take a look on it and see how it behaves on different spaces and monitors and if that's the desired behavior?

This can be overcome by adding the following to tao in src/platform_impl/macos/window.rs line 195.

ns_window.setCollectionBehavior_(NSWindowCollectionBehavior::NSWindowCollectionBehaviorCanJoinAllSpaces);
ns_window.setCollectionBehavior_(NSWindowCollectionBehavior::NSWindowCollectionBehaviorMoveToActiveSpace); 
// TODO: get a real level?
ns_window.setLevel_(10000);

This seems like a feature request for tao, I'd like to keep this issue about activation policy only.

@srsholmes
Copy link
Author

@amrbashir Ueli works perfectly as I would expect the behaviour to work.

It opens the popup on the active screen, with multiple monitors, where the mouse currently sits.

The popup works when the app are in full screen mode.

It also restores focus to the previous app when the pop up is closed.

I couldn't find anything regarding Activation Policy in Ueli, so i think you are correct, maybe the activation policy is not needed to produce this kind of app?

I believe the code for the window management can be found here

There is also some more config for the window here

mainWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });, which might be setting the NSWindowCollectionBehaviorCanJoinAllSpaces

There is a bit of code in electron for this here

Interestingly, on windows, the app appears to minimise, where as on MacOS the window calls show() and hide(). I tried to dig into what these were doing when i originally looked into this with tauri but wasn't able to figure it out unfortunately.

@amrbashir amrbashir changed the title feat: expose set_activation_policy for macOS feat(macos): expose set_activation_policy Aug 12, 2021
@amrbashir
Copy link
Member

amrbashir commented Aug 12, 2021

Cool, looks to me that needed methods are:

  1. dock.hide() and dock.show(), requested in feat(macos): dock management api  #2358 and macOS: Dock management tao#105
  2. app.hide() and app.show(), requested in feat: app.hide() and app.show() tao#182
  3. window.set_visible_on_all_workspaces()
  4. monitor::cursor_position()
  5. monitor::from_point()

I think we should keep this issue open for exposing activation policy only but feel free to file requests for other methods at Tao repo.

@probablykasper
Copy link
Member

probablykasper commented Aug 12, 2021

There are a few electron packages that enable NSPanels:
https://github.com/syed-umair/electron-window-nspanel
https://github.com/mznet/electron-nspanel
https://github.com/goabstract/electron-panel-window

No idea how they work, but they seem pretty lightweight

@amrbashir
Copy link
Member

There are a few electron packages that enable NSPanels:
https://github.com/syed-umair/electron-window-nspanel
https://github.com/mznet/electron-nspanel
https://github.com/goabstract/electron-panel-window

No idea how they work, but they seem pretty lightweight

NsPanel can be hard to do for 3 platforms, I think it us better to focus on necessary stuff so I don't think we should look into NsPanel for tauri v1 but we can consider it for v2 maybe or some can make a tauri plugin for it.

@ahkohd
Copy link
Sponsor Member

ahkohd commented Jan 7, 2023

If you're building a macOS Spotlight app with Tauri and have stumbled upon this issue, you're in luck! I've created an example project demonstrating how to build a Spotlight app using Tauri. See https://github.com/ahkohd/tauri-macos-spotlight-example

@rachtsingh
Copy link

@ahkohd Did you manage to figure out how to do that on Windows as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants