1 | //! Window startup notification to handle window raising. |
2 | //! |
3 | //! The [`ActivationToken`] is essential to ensure that your newly |
4 | //! created window will obtain the focus, otherwise the user could |
5 | //! be requered to click on the window. |
6 | //! |
7 | //! Such token is usually delivered via the environment variable and |
8 | //! could be read from it with the [`EventLoopExtStartupNotify::read_token_from_env`]. |
9 | //! |
10 | //! Such token must also be reset after reading it from your environment with |
11 | //! [`reset_activation_token_env`] otherwise child processes could inherit it. |
12 | //! |
13 | //! When starting a new child process with a newly obtained [`ActivationToken`] from |
14 | //! [`WindowExtStartupNotify::request_activation_token`] the [`set_activation_token_env`] |
15 | //! must be used to propagate it to the child |
16 | //! |
17 | //! To ensure the delivery of such token by other processes to you, the user should |
18 | //! set `StartupNotify=true` inside the `.desktop` file of their application. |
19 | //! |
20 | //! The specification could be found [`here`]. |
21 | //! |
22 | //! [`here`]: https://specifications.freedesktop.org/startup-notification-spec/startup-notification-latest.txt |
23 | |
24 | use std::env; |
25 | |
26 | use crate::error::NotSupportedError; |
27 | use crate::event_loop::{AsyncRequestSerial, EventLoopWindowTarget}; |
28 | use crate::window::{ActivationToken, Window, WindowBuilder}; |
29 | |
30 | /// The variable which is used mostly on X11. |
31 | const X11_VAR: &str = "DESKTOP_STARTUP_ID" ; |
32 | |
33 | /// The variable which is used mostly on Wayland. |
34 | const WAYLAND_VAR: &str = "XDG_ACTIVATION_TOKEN" ; |
35 | |
36 | pub trait EventLoopExtStartupNotify { |
37 | /// Read the token from the environment. |
38 | /// |
39 | /// It's recommended **to unset** this environment variable for child processes. |
40 | fn read_token_from_env(&self) -> Option<ActivationToken>; |
41 | } |
42 | |
43 | pub trait WindowExtStartupNotify { |
44 | /// Request a new activation token. |
45 | /// |
46 | /// The token will be delivered inside |
47 | fn request_activation_token(&self) -> Result<AsyncRequestSerial, NotSupportedError>; |
48 | } |
49 | |
50 | pub trait WindowBuilderExtStartupNotify { |
51 | /// Use this [`ActivationToken`] during window creation. |
52 | /// |
53 | /// Not using such a token upon a window could make your window not gaining |
54 | /// focus until the user clicks on the window. |
55 | fn with_activation_token(self, token: ActivationToken) -> Self; |
56 | } |
57 | |
58 | impl<T> EventLoopExtStartupNotify for EventLoopWindowTarget<T> { |
59 | fn read_token_from_env(&self) -> Option<ActivationToken> { |
60 | matchOption self.p { |
61 | #[cfg (wayland_platform)] |
62 | crate::platform_impl::EventLoopWindowTarget::Wayland(_) => env::var(WAYLAND_VAR), |
63 | #[cfg (x11_platform)] |
64 | crate::platform_impl::EventLoopWindowTarget::X(_) => env::var(X11_VAR), |
65 | } |
66 | .ok() |
67 | .map(ActivationToken::_new) |
68 | } |
69 | } |
70 | |
71 | impl WindowExtStartupNotify for Window { |
72 | fn request_activation_token(&self) -> Result<AsyncRequestSerial, NotSupportedError> { |
73 | self.window.request_activation_token() |
74 | } |
75 | } |
76 | |
77 | impl WindowBuilderExtStartupNotify for WindowBuilder { |
78 | fn with_activation_token(mut self, token: ActivationToken) -> Self { |
79 | self.platform_specific.activation_token = Some(token); |
80 | self |
81 | } |
82 | } |
83 | |
84 | /// Remove the activation environment variables from the current process. |
85 | /// |
86 | /// This is wise to do before running child processes, |
87 | /// which may not to support the activation token. |
88 | pub fn reset_activation_token_env() { |
89 | env::remove_var(X11_VAR); |
90 | env::remove_var(WAYLAND_VAR); |
91 | } |
92 | |
93 | /// Set environment variables responsible for activation token. |
94 | /// |
95 | /// This could be used before running daemon processes. |
96 | pub fn set_activation_token_env(token: ActivationToken) { |
97 | env::set_var(X11_VAR, &token._token); |
98 | env::set_var(WAYLAND_VAR, value:token._token); |
99 | } |
100 | |