diff options
| -rw-r--r-- | src/input.rs | 148 | ||||
| -rw-r--r-- | src/niri.rs | 10 |
2 files changed, 100 insertions, 58 deletions
diff --git a/src/input.rs b/src/input.rs index f01d66a5..850fb76a 100644 --- a/src/input.rs +++ b/src/input.rs @@ -1118,26 +1118,24 @@ impl State { // Handle wheel scroll bindings. if source == AxisSource::Wheel { - let comp_mod = self.backend.mod_key(); + // If we have a scroll bind with current modifiers, then accumulate and don't pass to + // Wayland. If there's no bind, reset the accumulator. let mods = self.niri.seat.get_keyboard().unwrap().modifier_state(); + let modifiers = modifiers_from_state(mods); + if self.niri.mods_with_wheel_binds.contains(&modifiers) { + let comp_mod = self.backend.mod_key(); + + let horizontal = horizontal_amount_v120.unwrap_or(0.); + let ticks = self.niri.horizontal_wheel_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::WheelScrollLeft, mods); + let bind_right = + find_configured_bind(bindings, comp_mod, Trigger::WheelScrollRight, mods); + drop(config); - // Winit sends scroll events where both directions are set at once, so we can't early - // return after handling just one. - let mut handled = false; - - if let Some(v120) = horizontal_amount_v120 { - let config = self.niri.config.borrow(); - let bindings = &config.binds; - let bind_left = - find_configured_bind(bindings, comp_mod, Trigger::WheelScrollLeft, mods); - let bind_right = - find_configured_bind(bindings, comp_mod, Trigger::WheelScrollRight, 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 bind_left.is_some() || bind_right.is_some() { - let ticks = self.niri.horizontal_wheel_tracker.accumulate(v120); if let Some(right) = bind_right { for _ in 0..ticks { self.handle_bind(right.clone()); @@ -1148,24 +1146,19 @@ impl State { self.handle_bind(left.clone()); } } - - handled = true; - } 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 bind_up = - find_configured_bind(bindings, comp_mod, Trigger::WheelScrollUp, mods); - let bind_down = - find_configured_bind(bindings, comp_mod, Trigger::WheelScrollDown, mods); - drop(config); - - if bind_up.is_some() || bind_down.is_some() { - let ticks = self.niri.vertical_wheel_tracker.accumulate(v120); + let vertical = vertical_amount_v120.unwrap_or(0.); + let ticks = self.niri.vertical_wheel_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::WheelScrollUp, mods); + let bind_down = + find_configured_bind(bindings, comp_mod, Trigger::WheelScrollDown, mods); + drop(config); + if let Some(down) = bind_down { for _ in 0..ticks { self.handle_bind(down.clone()); @@ -1176,15 +1169,12 @@ impl State { self.handle_bind(up.clone()); } } - - handled = true; - } else { - self.niri.vertical_wheel_tracker.reset(); } - } - if handled { return; + } else { + self.niri.horizontal_wheel_tracker.reset(); + self.niri.vertical_wheel_tracker.reset(); } } @@ -1836,22 +1826,7 @@ fn find_configured_bind( mods: ModifiersState, ) -> Option<Bind> { // Handle configured binds. - let mut modifiers = Modifiers::empty(); - if mods.ctrl { - modifiers |= Modifiers::CTRL; - } - if mods.shift { - modifiers |= Modifiers::SHIFT; - } - if mods.alt { - modifiers |= Modifiers::ALT; - } - if mods.logo { - modifiers |= Modifiers::SUPER; - } - if mods.iso_level3_shift { - modifiers |= Modifiers::ISO_LEVEL3_SHIFT; - } + let mut modifiers = modifiers_from_state(mods); let (mod_down, comp_mod) = match comp_mod { CompositorMod::Super => (mods.logo, Modifiers::SUPER), @@ -1881,6 +1856,26 @@ fn find_configured_bind( None } +fn modifiers_from_state(mods: ModifiersState) -> Modifiers { + let mut modifiers = Modifiers::empty(); + if mods.ctrl { + modifiers |= Modifiers::CTRL; + } + if mods.shift { + modifiers |= Modifiers::SHIFT; + } + if mods.alt { + modifiers |= Modifiers::ALT; + } + if mods.logo { + modifiers |= Modifiers::SUPER; + } + if mods.iso_level3_shift { + modifiers |= Modifiers::ISO_LEVEL3_SHIFT; + } + modifiers +} + fn should_activate_monitors<I: InputBackend>(event: &InputEvent<I>) -> bool { match event { InputEvent::Keyboard { event } if event.state() == KeyState::Pressed => true, @@ -2031,6 +2026,47 @@ pub fn apply_libinput_settings(config: &niri_config::Input, device: &mut input:: } } +pub fn mods_with_binds( + comp_mod: CompositorMod, + binds: &Binds, + triggers: &[Trigger], +) -> HashSet<Modifiers> { + let comp_mod = match comp_mod { + CompositorMod::Super => Modifiers::SUPER, + CompositorMod::Alt => Modifiers::ALT, + }; + + let mut rv = HashSet::new(); + for bind in &binds.0 { + if !triggers.iter().any(|trigger| bind.key.trigger == *trigger) { + continue; + } + + let mut mods = bind.key.modifiers; + if mods.contains(Modifiers::COMPOSITOR) { + mods.remove(Modifiers::COMPOSITOR); + mods.insert(comp_mod); + } + + rv.insert(mods); + } + + rv +} + +pub fn mods_with_wheel_binds(comp_mod: CompositorMod, binds: &Binds) -> HashSet<Modifiers> { + mods_with_binds( + comp_mod, + binds, + &[ + Trigger::WheelScrollUp, + Trigger::WheelScrollDown, + Trigger::WheelScrollLeft, + Trigger::WheelScrollRight, + ], + ) +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/niri.rs b/src/niri.rs index 33e7d2eb..5ba10a82 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -11,7 +11,7 @@ use std::{env, mem, thread}; use _server_decoration::server::org_kde_kwin_server_decoration_manager::Mode as KdeDecorationsMode; use anyhow::{ensure, Context}; use calloop::futures::Scheduler; -use niri_config::{Config, Key, TrackLayout}; +use niri_config::{Config, Key, Modifiers, TrackLayout}; use smithay::backend::allocator::Fourcc; use smithay::backend::renderer::element::memory::MemoryRenderBufferRenderElement; use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement}; @@ -97,7 +97,7 @@ 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, TabletData}; +use crate::input::{apply_libinput_settings, mods_with_wheel_binds, TabletData}; use crate::ipc::server::IpcServer; use crate::layout::{Layout, MonitorRenderElement}; use crate::protocols::foreign_toplevel::{self, ForeignToplevelManagerState}; @@ -208,6 +208,7 @@ pub struct Niri { pub gesture_swipe_3f_cumulative: Option<(f64, f64)>, pub vertical_wheel_tracker: WheelTracker, pub horizontal_wheel_tracker: WheelTracker, + pub mods_with_wheel_binds: HashSet<Modifiers>, pub lock_state: LockState, @@ -853,6 +854,8 @@ impl State { if config.binds != old_config.binds { self.niri.hotkey_overlay.on_hotkey_config_updated(); + self.niri.mods_with_wheel_binds = + mods_with_wheel_binds(self.backend.mod_key(), &config.binds); } if config.window_rules != old_config.window_rules { @@ -1162,6 +1165,8 @@ impl Niri { let cursor_manager = 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 (tx, rx) = calloop::channel::channel(); event_loop .insert_source(rx, move |event, _, state| { @@ -1318,6 +1323,7 @@ impl Niri { gesture_swipe_3f_cumulative: None, vertical_wheel_tracker: WheelTracker::new(), horizontal_wheel_tracker: WheelTracker::new(), + mods_with_wheel_binds, lock_state: LockState::Unlocked, |
