Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MouseButton::{Back, Forward} to mouse input events on Wayland, X11, Windows, macOS and Web #2770

Merged
merged 9 commits into from
Jun 16, 2023
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)]
daxpedda marked this conversation as resolved.
Show resolved Hide resolved
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