diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/input.rs | 58 | ||||
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/niri.rs | 5 | ||||
| -rw-r--r-- | src/wheel_tracker.rs | 36 |
4 files changed, 100 insertions, 0 deletions
diff --git a/src/input.rs b/src/input.rs index 0c106e20..dca07316 100644 --- a/src/input.rs +++ b/src/input.rs @@ -1081,6 +1081,64 @@ impl State { let horizontal_amount_v120 = event.amount_v120(Axis::Horizontal); let vertical_amount_v120 = event.amount_v120(Axis::Vertical); + // Handle wheel bindings. + if source == AxisSource::Wheel { + let comp_mod = self.backend.mod_key(); + let mods = self.niri.seat.get_keyboard().unwrap().modifier_state(); + + if let Some(v120) = horizontal_amount_v120 { + let config = self.niri.config.borrow(); + let bindings = &config.binds; + let action_left = bound_action(bindings, comp_mod, Trigger::WheelLeft, mods); + let action_right = bound_action(bindings, comp_mod, Trigger::WheelRight, mods); + drop(config); + + // If we have a bind with current modifiers along the scroll direction, then + // accumulate and don't pass to Wayland. If there's no bind, reset the accumulator. + if action_left.is_some() || action_right.is_some() { + let ticks = self.niri.horizontal_wheel_tracker.accumulate(v120); + if let Some(right) = action_right { + for _ in 0..ticks { + self.do_action(right.clone()); + } + } + if let Some(left) = action_left { + for _ in ticks..0 { + self.do_action(left.clone()); + } + } + return; + } else { + self.niri.horizontal_wheel_tracker.reset(); + } + } + + if let Some(v120) = vertical_amount_v120 { + let config = self.niri.config.borrow(); + let bindings = &config.binds; + let action_up = bound_action(bindings, comp_mod, Trigger::WheelUp, mods); + let action_down = bound_action(bindings, comp_mod, Trigger::WheelDown, mods); + drop(config); + + if action_up.is_some() || action_down.is_some() { + let ticks = self.niri.vertical_wheel_tracker.accumulate(v120); + if let Some(down) = action_down { + for _ in 0..ticks { + self.do_action(down.clone()); + } + } + if let Some(up) = action_up { + for _ in ticks..0 { + self.do_action(up.clone()); + } + } + return; + } else { + self.niri.vertical_wheel_tracker.reset(); + } + } + } + let horizontal_amount = event.amount(Axis::Horizontal).unwrap_or_else(|| { // Winit backend, discrete scrolling. horizontal_amount_v120.unwrap_or(0.0) / 120. * 15. @@ -19,6 +19,7 @@ pub mod rubber_band; pub mod swipe_tracker; pub mod ui; pub mod utils; +pub mod wheel_tracker; pub mod window; #[cfg(not(feature = "xdp-gnome-screencast"))] diff --git a/src/niri.rs b/src/niri.rs index 08f195fc..babd961c 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -114,6 +114,7 @@ use crate::utils::spawning::CHILD_ENV; use crate::utils::{ center, center_f64, get_monotonic_time, make_screenshot_path, output_size, write_png_rgba8, }; +use crate::wheel_tracker::WheelTracker; use crate::window::{InitialConfigureState, Mapped, ResolvedWindowRules, Unmapped}; use crate::{animation, niri_render_elements}; @@ -204,6 +205,8 @@ pub struct Niri { pub pointer_focus: PointerFocus, pub tablet_cursor_location: Option<Point<f64, Logical>>, pub gesture_swipe_3f_cumulative: Option<(f64, f64)>, + pub vertical_wheel_tracker: WheelTracker, + pub horizontal_wheel_tracker: WheelTracker, pub lock_state: LockState, @@ -1263,6 +1266,8 @@ impl Niri { pointer_focus: PointerFocus::default(), tablet_cursor_location: None, gesture_swipe_3f_cumulative: None, + vertical_wheel_tracker: WheelTracker::new(), + horizontal_wheel_tracker: WheelTracker::new(), lock_state: LockState::Unlocked, diff --git a/src/wheel_tracker.rs b/src/wheel_tracker.rs new file mode 100644 index 00000000..0163548a --- /dev/null +++ b/src/wheel_tracker.rs @@ -0,0 +1,36 @@ +pub struct WheelTracker { + last: f64, + acc: f64, +} + +impl WheelTracker { + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + Self { last: 0., acc: 0. } + } + + pub fn accumulate(&mut self, amount_v120: f64) -> i8 { + let changed_direction = + (self.last > 0. && amount_v120 < 0.) || (self.last < 0. && amount_v120 > 0.); + if changed_direction { + self.acc = 0. + } + + self.last = amount_v120; + self.acc += amount_v120; + + let mut ticks = 0; + if self.acc.abs() >= 120. { + let clamped = self.acc.clamp(-127. * 120., 127. * 120.); + ticks = (clamped as i16 / 120) as i8; + self.acc %= 120.; + } + + ticks + } + + pub fn reset(&mut self) { + self.last = 0.; + self.acc = 0.; + } +} |
