diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2025-04-25 09:48:54 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-04-25 02:00:18 -0700 |
| commit | 59de6918b3c7f3bc8e988046b3fef2cead322f9a (patch) | |
| tree | 5927c18cfe0486e0582a31cf09f0f244fe4708a2 /src/input | |
| parent | bd3d55438993a898f94500bea194377fb93004f3 (diff) | |
| download | niri-59de6918b3c7f3bc8e988046b3fef2cead322f9a.tar.gz niri-59de6918b3c7f3bc8e988046b3fef2cead322f9a.tar.bz2 niri-59de6918b3c7f3bc8e988046b3fef2cead322f9a.zip | |
overview: Add two-finger touchpad scroll
Diffstat (limited to 'src/input')
| -rw-r--r-- | src/input/mod.rs | 104 | ||||
| -rw-r--r-- | src/input/scroll_swipe_gesture.rs | 69 |
2 files changed, 171 insertions, 2 deletions
diff --git a/src/input/mod.rs b/src/input/mod.rs index 71cc5781..44527b8a 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -51,6 +51,7 @@ pub mod move_grab; pub mod pick_color_grab; pub mod pick_window_grab; pub mod resize_grab; +pub mod scroll_swipe_gesture; pub mod scroll_tracker; pub mod spatial_movement_grab; pub mod swipe_tracker; @@ -2568,6 +2569,8 @@ impl State { self.niri.pointer_hidden = false; self.niri.tablet_cursor_location = None; + let timestamp = Duration::from_micros(event.time()); + let horizontal_amount_v120 = event.amount_v120(Axis::Horizontal); let vertical_amount_v120 = event.amount_v120(Axis::Vertical); @@ -2751,8 +2754,106 @@ impl State { if source == AxisSource::Finger { let mods = self.niri.seat.get_keyboard().unwrap().modifier_state(); let modifiers = modifiers_from_state(mods); + + let horizontal = horizontal_amount.unwrap_or(0.); + let vertical = vertical_amount.unwrap_or(0.); + + if should_handle_in_overview && modifiers.is_empty() { + let mut redraw = false; + + let action = self + .niri + .overview_scroll_swipe_gesture + .update(horizontal, vertical); + let is_vertical = self.niri.overview_scroll_swipe_gesture.is_vertical(); + + if action.end() { + if is_vertical { + redraw |= self + .niri + .layout + .workspace_switch_gesture_end(Some(true)) + .is_some(); + } else { + redraw |= self + .niri + .layout + .view_offset_gesture_end(Some(true)) + .is_some(); + } + } else { + // Maybe begin, then update. + if is_vertical { + if action.begin() { + if let Some(output) = self.niri.output_under_cursor() { + self.niri + .layout + .workspace_switch_gesture_begin(&output, true); + redraw = true; + } + } + + let res = self + .niri + .layout + .workspace_switch_gesture_update(vertical, timestamp, true); + if let Some(Some(_)) = res { + redraw = true; + } + } else { + if action.begin() { + if let Some((output, ws)) = self.niri.workspace_under_cursor(true) { + let ws_id = ws.id(); + let ws_idx = + self.niri.layout.find_workspace_by_id(ws_id).unwrap().0; + + self.niri.layout.view_offset_gesture_begin( + &output, + Some(ws_idx), + true, + ); + redraw = true; + } + } + + let res = self + .niri + .layout + .view_offset_gesture_update(horizontal, timestamp, true); + if let Some(Some(_)) = res { + redraw = true; + } + } + } + + if redraw { + self.niri.queue_redraw_all(); + } + + return; + } else { + let mut redraw = false; + if self.niri.overview_scroll_swipe_gesture.reset() { + if self.niri.overview_scroll_swipe_gesture.is_vertical() { + redraw |= self + .niri + .layout + .workspace_switch_gesture_end(Some(true)) + .is_some(); + } else { + redraw |= self + .niri + .layout + .view_offset_gesture_end(Some(true)) + .is_some(); + } + } + if redraw { + self.niri.queue_redraw_all(); + } + } + if self.niri.mods_with_finger_scroll_binds.contains(&modifiers) { - let horizontal = horizontal_amount.unwrap_or(0.); let ticks = self .niri .horizontal_finger_scroll_tracker @@ -2778,7 +2879,6 @@ impl State { } } - let vertical = vertical_amount.unwrap_or(0.); let ticks = self .niri .vertical_finger_scroll_tracker diff --git a/src/input/scroll_swipe_gesture.rs b/src/input/scroll_swipe_gesture.rs new file mode 100644 index 00000000..c15ace23 --- /dev/null +++ b/src/input/scroll_swipe_gesture.rs @@ -0,0 +1,69 @@ +//! Swipe gesture from scroll events. +//! +//! Tracks when to begin, update, and end a swipe gesture from pointer axis events, also whether +//! the gesture is vertical or horizontal. Necessary because libinput only provides touchpad swipe +//! gesture events for 3+ fingers. + +#[derive(Debug)] +pub struct ScrollSwipeGesture { + ongoing: bool, + vertical: bool, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Action { + BeginUpdate, + Update, + End, +} + +impl ScrollSwipeGesture { + pub const fn new() -> Self { + Self { + ongoing: false, + vertical: false, + } + } + + pub fn update(&mut self, dx: f64, dy: f64) -> Action { + if dx == 0. && dy == 0. { + self.ongoing = false; + Action::End + } else if !self.ongoing { + self.ongoing = true; + self.vertical = dy != 0.; + Action::BeginUpdate + } else { + Action::Update + } + } + + pub fn reset(&mut self) -> bool { + if self.ongoing { + self.ongoing = false; + true + } else { + false + } + } + + pub fn is_vertical(&self) -> bool { + self.vertical + } +} + +impl Default for ScrollSwipeGesture { + fn default() -> Self { + Self::new() + } +} + +impl Action { + pub fn begin(self) -> bool { + self == Action::BeginUpdate + } + + pub fn end(self) -> bool { + self == Action::End + } +} |
