1#[cfg(feature = "gnome")]
2pub mod gnome;
3#[cfg(feature = "kde")]
4pub mod kde;
5#[cfg(feature = "wayland")]
6pub mod wayland_idle;
7#[cfg(feature = "wayland")]
8pub mod wayland_wlr;
9#[cfg(feature = "win")]
10pub mod win;
11#[cfg(feature = "wayland")]
12pub mod wl_connection;
13#[cfg(feature = "x11")]
14pub mod x11;
15
16pub mod idle;
17pub mod utils;
18
19#[cfg(feature = "win")]
20extern crate windows;
21
22use std::{sync::Arc, time::Duration};
26
27use anyhow::Result;
28use async_trait::async_trait;
29use tracing::info;
30
31#[derive(Debug, Clone)]
32pub struct ActiveWindowData {
33 pub window_title: Arc<str>,
36 pub app_identifier: Arc<str>,
41}
42
43#[cfg_attr(test, mockall::automock)]
45#[async_trait]
46pub trait WindowManager {
47 async fn get_active_window_data(&mut self) -> Result<ActiveWindowData>;
48
49 async fn is_idle(&mut self) -> Result<bool>;
51}
52
53pub struct GenericWindowManager {
55 inner: Box<dyn WindowManager + Send + Sync>,
56}
57
58impl GenericWindowManager {
59 pub async fn new(idle_timeout: Duration) -> Result<Self> {
60 #[cfg(feature = "win")]
61 {
62 use win::WindowsWindowManager;
63 return Ok(Self {
64 inner: Box::new(WindowsWindowManager::new(idle_timeout)),
65 });
66 }
67 #[cfg(feature = "gnome")]
69 {
70 use gnome::GnomeWindowWatcher;
71 let watcher = GnomeWindowWatcher::new(idle_timeout.into()).await;
72 match watcher {
73 Ok(watcher) => {
74 let result = Ok(Self {
75 inner: Box::new(watcher),
76 });
77 info!("Loaded Gnome Wayland watcher");
78 return result;
79 }
80 Err(e) => {
81 use tracing::warn;
82 warn!("Failed to load Gnome Wayland watcher: {e}");
83 }
84 }
85 }
86 #[cfg(feature = "kde")]
87 {
88 use kde::KdeWindowManager;
89 let watcher = KdeWindowManager::new(idle_timeout).await;
90 match watcher {
91 Ok(watcher) => {
92 let result = Ok(Self {
93 inner: Box::new(watcher),
94 });
95 info!("Loaded Kde wayland watcher");
96 return result;
97 }
98 Err(e) => {
99 use tracing::warn;
100 warn!("Failed to load Gnome Wayland watcher: {e}");
101 }
102 }
103 }
104 #[cfg(feature = "wayland")]
105 {
106 use wayland_wlr::WaylandWindowWatcher;
107 let watcher = WaylandWindowWatcher::new(idle_timeout).await;
108 match watcher {
109 Ok(watcher) => {
110 let result = Ok(Self {
111 inner: Box::new(watcher),
112 });
113 info!("Loaded Wayland window watcher");
114 return result;
115 }
116 Err(e) => {
117 use tracing::warn;
118 warn!("Failed to load Wayland window watcher: {e}");
119 }
120 }
121 }
122 #[cfg(feature = "x11")]
123 {
124 use x11::LinuxWindowManager;
125 let watcher = LinuxWindowManager::new(idle_timeout);
126 match watcher {
127 Ok(watcher) => {
128 let result = Ok(Self {
129 inner: Box::new(watcher),
130 });
131 info!("Loaded X11 window manager");
132 return result;
133 }
134 Err(e) => {
135 use tracing::warn;
136 warn!("Failed to load X11 window manager: {e}");
137 }
138 }
139 }
140 #[allow(unreachable_code)]
141 {
142 Err(anyhow::anyhow!("No window manager was selected"))
143 }
144 }
145}
146
147#[async_trait]
148impl WindowManager for GenericWindowManager {
149 async fn get_active_window_data(&mut self) -> Result<ActiveWindowData> {
150 self.inner.get_active_window_data().await
151 }
152
153 async fn is_idle(&mut self) -> Result<bool> {
154 self.inner.is_idle().await
155 }
156}