You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
To ensure only a single instance of your app can run, you can make use of a crate like single-instance. But an end user expects that, when trying to open the app by running its executable, the app is unconditionally brought into the foreground, no matter whether its relevant window is in the background, arranged, minimized, or hidden, because the app works with a tray icon.
I don't know whether Windows support for such functionality would fit into winit's existing ActivationToken API. In any case, an easy way to implement this functionality on Windows on a low level, is to retrieve a window message via RegisterWindowMessageW() in every app instance using the same app-specific string, and, if the app instance is a follow-up instance, use PostMessageW(HWND_BROADCAST, ...) to request the original app instance to activate its relevant window.
Note: You will know that Windows' SetForegroundWindow() is subject to certain restrictions. In my winit-using Slint app, though, I didn't have any trouble with activating the original app instance's window. The file manager will be the foreground process. Then this from the Microsoft docs will apply: "A process can set the foreground window...only if: ...The calling process was started by the foreground process..." Then, from my anecdotal evidence, Windows seems to allow this follow-up process of my app to transfer the right to successfully call SetForegroundWindow() to my original app instance (maybe because its the same executable path). (Alternatively, there would also be AllowSetForegroundWindow(), which requires retrieving the original app instance's process ID, though.)
However, as far as I can see, winit currently doesn't even support bringing a window into the foreground unconditionally. Window::focus_window() doesn't work for minimized and invisible windows, e.g., and Window::set_visible() probably also doesn't unminimize. Even though at least Windows 10 has a bug regarding arranged windows, there's a way to unconditionally bring a window into the foreground in its correct state: See this code (in another case, I only had success when calling SetForegroundWindow() before ShowWindowAsync(), in a branch where IsWindowVisible() returned true).
I think the functionality of unconditionally bringing a window to the foreground isn't only useful in the context of follow-up app instances, but also, e.g., when your app works with a tray icon, its window was minimized before hiding it in the tray, and the end user wants to show the app's window by clicking on the tray icon.
Wayland/X11 usually activate with dbus in case of IPC happening, so you pass some token to your main app, and then it acts based on the message you've passed, etc.
So no cross platform thing can not be done, really.
ActivationToken is just a string you pass via IPC to e.g. activate yourself and in some cases you can not really focus with it, like it should be passed to you via some sort of launcher for that to happen, etc.
What you describe sounds like you have IPC + some activation right in the windows API without a need for tokens, etc, since you basically do everything yourself, unlike like on Wayland where you get your token from somewhere else in cases of being activated.
In the case of macOS, this is handled automatically when the application is bundled (and if really necessary, the user can spawn a separate process with open -n). So there is nothing for Winit to do there.
So I've marked this with the
DS - windows
label, since it sounds like it's mostly an issue on Windows where this sort of behaviour isn't standardized.
Description
To ensure only a single instance of your app can run, you can make use of a crate like
single-instance
. But an end user expects that, when trying to open the app by running its executable, the app is unconditionally brought into the foreground, no matter whether its relevant window is in the background, arranged, minimized, or hidden, because the app works with a tray icon.I don't know whether Windows support for such functionality would fit into winit's existing
ActivationToken
API. In any case, an easy way to implement this functionality on Windows on a low level, is to retrieve a window message viaRegisterWindowMessageW()
in every app instance using the same app-specific string, and, if the app instance is a follow-up instance, usePostMessageW(HWND_BROADCAST, ...)
to request the original app instance to activate its relevant window.Note: You will know that Windows'
SetForegroundWindow()
is subject to certain restrictions. In my winit-using Slint app, though, I didn't have any trouble with activating the original app instance's window. The file manager will be the foreground process. Then this from the Microsoft docs will apply: "A process can set the foreground window...only if: ...The calling process was started by the foreground process..." Then, from my anecdotal evidence, Windows seems to allow this follow-up process of my app to transfer the right to successfully callSetForegroundWindow()
to my original app instance (maybe because its the same executable path). (Alternatively, there would also beAllowSetForegroundWindow()
, which requires retrieving the original app instance's process ID, though.)However, as far as I can see, winit currently doesn't even support bringing a window into the foreground unconditionally.
Window::focus_window()
doesn't work for minimized and invisible windows, e.g., andWindow::set_visible()
probably also doesn't unminimize. Even though at least Windows 10 has a bug regarding arranged windows, there's a way to unconditionally bring a window into the foreground in its correct state: See this code (in another case, I only had success when callingSetForegroundWindow()
beforeShowWindowAsync()
, in a branch whereIsWindowVisible()
returned true).I think the functionality of unconditionally bringing a window to the foreground isn't only useful in the context of follow-up app instances, but also, e.g., when your app works with a tray icon, its window was minimized before hiding it in the tray, and the end user wants to show the app's window by clicking on the tray icon.
Somewhat similar issue regarding Wayland: #3633.
Relevant platforms
Windows
The text was updated successfully, but these errors were encountered: