diff --git a/src/input/mod.rs b/src/input/mod.rs index 8eb657ad..2dd59c03 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -198,6 +198,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); let current_output = seat.active_output(); let shortcuts_inhibited = self .common @@ -512,6 +513,7 @@ impl State { let mut shell = self.common.shell.write().unwrap(); if let Some(seat) = shell.seats.for_device(&event.device()).cloned() { + self.common.idle_notifier_state.notify_activity(&seat); let current_output = seat.active_output(); let mut position = seat.get_pointer().unwrap().current_location().as_global(); @@ -718,6 +720,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); let output = seat.active_output(); let geometry = output.geometry(); let position = geometry.loc.to_f64() @@ -785,6 +788,7 @@ impl State { let mut shell = self.common.shell.write().unwrap(); if let Some(seat) = shell.seats.for_device(&event.device()).cloned() { + self.common.idle_notifier_state.notify_activity(&seat); #[cfg(feature = "debug")] if shell.seats.iter().position(|x| x == &seat).unwrap() == 0 && self.common.egui.active @@ -994,6 +998,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); #[cfg(feature = "debug")] if self .common @@ -1065,6 +1070,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); if event.fingers() >= 3 { self.common.gesture_state = Some(GestureState::new(event.fingers())); } else { @@ -1091,6 +1097,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); let mut activate_action: Option = None; if let Some(ref mut gesture_state) = self.common.gesture_state { let first_update = gesture_state.update( @@ -1180,6 +1187,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); if let Some(ref gesture_state) = self.common.gesture_state { match gesture_state.action { Some(SwipeAction::NextWorkspace) | Some(SwipeAction::PrevWorkspace) => { @@ -1225,6 +1233,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); let serial = SERIAL_COUNTER.next_serial(); let pointer = seat.get_pointer().unwrap(); pointer.gesture_pinch_begin( @@ -1247,6 +1256,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); let pointer = seat.get_pointer().unwrap(); pointer.gesture_pinch_update( self, @@ -1269,6 +1279,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); let serial = SERIAL_COUNTER.next_serial(); let pointer = seat.get_pointer().unwrap(); pointer.gesture_pinch_end( @@ -1291,6 +1302,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); let serial = SERIAL_COUNTER.next_serial(); let pointer = seat.get_pointer().unwrap(); pointer.gesture_hold_begin( @@ -1313,6 +1325,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); let serial = SERIAL_COUNTER.next_serial(); let pointer = seat.get_pointer().unwrap(); pointer.gesture_hold_end( @@ -1328,6 +1341,7 @@ impl State { InputEvent::TouchDown { event, .. } => { let mut shell = self.common.shell.write().unwrap(); if let Some(seat) = shell.seats.for_device(&event.device()).cloned() { + self.common.idle_notifier_state.notify_activity(&seat); let Some(output) = mapped_output_for_device(&self.common.config, &*shell, &event.device()) .cloned() @@ -1364,6 +1378,7 @@ impl State { InputEvent::TouchMotion { event, .. } => { let mut shell = self.common.shell.write().unwrap(); if let Some(seat) = shell.seats.for_device(&event.device()).cloned() { + self.common.idle_notifier_state.notify_activity(&seat); let Some(output) = mapped_output_for_device(&self.common.config, &*shell, &event.device()) .cloned() @@ -1405,6 +1420,7 @@ impl State { let maybe_seat = shell.seats.for_device(&event.device()).cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); std::mem::drop(shell); let serial = SERIAL_COUNTER.next_serial(); let touch = seat.get_touch().unwrap(); @@ -1428,6 +1444,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); let touch = seat.get_touch().unwrap(); touch.cancel(self); } @@ -1442,6 +1459,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); let touch = seat.get_touch().unwrap(); touch.frame(self); } @@ -1449,6 +1467,7 @@ impl State { InputEvent::TabletToolAxis { event, .. } => { let mut shell = self.common.shell.write().unwrap(); if let Some(seat) = shell.seats.for_device(&event.device()).cloned() { + self.common.idle_notifier_state.notify_activity(&seat); let Some(output) = mapped_output_for_device(&self.common.config, &shell, &event.device()) .cloned() @@ -1516,6 +1535,7 @@ impl State { InputEvent::TabletToolProximity { event, .. } => { let mut shell = self.common.shell.write().unwrap(); if let Some(seat) = shell.seats.for_device(&event.device()).cloned() { + self.common.idle_notifier_state.notify_activity(&seat); let Some(output) = mapped_output_for_device(&self.common.config, &shell, &event.device()) .cloned() @@ -1580,6 +1600,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); if let Some(tool) = seat.tablet_seat().get_tool(&event.tool()) { match event.tip_state() { TabletToolTipState::Down => { @@ -1602,6 +1623,7 @@ impl State { .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { + self.common.idle_notifier_state.notify_activity(&seat); if let Some(tool) = seat.tablet_seat().get_tool(&event.tool()) { tool.button( event.button(), diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 3abf5532..035de883 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -15,8 +15,8 @@ use keyframe::{ease, functions::EaseInOutCubic}; use smithay::{ backend::input::TouchSlot, desktop::{ - layer_map_for_output, space::SpaceElement, LayerSurface, PopupKind, WindowSurface, - WindowSurfaceType, + layer_map_for_output, space::SpaceElement, utils::surface_primary_scanout_output, + LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, }, input::{ pointer::{Focus, GrabStartData as PointerGrabStartData}, @@ -1105,6 +1105,18 @@ impl Common { ); self.popups.cleanup(); self.toplevel_info_state.refresh(&self.workspace_state); + self.refresh_idle_inhibit(); + } + + pub fn refresh_idle_inhibit(&mut self) { + self.idle_inhibiting_surfaces.retain(|s| s.alive()); + + let is_inhibited = self.idle_inhibiting_surfaces.iter().any(|surface| { + with_states(surface, |states| { + surface_primary_scanout_output(surface, states).is_some() + }) + }); + self.idle_notifier_state.set_is_inhibited(is_inhibited); } pub fn on_commit(&mut self, surface: &WlSurface) { diff --git a/src/state.rs b/src/state.rs index 8ed9a22f..471582b3 100644 --- a/src/state.rs +++ b/src/state.rs @@ -65,6 +65,8 @@ use smithay::{ compositor::{CompositorClientState, CompositorState}, dmabuf::{DmabufFeedback, DmabufGlobal, DmabufState}, fractional_scale::{with_fractional_scale, FractionalScaleManagerState}, + idle_inhibit::IdleInhibitManagerState, + idle_notify::IdleNotifierState, input_method::InputMethodManagerState, keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState, output::OutputManagerState, @@ -96,8 +98,11 @@ use smithay::{ use time::UtcOffset; use tracing::error; -use std::sync::{Arc, RwLock}; use std::{cell::RefCell, ffi::OsString, time::Duration}; +use std::{ + collections::HashSet, + sync::{Arc, RwLock}, +}; use std::{collections::VecDeque, time::Instant}; #[derive(RustEmbed)] @@ -188,6 +193,9 @@ pub struct Common { pub screencopy_state: ScreencopyState, pub seat_state: SeatState, pub session_lock_manager_state: SessionLockManagerState, + pub idle_notifier_state: IdleNotifierState, + pub idle_inhibit_manager_state: IdleInhibitManagerState, + pub idle_inhibiting_surfaces: HashSet, pub shm_state: ShmState, pub wl_drm_state: WlDrmState>, pub viewporter_state: ViewporterState, @@ -415,6 +423,10 @@ impl State { TextInputManagerState::new::(&dh); VirtualKeyboardManagerState::new::(&dh, client_should_see_privileged_protocols); + let idle_notifier_state = IdleNotifierState::::new(&dh, handle.clone()); + let idle_inhibit_manager_state = IdleInhibitManagerState::new::(&dh); + let idle_inhibiting_surfaces = HashSet::new(); + let data_control_state = config.static_conf.data_control_enabled.then(|| { DataControlState::new::(dh, Some(&primary_selection_state), |_| true) }); @@ -486,6 +498,9 @@ impl State { data_device_state, dmabuf_state, fractional_scale_state, + idle_notifier_state, + idle_inhibit_manager_state, + idle_inhibiting_surfaces, image_source_state, screencopy_state, shm_state, diff --git a/src/wayland/handlers/idle_inhibit.rs b/src/wayland/handlers/idle_inhibit.rs new file mode 100644 index 00000000..403b5d3e --- /dev/null +++ b/src/wayland/handlers/idle_inhibit.rs @@ -0,0 +1,19 @@ +use smithay::{ + delegate_idle_inhibit, reexports::wayland_server::protocol::wl_surface::WlSurface, + wayland::idle_inhibit::IdleInhibitHandler, +}; + +use crate::state::State; + +impl IdleInhibitHandler for State { + fn inhibit(&mut self, surface: WlSurface) { + self.common.idle_inhibiting_surfaces.insert(surface); + self.common.idle_notifier_state.set_is_inhibited(true); + } + + fn uninhibit(&mut self, surface: WlSurface) { + self.common.idle_inhibiting_surfaces.remove(&surface); + self.common.refresh_idle_inhibit(); + } +} +delegate_idle_inhibit!(State); diff --git a/src/wayland/handlers/idle_notify.rs b/src/wayland/handlers/idle_notify.rs new file mode 100644 index 00000000..f606f266 --- /dev/null +++ b/src/wayland/handlers/idle_notify.rs @@ -0,0 +1,12 @@ +use smithay::{delegate_idle_notify, wayland::idle_notify::IdleNotifierHandler}; + +use crate::state::State; + +impl IdleNotifierHandler for State { + fn idle_notifier_state( + &mut self, + ) -> &mut smithay::wayland::idle_notify::IdleNotifierState { + &mut self.common.idle_notifier_state + } +} +delegate_idle_notify!(State); diff --git a/src/wayland/handlers/mod.rs b/src/wayland/handlers/mod.rs index a5c02584..6b9c7c2d 100644 --- a/src/wayland/handlers/mod.rs +++ b/src/wayland/handlers/mod.rs @@ -9,6 +9,8 @@ pub mod dmabuf; pub mod drm; pub mod drm_lease; pub mod fractional_scale; +pub mod idle_inhibit; +pub mod idle_notify; pub mod image_source; pub mod input_method; pub mod keyboard_shortcuts_inhibit;