From 47488909353bb6d8e52801b8824b0e2352e4ab63 Mon Sep 17 00:00:00 2001 From: bbb651 <53972231+bbb651@users.noreply.github.com> Date: Fri, 16 Jun 2023 11:51:09 +0300 Subject: [PATCH] Add MouseButton::{Back, Forward} to `MouseInput` 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 --- CHANGELOG.md | 2 ++ src/event.rs | 7 +++++++ .../linux/wayland/seat/pointer/mod.rs | 8 +++++++- .../linux/x11/event_processor.rs | 19 ++++++++++++++++++- src/platform_impl/macos/view.rs | 4 ++++ src/platform_impl/web/web_sys/event.rs | 18 +++++++++++++++--- src/platform_impl/windows/event_loop.rs | 18 ++++++++++++++---- 7 files changed, 67 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb1d4fe9..9229c5f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/event.rs b/src/event.rs index a658dc4d..4111e1f6 100644 --- a/src/event.rs +++ b/src/event.rs @@ -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), } diff --git a/src/platform_impl/linux/wayland/seat/pointer/mod.rs b/src/platform_impl/linux/wayland/seat/pointer/mod.rs index 1b933028..607b0e1b 100644 --- a/src/platform_impl/linux/wayland/seat/pointer/mod.rs +++ b/src/platform_impl/linux/wayland/seat/pointer/mod.rs @@ -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 . + // These values are coming from . 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), } } diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index a32f3d9e..67e321b4 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -579,7 +579,7 @@ impl EventProcessor { use crate::event::{ ElementState::{Pressed, Released}, - MouseButton::{Left, Middle, Other, Right}, + MouseButton::{Back, Forward, Left, Middle, Other, Right}, MouseScrollDelta::LineDelta, Touch, WindowEvent::{ @@ -651,6 +651,23 @@ impl EventProcessor { } } + 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 { diff --git a/src/platform_impl/macos/view.rs b/src/platform_impl/macos/view.rs index 314dc2cf..faecdd15 100644 --- a/src/platform_impl/macos/view.rs +++ b/src/platform_impl/macos/view.rs @@ -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), } } diff --git a/src/platform_impl/web/web_sys/event.rs b/src/platform_impl/web/web_sys/event.rs index 92020463..70ece5fe 100644 --- a/src/platform_impl/web/web_sys/event.rs +++ b/src/platform_impl/web/web_sys/event.rs @@ -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; } } @@ -24,6 +27,8 @@ impl From 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()), } } @@ -35,6 +40,8 @@ impl From 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), } } @@ -45,11 +52,14 @@ pub fn mouse_buttons(event: &MouseEvent) -> ButtonsState { } pub fn mouse_button(event: &MouseEvent) -> Option { + // 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"), @@ -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(), } } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 7ed5b820..d3b4bf6a 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -1647,7 +1647,8 @@ unsafe fn public_window_callback_inner( 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); @@ -1660,7 +1661,11 @@ unsafe fn public_window_callback_inner( event: MouseInput { device_id: DEVICE_ID, state: Pressed, - button: Other(xbutton), + button: match xbutton { + 1 => Back, + 2 => Forward, + _ => Other(xbutton), + }, }, }); result = ProcResult::Value(0); @@ -1668,7 +1673,8 @@ unsafe fn public_window_callback_inner( 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); @@ -1681,7 +1687,11 @@ unsafe fn public_window_callback_inner( event: MouseInput { device_id: DEVICE_ID, state: Released, - button: Other(xbutton), + button: match xbutton { + 1 => Back, + 2 => Forward, + _ => Other(xbutton), + }, }, }); result = ProcResult::Value(0);