1- use std:: sync:: Arc ;
2- use std:: sync:: atomic:: { AtomicBool , Ordering } ;
3- use std:: time:: { Duration , Instant } ;
1+ use std:: time:: Duration ;
42
53use user_idle:: UserIdle ;
64
@@ -13,21 +11,28 @@ pub(crate) enum IdleState {
1311/// Provider that monitors user idle state across Wayland (ext-idle-notify-v1),
1412/// DBus (GNOME / KDE), X11, and OS-native APIs.
1513pub ( crate ) struct IdleMonitor {
16- wayland : Option < WaylandIdleTracker > ,
14+ #[ cfg( target_os = "linux" ) ]
15+ wayland : Option < wayland:: WaylandIdleTracker > ,
1716}
1817
1918impl IdleMonitor {
20- pub ( crate ) fn new ( threshold : Duration ) -> Self {
21- let wayland = WaylandIdleTracker :: start ( threshold) ;
22- Self { wayland }
19+ pub ( crate ) fn new ( _threshold : Duration ) -> Self {
20+ #[ cfg( target_os = "linux" ) ]
21+ let wayland = wayland:: WaylandIdleTracker :: start ( _threshold) ;
22+ Self {
23+ #[ cfg( target_os = "linux" ) ]
24+ wayland,
25+ }
2326 }
2427
2528 /// Checks the current idle state. Returns `IdleState::Idle(elapsed)` if the user
2629 /// has been idle for at least the threshold, or `IdleState::Active` otherwise.
30+ #[ allow( clippy:: needless_pass_by_ref_mut) ]
2731 pub ( crate ) fn check_idle ( & mut self , threshold : Duration ) -> IdleState {
2832 if threshold == Duration :: ZERO {
2933 return IdleState :: Idle ( Duration :: ZERO ) ;
3034 }
35+ #[ cfg( target_os = "linux" ) ]
3136 if let Some ( wayland) = & mut self . wayland {
3237 if let Some ( state) = wayland. get_state ( threshold) {
3338 return state;
@@ -78,161 +83,170 @@ fn get_gnome_mutter_idle() -> Result<Duration, ()> {
7883// Wayland ext-idle-notify-v1 implementation
7984// ---------------------------------------------------------------------------
8085
81- use wayland_client:: protocol:: wl_registry;
82- use wayland_client:: protocol:: wl_seat:: WlSeat ;
83- use wayland_client:: { Connection , Dispatch , EventQueue , QueueHandle } ;
84- use wayland_protocols:: ext:: idle_notify:: v1:: client:: ext_idle_notification_v1:: {
85- self , ExtIdleNotificationV1 ,
86- } ;
87- use wayland_protocols:: ext:: idle_notify:: v1:: client:: ext_idle_notifier_v1:: ExtIdleNotifierV1 ;
88-
89- struct WaylandState {
90- seat : Option < WlSeat > ,
91- notifier : Option < ExtIdleNotifierV1 > ,
92- notification : Option < ExtIdleNotificationV1 > ,
93- is_idle : Arc < AtomicBool > ,
94- idle_since : Arc < parking_lot:: Mutex < Option < Instant > > > ,
95- }
86+ #[ cfg( target_os = "linux" ) ]
87+ mod wayland {
88+ use std:: sync:: Arc ;
89+ use std:: sync:: atomic:: { AtomicBool , Ordering } ;
90+ use std:: time:: { Duration , Instant } ;
91+
92+ use wayland_client:: protocol:: wl_registry;
93+ use wayland_client:: protocol:: wl_seat:: WlSeat ;
94+ use wayland_client:: { Connection , Dispatch , EventQueue , QueueHandle } ;
95+ use wayland_protocols:: ext:: idle_notify:: v1:: client:: ext_idle_notification_v1:: {
96+ self , ExtIdleNotificationV1 ,
97+ } ;
98+ use wayland_protocols:: ext:: idle_notify:: v1:: client:: ext_idle_notifier_v1:: ExtIdleNotifierV1 ;
99+
100+ use super :: IdleState ;
101+
102+ struct WaylandState {
103+ seat : Option < WlSeat > ,
104+ notifier : Option < ExtIdleNotifierV1 > ,
105+ notification : Option < ExtIdleNotificationV1 > ,
106+ is_idle : Arc < AtomicBool > ,
107+ idle_since : Arc < parking_lot:: Mutex < Option < Instant > > > ,
108+ }
96109
97- struct WaylandIdleTracker {
98- conn : Connection ,
99- event_queue : EventQueue < WaylandState > ,
100- state : WaylandState ,
101- }
110+ pub ( super ) struct WaylandIdleTracker {
111+ conn : Connection ,
112+ event_queue : EventQueue < WaylandState > ,
113+ state : WaylandState ,
114+ }
102115
103- impl WaylandIdleTracker {
104- fn start ( threshold : Duration ) -> Option < Self > {
105- if std:: env:: var_os ( "WAYLAND_DISPLAY" ) . is_none ( )
106- && std:: env:: var_os ( "WAYLAND_SOCKET" ) . is_none ( )
107- {
108- return None ;
109- }
116+ impl WaylandIdleTracker {
117+ pub ( super ) fn start ( threshold : Duration ) -> Option < Self > {
118+ if std:: env:: var_os ( "WAYLAND_DISPLAY" ) . is_none ( )
119+ && std:: env:: var_os ( "WAYLAND_SOCKET" ) . is_none ( )
120+ {
121+ return None ;
122+ }
110123
111- let conn = Connection :: connect_to_env ( ) . ok ( ) ?;
112- let display = conn. display ( ) ;
113- let mut event_queue = conn. new_event_queue ( ) ;
114- let qh = event_queue. handle ( ) ;
124+ let conn = Connection :: connect_to_env ( ) . ok ( ) ?;
125+ let display = conn. display ( ) ;
126+ let mut event_queue = conn. new_event_queue ( ) ;
127+ let qh = event_queue. handle ( ) ;
115128
116- let is_idle = Arc :: new ( AtomicBool :: new ( false ) ) ;
117- let idle_since = Arc :: new ( parking_lot:: Mutex :: new ( None ) ) ;
129+ let is_idle = Arc :: new ( AtomicBool :: new ( false ) ) ;
130+ let idle_since = Arc :: new ( parking_lot:: Mutex :: new ( None ) ) ;
118131
119- let mut state = WaylandState {
120- seat : None ,
121- notifier : None ,
122- notification : None ,
123- is_idle : is_idle. clone ( ) ,
124- idle_since : idle_since. clone ( ) ,
125- } ;
132+ let mut state = WaylandState {
133+ seat : None ,
134+ notifier : None ,
135+ notification : None ,
136+ is_idle : is_idle. clone ( ) ,
137+ idle_since : idle_since. clone ( ) ,
138+ } ;
126139
127- let _registry = display. get_registry ( & qh, ( ) ) ;
140+ let _registry = display. get_registry ( & qh, ( ) ) ;
128141
129- // Initial roundtrip to get registry globals
130- event_queue. roundtrip ( & mut state) . ok ( ) ?;
142+ // Initial roundtrip to get registry globals
143+ event_queue. roundtrip ( & mut state) . ok ( ) ?;
131144
132- let seat = state. seat . as_ref ( ) ?;
133- let notifier = state. notifier . as_ref ( ) ?;
145+ let seat = state. seat . as_ref ( ) ?;
146+ let notifier = state. notifier . as_ref ( ) ?;
134147
135- let timeout_ms = threshold. as_millis ( ) . max ( 1 ) . min ( u32:: MAX as u128 ) as u32 ;
136- let notification = notifier. get_idle_notification ( timeout_ms, seat, & qh, ( ) ) ;
137- state. notification = Some ( notification) ;
148+ let timeout_ms = threshold. as_millis ( ) . max ( 1 ) . min ( u32:: MAX as u128 ) as u32 ;
149+ let notification = notifier. get_idle_notification ( timeout_ms, seat, & qh, ( ) ) ;
150+ state. notification = Some ( notification) ;
138151
139- let _ = conn. flush ( ) ;
152+ let _ = conn. flush ( ) ;
140153
141- Some ( Self {
142- conn,
143- event_queue,
144- state,
145- } )
146- }
154+ Some ( Self {
155+ conn,
156+ event_queue,
157+ state,
158+ } )
159+ }
147160
148- fn get_state ( & mut self , threshold : Duration ) -> Option < IdleState > {
149- // Dispatch pending wayland events non-blockingly
150- let _ = self . event_queue . dispatch_pending ( & mut self . state ) ;
151- let _ = self . conn . flush ( ) ;
152-
153- let is_idle = self . state . is_idle . load ( Ordering :: Acquire ) ;
154- if is_idle {
155- let mut guard = self . state . idle_since . lock ( ) ;
156- let start = * guard. get_or_insert_with ( Instant :: now) ;
157- let elapsed = threshold + start. elapsed ( ) ;
158- Some ( IdleState :: Idle ( elapsed) )
159- } else {
160- * self . state . idle_since . lock ( ) = None ;
161- Some ( IdleState :: Active )
161+ pub ( super ) fn get_state ( & mut self , threshold : Duration ) -> Option < IdleState > {
162+ // Dispatch pending wayland events non-blockingly
163+ let _ = self . event_queue . dispatch_pending ( & mut self . state ) ;
164+ let _ = self . conn . flush ( ) ;
165+
166+ let is_idle = self . state . is_idle . load ( Ordering :: Acquire ) ;
167+ if is_idle {
168+ let mut guard = self . state . idle_since . lock ( ) ;
169+ let start = * guard. get_or_insert_with ( Instant :: now) ;
170+ let elapsed = threshold + start. elapsed ( ) ;
171+ Some ( IdleState :: Idle ( elapsed) )
172+ } else {
173+ * self . state . idle_since . lock ( ) = None ;
174+ Some ( IdleState :: Active )
175+ }
162176 }
163177 }
164- }
165178
166- impl Dispatch < wl_registry:: WlRegistry , ( ) > for WaylandState {
167- fn event (
168- state : & mut Self ,
169- registry : & wl_registry:: WlRegistry ,
170- event : wl_registry:: Event ,
171- _: & ( ) ,
172- _: & Connection ,
173- qh : & QueueHandle < Self > ,
174- ) {
175- if let wl_registry:: Event :: Global {
176- name,
177- interface,
178- version,
179- } = event
180- {
181- if interface == "wl_seat" && state. seat . is_none ( ) {
182- state. seat = Some ( registry. bind ( name, version. min ( 1 ) , qh, ( ) ) ) ;
183- } else if interface == "ext_idle_notifier_v1" && state. notifier . is_none ( ) {
184- state. notifier = Some ( registry. bind ( name, version. min ( 1 ) , qh, ( ) ) ) ;
179+ impl Dispatch < wl_registry:: WlRegistry , ( ) > for WaylandState {
180+ fn event (
181+ state : & mut Self ,
182+ registry : & wl_registry:: WlRegistry ,
183+ event : wl_registry:: Event ,
184+ _: & ( ) ,
185+ _: & Connection ,
186+ qh : & QueueHandle < Self > ,
187+ ) {
188+ if let wl_registry:: Event :: Global {
189+ name,
190+ interface,
191+ version,
192+ } = event
193+ {
194+ if interface == "wl_seat" && state. seat . is_none ( ) {
195+ state. seat = Some ( registry. bind ( name, version. min ( 1 ) , qh, ( ) ) ) ;
196+ } else if interface == "ext_idle_notifier_v1" && state. notifier . is_none ( ) {
197+ state. notifier = Some ( registry. bind ( name, version. min ( 1 ) , qh, ( ) ) ) ;
198+ }
185199 }
186200 }
187201 }
188- }
189202
190- impl Dispatch < WlSeat , ( ) > for WaylandState {
191- fn event (
192- _: & mut Self ,
193- _: & WlSeat ,
194- _: wayland_client:: protocol:: wl_seat:: Event ,
195- _: & ( ) ,
196- _: & Connection ,
197- _: & QueueHandle < Self > ,
198- ) {
203+ impl Dispatch < WlSeat , ( ) > for WaylandState {
204+ fn event (
205+ _: & mut Self ,
206+ _: & WlSeat ,
207+ _: wayland_client:: protocol:: wl_seat:: Event ,
208+ _: & ( ) ,
209+ _: & Connection ,
210+ _: & QueueHandle < Self > ,
211+ ) {
212+ }
199213 }
200- }
201214
202- impl Dispatch < ExtIdleNotifierV1 , ( ) > for WaylandState {
203- fn event (
204- _: & mut Self ,
205- _: & ExtIdleNotifierV1 ,
206- _: wayland_protocols:: ext:: idle_notify:: v1:: client:: ext_idle_notifier_v1:: Event ,
207- _: & ( ) ,
208- _: & Connection ,
209- _: & QueueHandle < Self > ,
210- ) {
215+ impl Dispatch < ExtIdleNotifierV1 , ( ) > for WaylandState {
216+ fn event (
217+ _: & mut Self ,
218+ _: & ExtIdleNotifierV1 ,
219+ _: wayland_protocols:: ext:: idle_notify:: v1:: client:: ext_idle_notifier_v1:: Event ,
220+ _: & ( ) ,
221+ _: & Connection ,
222+ _: & QueueHandle < Self > ,
223+ ) {
224+ }
211225 }
212- }
213226
214- impl Dispatch < ExtIdleNotificationV1 , ( ) > for WaylandState {
215- fn event (
216- state : & mut Self ,
217- _: & ExtIdleNotificationV1 ,
218- event : ext_idle_notification_v1:: Event ,
219- _: & ( ) ,
220- _: & Connection ,
221- _: & QueueHandle < Self > ,
222- ) {
223- match event {
224- ext_idle_notification_v1:: Event :: Idled => {
225- state. is_idle . store ( true , Ordering :: Release ) ;
226- let mut guard = state. idle_since . lock ( ) ;
227- if guard. is_none ( ) {
228- * guard = Some ( Instant :: now ( ) ) ;
227+ impl Dispatch < ExtIdleNotificationV1 , ( ) > for WaylandState {
228+ fn event (
229+ state : & mut Self ,
230+ _: & ExtIdleNotificationV1 ,
231+ event : ext_idle_notification_v1:: Event ,
232+ _: & ( ) ,
233+ _: & Connection ,
234+ _: & QueueHandle < Self > ,
235+ ) {
236+ match event {
237+ ext_idle_notification_v1:: Event :: Idled => {
238+ state. is_idle . store ( true , Ordering :: Release ) ;
239+ let mut guard = state. idle_since . lock ( ) ;
240+ if guard. is_none ( ) {
241+ * guard = Some ( Instant :: now ( ) ) ;
242+ }
229243 }
244+ ext_idle_notification_v1:: Event :: Resumed => {
245+ state. is_idle . store ( false , Ordering :: Release ) ;
246+ * state. idle_since . lock ( ) = None ;
247+ }
248+ _ => { }
230249 }
231- ext_idle_notification_v1:: Event :: Resumed => {
232- state. is_idle . store ( false , Ordering :: Release ) ;
233- * state. idle_since . lock ( ) = None ;
234- }
235- _ => { }
236250 }
237251 }
238252}
0 commit comments