Skip to content

Commit

Permalink
Rework pointer inactivity hide as a timer
Browse files Browse the repository at this point in the history
The previous way was prone to triggering late due to compositor idling
and therefore never calling the check function.
  • Loading branch information
YaLTeR committed Oct 7, 2024
1 parent 42a9dae commit 6fb60da
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 27 deletions.
8 changes: 4 additions & 4 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 _;
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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 { .. }
Expand Down
67 changes: 44 additions & 23 deletions src/niri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>,
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1784,7 +1794,7 @@ impl Niri {
.unwrap();

drop(config_);
Self {
let mut niri = Self {
config,
config_file_output_config,

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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")]
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 6fb60da

Please sign in to comment.