Skip to content

Commit

Permalink
Add Mouse{Left,Right,Middle,Back,Forward} binds
Browse files Browse the repository at this point in the history
I don't know the history behind `BTN_BACK == BTN_SIDE` and `BTN_FORWARD == BTN_EXTRA`,
but everyone seems to be doing it so if it's "wrong" it's better for compatability.
It's my fault it's like that on winit too :P

Fixes YaLTeR#761.
  • Loading branch information
bbb651 committed Dec 13, 2024
1 parent 82e3024 commit 8c69b66
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 5 deletions.
17 changes: 16 additions & 1 deletion niri-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,11 @@ pub struct Key {
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum Trigger {
Keysym(Keysym),
MouseLeft,
MouseRight,
MouseMiddle,
MouseBack,
MouseForward,
WheelScrollDown,
WheelScrollUp,
WheelScrollLeft,
Expand Down Expand Up @@ -2822,7 +2827,17 @@ impl FromStr for Key {
}
}

let trigger = if key.eq_ignore_ascii_case("WheelScrollDown") {
let trigger = if key.eq_ignore_ascii_case("MouseLeft") {
Trigger::MouseLeft
} else if key.eq_ignore_ascii_case("MouseRight") {
Trigger::MouseRight
} else if key.eq_ignore_ascii_case("MouseMiddle") {
Trigger::MouseMiddle
} else if key.eq_ignore_ascii_case("MouseBack") {
Trigger::MouseBack
} else if key.eq_ignore_ascii_case("MouseForward") {
Trigger::MouseForward
} else if key.eq_ignore_ascii_case("WheelScrollDown") {
Trigger::WheelScrollDown
} else if key.eq_ignore_ascii_case("WheelScrollUp") {
Trigger::WheelScrollUp
Expand Down
51 changes: 48 additions & 3 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,15 @@ impl State {
}

fn on_pointer_button<I: InputBackend>(&mut self, event: I::PointerButtonEvent) {
// These values are coming from <linux/input-event-codes.h>.
const BTN_LEFT: u32 = 0x110;
const BTN_RIGHT: u32 = 0x111;
const BTN_MIDDLE: u32 = 0x112;
const BTN_SIDE: u32 = 0x113;
const BTN_EXTRA: u32 = 0x114;
const BTN_FORWARD: u32 = 0x115;
const BTN_BACK: u32 = 0x116;

let pointer = self.niri.seat.get_pointer().unwrap();

let serial = SERIAL_COUNTER.next_serial();
Expand All @@ -1552,6 +1561,31 @@ impl State {
let button_state = event.state();

if ButtonState::Pressed == button_state {
let mods = self.niri.seat.get_keyboard().unwrap().modifier_state();
let modifiers = modifiers_from_state(mods);

if self.niri.mods_with_mouse_binds.contains(&modifiers) {
let comp_mod = self.backend.mod_key();

if let Some(bind) = match button {
BTN_LEFT => Some(Trigger::MouseLeft),
BTN_RIGHT => Some(Trigger::MouseRight),
BTN_MIDDLE => Some(Trigger::MouseMiddle),
// Chromium treats these as equivalent: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/ui/ozone/platform/wayland/host/wayland_pointer.cc
BTN_BACK | BTN_SIDE => Some(Trigger::MouseBack),
BTN_FORWARD | BTN_EXTRA => Some(Trigger::MouseForward),
_ => None,
}
.and_then(|trigger| {
let config = self.niri.config.borrow();
let bindings = &config.binds;
find_configured_bind(bindings, comp_mod, trigger, mods)
}) {
self.handle_bind(bind.clone());
return;
};
}

// We received an event for the regular pointer, so show it now.
self.niri.pointer_hidden = false;
self.niri.tablet_cursor_location = None;
Expand All @@ -1561,7 +1595,6 @@ impl State {

// Check if we need to start an interactive move.
if event.button() == Some(MouseButton::Left) && !pointer.is_grabbed() {
let mods = self.niri.seat.get_keyboard().unwrap().modifier_state();
let mod_down = match self.backend.mod_key() {
CompositorMod::Super => mods.logo,
CompositorMod::Alt => mods.alt,
Expand Down Expand Up @@ -1593,7 +1626,6 @@ impl State {
}
// Check if we need to start an interactive resize.
else if event.button() == Some(MouseButton::Right) && !pointer.is_grabbed() {
let mods = self.niri.seat.get_keyboard().unwrap().modifier_state();
let mod_down = match self.backend.mod_key() {
CompositorMod::Super => mods.logo,
CompositorMod::Alt => mods.alt,
Expand Down Expand Up @@ -1670,7 +1702,6 @@ impl State {
}

if event.button() == Some(MouseButton::Middle) && !pointer.is_grabbed() {
let mods = self.niri.seat.get_keyboard().unwrap().modifier_state();
let mod_down = match self.backend.mod_key() {
CompositorMod::Super => mods.logo,
CompositorMod::Alt => mods.alt,
Expand Down Expand Up @@ -2993,6 +3024,20 @@ pub fn mods_with_binds(
rv
}

pub fn mods_with_mouse_binds(comp_mod: CompositorMod, binds: &Binds) -> HashSet<Modifiers> {
mods_with_binds(
comp_mod,
binds,
&[
Trigger::MouseLeft,
Trigger::MouseRight,
Trigger::MouseMiddle,
Trigger::MouseBack,
Trigger::MouseForward,
],
)
}

pub fn mods_with_wheel_binds(comp_mod: CompositorMod, binds: &Binds) -> HashSet<Modifiers> {
mods_with_binds(
comp_mod,
Expand Down
6 changes: 5 additions & 1 deletion src/niri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ use crate::frame_clock::FrameClock;
use crate::handlers::{configure_lock_surface, XDG_ACTIVATION_TOKEN_TIMEOUT};
use crate::input::scroll_tracker::ScrollTracker;
use crate::input::{
apply_libinput_settings, mods_with_finger_scroll_binds, mods_with_wheel_binds, TabletData,
apply_libinput_settings, mods_with_finger_scroll_binds, mods_with_mouse_binds,
mods_with_wheel_binds, TabletData,
};
use crate::ipc::server::IpcServer;
use crate::layer::mapped::LayerSurfaceRenderElement;
Expand Down Expand Up @@ -302,6 +303,7 @@ pub struct Niri {
pub gesture_swipe_3f_cumulative: Option<(f64, f64)>,
pub vertical_wheel_tracker: ScrollTracker,
pub horizontal_wheel_tracker: ScrollTracker,
pub mods_with_mouse_binds: HashSet<Modifiers>,
pub mods_with_wheel_binds: HashSet<Modifiers>,
pub vertical_finger_scroll_tracker: ScrollTracker,
pub horizontal_finger_scroll_tracker: ScrollTracker,
Expand Down Expand Up @@ -1813,6 +1815,7 @@ impl Niri {
let cursor_manager =
CursorManager::new(&config_.cursor.xcursor_theme, config_.cursor.xcursor_size);

let mods_with_mouse_binds = mods_with_mouse_binds(backend.mod_key(), &config_.binds);
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);
Expand Down Expand Up @@ -1989,6 +1992,7 @@ impl Niri {
gesture_swipe_3f_cumulative: None,
vertical_wheel_tracker: ScrollTracker::new(120),
horizontal_wheel_tracker: ScrollTracker::new(120),
mods_with_mouse_binds,
mods_with_wheel_binds,

// 10 is copied from Clutter: DISCRETE_SCROLL_STEP.
Expand Down
5 changes: 5 additions & 0 deletions src/ui/hotkey_overlay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,11 @@ fn key_name(comp_mod: CompositorMod, key: &Key) -> String {

let pretty = match key.trigger {
Trigger::Keysym(keysym) => prettify_keysym_name(&keysym_get_name(keysym)),
Trigger::MouseLeft => String::from("Mouse Left"),
Trigger::MouseRight => String::from("Mouse Right"),
Trigger::MouseMiddle => String::from("Mouse Middle"),
Trigger::MouseBack => String::from("Mouse Back"),
Trigger::MouseForward => String::from("Mouse Forward"),
Trigger::WheelScrollDown => String::from("Wheel Scroll Down"),
Trigger::WheelScrollUp => String::from("Wheel Scroll Up"),
Trigger::WheelScrollLeft => String::from("Wheel Scroll Left"),
Expand Down

0 comments on commit 8c69b66

Please sign in to comment.