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
24use std::env;
25
26use crate::error::NotSupportedError;
27use crate::event_loop::{AsyncRequestSerial, EventLoopWindowTarget};
28use crate::window::{ActivationToken, Window, WindowBuilder};
29
30/// The variable which is used mostly on X11.
31const X11_VAR: &str = "DESKTOP_STARTUP_ID";
32
33/// The variable which is used mostly on Wayland.
34const WAYLAND_VAR: &str = "XDG_ACTIVATION_TOKEN";
35
36pub 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
43pub 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
50pub 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
58impl<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
71impl WindowExtStartupNotify for Window {
72 fn request_activation_token(&self) -> Result<AsyncRequestSerial, NotSupportedError> {
73 self.window.request_activation_token()
74 }
75}
76
77impl 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.
88pub 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.
96pub 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