diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/handlers/mod.rs | 4 | ||||
| -rw-r--r-- | src/input/mod.rs | 24 | ||||
| -rw-r--r-- | src/niri.rs | 48 |
3 files changed, 49 insertions, 27 deletions
diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index d9b029c5..f2613d19 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -211,7 +211,7 @@ impl PointerConstraintsHandler for State { pointer.set_location(target); // Redraw to update the cursor position if it's visible. - if !self.niri.pointer_hidden { + if self.niri.pointer_visibility.is_visible() { // FIXME: redraw only outputs overlapping the cursor. self.niri.queue_redraw_all(); } @@ -369,7 +369,7 @@ impl ClientDndGrabHandler for State { // parameters from Smithay I guess. // // Assume that hidden pointer means touch DnD. - if !self.niri.pointer_hidden { + if self.niri.pointer_visibility.is_visible() { // We can't even get the current pointer location because it's locked (we're deep // in the grab call stack here). So use the last known one. if let Some(output) = &self.niri.pointer_contents.output { diff --git a/src/input/mod.rs b/src/input/mod.rs index e7c2e38f..b5213351 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -42,7 +42,7 @@ use self::resize_grab::ResizeGrab; use self::spatial_movement_grab::SpatialMovementGrab; use crate::layout::scrolling::ScrollDirection; use crate::layout::{ActivateWindow, LayoutElement as _}; -use crate::niri::{CastTarget, State}; +use crate::niri::{CastTarget, PointerVisibility, State}; use crate::ui::screenshot_ui::ScreenshotUi; use crate::utils::spawning::spawn; use crate::utils::{center, get_monotonic_time, ResizeEdge}; @@ -477,13 +477,13 @@ impl State { } // niri keeps this set only while actively using a tablet, which means the cursor position - // is likely to change almost immediately, causing pointer_hidden to just flicker back and - // forth. + // is likely to change almost immediately, causing pointer_visibility to just flicker back + // and forth. if self.niri.tablet_cursor_location.is_some() { return; } - self.niri.pointer_hidden = true; + self.niri.pointer_visibility = PointerVisibility::Hidden; self.niri.queue_redraw_all(); } @@ -2014,7 +2014,7 @@ impl State { let mut new_pos = pos + event.delta(); // We received an event for the regular pointer, so show it now. - self.niri.pointer_hidden = false; + self.niri.pointer_visibility = PointerVisibility::Visible; self.niri.tablet_cursor_location = None; // Check if we have an active pointer constraint. @@ -2283,7 +2283,7 @@ impl State { self.niri.maybe_activate_pointer_constraint(); // We moved the pointer, show it. - self.niri.pointer_hidden = false; + self.niri.pointer_visibility = PointerVisibility::Visible; // We moved the regular pointer, so show it now. self.niri.tablet_cursor_location = None; @@ -2348,7 +2348,7 @@ impl State { } // We received an event for the regular pointer, so show it now. - self.niri.pointer_hidden = false; + self.niri.pointer_visibility = PointerVisibility::Visible; self.niri.tablet_cursor_location = None; let is_overview_open = self.niri.layout.is_overview_open(); @@ -2608,7 +2608,7 @@ impl State { // We received an event for the regular pointer, so show it now. This is also needed for // update_pointer_contents() below to return the real contents, necessary for the pointer // axis event to reach the window. - self.niri.pointer_hidden = false; + self.niri.pointer_visibility = PointerVisibility::Visible; self.niri.tablet_cursor_location = None; let timestamp = Duration::from_micros(event.time()); @@ -3053,7 +3053,7 @@ impl State { event.time_msec(), ); - self.niri.pointer_hidden = false; + self.niri.pointer_visibility = PointerVisibility::Visible; self.niri.tablet_cursor_location = Some(pos); } @@ -3145,7 +3145,7 @@ impl State { event.time_msec(), ); } - self.niri.pointer_hidden = false; + self.niri.pointer_visibility = PointerVisibility::Visible; self.niri.tablet_cursor_location = Some(pos); } ProximityState::Out => { @@ -3159,7 +3159,7 @@ impl State { self.move_cursor(pos); } - self.niri.pointer_hidden = false; + self.niri.pointer_visibility = PointerVisibility::Visible; self.niri.tablet_cursor_location = None; } } @@ -3591,7 +3591,7 @@ impl State { ); // We're using touch, hide the pointer. - self.niri.pointer_hidden = true; + self.niri.pointer_visibility = PointerVisibility::Disabled; } fn on_touch_up<I: InputBackend>(&mut self, evt: I::TouchUpEvent) { let Some(handle) = self.niri.seat.get_touch() else { diff --git a/src/niri.rs b/src/niri.rs index f33bb74d..28fac293 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -331,11 +331,7 @@ pub struct Niri { /// taking grabs into account is expected, because we pass the information to pointer.motion() /// which passes it down through grabs, which decide what to do with it as they see fit. pub pointer_contents: PointContents, - /// Whether the pointer is hidden, for example due to a previous touch input. - /// - /// 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 pointer_visibility: PointerVisibility, pub pointer_inactivity_timer: Option<RegistrationToken>, /// Whether the pointer inactivity timer got reset this event loop iteration. /// @@ -395,6 +391,28 @@ pub struct Niri { pub dynamic_cast_id_for_portal: MappedId, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum PointerVisibility { + /// The pointer is visible. + Visible, + /// The pointer is invisible, but retains its focus. + /// + /// This state is set temporarily after auto-hiding the pointer to keep tooltips open and grabs + /// ongoing. + Hidden, + /// The pointer is invisible and cannot focus. + /// + /// Corresponds to a fully disabled pointer, for example after a touchscreen input, or after + /// the pointer contents changed in a Hidden state. + Disabled, +} + +impl PointerVisibility { + pub fn is_visible(&self) -> bool { + matches!(self, Self::Visible) + } +} + #[derive(Debug)] pub struct DndIcon { pub surface: WlSurface, @@ -911,10 +929,9 @@ impl State { let pointer = &self.niri.seat.get_pointer().unwrap(); let location = pointer.current_location(); - let under = if self.niri.pointer_hidden { - PointContents::default() - } else { - self.niri.contents_under(location) + let under = match self.niri.pointer_visibility { + PointerVisibility::Disabled => PointContents::default(), + _ => self.niri.contents_under(location), }; // We're not changing the global cursor location here, so if the contents did not change, @@ -923,6 +940,11 @@ impl State { return false; } + // Disable the hidden pointer if the contents underneath have changed. + if !self.niri.pointer_visibility.is_visible() { + self.niri.pointer_visibility = PointerVisibility::Disabled; + } + self.niri.pointer_contents.clone_from(&under); pointer.motion( @@ -2424,7 +2446,7 @@ impl Niri { cursor_shape_manager_state, dnd_icon: None, pointer_contents: PointContents::default(), - pointer_hidden: false, + pointer_visibility: PointerVisibility::Visible, pointer_inactivity_timer: None, pointer_inactivity_timer_got_reset: false, notified_activity_this_iteration: false, @@ -3420,7 +3442,7 @@ impl Niri { renderer: &mut R, output: &Output, ) -> Vec<OutputRenderElements<R>> { - if self.pointer_hidden { + if !self.pointer_visibility.is_visible() { return vec![]; } @@ -3507,7 +3529,7 @@ impl Niri { } pub fn refresh_pointer_outputs(&mut self) { - if self.pointer_hidden { + if !self.pointer_visibility.is_visible() { return; } @@ -5850,7 +5872,7 @@ impl Niri { .event_loop .insert_source(timer, move |_, _, state| { state.niri.pointer_inactivity_timer = None; - state.niri.pointer_hidden = true; + state.niri.pointer_visibility = PointerVisibility::Hidden; state.niri.queue_redraw_all(); TimeoutAction::Drop |
