diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-10-06 20:27:04 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-10-06 22:09:19 -0700 |
| commit | 6fb60dacd2f6743b13ee955234f025015dbe5f87 (patch) | |
| tree | 4b214e1e6a7fe62be9592ef0c142e59acc24c1b9 | |
| parent | 42a9daec9db57e16541b6ef236b695b71bfb1199 (diff) | |
| download | niri-6fb60dacd2f6743b13ee955234f025015dbe5f87.tar.gz niri-6fb60dacd2f6743b13ee955234f025015dbe5f87.tar.bz2 niri-6fb60dacd2f6743b13ee955234f025015dbe5f87.zip | |
Rework pointer inactivity hide as a timer
The previous way was prone to triggering late due to compositor idling
and therefore never calling the check function.
| -rw-r--r-- | src/input/mod.rs | 8 | ||||
| -rw-r--r-- | src/niri.rs | 67 |
2 files changed, 48 insertions, 27 deletions
diff --git a/src/input/mod.rs b/src/input/mod.rs index 440fcb36..7c43c896 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -2,7 +2,7 @@ use std::any::Any; use std::cmp::min; use std::collections::hash_map::Entry; use std::collections::HashSet; -use std::time::{Duration, Instant}; +use std::time::Duration; use calloop::timer::{TimeoutAction, Timer}; use input::event::gesture::GestureEventCoordinates as _; @@ -87,8 +87,8 @@ impl State { } } - if should_update_cursor_timeout(&event) { - self.niri.last_cursor_movement = Instant::now(); + if should_reset_pointer_inactivity_timer(&event) { + self.niri.reset_pointer_inactivity_timer(); } let hide_hotkey_overlay = @@ -2561,7 +2561,7 @@ fn should_notify_activity<I: InputBackend>(event: &InputEvent<I>) -> bool { ) } -fn should_update_cursor_timeout<I: InputBackend>(event: &InputEvent<I>) -> bool { +fn should_reset_pointer_inactivity_timer<I: InputBackend>(event: &InputEvent<I>) -> bool { matches!( event, InputEvent::PointerAxis { .. } diff --git a/src/niri.rs b/src/niri.rs index 6119c4d6..7c3052ec 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -267,7 +267,7 @@ pub struct Niri { /// When this happens, the pointer also loses any focus. This is so that touch can prevent /// various tooltips from sticking around. pub pointer_hidden: bool, - pub last_cursor_movement: Instant, + pub pointer_inactivity_timer: Option<RegistrationToken>, // FIXME: this should be able to be removed once PointerFocus takes grabs into account. pub pointer_grab_ongoing: bool, pub tablet_cursor_location: Option<Point<f64, Logical>>, @@ -589,6 +589,7 @@ impl State { // We moved the pointer, show it. self.niri.pointer_hidden = false; + self.niri.reset_pointer_inactivity_timer(); // FIXME: granular self.niri.queue_redraw_all(); @@ -991,6 +992,7 @@ impl State { let mut window_rules_changed = false; let mut debug_config_changed = false; let mut shaders_changed = false; + let mut cursor_inactivity_timeout_changed = false; let mut old_config = self.niri.config.borrow_mut(); // Reload the cursor. @@ -1077,6 +1079,10 @@ impl State { shaders_changed = true; } + if config.cursor.hide_after_inactive_ms != old_config.cursor.hide_after_inactive_ms { + cursor_inactivity_timeout_changed = true; + } + if config.debug != old_config.debug { debug_config_changed = true; } @@ -1123,6 +1129,10 @@ impl State { self.niri.layout.update_shaders(); } + if cursor_inactivity_timeout_changed { + self.niri.reset_pointer_inactivity_timer(); + } + // Can't really update xdg-decoration settings since we have to hide the globals for CSD // due to the SDL2 bug... I don't imagine clients are prepared for the xdg-decoration // global suddenly appearing? Either way, right now it's live-reloaded in a sense that new @@ -1784,7 +1794,7 @@ impl Niri { .unwrap(); drop(config_); - Self { + let mut niri = Self { config, config_file_output_config, @@ -1861,7 +1871,7 @@ impl Niri { dnd_icon: None, pointer_focus: PointerFocus::default(), pointer_hidden: false, - last_cursor_movement: Instant::now(), + pointer_inactivity_timer: None, pointer_grab_ongoing: false, tablet_cursor_location: None, gesture_swipe_3f_cumulative: None, @@ -1897,7 +1907,11 @@ impl Niri { #[cfg(feature = "xdp-gnome-screencast")] mapped_cast_output: HashMap::new(), - } + }; + + niri.reset_pointer_inactivity_timer(); + + niri } #[cfg(feature = "dbus")] @@ -2665,26 +2679,7 @@ impl Niri { pointer_elements } - fn hide_cursor_after_timeout_if_needed(&mut self) { - if self.pointer_hidden { - return; - } - - let config = self.config.borrow(); - let timeout = &config.cursor.hide_after_inactive_ms; - - if let Some(duration_ms) = timeout { - let timeout = Duration::from_millis(*duration_ms as u64); - - if self.last_cursor_movement.elapsed() >= timeout { - self.pointer_hidden = true; - } - } - } - pub fn refresh_pointer_outputs(&mut self) { - self.hide_cursor_after_timeout_if_needed(); - if self.pointer_hidden { return; } @@ -4728,6 +4723,32 @@ impl Niri { self.queue_redraw_all(); } } + + pub fn reset_pointer_inactivity_timer(&mut self) { + let _span = tracy_client::span!("Niri::reset_pointer_inactivity_timer"); + + if let Some(token) = self.pointer_inactivity_timer.take() { + self.event_loop.remove(token); + } + + let Some(timeout_ms) = self.config.borrow().cursor.hide_after_inactive_ms else { + return; + }; + + let duration = Duration::from_millis(timeout_ms as u64); + let timer = Timer::from_duration(duration); + let token = self + .event_loop + .insert_source(timer, move |_, _, state| { + state.niri.pointer_inactivity_timer = None; + state.niri.pointer_hidden = true; + state.niri.queue_redraw_all(); + + TimeoutAction::Drop + }) + .unwrap(); + self.pointer_inactivity_timer = Some(token); + } } pub struct ClientState { |
