From a16a0f0e52d6df8abd602baa15cee44e0656d790 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Sat, 23 Mar 2024 20:23:21 +0400 Subject: Implement TouchpadScroll binds --- src/input.rs | 90 ++++++++++++++++++++++++++++++++++++++++++++++-- src/niri.rs | 16 ++++++++- src/ui/hotkey_overlay.rs | 6 ++++ 3 files changed, 109 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/input.rs b/src/input.rs index 850fb76a..a47f9151 100644 --- a/src/input.rs +++ b/src/input.rs @@ -1178,11 +1178,84 @@ impl State { } } - let horizontal_amount = event.amount(Axis::Horizontal).unwrap_or_else(|| { + let horizontal_amount = event.amount(Axis::Horizontal); + let vertical_amount = event.amount(Axis::Vertical); + + // Handle touchpad scroll bindings. + if source == AxisSource::Finger { + let mods = self.niri.seat.get_keyboard().unwrap().modifier_state(); + let modifiers = modifiers_from_state(mods); + if self.niri.mods_with_finger_scroll_binds.contains(&modifiers) { + let comp_mod = self.backend.mod_key(); + + let horizontal = horizontal_amount.unwrap_or(0.); + let ticks = self + .niri + .horizontal_finger_scroll_tracker + .accumulate(horizontal); + if ticks != 0 { + let config = self.niri.config.borrow(); + let bindings = &config.binds; + let bind_left = + find_configured_bind(bindings, comp_mod, Trigger::TouchpadScrollLeft, mods); + let bind_right = find_configured_bind( + bindings, + comp_mod, + Trigger::TouchpadScrollRight, + mods, + ); + drop(config); + + if let Some(right) = bind_right { + for _ in 0..ticks { + self.handle_bind(right.clone()); + } + } + if let Some(left) = bind_left { + for _ in ticks..0 { + self.handle_bind(left.clone()); + } + } + } + + let vertical = vertical_amount.unwrap_or(0.); + let ticks = self + .niri + .vertical_finger_scroll_tracker + .accumulate(vertical); + if ticks != 0 { + let config = self.niri.config.borrow(); + let bindings = &config.binds; + let bind_up = + find_configured_bind(bindings, comp_mod, Trigger::TouchpadScrollUp, mods); + let bind_down = + find_configured_bind(bindings, comp_mod, Trigger::TouchpadScrollDown, mods); + drop(config); + + if let Some(down) = bind_down { + for _ in 0..ticks { + self.handle_bind(down.clone()); + } + } + if let Some(up) = bind_up { + for _ in ticks..0 { + self.handle_bind(up.clone()); + } + } + } + + return; + } else { + self.niri.horizontal_finger_scroll_tracker.reset(); + self.niri.vertical_finger_scroll_tracker.reset(); + } + } + + let horizontal_amount = horizontal_amount.unwrap_or_else(|| { // Winit backend, discrete scrolling. horizontal_amount_v120.unwrap_or(0.0) / 120. * 15. }); - let vertical_amount = event.amount(Axis::Vertical).unwrap_or_else(|| { + let vertical_amount = vertical_amount.unwrap_or_else(|| { // Winit backend, discrete scrolling. vertical_amount_v120.unwrap_or(0.0) / 120. * 15. }); @@ -2067,6 +2140,19 @@ pub fn mods_with_wheel_binds(comp_mod: CompositorMod, binds: &Binds) -> HashSet< ) } +pub fn mods_with_finger_scroll_binds(comp_mod: CompositorMod, binds: &Binds) -> HashSet { + mods_with_binds( + comp_mod, + binds, + &[ + Trigger::TouchpadScrollUp, + Trigger::TouchpadScrollDown, + Trigger::TouchpadScrollLeft, + Trigger::TouchpadScrollRight, + ], + ) +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/niri.rs b/src/niri.rs index e2b83930..363c2ae6 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -97,7 +97,9 @@ use crate::dbus::gnome_shell_screenshot::{NiriToScreenshot, ScreenshotToNiri}; use crate::dbus::mutter_screen_cast::{self, ScreenCastToNiri}; use crate::frame_clock::FrameClock; use crate::handlers::configure_lock_surface; -use crate::input::{apply_libinput_settings, mods_with_wheel_binds, TabletData}; +use crate::input::{ + apply_libinput_settings, mods_with_finger_scroll_binds, mods_with_wheel_binds, TabletData, +}; use crate::ipc::server::IpcServer; use crate::layout::{Layout, MonitorRenderElement}; use crate::protocols::foreign_toplevel::{self, ForeignToplevelManagerState}; @@ -209,6 +211,9 @@ pub struct Niri { pub vertical_wheel_tracker: ScrollTracker, pub horizontal_wheel_tracker: ScrollTracker, pub mods_with_wheel_binds: HashSet, + pub vertical_finger_scroll_tracker: ScrollTracker, + pub horizontal_finger_scroll_tracker: ScrollTracker, + pub mods_with_finger_scroll_binds: HashSet, pub lock_state: LockState, @@ -856,6 +861,8 @@ impl State { self.niri.hotkey_overlay.on_hotkey_config_updated(); self.niri.mods_with_wheel_binds = mods_with_wheel_binds(self.backend.mod_key(), &config.binds); + self.niri.mods_with_finger_scroll_binds = + mods_with_finger_scroll_binds(self.backend.mod_key(), &config.binds); } if config.window_rules != old_config.window_rules { @@ -1166,6 +1173,8 @@ impl Niri { CursorManager::new(&config_.cursor.xcursor_theme, config_.cursor.xcursor_size); let mods_with_wheel_binds = mods_with_wheel_binds(backend.mod_key(), &config_.binds); + let mods_with_finger_scroll_binds = + mods_with_finger_scroll_binds(backend.mod_key(), &config_.binds); let (tx, rx) = calloop::channel::channel(); event_loop @@ -1325,6 +1334,11 @@ impl Niri { horizontal_wheel_tracker: ScrollTracker::new(120), mods_with_wheel_binds, + // 10 is copied from Clutter: DISCRETE_SCROLL_STEP. + vertical_finger_scroll_tracker: ScrollTracker::new(10), + horizontal_finger_scroll_tracker: ScrollTracker::new(10), + mods_with_finger_scroll_binds, + lock_state: LockState::Unlocked, screenshot_ui, diff --git a/src/ui/hotkey_overlay.rs b/src/ui/hotkey_overlay.rs index 2f658dc3..3db3879a 100644 --- a/src/ui/hotkey_overlay.rs +++ b/src/ui/hotkey_overlay.rs @@ -226,6 +226,8 @@ fn render(config: &Config, comp_mod: CompositorMod, scale: i32) -> anyhow::Resul // Only show binds with Mod or Super to filter out stuff like volume up/down. && (bind.key.modifiers.contains(Modifiers::COMPOSITOR) || bind.key.modifiers.contains(Modifiers::SUPER)) + // Also filter out wheel and touchpad scroll binds. + && matches!(bind.key.trigger, Trigger::Keysym(_)) }) { let action = &bind.action; @@ -421,6 +423,10 @@ fn key_name(comp_mod: CompositorMod, key: &Key) -> String { Trigger::WheelScrollUp => String::from("Wheel Scroll Up"), Trigger::WheelScrollLeft => String::from("Wheel Scroll Left"), Trigger::WheelScrollRight => String::from("Wheel Scroll Right"), + Trigger::TouchpadScrollDown => String::from("Touchpad Scroll Down"), + Trigger::TouchpadScrollUp => String::from("Touchpad Scroll Up"), + Trigger::TouchpadScrollLeft => String::from("Touchpad Scroll Left"), + Trigger::TouchpadScrollRight => String::from("Touchpad Scroll Right"), }; name.push_str(&pretty); -- cgit