diff --git a/winit-appkit/src/view.rs b/winit-appkit/src/view.rs index dc57fa7dc3..9aa65b89d8 100644 --- a/winit-appkit/src/view.rs +++ b/winit-appkit/src/view.rs @@ -1096,14 +1096,11 @@ fn mouse_button(event: &NSEvent) -> MouseButton { // 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 unsafe { event.buttonNumber() } { - 0 => MouseButton::Left, - 1 => MouseButton::Right, - 2 => MouseButton::Middle, - 3 => MouseButton::Back, - 4 => MouseButton::Forward, - n => MouseButton::Other(n as u16), - } + let b: isize = unsafe { event.buttonNumber() }; + b.try_into() + .ok() + .and_then(MouseButton::try_from_u8) + .expect("expected MacOS button number in the range 0..=31") } // NOTE: to get option as alt working we need to rewrite events diff --git a/winit-core/src/event.rs b/winit-core/src/event.rs index cb3c606c98..865ae19820 100644 --- a/winit-core/src/event.rs +++ b/winit-core/src/event.rs @@ -514,25 +514,21 @@ pub enum ButtonSource { finger_id: FingerId, force: Option, }, + /// A pointer button of unknown source. + /// + /// Codes are undefined and may not be reproducible across platforms or winit versions. Unknown(u16), } impl ButtonSource { - /// Convert any [`ButtonSource`] to an equivalent [`MouseButton`]. If a pointer type has no + /// Try to convert a [`ButtonSource`] to an equivalent [`MouseButton`]. If a pointer type has no /// special handling in an application, this method can be used to handle it like any generic /// mouse input. - pub fn mouse_button(self) -> MouseButton { + pub fn mouse_button(self) -> Option { match self { - ButtonSource::Mouse(mouse) => mouse, - ButtonSource::Touch { .. } => MouseButton::Left, - ButtonSource::Unknown(button) => match button { - 0 => MouseButton::Left, - 1 => MouseButton::Middle, - 2 => MouseButton::Right, - 3 => MouseButton::Back, - 4 => MouseButton::Forward, - _ => MouseButton::Other(button), - }, + ButtonSource::Mouse(mouse) => Some(mouse), + ButtonSource::Touch { .. } => Some(MouseButton::Left), + ButtonSource::Unknown(_) => None, } } } @@ -1041,21 +1037,113 @@ impl ElementState { } } -/// Describes a button of a mouse controller. +/// Identifies 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. +/// The first three buttons should be supported on all platforms. +/// [`Self::Back`] and [`Self::Forward`] are supported on most platforms +/// (when using a compatible mouse). +/// +/// - **Android, iOS:** Currently not supported. +/// - **Orbital:** Only left/right/middle buttons are supported at this time. +/// - **Web, Windows:** Supports left/right/middle/back/forward buttons. +/// - **Wayland:** Supports buttons 0..=15. +/// - **macOS, X11:** Supports all button variants. +/// - **X11:** Supports buttons 0..=250. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[repr(u8)] pub enum MouseButton { - Left, - Right, - Middle, - Back, - Forward, - Other(u16), + /// The primary (usually left) button + Left = 0, + /// The secondary (usually right) button + Right = 1, + /// The tertiary (usually middle) button + Middle = 2, + /// The first side button, frequently assigned a back function + Back = 3, + /// The second side button, frequently assigned a forward function + Forward = 4, + /// The sixth button + Button5 = 5, + /// The seventh button + Button6 = 6, + /// The eighth button + Button7 = 7, + /// The ninth button + Button8 = 8, + /// The tenth button + Button9 = 9, + /// The eleventh button + Button10 = 10, + /// The twelfth button + Button11 = 11, + /// The thirteenth button + Button12 = 12, + /// The fourteenth button + Button13 = 13, + /// The fifteenth button + Button14 = 14, + /// The sixteenth button + Button15 = 15, + Button16 = 16, + Button17 = 17, + Button18 = 18, + Button19 = 19, + Button20 = 20, + Button21 = 21, + Button22 = 22, + Button23 = 23, + Button24 = 24, + Button25 = 25, + Button26 = 26, + Button27 = 27, + Button28 = 28, + Button29 = 29, + Button30 = 30, + Button31 = 31, +} + +impl MouseButton { + /// Construct from a `u8` if within the range `0..=31` + pub fn try_from_u8(b: u8) -> Option { + Some(match b { + 0 => MouseButton::Left, + 1 => MouseButton::Right, + 2 => MouseButton::Middle, + 3 => MouseButton::Back, + 4 => MouseButton::Forward, + 5 => MouseButton::Button5, + 6 => MouseButton::Button6, + 7 => MouseButton::Button7, + 8 => MouseButton::Button8, + 9 => MouseButton::Button9, + 10 => MouseButton::Button10, + 11 => MouseButton::Button11, + 12 => MouseButton::Button12, + 13 => MouseButton::Button13, + 14 => MouseButton::Button14, + 15 => MouseButton::Button15, + 16 => MouseButton::Button16, + 17 => MouseButton::Button17, + 18 => MouseButton::Button18, + 19 => MouseButton::Button19, + 20 => MouseButton::Button20, + 21 => MouseButton::Button21, + 22 => MouseButton::Button22, + 23 => MouseButton::Button23, + 24 => MouseButton::Button24, + 25 => MouseButton::Button25, + 26 => MouseButton::Button26, + 27 => MouseButton::Button27, + 28 => MouseButton::Button28, + 29 => MouseButton::Button29, + 30 => MouseButton::Button30, + 31 => MouseButton::Button31, + _ => return None, + }) + } } /// Describes a difference in the mouse scroll wheel state. @@ -1188,7 +1276,7 @@ mod tests { primary: true, state: event::ElementState::Pressed, position: (0, 0).into(), - button: event::MouseButton::Other(0).into(), + button: event::ButtonSource::Unknown(0), }); with_window_event(PointerButton { device_id: None, diff --git a/winit-wayland/src/seat/pointer/mod.rs b/winit-wayland/src/seat/pointer/mod.rs index 3e7df4b6d7..46111c968f 100644 --- a/winit-wayland/src/seat/pointer/mod.rs +++ b/winit-wayland/src/seat/pointer/mod.rs @@ -30,7 +30,7 @@ use sctk::seat::SeatState; use dpi::{LogicalPosition, PhysicalPosition}; use winit_core::event::{ ElementState, MouseButton, MouseScrollDelta, PointerKind, PointerSource, TouchPhase, - WindowEvent, + WindowEvent, ButtonSource, }; use crate::state::WinitState; @@ -108,8 +108,8 @@ impl PointerHandler for WinitState { if parent_surface != surface => { let click = match wayland_button_to_winit(button) { - MouseButton::Left => FrameClick::Normal, - MouseButton::Right => FrameClick::Alternate, + ButtonSource::Mouse(MouseButton::Left) => FrameClick::Normal, + ButtonSource::Mouse(MouseButton::Right) => FrameClick::Alternate, _ => continue, }; let pressed = matches!(kind, PointerEventKind::Press { .. }); @@ -186,7 +186,7 @@ impl PointerHandler for WinitState { device_id: None, state, position, - button: button.into(), + button, }, window_id, ); @@ -402,23 +402,16 @@ impl Default for WinitPointerDataInner { } /// Convert the Wayland button into winit. -fn wayland_button_to_winit(button: u32) -> MouseButton { +fn wayland_button_to_winit(button: u32) -> ButtonSource { // 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), + const BTN_MOUSE: u32 = 0x110; + const BTN_JOYSTICK: u32 = 0x120; + + if (BTN_MOUSE..BTN_JOYSTICK).contains(&button) { + // Mapping orders match + MouseButton::try_from_u8((button - BTN_MOUSE) as u8).unwrap().into() + } else { + ButtonSource::Unknown(button as u16) } } diff --git a/winit-web/src/event_loop/runner.rs b/winit-web/src/event_loop/runner.rs index 4aeaf383e1..7fefda7a6b 100644 --- a/winit-web/src/event_loop/runner.rs +++ b/winit-web/src/event_loop/runner.rs @@ -24,7 +24,6 @@ use crate::event_loop::ActiveEventLoop; use crate::main_thread::MainThreadMarker; use crate::monitor::MonitorHandler; use crate::r#async::DispatchRunner; -use crate::web_sys::event::mouse_button_to_id; use crate::window::Inner; use crate::{backend, event, EventLoop, PollStrategy, WaitUntilStrategy}; @@ -319,7 +318,7 @@ impl Shared { let device_id = event::mkdid(event.pointer_id()); if let Some(button) = backend::event::mouse_button(&event) { - let state = if backend::event::mouse_buttons(&event).contains(button.into()) { + let state = if backend::event::mouse_buttons(&event).contains(button.state()) { ElementState::Pressed } else { ElementState::Released @@ -327,10 +326,7 @@ impl Shared { runner.send_event(Event::DeviceEvent { device_id, - event: DeviceEvent::Button { - button: mouse_button_to_id(button).into(), - state, - }, + event: DeviceEvent::Button { button: button.raw().into(), state }, }); return; @@ -379,7 +375,7 @@ impl Shared { runner.send_event(Event::DeviceEvent { device_id: event::mkdid(event.pointer_id()), event: DeviceEvent::Button { - button: mouse_button_to_id(button).into(), + button: button.raw().into(), state: ElementState::Pressed, }, }); @@ -398,7 +394,7 @@ impl Shared { runner.send_event(Event::DeviceEvent { device_id: event::mkdid(event.pointer_id()), event: DeviceEvent::Button { - button: mouse_button_to_id(button).into(), + button: button.raw().into(), state: ElementState::Released, }, }); diff --git a/winit-web/src/web_sys/event.rs b/winit-web/src/web_sys/event.rs index 69a1635abe..654dc5736a 100644 --- a/winit-web/src/web_sys/event.rs +++ b/winit-web/src/web_sys/event.rs @@ -5,7 +5,7 @@ use smol_str::SmolStr; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::{JsCast, JsValue}; use web_sys::{KeyboardEvent, MouseEvent, Navigator, PointerEvent, WheelEvent}; -use winit_core::event::{FingerId, MouseButton, MouseScrollDelta, PointerKind}; +use winit_core::event::{FingerId, MouseScrollDelta, PointerKind}; use winit_core::keyboard::{ Key, KeyCode, KeyLocation, ModifiersState, NamedKey, NativeKey, NativeKeyCode, PhysicalKey, }; @@ -24,59 +24,52 @@ bitflags::bitflags! { } } -impl From for MouseButton { - fn from(value: ButtonsState) -> Self { - match value { - ButtonsState::LEFT => MouseButton::Left, - ButtonsState::RIGHT => MouseButton::Right, - ButtonsState::MIDDLE => MouseButton::Middle, - ButtonsState::BACK => MouseButton::Back, - ButtonsState::FORWARD => MouseButton::Forward, - _ => MouseButton::Other(value.bits()), - } - } +pub fn mouse_buttons(event: &MouseEvent) -> ButtonsState { + ButtonsState::from_bits_retain(event.buttons()) } -impl From for ButtonsState { - fn from(value: MouseButton) -> Self { - match value { - 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), - } +// https://www.w3.org/TR/pointerevents3/#the-button-property +#[derive(Clone, Copy)] +pub struct MouseButton(u16); + +impl MouseButton { + // raw code + pub fn raw(self) -> u16 { + self.0 } -} -pub fn mouse_buttons(event: &MouseEvent) -> ButtonsState { - ButtonsState::from_bits_retain(event.buttons()) + // Map known buttons to [`ButtonsState`], unknown to an empty state + pub fn state(self) -> ButtonsState { + match self.0 { + 0 => ButtonsState::LEFT, + 1 => ButtonsState::MIDDLE, + 2 => ButtonsState::RIGHT, + 3 => ButtonsState::BACK, + 4 => ButtonsState::FORWARD, + _ => ButtonsState::empty(), + } + } } 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"))) - }, - } + // NOTE: any negative value gets mapped to `None`, though only -1 is documented + event.button().try_into().ok().map(MouseButton) } -pub fn mouse_button_to_id(button: MouseButton) -> u16 { - match button { - MouseButton::Left => 0, - MouseButton::Right => 1, - MouseButton::Middle => 2, - MouseButton::Back => 3, - MouseButton::Forward => 4, - MouseButton::Other(value) => value, +impl From for winit_core::event::ButtonSource { + fn from(button: MouseButton) -> Self { + use winit_core::event::{ButtonSource, MouseButton as MB}; + + match button.0 { + 0 => MB::Left.into(), + 1 => MB::Middle.into(), + 2 => MB::Right.into(), + 3 => MB::Back.into(), + 4 => MB::Forward.into(), + // Codes above 4 are not observed on Firefox or Chromium. 5 is defined as an eraser, + // which is not a mouse button. No other codes are defined. + i => ButtonSource::Unknown(i), + } } } diff --git a/winit-web/src/web_sys/pointer.rs b/winit-web/src/web_sys/pointer.rs index 0187947eeb..fd6f9d3a36 100644 --- a/winit-web/src/web_sys/pointer.rs +++ b/winit-web/src/web_sys/pointer.rs @@ -10,7 +10,6 @@ use super::canvas::Common; use super::event; use super::event_handle::EventListenerHandle; use crate::event::mkdid; -use crate::web_sys::event::mouse_button_to_id; #[allow(dead_code)] pub(super) struct PointerHandler { @@ -85,12 +84,12 @@ impl PointerHandler { let button = event::mouse_button(&event).expect("no mouse button pressed"); let source = match kind { - PointerKind::Mouse => ButtonSource::Mouse(button), + PointerKind::Mouse => button.into(), PointerKind::Touch(finger_id) => ButtonSource::Touch { finger_id, force: Some(Force::Normalized(event.pressure().into())), }, - PointerKind::Unknown => ButtonSource::Unknown(mouse_button_to_id(button)), + PointerKind::Unknown => ButtonSource::Unknown(button.raw()), }; handler( @@ -137,13 +136,13 @@ impl PointerHandler { // care if it fails. let _e = canvas.set_pointer_capture(pointer_id); - ButtonSource::Mouse(button) + button.into() }, PointerKind::Touch(finger_id) => ButtonSource::Touch { finger_id, force: Some(Force::Normalized(event.pressure().into())), }, - PointerKind::Unknown => ButtonSource::Unknown(mouse_button_to_id(button)), + PointerKind::Unknown => ButtonSource::Unknown(button.raw()), }; handler( @@ -198,17 +197,16 @@ impl PointerHandler { let _ = canvas.focus(); } - let state = if event::mouse_buttons(&event).contains(button.into()) { + let state = if event::mouse_buttons(&event).contains(button.state()) { ElementState::Pressed } else { ElementState::Released }; let button = match kind { - PointerKind::Mouse => ButtonSource::Mouse(button), + PointerKind::Mouse => button.into(), PointerKind::Touch(finger_id) => { - let button_id = mouse_button_to_id(button); - + let button_id = button.raw(); if button_id != 1 { tracing::error!("unexpected touch button id: {button_id}"); } diff --git a/winit-win32/src/event_loop.rs b/winit-win32/src/event_loop.rs index 974170a5fa..80c070a65d 100644 --- a/winit-win32/src/event_loop.rs +++ b/winit-win32/src/event_loop.rs @@ -1715,9 +1715,9 @@ unsafe fn public_window_callback_inner( } }, - WM_LBUTTONDOWN => { + WM_LBUTTONDOWN | WM_RBUTTONDOWN | WM_MBUTTONDOWN => { use winit_core::event::ElementState::Pressed; - use winit_core::event::MouseButton::Left; + use winit_core::event::MouseButton; use winit_core::event::WindowEvent::PointerButton; unsafe { capture_mouse(window, &mut userdata.window_state_lock()) }; @@ -1733,106 +1733,20 @@ unsafe fn public_window_callback_inner( primary: true, state: Pressed, position, - button: Left.into(), - }); - result = ProcResult::Value(0); - }, - - WM_LBUTTONUP => { - use winit_core::event::ElementState::Released; - use winit_core::event::MouseButton::Left; - use winit_core::event::WindowEvent::PointerButton; - - unsafe { release_mouse(userdata.window_state_lock()) }; - - update_modifiers(window, userdata); - - let x = util::get_x_lparam(lparam as u32) as i32; - let y = util::get_y_lparam(lparam as u32) as i32; - let position = PhysicalPosition::new(x as f64, y as f64); - - userdata.send_window_event(window, PointerButton { - device_id: None, - primary: true, - state: Released, - position, - button: Left.into(), - }); - result = ProcResult::Value(0); - }, - - WM_RBUTTONDOWN => { - use winit_core::event::ElementState::Pressed; - use winit_core::event::MouseButton::Right; - use winit_core::event::WindowEvent::PointerButton; - - unsafe { capture_mouse(window, &mut userdata.window_state_lock()) }; - - update_modifiers(window, userdata); - - let x = util::get_x_lparam(lparam as u32) as i32; - let y = util::get_y_lparam(lparam as u32) as i32; - let position = PhysicalPosition::new(x as f64, y as f64); - - userdata.send_window_event(window, PointerButton { - device_id: None, - primary: true, - state: Pressed, - position, - button: Right.into(), - }); - result = ProcResult::Value(0); - }, - - WM_RBUTTONUP => { - use winit_core::event::ElementState::Released; - use winit_core::event::MouseButton::Right; - use winit_core::event::WindowEvent::PointerButton; - - unsafe { release_mouse(userdata.window_state_lock()) }; - - update_modifiers(window, userdata); - - let x = util::get_x_lparam(lparam as u32) as i32; - let y = util::get_y_lparam(lparam as u32) as i32; - let position = PhysicalPosition::new(x as f64, y as f64); - - userdata.send_window_event(window, PointerButton { - device_id: None, - primary: true, - state: Released, - position, - button: Right.into(), - }); - result = ProcResult::Value(0); - }, - - WM_MBUTTONDOWN => { - use winit_core::event::ElementState::Pressed; - use winit_core::event::MouseButton::Middle; - use winit_core::event::WindowEvent::PointerButton; - - unsafe { capture_mouse(window, &mut userdata.window_state_lock()) }; - - update_modifiers(window, userdata); - - let x = util::get_x_lparam(lparam as u32) as i32; - let y = util::get_y_lparam(lparam as u32) as i32; - let position = PhysicalPosition::new(x as f64, y as f64); - - userdata.send_window_event(window, PointerButton { - device_id: None, - primary: true, - state: Pressed, - position, - button: Middle.into(), + button: match msg { + WM_LBUTTONDOWN => MouseButton::Left, + WM_RBUTTONDOWN => MouseButton::Right, + WM_MBUTTONDOWN => MouseButton::Middle, + _ => unreachable!(), + } + .into(), }); result = ProcResult::Value(0); }, - WM_MBUTTONUP => { + WM_LBUTTONUP | WM_RBUTTONUP | WM_MBUTTONUP => { use winit_core::event::ElementState::Released; - use winit_core::event::MouseButton::Middle; + use winit_core::event::MouseButton; use winit_core::event::WindowEvent::PointerButton; unsafe { release_mouse(userdata.window_state_lock()) }; @@ -1848,14 +1762,20 @@ unsafe fn public_window_callback_inner( primary: true, state: Released, position, - button: Middle.into(), + button: match msg { + WM_LBUTTONUP => MouseButton::Left, + WM_RBUTTONUP => MouseButton::Right, + WM_MBUTTONUP => MouseButton::Middle, + _ => unreachable!(), + } + .into(), }); result = ProcResult::Value(0); }, WM_XBUTTONDOWN => { use winit_core::event::ElementState::Pressed; - use winit_core::event::MouseButton::{Back, Forward, Other}; + use winit_core::event::MouseButton; use winit_core::event::WindowEvent::PointerButton; let xbutton = util::get_xbutton_wparam(wparam as u32); @@ -1867,25 +1787,25 @@ unsafe fn public_window_callback_inner( let y = util::get_y_lparam(lparam as u32) as i32; let position = PhysicalPosition::new(x as f64, y as f64); + // 1 is defined as back, 2 as forward; other codes are unexpected. + let b = xbutton as u8 + MouseButton::Back as u8 - 1; + userdata.send_window_event(window, PointerButton { device_id: None, primary: true, state: Pressed, position, - button: match xbutton { - 1 => Back, - 2 => Forward, - _ => Other(xbutton), - } - .into(), + // 1 is defined as back, 2 as forward; other codes are unexpected. + button: MouseButton::try_from_u8(b).unwrap().into(), }); result = ProcResult::Value(0); }, WM_XBUTTONUP => { use winit_core::event::ElementState::Released; - use winit_core::event::MouseButton::{Back, Forward, Other}; + use winit_core::event::MouseButton; use winit_core::event::WindowEvent::PointerButton; + let xbutton = util::get_xbutton_wparam(wparam as u32); unsafe { release_mouse(userdata.window_state_lock()) }; @@ -1896,17 +1816,16 @@ unsafe fn public_window_callback_inner( let y = util::get_y_lparam(lparam as u32) as i32; let position = PhysicalPosition::new(x as f64, y as f64); + // 1 is defined as back, 2 as forward; other codes are unexpected. + let b = xbutton as u8 + MouseButton::Back as u8 - 1; + userdata.send_window_event(window, PointerButton { device_id: None, primary: true, state: Released, position, - button: match xbutton { - 1 => Back, - 2 => Forward, - _ => Other(xbutton), - } - .into(), + // 1 is defined as back, 2 as forward; other codes are unexpected. + button: MouseButton::try_from_u8(b).unwrap().into(), }); result = ProcResult::Value(0); }, diff --git a/winit-x11/src/event_processor.rs b/winit-x11/src/event_processor.rs index eaf50260e4..c18c534e6c 100644 --- a/winit-x11/src/event_processor.rs +++ b/winit-x11/src/event_processor.rs @@ -996,7 +996,6 @@ impl EventProcessor { position, button: MouseButton::Middle.into(), }, - xlib::Button3 => WindowEvent::PointerButton { device_id, primary: true, @@ -1020,28 +1019,25 @@ impl EventProcessor { }, phase: TouchPhase::Moved, }, - 8 => WindowEvent::PointerButton { - device_id, - primary: true, - state, - position, - button: MouseButton::Back.into(), - }, - 9 => WindowEvent::PointerButton { + x @ 8..37 => WindowEvent::PointerButton { device_id, primary: true, state, position, - button: MouseButton::Forward.into(), + // Button 8 maps to MouseButton::BACK = 3; 36 maps to MouseButton::Button::Button31. + // 255 is the largest code yielded on X11 (tested). + button: MouseButton::try_from_u8((x - 5) as u8).unwrap().into(), }, - x => WindowEvent::PointerButton { + x @ 37..=0xff => WindowEvent::PointerButton { device_id, primary: true, state, position, - button: MouseButton::Other(x as u16).into(), + // 255 is the largest code yielded on X11 (tested). + button: ButtonSource::Unknown(x as u16), }, + _ => return, }; app.window_event(&self.target, window_id, event); diff --git a/winit/examples/application.rs b/winit/examples/application.rs index 2abc1b428b..a804f48dbf 100644 --- a/winit/examples/application.rs +++ b/winit/examples/application.rs @@ -3,6 +3,7 @@ //! Note that a real application accepting text input **should** support //! the IME interface. See the `ime` example. +use std::borrow::Cow; use std::collections::HashMap; use std::error::Error; use std::fmt::Debug; @@ -485,8 +486,9 @@ impl ApplicationHandler for Application { let mods = window.modifiers; if let Some(action) = state .is_pressed() - .then(|| Self::process_mouse_binding(button.mouse_button(), &mods)) + .then(|| button.mouse_button()) .flatten() + .and_then(|button| Self::process_mouse_binding(button, &mods)) { self.handle_action_with_window(event_loop, window_id, action); } @@ -1145,15 +1147,16 @@ fn modifiers_to_string(mods: ModifiersState) -> String { mods_line } -fn mouse_button_to_string(button: MouseButton) -> &'static str { +fn mouse_button_to_string(button: MouseButton) -> Cow<'static, str> { match button { MouseButton::Left => "LMB", MouseButton::Right => "RMB", MouseButton::Middle => "MMB", MouseButton::Back => "Back", MouseButton::Forward => "Forward", - MouseButton::Other(_) => "", + other => return format!("button {}", other as u8 + 1).into(), } + .into() } #[cfg(web_platform)]