Skip to content

Commit

Permalink
Add MouseButton::{Back, Forward} to MouseInput
Browse files Browse the repository at this point in the history
Add named variants for physical back and forward keys which could
be found on some mice. The macOS bits may not work on all the
hardware given that apple doesn't directly support such a thing.

Co-authored-by: daxpedda <daxpedda@gmail.com>
  • Loading branch information
bbb651 and daxpedda committed Jun 16, 2023
1 parent 6300cf9 commit 4748890
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ And please only add new entries to the top of this list, right below the `# Unre
- On Web, fix `DeviceEvent::MouseMotion` only being emitted for each canvas instead of the whole window.
- On Web, add `DeviceEvent::Motion`, `DeviceEvent::MouseWheel`, `DeviceEvent::Button` and
`DeviceEvent::Key` support.
- **Breaking** `MouseButton` now supports `Back` and `Forward` variants, emitted from mouse events
on Wayland, X11, Windows, macOS and Web.

# 0.28.6

Expand Down
7 changes: 7 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1202,12 +1202,19 @@ pub enum ElementState {
}

/// Describes a button of a mouse controller.
///
/// ## Platform-specific
///
/// **macOS:** `Back` and `Forward` might not work with all hardware.
/// **Orbital:** `Back` and `Forward` are unsupported due to orbital not supporting them.
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum MouseButton {
Left,
Right,
Middle,
Back,
Forward,
Other(u16),
}

Expand Down
8 changes: 7 additions & 1 deletion src/platform_impl/linux/wayland/seat/pointer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,15 +397,21 @@ impl Default for WinitPointerDataInner {

/// Convert the Wayland button into winit.
fn wayland_button_to_winit(button: u32) -> MouseButton {
// These values are comming from <linux/input-event-codes.h>.
// 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;

match button {
BTN_LEFT => MouseButton::Left,
BTN_RIGHT => MouseButton::Right,
BTN_MIDDLE => MouseButton::Middle,
BTN_BACK | BTN_SIDE => MouseButton::Back,
BTN_FORWARD | BTN_EXTRA => MouseButton::Forward,
button => MouseButton::Other(button as u16),
}
}
Expand Down
19 changes: 18 additions & 1 deletion src/platform_impl/linux/x11/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ impl<T: 'static> EventProcessor<T> {

use crate::event::{
ElementState::{Pressed, Released},
MouseButton::{Left, Middle, Other, Right},
MouseButton::{Back, Forward, Left, Middle, Other, Right},
MouseScrollDelta::LineDelta,
Touch,
WindowEvent::{
Expand Down Expand Up @@ -651,6 +651,23 @@ impl<T: 'static> EventProcessor<T> {
}
}

8 => callback(Event::WindowEvent {
window_id,
event: MouseInput {
device_id,
state,
button: Back,
},
}),
9 => callback(Event::WindowEvent {
window_id,
event: MouseInput {
device_id,
state,
button: Forward,
},
}),

x => callback(Event::WindowEvent {
window_id,
event: MouseInput {
Expand Down
4 changes: 4 additions & 0 deletions src/platform_impl/macos/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1027,10 +1027,14 @@ fn mouse_button(event: &NSEvent) -> MouseButton {
// The buttonNumber property only makes sense for the mouse events:
// NSLeftMouse.../NSRightMouse.../NSOtherMouse...
// For the other events, it's always set to 0.
// MacOS only defines the left, right and middle buttons, 3..=31 are left as generic buttons,
// but 3 and 4 are very commonly used as Back and Forward by hardware vendors and applications.
match event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Back,
4 => MouseButton::Forward,
n => MouseButton::Other(n as u16),
}
}
18 changes: 15 additions & 3 deletions src/platform_impl/web/web_sys/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ use wasm_bindgen::{JsCast, JsValue};
use web_sys::{HtmlCanvasElement, KeyboardEvent, MouseEvent, PointerEvent, WheelEvent};

bitflags! {
// https://www.w3.org/TR/pointerevents3/#the-buttons-property
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ButtonsState: u16 {
const LEFT = 0b001;
const RIGHT = 0b010;
const MIDDLE = 0b100;
const LEFT = 0b00001;
const RIGHT = 0b00010;
const MIDDLE = 0b00100;
const BACK = 0b01000;
const FORWARD = 0b10000;
}
}

Expand All @@ -24,6 +27,8 @@ impl From<ButtonsState> for MouseButton {
ButtonsState::LEFT => MouseButton::Left,
ButtonsState::RIGHT => MouseButton::Right,
ButtonsState::MIDDLE => MouseButton::Middle,
ButtonsState::BACK => MouseButton::Back,
ButtonsState::FORWARD => MouseButton::Forward,
_ => MouseButton::Other(value.bits()),
}
}
Expand All @@ -35,6 +40,8 @@ impl From<MouseButton> for ButtonsState {
MouseButton::Left => ButtonsState::LEFT,
MouseButton::Right => ButtonsState::RIGHT,
MouseButton::Middle => ButtonsState::MIDDLE,
MouseButton::Back => ButtonsState::BACK,
MouseButton::Forward => ButtonsState::FORWARD,
MouseButton::Other(value) => ButtonsState::from_bits_retain(value),
}
}
Expand All @@ -45,11 +52,14 @@ pub fn mouse_buttons(event: &MouseEvent) -> ButtonsState {
}

pub fn mouse_button(event: &MouseEvent) -> Option<MouseButton> {
// https://www.w3.org/TR/pointerevents3/#the-button-property
match event.button() {
-1 => None,
0 => Some(MouseButton::Left),
1 => Some(MouseButton::Middle),
2 => Some(MouseButton::Right),
3 => Some(MouseButton::Back),
4 => Some(MouseButton::Forward),
i => Some(MouseButton::Other(
i.try_into()
.expect("unexpected negative mouse button value"),
Expand All @@ -63,6 +73,8 @@ impl MouseButton {
MouseButton::Left => 0,
MouseButton::Right => 1,
MouseButton::Middle => 2,
MouseButton::Back => 3,
MouseButton::Forward => 4,
MouseButton::Other(value) => value.into(),
}
}
Expand Down
18 changes: 14 additions & 4 deletions src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1647,7 +1647,8 @@ unsafe fn public_window_callback_inner<T: 'static>(

WM_XBUTTONDOWN => {
use crate::event::{
ElementState::Pressed, MouseButton::Other, WindowEvent::MouseInput,
ElementState::Pressed, MouseButton::Back, MouseButton::Forward, MouseButton::Other,
WindowEvent::MouseInput,
};
let xbutton = super::get_xbutton_wparam(wparam as u32);

Expand All @@ -1660,15 +1661,20 @@ unsafe fn public_window_callback_inner<T: 'static>(
event: MouseInput {
device_id: DEVICE_ID,
state: Pressed,
button: Other(xbutton),
button: match xbutton {
1 => Back,
2 => Forward,
_ => Other(xbutton),
},
},
});
result = ProcResult::Value(0);
}

WM_XBUTTONUP => {
use crate::event::{
ElementState::Released, MouseButton::Other, WindowEvent::MouseInput,
ElementState::Released, MouseButton::Back, MouseButton::Forward,
MouseButton::Other, WindowEvent::MouseInput,
};
let xbutton = super::get_xbutton_wparam(wparam as u32);

Expand All @@ -1681,7 +1687,11 @@ unsafe fn public_window_callback_inner<T: 'static>(
event: MouseInput {
device_id: DEVICE_ID,
state: Released,
button: Other(xbutton),
button: match xbutton {
1 => Back,
2 => Forward,
_ => Other(xbutton),
},
},
});
result = ProcResult::Value(0);
Expand Down

0 comments on commit 4748890

Please sign in to comment.