diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/input/mod.rs | 104 | ||||
| -rw-r--r-- | src/input/scroll_swipe_gesture.rs | 69 | ||||
| -rw-r--r-- | src/niri.rs | 3 |
3 files changed, 174 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 + } +} diff --git a/src/niri.rs b/src/niri.rs index 3ba1b9a4..225a3702 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -124,6 +124,7 @@ use crate::dbus::mutter_screen_cast::{self, ScreenCastToNiri}; use crate::frame_clock::FrameClock; use crate::handlers::{configure_lock_surface, XDG_ACTIVATION_TOKEN_TIMEOUT}; use crate::input::pick_color_grab::PickColorGrab; +use crate::input::scroll_swipe_gesture::ScrollSwipeGesture; use crate::input::scroll_tracker::ScrollTracker; use crate::input::{ apply_libinput_settings, mods_with_finger_scroll_binds, mods_with_mouse_binds, @@ -348,6 +349,7 @@ pub struct Niri { pub notified_activity_this_iteration: bool, pub tablet_cursor_location: Option<Point<f64, Logical>>, pub gesture_swipe_3f_cumulative: Option<(f64, f64)>, + pub overview_scroll_swipe_gesture: ScrollSwipeGesture, pub vertical_wheel_tracker: ScrollTracker, pub horizontal_wheel_tracker: ScrollTracker, pub mods_with_mouse_binds: HashSet<Modifiers>, @@ -2427,6 +2429,7 @@ impl Niri { notified_activity_this_iteration: false, tablet_cursor_location: None, gesture_swipe_3f_cumulative: None, + overview_scroll_swipe_gesture: ScrollSwipeGesture::new(), vertical_wheel_tracker: ScrollTracker::new(120), horizontal_wheel_tracker: ScrollTracker::new(120), mods_with_mouse_binds, |
