aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/input.rs148
-rw-r--r--src/niri.rs10
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,