From 1d9c2a4b886df4ad0baf350dccd48a02087bb981 Mon Sep 17 00:00:00 2001 From: Osspial Date: Mon, 6 Jan 2020 17:12:22 -0500 Subject: [PATCH 01/29] Draft improved event API --- src/dpi.rs | 12 +- src/event.rs | 630 +++++++++++++++------------------------------------ 2 files changed, 194 insertions(+), 448 deletions(-) diff --git a/src/dpi.rs b/src/dpi.rs index 8a56ae6e06..dcbeb0049c 100644 --- a/src/dpi.rs +++ b/src/dpi.rs @@ -160,7 +160,7 @@ pub fn validate_scale_factor(scale_factor: f64) -> bool { /// The position is stored as floats, so please be careful. Casting floats to integers truncates the /// fractional part, which can cause noticable issues. To help with that, an `Into<(i32, i32)>` /// implementation is provided which does the rounding for you. -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct LogicalPosition

{ pub x: P, @@ -225,7 +225,7 @@ impl Into<[X; 2]> for LogicalPosition

{ } /// A position represented in physical pixels. -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct PhysicalPosition

{ pub x: P, @@ -290,7 +290,7 @@ impl Into<[X; 2]> for PhysicalPosition

{ } /// A size represented in logical pixels. -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct LogicalSize

{ pub width: P, @@ -355,7 +355,7 @@ impl Into<[X; 2]> for LogicalSize

{ } /// A size represented in physical pixels. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct PhysicalSize

{ pub width: P, @@ -417,7 +417,7 @@ impl Into<[X; 2]> for PhysicalSize

{ } /// A size that's either physical or logical. -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum Size { Physical(PhysicalSize), @@ -459,7 +459,7 @@ impl From> for Size { } /// A position that's either physical or logical. -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum Position { Physical(PhysicalPosition), diff --git a/src/event.rs b/src/event.rs index 47119fa807..0212425aed 100644 --- a/src/event.rs +++ b/src/event.rs @@ -34,10 +34,13 @@ //! //! [event_loop_run]: crate::event_loop::EventLoop::run use instant::Instant; -use std::path::PathBuf; +use std::{ + path::PathBuf, + fmt, +}; use crate::{ - dpi::{LogicalPosition, PhysicalPosition, PhysicalSize}, + dpi::{PhysicalPosition, PhysicalSize}, platform_impl, window::{Theme, WindowId}, }; @@ -56,16 +59,11 @@ pub enum Event<'a, T: 'static> { NewEvents(StartCause), /// Emitted when the OS sends an event to a winit window. - WindowEvent { - window_id: WindowId, - event: WindowEvent<'a>, - }, + WindowEvent(WindowId, WindowEvent), + WindowEventImmediate(WindowId, WindowEventImmediate<'a>), - /// Emitted when the OS sends an event to a device. - DeviceEvent { - device_id: DeviceId, - event: DeviceEvent, - }, + RawPointerEvent(PointerDeviceId, RawPointerEvent), + RawKeyboardEvent(KeyboardDeviceId, RawKeyboardEvent), /// Emitted when an event is sent from [`EventLoopProxy::send_event`](crate::event_loop::EventLoopProxy::send_event) UserEvent(T), @@ -147,8 +145,10 @@ impl<'a, T> Event<'a, T> { use self::Event::*; match self { UserEvent(_) => Err(self), - WindowEvent { window_id, event } => Ok(WindowEvent { window_id, event }), - DeviceEvent { device_id, event } => Ok(DeviceEvent { device_id, event }), + WindowEvent(window_id, event) => Ok(WindowEvent(window_id, event)), + WindowEventImmediate(window_id, event) => Ok(WindowEventImmediate(window_id, event)), + RawPointerEvent(pointer_id, event) => Ok(RawPointerEvent(pointer_id, event)), + RawKeyboardEvent(keyboard_id, event) => Ok(RawKeyboardEvent(keyboard_id, event)), NewEvents(cause) => Ok(NewEvents(cause)), MainEventsCleared => Ok(MainEventsCleared), RedrawRequested(wid) => Ok(RedrawRequested(wid)), @@ -161,21 +161,21 @@ impl<'a, T> Event<'a, T> { /// If the event doesn't contain a reference, turn it into an event with a `'static` lifetime. /// Otherwise, return `None`. - pub fn to_static(self) -> Option> { + pub fn to_static(self) -> Result, Event<'a, T>> { use self::Event::*; match self { - WindowEvent { window_id, event } => event - .to_static() - .map(|event| WindowEvent { window_id, event }), - UserEvent(event) => Some(UserEvent(event)), - DeviceEvent { device_id, event } => Some(DeviceEvent { device_id, event }), - NewEvents(cause) => Some(NewEvents(cause)), - MainEventsCleared => Some(MainEventsCleared), - RedrawRequested(wid) => Some(RedrawRequested(wid)), - RedrawEventsCleared => Some(RedrawEventsCleared), - LoopDestroyed => Some(LoopDestroyed), - Suspended => Some(Suspended), - Resumed => Some(Resumed), + NewEvents(cause) => Ok(NewEvents(cause)), + WindowEvent(window_id, event) => Ok(WindowEvent(window_id, event)), + WindowEventImmediate(window_id, event) => Err(WindowEventImmediate(window_id, event)), + RawPointerEvent(pointer_id, event) => Ok(RawPointerEvent(pointer_id, event)), + RawKeyboardEvent(keyboard_id, event) => Ok(RawKeyboardEvent(keyboard_id, event)), + Suspended => Ok(Suspended), + Resumed => Ok(Resumed), + UserEvent(e) => Ok(UserEvent(e)), + MainEventsCleared => Ok(MainEventsCleared), + RedrawRequested(wid) => Ok(RedrawRequested(wid)), + RedrawEventsCleared => Ok(RedrawEventsCleared), + LoopDestroyed => Ok(LoopDestroyed), } } } @@ -207,8 +207,9 @@ pub enum StartCause { } /// Describes an event from a `Window`. -#[derive(Debug, PartialEq)] -pub enum WindowEvent<'a> { +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub enum WindowEvent { /// The size of the window has changed. Contains the client area's new dimensions. Resized(PhysicalSize), @@ -239,94 +240,92 @@ pub enum WindowEvent<'a> { /// hovered. HoveredFileCancelled, + /// The window gained focus. + FocusedGained, + + /// The window lost focus. + FocustLost, + /// The window received a unicode character. - ReceivedCharacter(char), + Char(char), - /// The window gained or lost focus. - /// - /// The parameter is true if the window has gained focus, and false if it has lost focus. - Focused(bool), - - /// An event from the keyboard has been received. - KeyboardInput { - device_id: DeviceId, - input: KeyboardInput, - /// If `true`, the event was generated synthetically by winit - /// in one of the following circumstances: - /// - /// * Synthetic key press events are generated for all keys pressed - /// when a window gains focus. Likewise, synthetic key release events - /// are generated for all keys pressed when a window goes out of focus. - /// ***Currently, this is only functional on X11 and Windows*** - /// - /// Otherwise, this value is always `false`. - is_synthetic: bool, - }, + KeyPress(Key, ScanCode, KeyFlags), /// The keyboard modifiers have changed. /// + /// This is tracked internally to avoid tracking errors arising from modifier key state changes when events from + /// this device are not being delivered to the application, e.g. due to keyboard focus being elsewhere. + /// /// Platform-specific behavior: /// - **Web**: This API is currently unimplemented on the web. This isn't by design - it's an /// issue, and it should get fixed - but it's the current state of the API. ModifiersChanged(ModifiersState), - /// The cursor has moved on the window. - CursorMoved { - device_id: DeviceId, + PointerCreated(PointerId), + PointerDestroyed(PointerId), - /// (x,y) coords in pixels relative to the top-left corner of the window. Because the range of this data is - /// limited by the display area and it may have been transformed by the OS to implement effects such as cursor - /// acceleration, it should not be used to implement non-cursor-like interactions such as 3D camera control. - position: PhysicalPosition, - #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"] - modifiers: ModifiersState, - }, + PointerMoved(PointerId, PhysicalPosition), - /// The cursor has entered the window. - CursorEntered { device_id: DeviceId }, + PointerEntered(PointerId), + PointerLeft(PointerId), - /// The cursor has left the window. - CursorLeft { device_id: DeviceId }, + PointerForce(PointerId, Force), - /// A mouse wheel movement or touchpad scroll occurred. - MouseWheel { - device_id: DeviceId, - delta: MouseScrollDelta, - phase: TouchPhase, - #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"] - modifiers: ModifiersState, - }, + PointerPress(PointerId, PointerButton, PointerFlags), - /// An mouse button press has been received. - MouseInput { - device_id: DeviceId, - state: ElementState, - button: MouseButton, - #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"] - modifiers: ModifiersState, - }, + ScrollDiscrete(Vector), + ScrollSmooth(Vector), - /// Touchpad pressure event. + /// The system window theme has changed. /// - /// At the moment, only supported on Apple forcetouch-capable macbooks. - /// The parameters are: pressure level (value between 0 and 1 representing how hard the touchpad - /// is being pressed) and stage (integer representing the click level). - TouchpadPressure { - device_id: DeviceId, - pressure: f32, - stage: i64, - }, + /// Applications might wish to react to this to change the theme of the content of the window + /// when the system changes the window theme. + /// + /// At the moment this is only supported on Windows. + ThemeChanged(Theme), +} - /// Motion on some analog axis. May report data redundant to other, more specific events. - AxisMotion { - device_id: DeviceId, - axis: AxisId, - value: f64, - }, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Vector { + pub x: T, + pub y: T, +} + +bitflags!{ + pub struct KeyFlags: u16 { + const IS_DOWN = 1 << 0; + const IS_SYNTHETIC = 1 << 0; + const IS_REPEAT = 1 << 1; + } +} + +impl KeyFlags { + pub fn is_down(&self) -> bool { + self.contains(Self::IS_DOWN) + } + pub fn is_synthetic(&self) -> bool { + self.contains(Self::IS_SYNTHETIC) + } + pub fn is_repeat(&self) -> bool { + self.contains(Self::IS_REPEAT) + } +} + +bitflags!{ + pub struct PointerFlags: u16 { + const IS_DOWN = 1 << 0; + } +} - /// Touch event has been received - Touch(Touch), +impl PointerFlags { + pub fn is_down(&self) -> bool { + self.contains(Self::IS_DOWN) + } +} +#[derive(Debug, PartialEq)] +pub enum WindowEventImmediate<'a> { /// The window's scale factor has changed. /// /// The following user actions can cause DPI changes: @@ -336,333 +335,126 @@ pub enum WindowEvent<'a> { /// * Moving the window to a display with a different scale factor. /// /// After this event callback has been processed, the window will be resized to whatever value - /// is pointed to by the `new_inner_size` reference. By default, this will contain the size suggested + /// is pointed to by the `PhysicalSize` reference. By default, this will contain the size suggested /// by the OS, but it can be changed to any value. /// /// For more information about DPI in general, see the [`dpi`](crate::dpi) module. - ScaleFactorChanged { - scale_factor: f64, - new_inner_size: &'a mut PhysicalSize, - }, - - /// The system window theme has changed. - /// - /// Applications might wish to react to this to change the theme of the content of the window - /// when the system changes the window theme. - /// - /// At the moment this is only supported on Windows. - ThemeChanged(Theme), + ScaleFactorChanged(f64, &'a mut PhysicalSize), } -impl Clone for WindowEvent<'static> { - fn clone(&self) -> Self { - use self::WindowEvent::*; - return match self { - Resized(size) => Resized(size.clone()), - Moved(pos) => Moved(pos.clone()), - CloseRequested => CloseRequested, - Destroyed => Destroyed, - DroppedFile(file) => DroppedFile(file.clone()), - HoveredFile(file) => HoveredFile(file.clone()), - HoveredFileCancelled => HoveredFileCancelled, - ReceivedCharacter(c) => ReceivedCharacter(*c), - Focused(f) => Focused(*f), - KeyboardInput { - device_id, - input, - is_synthetic, - } => KeyboardInput { - device_id: *device_id, - input: *input, - is_synthetic: *is_synthetic, - }, - - ModifiersChanged(modifiers) => ModifiersChanged(modifiers.clone()), - #[allow(deprecated)] - CursorMoved { - device_id, - position, - modifiers, - } => CursorMoved { - device_id: *device_id, - position: *position, - modifiers: *modifiers, - }, - CursorEntered { device_id } => CursorEntered { - device_id: *device_id, - }, - CursorLeft { device_id } => CursorLeft { - device_id: *device_id, - }, - #[allow(deprecated)] - MouseWheel { - device_id, - delta, - phase, - modifiers, - } => MouseWheel { - device_id: *device_id, - delta: *delta, - phase: *phase, - modifiers: *modifiers, - }, - #[allow(deprecated)] - MouseInput { - device_id, - state, - button, - modifiers, - } => MouseInput { - device_id: *device_id, - state: *state, - button: *button, - modifiers: *modifiers, - }, - TouchpadPressure { - device_id, - pressure, - stage, - } => TouchpadPressure { - device_id: *device_id, - pressure: *pressure, - stage: *stage, - }, - AxisMotion { - device_id, - axis, - value, - } => AxisMotion { - device_id: *device_id, - axis: *axis, - value: *value, - }, - Touch(touch) => Touch(*touch), - ThemeChanged(theme) => ThemeChanged(theme.clone()), - ScaleFactorChanged { .. } => { - unreachable!("Static event can't be about scale factor changing") - } - }; - } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum PointerId { + MouseId(MouseId), + TouchId(TouchId), + // PenId(PenId), } -impl<'a> WindowEvent<'a> { - pub fn to_static(self) -> Option> { - use self::WindowEvent::*; - match self { - Resized(size) => Some(Resized(size)), - Moved(position) => Some(Moved(position)), - CloseRequested => Some(CloseRequested), - Destroyed => Some(Destroyed), - DroppedFile(file) => Some(DroppedFile(file)), - HoveredFile(file) => Some(HoveredFile(file)), - HoveredFileCancelled => Some(HoveredFileCancelled), - ReceivedCharacter(c) => Some(ReceivedCharacter(c)), - Focused(focused) => Some(Focused(focused)), - KeyboardInput { - device_id, - input, - is_synthetic, - } => Some(KeyboardInput { - device_id, - input, - is_synthetic, - }), - ModifiersChanged(modifiers) => Some(ModifiersChanged(modifiers)), - #[allow(deprecated)] - CursorMoved { - device_id, - position, - modifiers, - } => Some(CursorMoved { - device_id, - position, - modifiers, - }), - CursorEntered { device_id } => Some(CursorEntered { device_id }), - CursorLeft { device_id } => Some(CursorLeft { device_id }), - #[allow(deprecated)] - MouseWheel { - device_id, - delta, - phase, - modifiers, - } => Some(MouseWheel { - device_id, - delta, - phase, - modifiers, - }), - #[allow(deprecated)] - MouseInput { - device_id, - state, - button, - modifiers, - } => Some(MouseInput { - device_id, - state, - button, - modifiers, - }), - TouchpadPressure { - device_id, - pressure, - stage, - } => Some(TouchpadPressure { - device_id, - pressure, - stage, - }), - AxisMotion { - device_id, - axis, - value, - } => Some(AxisMotion { - device_id, - axis, - value, - }), - Touch(touch) => Some(Touch(touch)), - ThemeChanged(theme) => Some(ThemeChanged(theme)), - ScaleFactorChanged { .. } => None, - } - } -} +/// Hardware-dependent keyboard scan code. +pub type ScanCode = u32; +pub type PointerButton = u8; -/// Identifier of an input device. -/// -/// Whenever you receive an event arising from a particular input device, this event contains a `DeviceId` which -/// identifies its origin. Note that devices may be virtual (representing an on-screen cursor and keyboard focus) or -/// physical. Virtual devices typically aggregate inputs from multiple physical devices. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct DeviceId(pub(crate) platform_impl::DeviceId); - -impl DeviceId { - /// Returns a dummy `DeviceId`, useful for unit testing. The only guarantee made about the return - /// value of this function is that it will always be equal to itself and to future values returned - /// by this function. No other guarantees are made. This may be equal to a real `DeviceId`. +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum RawPointerEvent { + /// A device has been added. + Added, + /// A device has been removed. + Removed, + Pressed(PointerButton), + Released(PointerButton), + /// Relative change in physical position of a pointing device. /// - /// **Passing this into a winit function will result in undefined behavior.** - pub unsafe fn dummy() -> Self { - DeviceId(platform_impl::DeviceId::dummy()) - } + /// This represents raw, unfiltered physical motion, NOT the position of the mouse. Accordingly, + /// the values provided here are the change in position of the mouse since the previous + /// `MovedRelative` event. + MovedRelative(Vector), + /// Change in absolute position of a pointing device. + /// + /// The `PhysicalPosition` value is the new position of the cursor relative to the desktop. This + /// generally doesn't get output by standard mouse devices, but can get output from tablet devices. + MovedAbsolute(PhysicalPosition), + /// Change in rotation of mouse wheel. + Wheel(Vector), } -/// Represents raw hardware events that are not associated with any particular window. -/// -/// Useful for interactions that diverge significantly from a conventional 2D GUI, such as 3D camera or first-person -/// game controls. Many physical actions, such as mouse movement, can produce both device and window events. Because -/// window events typically arise from virtual devices (corresponding to GUI cursors and keyboard focus) the device IDs -/// may not match. -/// -/// Note that these events are delivered regardless of input focus. -#[derive(Clone, Debug, PartialEq)] -pub enum DeviceEvent { +/// Raw keyboard events. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum RawKeyboardEvent { + /// A keyboard device has been added. Added, + /// A keyboard device has been removed. Removed, + Pressed(Option, ScanCode), + Released(Option, ScanCode), +} - /// Change in physical position of a pointing device. - /// - /// This represents raw, unfiltered physical motion. Not to be confused with `WindowEvent::CursorMoved`. - MouseMotion { - /// (x, y) change in position in unspecified units. - /// - /// Different devices may use different units. - delta: (f64, f64), - }, - - /// Physical scroll event - MouseWheel { - delta: MouseScrollDelta, - }, +/// A typed identifier for a mouse device. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct MouseId(pub(crate) platform_impl::MouseId); - /// Motion on some analog axis. This event will be reported for all arbitrary input devices - /// that winit supports on this platform, including mouse devices. If the device is a mouse - /// device then this will be reported alongside the MouseMotion event. - Motion { - axis: AxisId, - value: f64, - }, +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct TouchId(pub(crate) platform_impl::TouchId); - Button { - button: ButtonId, - state: ElementState, - }, +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct PointerDeviceId(pub(crate) platform_impl::PointerDeviceId); - Key(KeyboardInput), +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct KeyboardDeviceId(pub(crate) platform_impl::KeyboardDeviceId); - Text { - codepoint: char, - }, +impl MouseId { + /// Returns a dummy `MouseId`, useful for unit testing. The only guarantee made about the return + /// value of this function is that it will always be equal to itself and to future values returned + /// by this function. No other guarantees are made. This may be equal to a real `MouseId`. + /// + /// **Passing this into a winit function will result in undefined behavior.** + pub unsafe fn dummy() -> Self { + MouseId(platform_impl::MouseId::dummy()) + } } -/// Describes a keyboard input event. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct KeyboardInput { - /// Identifies the physical key pressed +impl PointerDeviceId { + /// Returns a dummy `PointerDeviceId`, useful for unit testing. The only guarantee made about the return + /// value of this function is that it will always be equal to itself and to future values returned + /// by this function. No other guarantees are made. This may be equal to a real `PointerDeviceId`. /// - /// This should not change if the user adjusts the host's keyboard map. Use when the physical location of the - /// key is more important than the key's host GUI semantics, such as for movement controls in a first-person - /// game. - pub scancode: ScanCode, - - pub state: ElementState, + /// **Passing this into a winit function will result in undefined behavior.** + pub unsafe fn dummy() -> Self { + PointerDeviceId(platform_impl::PointerDeviceId::dummy()) + } +} - /// Identifies the semantic meaning of the key +impl KeyboardDeviceId { + /// Returns a dummy `KeyboardDeviceId`, useful for unit testing. The only guarantee made about the return + /// value of this function is that it will always be equal to itself and to future values returned + /// by this function. No other guarantees are made. This may be equal to a real `KeyboardDeviceId`. /// - /// Use when the semantics of the key are more important than the physical location of the key, such as when - /// implementing appropriate behavior for "page up." - pub virtual_keycode: Option, + /// **Passing this into a winit function will result in undefined behavior.** + pub unsafe fn dummy() -> Self { + KeyboardDeviceId(platform_impl::KeyboardDeviceId::dummy()) + } +} - /// Modifier keys active at the time of this input. - /// - /// This is tracked internally to avoid tracking errors arising from modifier key state changes when events from - /// this device are not being delivered to the application, e.g. due to keyboard focus being elsewhere. - #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"] - pub modifiers: ModifiersState, +impl fmt::Debug for MouseId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + self.0.fmt(f) + } } -/// Describes touch-screen input state. -#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum TouchPhase { - Started, - Moved, - Ended, - Cancelled, +impl fmt::Debug for PointerDeviceId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + self.0.fmt(f) + } } -/// Represents a touch event -/// -/// Every time the user touches the screen, a new `Start` event with an unique -/// identifier for the finger is generated. When the finger is lifted, an `End` -/// event is generated with the same finger id. -/// -/// After a `Start` event has been emitted, there may be zero or more `Move` -/// events when the finger is moved or the touch pressure changes. -/// -/// The finger id may be reused by the system after an `End` event. The user -/// should assume that a new `Start` event received with the same id has nothing -/// to do with the old finger and is a new finger. -/// -/// A `Cancelled` event is emitted when the system has canceled tracking this -/// touch, such as when the window loses focus, or on iOS if the user moves the -/// device against their face. -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct Touch { - pub device_id: DeviceId, - pub phase: TouchPhase, - pub location: PhysicalPosition, - /// Describes how hard the screen was pressed. May be `None` if the platform - /// does not support pressure sensitivity. - /// - /// ## Platform-specific - /// - /// - Only available on **iOS** 9.0+ and **Windows** 8+. - pub force: Option, - /// Unique identifier of a finger. - pub id: u64, +impl fmt::Debug for KeyboardDeviceId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + self.0.fmt(f) + } +} + +impl fmt::Debug for TouchId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + self.0.fmt(f) + } } /// Describes the force of a touch event @@ -721,57 +513,11 @@ impl Force { } } -/// Hardware-dependent keyboard scan code. -pub type ScanCode = u32; - -/// Identifier for a specific analog axis on some device. -pub type AxisId = u32; - -/// Identifier for a specific button on some device. -pub type ButtonId = u32; - -/// Describes the input state of a key. -#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum ElementState { - Pressed, - Released, -} - -/// Describes a button of a mouse controller. -#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum MouseButton { - Left, - Right, - Middle, - Other(u8), -} - -/// Describes a difference in the mouse scroll wheel state. -#[derive(Debug, Clone, Copy, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum MouseScrollDelta { - /// Amount in lines or rows to scroll in the horizontal - /// and vertical directions. - /// - /// Positive values indicate movement forward - /// (away from the user) or rightwards. - LineDelta(f32, f32), - /// Amount in pixels to scroll in the horizontal and - /// vertical direction. - /// - /// Scroll events are expressed as a PixelDelta if - /// supported by the device (eg. a touchpad) and - /// platform. - PixelDelta(LogicalPosition), -} - /// Symbolic name for a keyboard key. #[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)] #[repr(u32)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum VirtualKeyCode { +pub enum Key { /// The '1' key over the letters. Key1, /// The '2' key over the letters. From 46176f3698255ed321635a6acf1714179d10cb7d Mon Sep 17 00:00:00 2001 From: Osspial Date: Tue, 7 Jan 2020 17:23:17 -0500 Subject: [PATCH 02/29] Modify press flags --- src/event.rs | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/event.rs b/src/event.rs index 0212425aed..0b853f16ae 100644 --- a/src/event.rs +++ b/src/event.rs @@ -249,7 +249,7 @@ pub enum WindowEvent { /// The window received a unicode character. Char(char), - KeyPress(Key, ScanCode, KeyFlags), + KeyPress(Key, ScanCode, KeyPressFlags), /// The keyboard modifiers have changed. /// @@ -271,7 +271,7 @@ pub enum WindowEvent { PointerForce(PointerId, Force), - PointerPress(PointerId, PointerButton, PointerFlags), + PointerPress(PointerId, PointerButton, PointerPressFlags), ScrollDiscrete(Vector), ScrollSmooth(Vector), @@ -293,14 +293,27 @@ pub struct Vector { } bitflags!{ - pub struct KeyFlags: u16 { + pub struct KeyPressFlags: u8 { const IS_DOWN = 1 << 0; const IS_SYNTHETIC = 1 << 0; const IS_REPEAT = 1 << 1; } } -impl KeyFlags { +bitflags!{ + pub struct PointerPressFlags: u8 { + const IS_DOWN = 1 << 0; + const IS_DOUBLE = 1 << 1; + } +} + +bitflags!{ + pub struct RawPressFlags: u8 { + const IS_DOWN = 1 << 0; + } +} + +impl KeyPressFlags { pub fn is_down(&self) -> bool { self.contains(Self::IS_DOWN) } @@ -312,13 +325,16 @@ impl KeyFlags { } } -bitflags!{ - pub struct PointerFlags: u16 { - const IS_DOWN = 1 << 0; +impl PointerPressFlags { + pub fn is_down(&self) -> bool { + self.contains(Self::IS_DOWN) + } + pub fn is_double(&self) -> bool { + self.contains(Self::IS_DOUBLE) } } -impl PointerFlags { +impl RawPressFlags { pub fn is_down(&self) -> bool { self.contains(Self::IS_DOWN) } @@ -359,8 +375,7 @@ pub enum RawPointerEvent { Added, /// A device has been removed. Removed, - Pressed(PointerButton), - Released(PointerButton), + Press(PointerButton, RawPressFlags), /// Relative change in physical position of a pointing device. /// /// This represents raw, unfiltered physical motion, NOT the position of the mouse. Accordingly, @@ -383,8 +398,7 @@ pub enum RawKeyboardEvent { Added, /// A keyboard device has been removed. Removed, - Pressed(Option, ScanCode), - Released(Option, ScanCode), + Press(Option, ScanCode, RawPressFlags), } /// A typed identifier for a mouse device. From 896f04228a6b3ef40a6fd853170fcd839cfd955b Mon Sep 17 00:00:00 2001 From: Osspial Date: Tue, 7 Jan 2020 17:57:38 -0500 Subject: [PATCH 03/29] Unify KeyPress and PointerPress flags --- src/event.rs | 50 +++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/event.rs b/src/event.rs index 0b853f16ae..471f32d8bb 100644 --- a/src/event.rs +++ b/src/event.rs @@ -249,7 +249,7 @@ pub enum WindowEvent { /// The window received a unicode character. Char(char), - KeyPress(Key, ScanCode, KeyPressFlags), + KeyPress(Key, ScanCode, PressFlags), /// The keyboard modifiers have changed. /// @@ -271,7 +271,7 @@ pub enum WindowEvent { PointerForce(PointerId, Force), - PointerPress(PointerId, PointerButton, PointerPressFlags), + PointerPress(PointerId, PointerButton, PressFlags), ScrollDiscrete(Vector), ScrollSmooth(Vector), @@ -293,44 +293,48 @@ pub struct Vector { } bitflags!{ - pub struct KeyPressFlags: u8 { + pub struct PressFlags: u8 { + /// Whether or not the button is currently pressed down. const IS_DOWN = 1 << 0; - const IS_SYNTHETIC = 1 << 0; + /// Whether or not this is a repeat press. + /// + /// This has different semantics for key and pointer events: + /// - If true in key event, the user has held down the key long enough to send duplicate + /// events. + /// - If true in pointer event, the user has pressed and released multiple times in a short + /// interval. + /// + /// TODO: SHOULD THIS BE SPLIT INTO TWO SEPARATE FLAGS? const IS_REPEAT = 1 << 1; - } -} - -bitflags!{ - pub struct PointerPressFlags: u8 { - const IS_DOWN = 1 << 0; - const IS_DOUBLE = 1 << 1; + /// If set, the event was generated synthetically by winit + /// in one of the following circumstances: + /// + /// * Synthetic key press events are generated for all keys pressed + /// when a window gains focus. Likewise, synthetic key release events + /// are generated for all keys pressed when a window goes out of focus. + /// ***Currently, this is only functional on X11 and Windows*** + /// + /// Otherwise, this value is always `false`. + const IS_SYNTHETIC = 1 << 2; } } bitflags!{ pub struct RawPressFlags: u8 { + /// Whether or not the button is currently pressed down. const IS_DOWN = 1 << 0; } } -impl KeyPressFlags { +impl PressFlags { pub fn is_down(&self) -> bool { self.contains(Self::IS_DOWN) } - pub fn is_synthetic(&self) -> bool { - self.contains(Self::IS_SYNTHETIC) - } pub fn is_repeat(&self) -> bool { self.contains(Self::IS_REPEAT) } -} - -impl PointerPressFlags { - pub fn is_down(&self) -> bool { - self.contains(Self::IS_DOWN) - } - pub fn is_double(&self) -> bool { - self.contains(Self::IS_DOUBLE) + pub fn is_synthetic(&self) -> bool { + self.contains(Self::IS_SYNTHETIC) } } From 761e456cfbd26550df6aeb7bb21ea27c3b18701a Mon Sep 17 00:00:00 2001 From: Osspial Date: Wed, 8 Jan 2020 14:29:08 -0500 Subject: [PATCH 04/29] Add AppEvent and ScrollStarted/Ended events --- src/event.rs | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/src/event.rs b/src/event.rs index 471f32d8bb..17091d851b 100644 --- a/src/event.rs +++ b/src/event.rs @@ -58,6 +58,8 @@ pub enum Event<'a, T: 'static> { /// [`ControlFlow::WaitUntil`](crate::event_loop::ControlFlow::WaitUntil) has elapsed. NewEvents(StartCause), + AppEvent(AppEvent), + /// Emitted when the OS sends an event to a winit window. WindowEvent(WindowId, WindowEvent), WindowEventImmediate(WindowId, WindowEventImmediate<'a>), @@ -68,12 +70,6 @@ pub enum Event<'a, T: 'static> { /// Emitted when an event is sent from [`EventLoopProxy::send_event`](crate::event_loop::EventLoopProxy::send_event) UserEvent(T), - /// Emitted when the application has been suspended. - Suspended, - - /// Emitted when the application has been resumed. - Resumed, - /// Emitted when all of the event loop's input events have been processed and redraw processing /// is about to begin. /// @@ -116,28 +112,13 @@ pub enum Event<'a, T: 'static> { LoopDestroyed, } -impl Clone for Event<'static, T> { - fn clone(&self) -> Self { - use self::Event::*; - match self { - WindowEvent { window_id, event } => WindowEvent { - window_id: *window_id, - event: event.clone(), - }, - UserEvent(event) => UserEvent(event.clone()), - DeviceEvent { device_id, event } => DeviceEvent { - device_id: *device_id, - event: event.clone(), - }, - NewEvents(cause) => NewEvents(cause.clone()), - MainEventsCleared => MainEventsCleared, - RedrawRequested(wid) => RedrawRequested(*wid), - RedrawEventsCleared => RedrawEventsCleared, - LoopDestroyed => LoopDestroyed, - Suspended => Suspended, - Resumed => Resumed, - } - } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum AppEvent { + /// Emitted when the application has been suspended. + Suspended, + + /// Emitted when the application has been resumed. + Resumed, } impl<'a, T> Event<'a, T> { @@ -273,8 +254,10 @@ pub enum WindowEvent { PointerPress(PointerId, PointerButton, PressFlags), + ScrollStarted, ScrollDiscrete(Vector), ScrollSmooth(Vector), + ScrollEnded, /// The system window theme has changed. /// From 986be4e8f926563ebcc0b02b5849a950c6c6bca9 Mon Sep 17 00:00:00 2001 From: Osspial Date: Wed, 8 Jan 2020 15:02:27 -0500 Subject: [PATCH 05/29] Rename Key to LogicalKey --- src/event.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/event.rs b/src/event.rs index 17091d851b..3215482d32 100644 --- a/src/event.rs +++ b/src/event.rs @@ -230,7 +230,7 @@ pub enum WindowEvent { /// The window received a unicode character. Char(char), - KeyPress(Key, ScanCode, PressFlags), + KeyPress(LogicalKey, ScanCode, PressFlags), /// The keyboard modifiers have changed. /// @@ -385,7 +385,7 @@ pub enum RawKeyboardEvent { Added, /// A keyboard device has been removed. Removed, - Press(Option, ScanCode, RawPressFlags), + Press(Option, ScanCode, RawPressFlags), } /// A typed identifier for a mouse device. @@ -518,7 +518,7 @@ impl Force { #[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)] #[repr(u32)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum Key { +pub enum LogicalKey { /// The '1' key over the letters. Key1, /// The '2' key over the letters. From 0afc10cff176c3db7e31a532db3baf1e7bf14324 Mon Sep 17 00:00:00 2001 From: Osspial Date: Fri, 15 May 2020 18:55:35 -0400 Subject: [PATCH 06/29] Implement opaque press events --- src/event.rs | 125 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 41 deletions(-) diff --git a/src/event.rs b/src/event.rs index 3215482d32..0766fcead1 100644 --- a/src/event.rs +++ b/src/event.rs @@ -230,7 +230,7 @@ pub enum WindowEvent { /// The window received a unicode character. Char(char), - KeyPress(LogicalKey, ScanCode, PressFlags), + KeyPress(KeyPress), /// The keyboard modifiers have changed. /// @@ -252,7 +252,7 @@ pub enum WindowEvent { PointerForce(PointerId, Force), - PointerPress(PointerId, PointerButton, PressFlags), + PointerPress(PointerId, PointerPress), ScrollStarted, ScrollDiscrete(Vector), @@ -275,55 +275,98 @@ pub struct Vector { pub y: T, } -bitflags!{ - pub struct PressFlags: u8 { - /// Whether or not the button is currently pressed down. - const IS_DOWN = 1 << 0; - /// Whether or not this is a repeat press. - /// - /// This has different semantics for key and pointer events: - /// - If true in key event, the user has held down the key long enough to send duplicate - /// events. - /// - If true in pointer event, the user has pressed and released multiple times in a short - /// interval. - /// - /// TODO: SHOULD THIS BE SPLIT INTO TWO SEPARATE FLAGS? - const IS_REPEAT = 1 << 1; - /// If set, the event was generated synthetically by winit - /// in one of the following circumstances: - /// - /// * Synthetic key press events are generated for all keys pressed - /// when a window gains focus. Likewise, synthetic key release events - /// are generated for all keys pressed when a window goes out of focus. - /// ***Currently, this is only functional on X11 and Windows*** - /// - /// Otherwise, this value is always `false`. - const IS_SYNTHETIC = 1 << 2; - } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct KeyPress { + pub(crate) logical_key: Option, + pub(crate) scan_code: u32, + pub(crate) is_down: bool, + pub(crate) repeat_count: u32, + pub(crate) is_synthetic: bool, } -bitflags!{ - pub struct RawPressFlags: u8 { - /// Whether or not the button is currently pressed down. - const IS_DOWN = 1 << 0; - } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct RawKeyPress { + pub(crate) logical_key: Option, + pub(crate) scan_code: u32, + pub(crate) is_down: bool, } -impl PressFlags { +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct PointerPress { + pub(crate) button: u8, + pub(crate) is_down: bool, + pub(crate) click_count: u32, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct RawPointerPress { + pub(crate) button: u8, + pub(crate) is_down: bool, +} + +impl KeyPress { + pub fn logical_key(&self) -> Option { + self.logical_key + } + pub fn scan_code(&self) -> u32 { + self.scan_code + } pub fn is_down(&self) -> bool { - self.contains(Self::IS_DOWN) + self.is_down } - pub fn is_repeat(&self) -> bool { - self.contains(Self::IS_REPEAT) + /// The number of repeat events that have been generated from the user holding the key down. Is + /// `0` for the first event, and increments by `1` for every further event. + /// + /// TODO PHRASE BETTER + pub fn repeat_count(&self) -> u32 { + self.repeat_count } + /// If set, the event was generated synthetically by winit + /// in one of the following circumstances: + /// + /// * Synthetic key press events are generated for all keys pressed + /// when a window gains focus. Likewise, synthetic key release events + /// are generated for all keys pressed when a window goes out of focus. + /// ***Currently, this is only functional on X11 and Windows*** + /// + /// Otherwise, this value is always `false`. pub fn is_synthetic(&self) -> bool { - self.contains(Self::IS_SYNTHETIC) + self.is_synthetic + } +} + +impl RawKeyPress { + pub fn logical_key(&self) -> Option { + self.logical_key + } + pub fn scan_code(&self) -> u32 { + self.scan_code + } + pub fn is_down(&self) -> bool { + self.is_down + } +} + +impl PointerPress { + pub fn button(&self) -> u8 { + self.button + } + pub fn is_down(&self) -> bool { + self.is_down + } + /// The number of clicks the user has made in the same spot. Is `1` for the first click, `2` + /// for the second click, etc. + pub fn click_count(&self) -> u32 { + self.click_count } } -impl RawPressFlags { +impl RawPointerPress { + pub fn button(&self) -> u8 { + self.button + } pub fn is_down(&self) -> bool { - self.contains(Self::IS_DOWN) + self.is_down } } @@ -362,7 +405,7 @@ pub enum RawPointerEvent { Added, /// A device has been removed. Removed, - Press(PointerButton, RawPressFlags), + Press(RawPointerPress), /// Relative change in physical position of a pointing device. /// /// This represents raw, unfiltered physical motion, NOT the position of the mouse. Accordingly, @@ -385,7 +428,7 @@ pub enum RawKeyboardEvent { Added, /// A keyboard device has been removed. Removed, - Press(Option, ScanCode, RawPressFlags), + Press(RawKeyPress), } /// A typed identifier for a mouse device. From 68761e648627ffa2df1c252a660f08a1803990f0 Mon Sep 17 00:00:00 2001 From: Osspial Date: Fri, 15 May 2020 20:20:21 -0400 Subject: [PATCH 07/29] Address @Ralith's feedback --- src/event.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/event.rs b/src/event.rs index 0766fcead1..c0865519db 100644 --- a/src/event.rs +++ b/src/event.rs @@ -280,7 +280,7 @@ pub struct KeyPress { pub(crate) logical_key: Option, pub(crate) scan_code: u32, pub(crate) is_down: bool, - pub(crate) repeat_count: u32, + pub(crate) is_repeat: bool, pub(crate) is_synthetic: bool, } @@ -314,11 +314,8 @@ impl KeyPress { pub fn is_down(&self) -> bool { self.is_down } - /// The number of repeat events that have been generated from the user holding the key down. Is - /// `0` for the first event, and increments by `1` for every further event. - /// - /// TODO PHRASE BETTER - pub fn repeat_count(&self) -> u32 { + /// Is `true` if the user has held down the key long enough to send duplicate events. + pub fn is_repeat(&self) -> bool { self.repeat_count } /// If set, the event was generated synthetically by winit @@ -354,8 +351,8 @@ impl PointerPress { pub fn is_down(&self) -> bool { self.is_down } - /// The number of clicks the user has made in the same spot. Is `1` for the first click, `2` - /// for the second click, etc. + /// The number of clicks the user has made in the same spot within the system's double-click + /// interval. `1` is emitted on the first click, `2` is emitted on the second click, etc. pub fn click_count(&self) -> u32 { self.click_count } From 60245601a555e28722fe6c1c542fee1a14b38495 Mon Sep 17 00:00:00 2001 From: Osspial Date: Sat, 16 May 2020 00:01:28 -0400 Subject: [PATCH 08/29] Redefine PointerButton --- src/event.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/src/event.rs b/src/event.rs index c0865519db..8b28431b95 100644 --- a/src/event.rs +++ b/src/event.rs @@ -293,14 +293,14 @@ pub struct RawKeyPress { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct PointerPress { - pub(crate) button: u8, + pub(crate) button: PointerButton, pub(crate) is_down: bool, pub(crate) click_count: u32, } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct RawPointerPress { - pub(crate) button: u8, + pub(crate) button: PointerButton, pub(crate) is_down: bool, } @@ -345,7 +345,7 @@ impl RawKeyPress { } impl PointerPress { - pub fn button(&self) -> u8 { + pub fn button(&self) -> PointerButton { self.button } pub fn is_down(&self) -> bool { @@ -359,7 +359,7 @@ impl PointerPress { } impl RawPointerPress { - pub fn button(&self) -> u8 { + pub fn button(&self) -> PointerButton { self.button } pub fn is_down(&self) -> bool { @@ -392,9 +392,63 @@ pub enum PointerId { // PenId(PenId), } -/// Hardware-dependent keyboard scan code. -pub type ScanCode = u32; -pub type PointerButton = u8; +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[repr(transparent)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(transparent))] +pub struct PointerButton(PointerButtonInner); + +/// We use an internal enum rather than exposing the variants directly so that the `BUTTON_n` +/// constants are formatted and exposed in a similar style to the `{MOUSE|TOUCH|PEN}_n` constants. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(rename = "PointerButton"))] +enum PointerButtonInner { + Button0, + Button1, + Button2, + Button3, + Button4, + Button5, +} + +impl PointerButton { + pub const MOUSE_LEFT: Self = Self::BUTTON_0; + pub const MOUSE_RIGHT: Self = Self::BUTTON_1; + pub const MOUSE_MIDDLE: Self = Self::BUTTON_2; + pub const MOUSE_X1: Self = Self::BUTTON_3; + pub const MOUSE_X2: Self = Self::BUTTON_4; + + pub const TOUCH_DOWN: Self = Self::BUTTON_0; + + // pub const PEN_DOWN: Self = Self::BUTTON_0; + // pub const PEN_BARREL: Self = Self::BUTTON_1; + // pub const PEN_ERASER: Self = Self::BUTTON_5; + + pub const BUTTON_0: Self = Self(PointerButtonInner::Button0); + pub const BUTTON_1: Self = Self(PointerButtonInner::Button1); + pub const BUTTON_2: Self = Self(PointerButtonInner::Button2); + pub const BUTTON_3: Self = Self(PointerButtonInner::Button3); + pub const BUTTON_4: Self = Self(PointerButtonInner::Button4); + // pub const BUTTON_5: Self = Self(PointerButtonInner::Button5); + + pub fn as_u8(&self) -> u8 { self.0 } + pub fn is_mouse_left(&self) -> bool { *self == Self::MOUSE_LEFT } + pub fn is_mouse_right(&self) -> bool { *self == Self::MOUSE_RIGHT } + pub fn is_mouse_middle(&self) -> bool { *self == Self::MOUSE_MIDDLE } + pub fn is_mouse_x1(&self) -> bool { *self == Self::MOUSE_X1 } + pub fn is_mouse_x2(&self) -> bool { *self == Self::MOUSE_X2 } + pub fn is_touch_down(&self) -> bool { *self == Self::TOUCH_DOWN } + // pub fn is_pen_down(&self) -> bool { *self == Self::PEN_DOWN } + // pub fn is_pen_barrel(&self) -> bool { *self == Self::PEN_BARREL } + // pub fn is_pen_eraser(&self) -> bool { *self == Self::PEN_ERASER } + pub fn is_button_0(&self) -> bool { *self == Self::BUTTON_0 } + pub fn is_button_1(&self) -> bool { *self == Self::BUTTON_1 } + pub fn is_button_2(&self) -> bool { *self == Self::BUTTON_2 } + pub fn is_button_3(&self) -> bool { *self == Self::BUTTON_3 } + pub fn is_button_4(&self) -> bool { *self == Self::BUTTON_4 } + // pub fn is_button_5(&self) -> bool { *self == Self::BUTTON_5 } +} #[derive(Debug, Copy, Clone, PartialEq)] pub enum RawPointerEvent { From 63dae5d7109a7bf5fc382f99f9fc9266fdbf7b74 Mon Sep 17 00:00:00 2001 From: Osspial Date: Sat, 16 May 2020 16:22:48 -0400 Subject: [PATCH 09/29] Make this compile on Windows --- src/dpi.rs | 503 +++++------ src/event.rs | 221 +++-- src/platform/windows.rs | 26 +- src/platform_impl/windows/drop_handler.rs | 29 +- src/platform_impl/windows/event.rs | 351 ++++---- src/platform_impl/windows/event_loop.rs | 835 +++++++++--------- .../windows/event_loop/runner.rs | 21 +- src/platform_impl/windows/mod.rs | 79 +- src/platform_impl/windows/raw_input.rs | 41 +- src/window.rs | 73 +- 10 files changed, 1118 insertions(+), 1061 deletions(-) diff --git a/src/dpi.rs b/src/dpi.rs index dcbeb0049c..8dd1d5638d 100644 --- a/src/dpi.rs +++ b/src/dpi.rs @@ -155,347 +155,238 @@ pub fn validate_scale_factor(scale_factor: f64) -> bool { scale_factor.is_sign_positive() && scale_factor.is_normal() } -/// A position represented in logical pixels. -/// -/// The position is stored as floats, so please be careful. Casting floats to integers truncates the -/// fractional part, which can cause noticable issues. To help with that, an `Into<(i32, i32)>` -/// implementation is provided which does the rounding for you. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct LogicalPosition

{ - pub x: P, - pub y: P, -} - -impl

LogicalPosition

{ - #[inline] - pub const fn new(x: P, y: P) -> Self { - LogicalPosition { x, y } - } -} - -impl LogicalPosition

{ - #[inline] - pub fn from_physical>, X: Pixel>( - physical: T, - scale_factor: f64, - ) -> Self { - physical.into().to_logical(scale_factor) - } - - #[inline] - pub fn to_physical(&self, scale_factor: f64) -> PhysicalPosition { - assert!(validate_scale_factor(scale_factor)); - let x = self.x.into() * scale_factor; - let y = self.y.into() * scale_factor; - PhysicalPosition::new(x, y).cast() - } - - #[inline] - pub fn cast(&self) -> LogicalPosition { - LogicalPosition { - x: self.x.cast(), - y: self.y.cast(), +macro_rules! dpi_type { + ( + let h = $h:ident; + let v = $v:ident; + + $(#[$logical_meta:meta])* + pub struct $LogicalType:ident; + $(#[$physical_meta:meta])* + pub struct $PhysicalType:ident; + $(#[$unified_meta:meta])* + pub enum $UnifiedType:ident; + ) => { + $(#[$logical_meta])* + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] + #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] + pub struct $LogicalType

{ + pub $h: P, + pub $v: P, } - } -} -impl From<(X, X)> for LogicalPosition

{ - fn from((x, y): (X, X)) -> LogicalPosition

{ - LogicalPosition::new(x.cast(), y.cast()) - } -} - -impl Into<(X, X)> for LogicalPosition

{ - fn into(self: Self) -> (X, X) { - (self.x.cast(), self.y.cast()) - } -} - -impl From<[X; 2]> for LogicalPosition

{ - fn from([x, y]: [X; 2]) -> LogicalPosition

{ - LogicalPosition::new(x.cast(), y.cast()) - } -} - -impl Into<[X; 2]> for LogicalPosition

{ - fn into(self: Self) -> [X; 2] { - [self.x.cast(), self.y.cast()] - } -} - -/// A position represented in physical pixels. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct PhysicalPosition

{ - pub x: P, - pub y: P, -} - -impl

PhysicalPosition

{ - #[inline] - pub const fn new(x: P, y: P) -> Self { - PhysicalPosition { x, y } - } -} - -impl PhysicalPosition

{ - #[inline] - pub fn from_logical>, X: Pixel>( - logical: T, - scale_factor: f64, - ) -> Self { - logical.into().to_physical(scale_factor) - } - - #[inline] - pub fn to_logical(&self, scale_factor: f64) -> LogicalPosition { - assert!(validate_scale_factor(scale_factor)); - let x = self.x.into() / scale_factor; - let y = self.y.into() / scale_factor; - LogicalPosition::new(x, y).cast() - } - - #[inline] - pub fn cast(&self) -> PhysicalPosition { - PhysicalPosition { - x: self.x.cast(), - y: self.y.cast(), + impl

$LogicalType

{ + #[inline] + pub const fn new($h: P, $v: P) -> Self { + $LogicalType { $h, $v } + } } - } -} - -impl From<(X, X)> for PhysicalPosition

{ - fn from((x, y): (X, X)) -> PhysicalPosition

{ - PhysicalPosition::new(x.cast(), y.cast()) - } -} -impl Into<(X, X)> for PhysicalPosition

{ - fn into(self: Self) -> (X, X) { - (self.x.cast(), self.y.cast()) - } -} - -impl From<[X; 2]> for PhysicalPosition

{ - fn from([x, y]: [X; 2]) -> PhysicalPosition

{ - PhysicalPosition::new(x.cast(), y.cast()) - } -} - -impl Into<[X; 2]> for PhysicalPosition

{ - fn into(self: Self) -> [X; 2] { - [self.x.cast(), self.y.cast()] - } -} - -/// A size represented in logical pixels. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct LogicalSize

{ - pub width: P, - pub height: P, -} - -impl

LogicalSize

{ - #[inline] - pub const fn new(width: P, height: P) -> Self { - LogicalSize { width, height } - } -} - -impl LogicalSize

{ - #[inline] - pub fn from_physical>, X: Pixel>( - physical: T, - scale_factor: f64, - ) -> Self { - physical.into().to_logical(scale_factor) - } - - #[inline] - pub fn to_physical(&self, scale_factor: f64) -> PhysicalSize { - assert!(validate_scale_factor(scale_factor)); - let width = self.width.into() * scale_factor; - let height = self.height.into() * scale_factor; - PhysicalSize::new(width, height).cast() - } - - #[inline] - pub fn cast(&self) -> LogicalSize { - LogicalSize { - width: self.width.cast(), - height: self.height.cast(), + impl $LogicalType

{ + #[inline] + pub fn from_physical>, X: Pixel>( + physical: T, + scale_factor: f64, + ) -> Self { + physical.into().to_logical(scale_factor) + } + + #[inline] + pub fn to_physical(&self, scale_factor: f64) -> $PhysicalType { + assert!(validate_scale_factor(scale_factor)); + let $h = self.$h.into() * scale_factor; + let $v = self.$v.into() * scale_factor; + $PhysicalType::new($h, $v).cast() + } + + #[inline] + pub fn cast(&self) -> $LogicalType { + $LogicalType { + $h: self.$h.cast(), + $v: self.$v.cast(), + } + } } - } -} - -impl From<(X, X)> for LogicalSize

{ - fn from((x, y): (X, X)) -> LogicalSize

{ - LogicalSize::new(x.cast(), y.cast()) - } -} - -impl Into<(X, X)> for LogicalSize

{ - fn into(self: LogicalSize

) -> (X, X) { - (self.width.cast(), self.height.cast()) - } -} -impl From<[X; 2]> for LogicalSize

{ - fn from([x, y]: [X; 2]) -> LogicalSize

{ - LogicalSize::new(x.cast(), y.cast()) - } -} + impl From<(X, X)> for $LogicalType

{ + fn from(($h, $v): (X, X)) -> $LogicalType

{ + $LogicalType::new($h.cast(), $v.cast()) + } + } -impl Into<[X; 2]> for LogicalSize

{ - fn into(self: Self) -> [X; 2] { - [self.width.cast(), self.height.cast()] - } -} + impl Into<(X, X)> for $LogicalType

{ + fn into(self: Self) -> (X, X) { + (self.$h.cast(), self.$v.cast()) + } + } -/// A size represented in physical pixels. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct PhysicalSize

{ - pub width: P, - pub height: P, -} + impl From<[X; 2]> for $LogicalType

{ + fn from([$h, $v]: [X; 2]) -> $LogicalType

{ + $LogicalType::new($h.cast(), $v.cast()) + } + } -impl

PhysicalSize

{ - #[inline] - pub const fn new(width: P, height: P) -> Self { - PhysicalSize { width, height } - } -} + impl Into<[X; 2]> for $LogicalType

{ + fn into(self: Self) -> [X; 2] { + [self.$h.cast(), self.$v.cast()] + } + } -impl PhysicalSize

{ - #[inline] - pub fn from_logical>, X: Pixel>(logical: T, scale_factor: f64) -> Self { - logical.into().to_physical(scale_factor) - } + $(#[$physical_meta])* + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] + #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] + pub struct $PhysicalType

{ + pub $h: P, + pub $v: P, + } - #[inline] - pub fn to_logical(&self, scale_factor: f64) -> LogicalSize { - assert!(validate_scale_factor(scale_factor)); - let width = self.width.into() / scale_factor; - let height = self.height.into() / scale_factor; - LogicalSize::new(width, height).cast() - } + impl

$PhysicalType

{ + #[inline] + pub const fn new($h: P, $v: P) -> Self { + $PhysicalType { $h, $v } + } + } - #[inline] - pub fn cast(&self) -> PhysicalSize { - PhysicalSize { - width: self.width.cast(), - height: self.height.cast(), + impl $PhysicalType

{ + #[inline] + pub fn from_logical>, X: Pixel>( + logical: T, + scale_factor: f64, + ) -> Self { + logical.into().to_physical(scale_factor) + } + + #[inline] + pub fn to_logical(&self, scale_factor: f64) -> $LogicalType { + assert!(validate_scale_factor(scale_factor)); + let $h = self.$h.into() / scale_factor; + let $v = self.$v.into() / scale_factor; + $LogicalType::new($h, $v).cast() + } + + #[inline] + pub fn cast(&self) -> $PhysicalType { + $PhysicalType { + $h: self.$h.cast(), + $v: self.$v.cast(), + } + } } - } -} -impl From<(X, X)> for PhysicalSize

{ - fn from((x, y): (X, X)) -> PhysicalSize

{ - PhysicalSize::new(x.cast(), y.cast()) - } -} + impl From<(X, X)> for $PhysicalType

{ + fn from(($h, $v): (X, X)) -> $PhysicalType

{ + $PhysicalType::new($h.cast(), $v.cast()) + } + } -impl Into<(X, X)> for PhysicalSize

{ - fn into(self: Self) -> (X, X) { - (self.width.cast(), self.height.cast()) - } -} + impl Into<(X, X)> for $PhysicalType

{ + fn into(self: Self) -> (X, X) { + (self.$h.cast(), self.$v.cast()) + } + } -impl From<[X; 2]> for PhysicalSize

{ - fn from([x, y]: [X; 2]) -> PhysicalSize

{ - PhysicalSize::new(x.cast(), y.cast()) - } -} + impl From<[X; 2]> for $PhysicalType

{ + fn from([$h, $v]: [X; 2]) -> $PhysicalType

{ + $PhysicalType::new($h.cast(), $v.cast()) + } + } -impl Into<[X; 2]> for PhysicalSize

{ - fn into(self: Self) -> [X; 2] { - [self.width.cast(), self.height.cast()] - } -} + impl Into<[X; 2]> for $PhysicalType

{ + fn into(self: Self) -> [X; 2] { + [self.$h.cast(), self.$v.cast()] + } + } -/// A size that's either physical or logical. -#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum Size { - Physical(PhysicalSize), - Logical(LogicalSize), -} + $(#[$unified_meta])* + #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] + #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] + pub enum $UnifiedType { + Physical($PhysicalType), + Logical($LogicalType), + } -impl Size { - pub fn new>(size: S) -> Size { - size.into() - } + impl $UnifiedType { + pub fn new>(val: S) -> $UnifiedType { + val.into() + } + + pub fn to_logical(&self, scale_factor: f64) -> $LogicalType

{ + match *self { + $UnifiedType::Physical(val) => val.to_logical(scale_factor), + $UnifiedType::Logical(val) => val.cast(), + } + } + + pub fn to_physical(&self, scale_factor: f64) -> $PhysicalType

{ + match *self { + $UnifiedType::Physical(val) => val.cast(), + $UnifiedType::Logical(val) => val.to_physical(scale_factor), + } + } + } - pub fn to_logical(&self, scale_factor: f64) -> LogicalSize

{ - match *self { - Size::Physical(size) => size.to_logical(scale_factor), - Size::Logical(size) => size.cast(), + impl From<$PhysicalType

> for $UnifiedType { + #[inline] + fn from(val: $PhysicalType

) -> $UnifiedType { + $UnifiedType::Physical(val.cast()) + } } - } - pub fn to_physical(&self, scale_factor: f64) -> PhysicalSize

{ - match *self { - Size::Physical(size) => size.cast(), - Size::Logical(size) => size.to_physical(scale_factor), + impl From<$LogicalType

> for $UnifiedType { + #[inline] + fn from(val: $LogicalType

) -> $UnifiedType { + $UnifiedType::Logical(val.cast()) + } } - } + }; } -impl From> for Size { - #[inline] - fn from(size: PhysicalSize

) -> Size { - Size::Physical(size.cast()) - } -} +dpi_type!{ + let h = x; + let v = y; -impl From> for Size { - #[inline] - fn from(size: LogicalSize

) -> Size { - Size::Logical(size.cast()) - } + /// A position represented in logical pixels. + pub struct LogicalPosition; + /// A position represented in physical pixels. + pub struct PhysicalPosition; + /// A position that's either physical or logical. + pub enum Position; } -/// A position that's either physical or logical. -#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum Position { - Physical(PhysicalPosition), - Logical(LogicalPosition), +dpi_type!{ + let h = width; + let v = height; + + /// A size represented in logical pixels. + pub struct LogicalSize; + /// A size represented in physical pixels. + pub struct PhysicalSize; + /// A size that's either physical or logical. + pub enum Size; } -impl Position { - pub fn new>(position: S) -> Position { - position.into() - } +dpi_type!{ + let h = x; + let v = y; - pub fn to_logical(&self, scale_factor: f64) -> LogicalPosition

{ - match *self { - Position::Physical(position) => position.to_logical(scale_factor), - Position::Logical(position) => position.cast(), - } - } - - pub fn to_physical(&self, scale_factor: f64) -> PhysicalPosition

{ - match *self { - Position::Physical(position) => position.cast(), - Position::Logical(position) => position.to_physical(scale_factor), - } - } + /// A delta represented in logical pixels. + pub struct LogicalDelta; + /// A delta represented in physical pixels. + pub struct PhysicalDelta; + /// A delta that's either physical or logical. + pub enum Delta; } -impl From> for Position { - #[inline] - fn from(position: PhysicalPosition

) -> Position { - Position::Physical(position.cast()) - } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct UnitlessDelta { + pub x: T, + pub y: T, } -impl From> for Position { +impl UnitlessDelta { #[inline] - fn from(position: LogicalPosition

) -> Position { - Position::Logical(position.cast()) + pub const fn new(x: T, y: T) -> Self { + UnitlessDelta { x, y } } } diff --git a/src/event.rs b/src/event.rs index 8b28431b95..3ca22d3df7 100644 --- a/src/event.rs +++ b/src/event.rs @@ -40,7 +40,7 @@ use std::{ }; use crate::{ - dpi::{PhysicalPosition, PhysicalSize}, + dpi::{PhysicalPosition, PhysicalSize, PhysicalDelta, UnitlessDelta}, platform_impl, window::{Theme, WindowId}, }; @@ -61,8 +61,7 @@ pub enum Event<'a, T: 'static> { AppEvent(AppEvent), /// Emitted when the OS sends an event to a winit window. - WindowEvent(WindowId, WindowEvent), - WindowEventImmediate(WindowId, WindowEventImmediate<'a>), + WindowEvent(WindowId, WindowEvent<'a>), RawPointerEvent(PointerDeviceId, RawPointerEvent), RawKeyboardEvent(KeyboardDeviceId, RawKeyboardEvent), @@ -127,16 +126,14 @@ impl<'a, T> Event<'a, T> { match self { UserEvent(_) => Err(self), WindowEvent(window_id, event) => Ok(WindowEvent(window_id, event)), - WindowEventImmediate(window_id, event) => Ok(WindowEventImmediate(window_id, event)), RawPointerEvent(pointer_id, event) => Ok(RawPointerEvent(pointer_id, event)), RawKeyboardEvent(keyboard_id, event) => Ok(RawKeyboardEvent(keyboard_id, event)), + AppEvent(app_event) => Ok(AppEvent(app_event)), NewEvents(cause) => Ok(NewEvents(cause)), MainEventsCleared => Ok(MainEventsCleared), RedrawRequested(wid) => Ok(RedrawRequested(wid)), RedrawEventsCleared => Ok(RedrawEventsCleared), LoopDestroyed => Ok(LoopDestroyed), - Suspended => Ok(Suspended), - Resumed => Ok(Resumed), } } @@ -146,12 +143,12 @@ impl<'a, T> Event<'a, T> { use self::Event::*; match self { NewEvents(cause) => Ok(NewEvents(cause)), - WindowEvent(window_id, event) => Ok(WindowEvent(window_id, event)), - WindowEventImmediate(window_id, event) => Err(WindowEventImmediate(window_id, event)), + WindowEvent(window_id, event) => event.to_static() + .map(|e| -> Event<'static, T> {WindowEvent(window_id, e)}) + .map_err(|e| -> Event<'a, T> {WindowEvent(window_id, e)}), RawPointerEvent(pointer_id, event) => Ok(RawPointerEvent(pointer_id, event)), RawKeyboardEvent(keyboard_id, event) => Ok(RawKeyboardEvent(keyboard_id, event)), - Suspended => Ok(Suspended), - Resumed => Ok(Resumed), + AppEvent(app_event) => Ok(AppEvent(app_event)), UserEvent(e) => Ok(UserEvent(e)), MainEventsCleared => Ok(MainEventsCleared), RedrawRequested(wid) => Ok(RedrawRequested(wid)), @@ -188,9 +185,9 @@ pub enum StartCause { } /// Describes an event from a `Window`. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum WindowEvent { +pub enum WindowEvent<'a> { /// The size of the window has changed. Contains the client area's new dimensions. Resized(PhysicalSize), @@ -207,28 +204,28 @@ pub enum WindowEvent { /// /// When the user drops multiple files at once, this event will be emitted for each file /// separately. - DroppedFile(PathBuf), + FileDropped(PathBuf), /// A file is being hovered over the window. /// /// When the user hovers multiple files at once, this event will be emitted for each file /// separately. - HoveredFile(PathBuf), + FileHovered(PathBuf), /// A file was hovered, but has exited the window. /// /// There will be a single `HoveredFileCancelled` event triggered even if multiple files were /// hovered. - HoveredFileCancelled, + FileHoverCancelled, /// The window gained focus. - FocusedGained, + FocusGained, /// The window lost focus. - FocustLost, + FocusLost, /// The window received a unicode character. - Char(char), + CharReceived(char), KeyPress(KeyPress), @@ -243,20 +240,16 @@ pub enum WindowEvent { ModifiersChanged(ModifiersState), PointerCreated(PointerId), - PointerDestroyed(PointerId), - + PointerForce(PointerId, Force), PointerMoved(PointerId, PhysicalPosition), - + PointerPress(PointerId, PointerPress), PointerEntered(PointerId), PointerLeft(PointerId), - - PointerForce(PointerId, Force), - - PointerPress(PointerId, PointerPress), + PointerDestroyed(PointerId), ScrollStarted, - ScrollDiscrete(Vector), - ScrollSmooth(Vector), + ScrollLines(UnitlessDelta), + ScrollPixels(PhysicalDelta), ScrollEnded, /// The system window theme has changed. @@ -266,13 +259,87 @@ pub enum WindowEvent { /// /// At the moment this is only supported on Windows. ThemeChanged(Theme), + + /// The window's scale factor has changed. + /// + /// The following user actions can cause DPI changes: + /// + /// * Changing the display's resolution. + /// * Changing the display's scale factor (e.g. in Control Panel on Windows). + /// * Moving the window to a display with a different scale factor. + /// + /// After this event callback has been processed, the window will be resized to whatever value + /// is pointed to by the `PhysicalSize` reference. By default, this will contain the size suggested + /// by the OS, but it can be changed to any value. + /// + /// For more information about DPI in general, see the [`dpi`](crate::dpi) module. + ScaleFactorChanged(f64, &'a mut PhysicalSize), } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct Vector { - pub x: T, - pub y: T, +impl Clone for WindowEvent<'static> { + fn clone(&self) -> Self { + use self::WindowEvent::*; + match *self { + Resized(size) => Resized(size), + Moved(position) => Moved(position), + CloseRequested => CloseRequested, + Destroyed => Destroyed, + FileDropped(ref path) => FileDropped(path.clone()), + FileHovered(ref path) => FileHovered(path.clone()), + FileHoverCancelled => FileHoverCancelled, + FocusGained => FocusGained, + FocusLost => FocusLost, + CharReceived(char) => CharReceived(char), + KeyPress(key_press) => KeyPress(key_press), + ModifiersChanged(state) => ModifiersChanged(state), + PointerCreated(id) => PointerCreated(id), + PointerForce(id, force) => PointerForce(id, force), + PointerMoved(id, position) => PointerMoved(id, position), + PointerPress(id, pointer_press) => PointerPress(id, pointer_press), + PointerEntered(id) => PointerEntered(id), + PointerLeft(id) => PointerLeft(id), + PointerDestroyed(id) => PointerDestroyed(id), + ScrollStarted => ScrollStarted, + ScrollLines(delta) => ScrollLines(delta), + ScrollPixels(delta) => ScrollPixels(delta), + ScrollEnded => ScrollEnded, + ThemeChanged(theme) => ThemeChanged(theme), + ScaleFactorChanged(..) => unreachable!("Static event can't be about scale factor changing") + } + } +} + +impl<'a> WindowEvent<'a> { + pub fn to_static(self) -> Result, WindowEvent<'a>> { + use self::WindowEvent::*; + match self { + Resized(size) => Ok(Resized(size)), + Moved(position) => Ok(Moved(position)), + CloseRequested => Ok(CloseRequested), + Destroyed => Ok(Destroyed), + FileDropped(path) => Ok(FileDropped(path)), + FileHovered(path) => Ok(FileHovered(path)), + FileHoverCancelled => Ok(FileHoverCancelled), + FocusGained => Ok(FocusGained), + FocusLost => Ok(FocusLost), + CharReceived(char) => Ok(CharReceived(char)), + KeyPress(key_press) => Ok(KeyPress(key_press)), + ModifiersChanged(state) => Ok(ModifiersChanged(state)), + PointerCreated(id) => Ok(PointerCreated(id)), + PointerForce(id, force) => Ok(PointerForce(id, force)), + PointerMoved(id, position) => Ok(PointerMoved(id, position)), + PointerPress(id, pointer_press) => Ok(PointerPress(id, pointer_press)), + PointerEntered(id) => Ok(PointerEntered(id)), + PointerLeft(id) => Ok(PointerLeft(id)), + PointerDestroyed(id) => Ok(PointerDestroyed(id)), + ScrollStarted => Ok(ScrollStarted), + ScrollLines(delta) => Ok(ScrollLines(delta)), + ScrollPixels(delta) => Ok(ScrollPixels(delta)), + ScrollEnded => Ok(ScrollEnded), + ThemeChanged(theme) => Ok(ThemeChanged(theme)), + ScaleFactorChanged(..) => Err(self), + } + } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] @@ -308,6 +375,11 @@ impl KeyPress { pub fn logical_key(&self) -> Option { self.logical_key } + + pub fn logical_key_is(&self, key: LogicalKey) -> bool { + self.logical_key == Some(key) + } + pub fn scan_code(&self) -> u32 { self.scan_code } @@ -315,8 +387,10 @@ impl KeyPress { self.is_down } /// Is `true` if the user has held down the key long enough to send duplicate events. + /// + /// Is always `false` if `is_down` is `false`. pub fn is_repeat(&self) -> bool { - self.repeat_count + self.is_repeat } /// If set, the event was generated synthetically by winit /// in one of the following circumstances: @@ -353,6 +427,8 @@ impl PointerPress { } /// The number of clicks the user has made in the same spot within the system's double-click /// interval. `1` is emitted on the first click, `2` is emitted on the second click, etc. + /// + /// Is always `0` if `is_down` is `false`. pub fn click_count(&self) -> u32 { self.click_count } @@ -367,24 +443,6 @@ impl RawPointerPress { } } -#[derive(Debug, PartialEq)] -pub enum WindowEventImmediate<'a> { - /// The window's scale factor has changed. - /// - /// The following user actions can cause DPI changes: - /// - /// * Changing the display's resolution. - /// * Changing the display's scale factor (e.g. in Control Panel on Windows). - /// * Moving the window to a display with a different scale factor. - /// - /// After this event callback has been processed, the window will be resized to whatever value - /// is pointed to by the `PhysicalSize` reference. By default, this will contain the size suggested - /// by the OS, but it can be changed to any value. - /// - /// For more information about DPI in general, see the [`dpi`](crate::dpi) module. - ScaleFactorChanged(f64, &'a mut PhysicalSize), -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum PointerId { MouseId(MouseId), @@ -392,6 +450,29 @@ pub enum PointerId { // PenId(PenId), } +impl PointerId { + pub fn is_mouse_id(&self) -> bool { + match *self { + PointerId::MouseId(_) => true, + _ => false, + } + } + + pub fn is_touch_id(&self) -> bool { + match *self { + PointerId::TouchId(_) => true, + _ => false, + } + } + + // pub fn is_pen_id(&self) -> bool { + // match *self { + // PointerId::PenId(_) => true, + // _ => false, + // } + // } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[repr(transparent)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -404,50 +485,50 @@ pub struct PointerButton(PointerButtonInner); #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(rename = "PointerButton"))] enum PointerButtonInner { - Button0, Button1, Button2, Button3, Button4, Button5, + // Button6, } impl PointerButton { - pub const MOUSE_LEFT: Self = Self::BUTTON_0; - pub const MOUSE_RIGHT: Self = Self::BUTTON_1; - pub const MOUSE_MIDDLE: Self = Self::BUTTON_2; - pub const MOUSE_X1: Self = Self::BUTTON_3; - pub const MOUSE_X2: Self = Self::BUTTON_4; + pub const MOUSE_LEFT: Self = Self::BUTTON_1; + pub const MOUSE_RIGHT: Self = Self::BUTTON_2; + pub const MOUSE_MIDDLE: Self = Self::BUTTON_3; + pub const MOUSE_X1: Self = Self::BUTTON_4; + pub const MOUSE_X2: Self = Self::BUTTON_5; - pub const TOUCH_DOWN: Self = Self::BUTTON_0; + pub const TOUCH_CONTACT: Self = Self::BUTTON_1; - // pub const PEN_DOWN: Self = Self::BUTTON_0; - // pub const PEN_BARREL: Self = Self::BUTTON_1; - // pub const PEN_ERASER: Self = Self::BUTTON_5; + // pub const PEN_DOWN: Self = Self::BUTTON_1; + // pub const PEN_BARREL: Self = Self::BUTTON_2; + // pub const PEN_ERASER: Self = Self::BUTTON_6; - pub const BUTTON_0: Self = Self(PointerButtonInner::Button0); pub const BUTTON_1: Self = Self(PointerButtonInner::Button1); pub const BUTTON_2: Self = Self(PointerButtonInner::Button2); pub const BUTTON_3: Self = Self(PointerButtonInner::Button3); pub const BUTTON_4: Self = Self(PointerButtonInner::Button4); - // pub const BUTTON_5: Self = Self(PointerButtonInner::Button5); + pub const BUTTON_5: Self = Self(PointerButtonInner::Button5); + // pub const BUTTON_6: Self = Self(PointerButtonInner::Button6); - pub fn as_u8(&self) -> u8 { self.0 } + pub fn as_u8(&self) -> u8 { self.0 as u8 } pub fn is_mouse_left(&self) -> bool { *self == Self::MOUSE_LEFT } pub fn is_mouse_right(&self) -> bool { *self == Self::MOUSE_RIGHT } pub fn is_mouse_middle(&self) -> bool { *self == Self::MOUSE_MIDDLE } pub fn is_mouse_x1(&self) -> bool { *self == Self::MOUSE_X1 } pub fn is_mouse_x2(&self) -> bool { *self == Self::MOUSE_X2 } - pub fn is_touch_down(&self) -> bool { *self == Self::TOUCH_DOWN } - // pub fn is_pen_down(&self) -> bool { *self == Self::PEN_DOWN } + pub fn is_touch_contact(&self) -> bool { *self == Self::TOUCH_CONTACT } + // pub fn is_pen_contact(&self) -> bool { *self == Self::PEN_CONTACT } // pub fn is_pen_barrel(&self) -> bool { *self == Self::PEN_BARREL } // pub fn is_pen_eraser(&self) -> bool { *self == Self::PEN_ERASER } - pub fn is_button_0(&self) -> bool { *self == Self::BUTTON_0 } pub fn is_button_1(&self) -> bool { *self == Self::BUTTON_1 } pub fn is_button_2(&self) -> bool { *self == Self::BUTTON_2 } pub fn is_button_3(&self) -> bool { *self == Self::BUTTON_3 } pub fn is_button_4(&self) -> bool { *self == Self::BUTTON_4 } - // pub fn is_button_5(&self) -> bool { *self == Self::BUTTON_5 } + pub fn is_button_5(&self) -> bool { *self == Self::BUTTON_5 } + // pub fn is_button_6(&self) -> bool { *self == Self::BUTTON_6 } } #[derive(Debug, Copy, Clone, PartialEq)] @@ -462,14 +543,14 @@ pub enum RawPointerEvent { /// This represents raw, unfiltered physical motion, NOT the position of the mouse. Accordingly, /// the values provided here are the change in position of the mouse since the previous /// `MovedRelative` event. - MovedRelative(Vector), + MovedRelative(PhysicalDelta), /// Change in absolute position of a pointing device. /// /// The `PhysicalPosition` value is the new position of the cursor relative to the desktop. This /// generally doesn't get output by standard mouse devices, but can get output from tablet devices. MovedAbsolute(PhysicalPosition), /// Change in rotation of mouse wheel. - Wheel(Vector), + Wheel(UnitlessDelta), } /// Raw keyboard events. diff --git a/src/platform/windows.rs b/src/platform/windows.rs index a356f1e1c0..8741b6754d 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -9,7 +9,7 @@ use winapi::shared::windef::HWND; use crate::{ dpi::PhysicalSize, - event::DeviceId, + event::{PointerDeviceId, KeyboardDeviceId}, event_loop::EventLoop, monitor::MonitorHandle, platform_impl::{EventLoop as WindowsEventLoop, WinIcon}, @@ -160,19 +160,39 @@ impl MonitorHandleExtWindows for MonitorHandle { } } -/// Additional methods on `DeviceId` that are specific to Windows. +/// Additional methods on device IDs that are specific to Windows. pub trait DeviceIdExtWindows { /// Returns an identifier that persistently refers to this specific device. /// /// Will return `None` if the device is no longer available. fn persistent_identifier(&self) -> Option; + + /// Returns the handle of the device - `HANDLE`. + fn handle(&self) -> *mut c_void; } -impl DeviceIdExtWindows for DeviceId { +impl DeviceIdExtWindows for PointerDeviceId { #[inline] fn persistent_identifier(&self) -> Option { self.0.persistent_identifier() } + + #[inline] + fn handle(&self) -> *mut c_void { + self.0.handle() as _ + } +} + +impl DeviceIdExtWindows for KeyboardDeviceId { + #[inline] + fn persistent_identifier(&self) -> Option { + self.0.persistent_identifier() + } + + #[inline] + fn handle(&self) -> *mut c_void { + self.0.handle() as _ + } } /// Additional methods on `Icon` that are specific to Windows. diff --git a/src/platform_impl/windows/drop_handler.rs b/src/platform_impl/windows/drop_handler.rs index f6c7a044d4..cbcda08e0f 100644 --- a/src/platform_impl/windows/drop_handler.rs +++ b/src/platform_impl/windows/drop_handler.rs @@ -24,7 +24,7 @@ use winapi::{ use crate::platform_impl::platform::WindowId; -use crate::{event::Event, window::WindowId as SuperWindowId}; +use crate::event::{Event, WindowEvent}; #[repr(C)] pub struct FileDropHandlerData { @@ -92,13 +92,12 @@ impl FileDropHandler { _pt: *const POINTL, pdwEffect: *mut DWORD, ) -> HRESULT { - use crate::event::WindowEvent::HoveredFile; let drop_handler = Self::from_interface(this); let hdrop = Self::iterate_filenames(pDataObj, |filename| { - drop_handler.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(drop_handler.window)), - event: HoveredFile(filename), - }); + drop_handler.send_event(Event::WindowEvent( + WindowId(drop_handler.window).into(), + WindowEvent::FileHovered(filename), + )); }); drop_handler.hovered_is_valid = hdrop.is_some(); drop_handler.cursor_effect = if drop_handler.hovered_is_valid { @@ -124,13 +123,12 @@ impl FileDropHandler { } pub unsafe extern "system" fn DragLeave(this: *mut IDropTarget) -> HRESULT { - use crate::event::WindowEvent::HoveredFileCancelled; let drop_handler = Self::from_interface(this); if drop_handler.hovered_is_valid { - drop_handler.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(drop_handler.window)), - event: HoveredFileCancelled, - }); + drop_handler.send_event(Event::WindowEvent( + WindowId(drop_handler.window).into(), + WindowEvent::FileHoverCancelled + )); } S_OK @@ -143,13 +141,12 @@ impl FileDropHandler { _pt: *const POINTL, _pdwEffect: *mut DWORD, ) -> HRESULT { - use crate::event::WindowEvent::DroppedFile; let drop_handler = Self::from_interface(this); let hdrop = Self::iterate_filenames(pDataObj, |filename| { - drop_handler.send_event(Event::WindowEvent { - window_id: SuperWindowId(WindowId(drop_handler.window)), - event: DroppedFile(filename), - }); + drop_handler.send_event(Event::WindowEvent( + WindowId(drop_handler.window).into(), + WindowEvent::FileDropped(filename), + )); }); if let Some(hdrop) = hdrop { shellapi::DragFinish(hdrop); diff --git a/src/platform_impl/windows/event.rs b/src/platform_impl/windows/event.rs index 49501f1a3c..4ccef008a2 100644 --- a/src/platform_impl/windows/event.rs +++ b/src/platform_impl/windows/event.rs @@ -5,7 +5,7 @@ use std::{ sync::atomic::{AtomicBool, AtomicPtr, Ordering}, }; -use crate::event::{ModifiersState, ScanCode, VirtualKeyCode}; +use crate::event::{ModifiersState, LogicalKey}; use winapi::{ shared::minwindef::{HKL, HKL__, LPARAM, UINT, WPARAM}, @@ -160,159 +160,159 @@ fn layout_uses_altgr() -> bool { } } -pub fn vkey_to_winit_vkey(vkey: c_int) -> Option { +pub fn vkey_to_winit_vkey(vkey: c_int) -> Option { // VK_* codes are documented here https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx match vkey { - //winuser::VK_LBUTTON => Some(VirtualKeyCode::Lbutton), - //winuser::VK_RBUTTON => Some(VirtualKeyCode::Rbutton), - //winuser::VK_CANCEL => Some(VirtualKeyCode::Cancel), - //winuser::VK_MBUTTON => Some(VirtualKeyCode::Mbutton), - //winuser::VK_XBUTTON1 => Some(VirtualKeyCode::Xbutton1), - //winuser::VK_XBUTTON2 => Some(VirtualKeyCode::Xbutton2), - winuser::VK_BACK => Some(VirtualKeyCode::Back), - winuser::VK_TAB => Some(VirtualKeyCode::Tab), - //winuser::VK_CLEAR => Some(VirtualKeyCode::Clear), - winuser::VK_RETURN => Some(VirtualKeyCode::Return), - winuser::VK_LSHIFT => Some(VirtualKeyCode::LShift), - winuser::VK_RSHIFT => Some(VirtualKeyCode::RShift), - winuser::VK_LCONTROL => Some(VirtualKeyCode::LControl), - winuser::VK_RCONTROL => Some(VirtualKeyCode::RControl), - winuser::VK_LMENU => Some(VirtualKeyCode::LAlt), - winuser::VK_RMENU => Some(VirtualKeyCode::RAlt), - winuser::VK_PAUSE => Some(VirtualKeyCode::Pause), - winuser::VK_CAPITAL => Some(VirtualKeyCode::Capital), - winuser::VK_KANA => Some(VirtualKeyCode::Kana), - //winuser::VK_HANGUEL => Some(VirtualKeyCode::Hanguel), - //winuser::VK_HANGUL => Some(VirtualKeyCode::Hangul), - //winuser::VK_JUNJA => Some(VirtualKeyCode::Junja), - //winuser::VK_FINAL => Some(VirtualKeyCode::Final), - //winuser::VK_HANJA => Some(VirtualKeyCode::Hanja), - winuser::VK_KANJI => Some(VirtualKeyCode::Kanji), - winuser::VK_ESCAPE => Some(VirtualKeyCode::Escape), - winuser::VK_CONVERT => Some(VirtualKeyCode::Convert), - winuser::VK_NONCONVERT => Some(VirtualKeyCode::NoConvert), - //winuser::VK_ACCEPT => Some(VirtualKeyCode::Accept), - //winuser::VK_MODECHANGE => Some(VirtualKeyCode::Modechange), - winuser::VK_SPACE => Some(VirtualKeyCode::Space), - winuser::VK_PRIOR => Some(VirtualKeyCode::PageUp), - winuser::VK_NEXT => Some(VirtualKeyCode::PageDown), - winuser::VK_END => Some(VirtualKeyCode::End), - winuser::VK_HOME => Some(VirtualKeyCode::Home), - winuser::VK_LEFT => Some(VirtualKeyCode::Left), - winuser::VK_UP => Some(VirtualKeyCode::Up), - winuser::VK_RIGHT => Some(VirtualKeyCode::Right), - winuser::VK_DOWN => Some(VirtualKeyCode::Down), - //winuser::VK_SELECT => Some(VirtualKeyCode::Select), - //winuser::VK_PRINT => Some(VirtualKeyCode::Print), - //winuser::VK_EXECUTE => Some(VirtualKeyCode::Execute), - winuser::VK_SNAPSHOT => Some(VirtualKeyCode::Snapshot), - winuser::VK_INSERT => Some(VirtualKeyCode::Insert), - winuser::VK_DELETE => Some(VirtualKeyCode::Delete), - //winuser::VK_HELP => Some(VirtualKeyCode::Help), - 0x30 => Some(VirtualKeyCode::Key0), - 0x31 => Some(VirtualKeyCode::Key1), - 0x32 => Some(VirtualKeyCode::Key2), - 0x33 => Some(VirtualKeyCode::Key3), - 0x34 => Some(VirtualKeyCode::Key4), - 0x35 => Some(VirtualKeyCode::Key5), - 0x36 => Some(VirtualKeyCode::Key6), - 0x37 => Some(VirtualKeyCode::Key7), - 0x38 => Some(VirtualKeyCode::Key8), - 0x39 => Some(VirtualKeyCode::Key9), - 0x41 => Some(VirtualKeyCode::A), - 0x42 => Some(VirtualKeyCode::B), - 0x43 => Some(VirtualKeyCode::C), - 0x44 => Some(VirtualKeyCode::D), - 0x45 => Some(VirtualKeyCode::E), - 0x46 => Some(VirtualKeyCode::F), - 0x47 => Some(VirtualKeyCode::G), - 0x48 => Some(VirtualKeyCode::H), - 0x49 => Some(VirtualKeyCode::I), - 0x4A => Some(VirtualKeyCode::J), - 0x4B => Some(VirtualKeyCode::K), - 0x4C => Some(VirtualKeyCode::L), - 0x4D => Some(VirtualKeyCode::M), - 0x4E => Some(VirtualKeyCode::N), - 0x4F => Some(VirtualKeyCode::O), - 0x50 => Some(VirtualKeyCode::P), - 0x51 => Some(VirtualKeyCode::Q), - 0x52 => Some(VirtualKeyCode::R), - 0x53 => Some(VirtualKeyCode::S), - 0x54 => Some(VirtualKeyCode::T), - 0x55 => Some(VirtualKeyCode::U), - 0x56 => Some(VirtualKeyCode::V), - 0x57 => Some(VirtualKeyCode::W), - 0x58 => Some(VirtualKeyCode::X), - 0x59 => Some(VirtualKeyCode::Y), - 0x5A => Some(VirtualKeyCode::Z), - winuser::VK_LWIN => Some(VirtualKeyCode::LWin), - winuser::VK_RWIN => Some(VirtualKeyCode::RWin), - winuser::VK_APPS => Some(VirtualKeyCode::Apps), - winuser::VK_SLEEP => Some(VirtualKeyCode::Sleep), - winuser::VK_NUMPAD0 => Some(VirtualKeyCode::Numpad0), - winuser::VK_NUMPAD1 => Some(VirtualKeyCode::Numpad1), - winuser::VK_NUMPAD2 => Some(VirtualKeyCode::Numpad2), - winuser::VK_NUMPAD3 => Some(VirtualKeyCode::Numpad3), - winuser::VK_NUMPAD4 => Some(VirtualKeyCode::Numpad4), - winuser::VK_NUMPAD5 => Some(VirtualKeyCode::Numpad5), - winuser::VK_NUMPAD6 => Some(VirtualKeyCode::Numpad6), - winuser::VK_NUMPAD7 => Some(VirtualKeyCode::Numpad7), - winuser::VK_NUMPAD8 => Some(VirtualKeyCode::Numpad8), - winuser::VK_NUMPAD9 => Some(VirtualKeyCode::Numpad9), - winuser::VK_MULTIPLY => Some(VirtualKeyCode::Multiply), - winuser::VK_ADD => Some(VirtualKeyCode::Add), - //winuser::VK_SEPARATOR => Some(VirtualKeyCode::Separator), - winuser::VK_SUBTRACT => Some(VirtualKeyCode::Subtract), - winuser::VK_DECIMAL => Some(VirtualKeyCode::Decimal), - winuser::VK_DIVIDE => Some(VirtualKeyCode::Divide), - winuser::VK_F1 => Some(VirtualKeyCode::F1), - winuser::VK_F2 => Some(VirtualKeyCode::F2), - winuser::VK_F3 => Some(VirtualKeyCode::F3), - winuser::VK_F4 => Some(VirtualKeyCode::F4), - winuser::VK_F5 => Some(VirtualKeyCode::F5), - winuser::VK_F6 => Some(VirtualKeyCode::F6), - winuser::VK_F7 => Some(VirtualKeyCode::F7), - winuser::VK_F8 => Some(VirtualKeyCode::F8), - winuser::VK_F9 => Some(VirtualKeyCode::F9), - winuser::VK_F10 => Some(VirtualKeyCode::F10), - winuser::VK_F11 => Some(VirtualKeyCode::F11), - winuser::VK_F12 => Some(VirtualKeyCode::F12), - winuser::VK_F13 => Some(VirtualKeyCode::F13), - winuser::VK_F14 => Some(VirtualKeyCode::F14), - winuser::VK_F15 => Some(VirtualKeyCode::F15), - winuser::VK_F16 => Some(VirtualKeyCode::F16), - winuser::VK_F17 => Some(VirtualKeyCode::F17), - winuser::VK_F18 => Some(VirtualKeyCode::F18), - winuser::VK_F19 => Some(VirtualKeyCode::F19), - winuser::VK_F20 => Some(VirtualKeyCode::F20), - winuser::VK_F21 => Some(VirtualKeyCode::F21), - winuser::VK_F22 => Some(VirtualKeyCode::F22), - winuser::VK_F23 => Some(VirtualKeyCode::F23), - winuser::VK_F24 => Some(VirtualKeyCode::F24), - winuser::VK_NUMLOCK => Some(VirtualKeyCode::Numlock), - winuser::VK_SCROLL => Some(VirtualKeyCode::Scroll), - winuser::VK_BROWSER_BACK => Some(VirtualKeyCode::NavigateBackward), - winuser::VK_BROWSER_FORWARD => Some(VirtualKeyCode::NavigateForward), - winuser::VK_BROWSER_REFRESH => Some(VirtualKeyCode::WebRefresh), - winuser::VK_BROWSER_STOP => Some(VirtualKeyCode::WebStop), - winuser::VK_BROWSER_SEARCH => Some(VirtualKeyCode::WebSearch), - winuser::VK_BROWSER_FAVORITES => Some(VirtualKeyCode::WebFavorites), - winuser::VK_BROWSER_HOME => Some(VirtualKeyCode::WebHome), - winuser::VK_VOLUME_MUTE => Some(VirtualKeyCode::Mute), - winuser::VK_VOLUME_DOWN => Some(VirtualKeyCode::VolumeDown), - winuser::VK_VOLUME_UP => Some(VirtualKeyCode::VolumeUp), - winuser::VK_MEDIA_NEXT_TRACK => Some(VirtualKeyCode::NextTrack), - winuser::VK_MEDIA_PREV_TRACK => Some(VirtualKeyCode::PrevTrack), - winuser::VK_MEDIA_STOP => Some(VirtualKeyCode::MediaStop), - winuser::VK_MEDIA_PLAY_PAUSE => Some(VirtualKeyCode::PlayPause), - winuser::VK_LAUNCH_MAIL => Some(VirtualKeyCode::Mail), - winuser::VK_LAUNCH_MEDIA_SELECT => Some(VirtualKeyCode::MediaSelect), - /*winuser::VK_LAUNCH_APP1 => Some(VirtualKeyCode::Launch_app1), - winuser::VK_LAUNCH_APP2 => Some(VirtualKeyCode::Launch_app2),*/ - winuser::VK_OEM_PLUS => Some(VirtualKeyCode::Equals), - winuser::VK_OEM_COMMA => Some(VirtualKeyCode::Comma), - winuser::VK_OEM_MINUS => Some(VirtualKeyCode::Minus), - winuser::VK_OEM_PERIOD => Some(VirtualKeyCode::Period), + //winuser::VK_LBUTTON => Some(LogicalKey::Lbutton), + //winuser::VK_RBUTTON => Some(LogicalKey::Rbutton), + //winuser::VK_CANCEL => Some(LogicalKey::Cancel), + //winuser::VK_MBUTTON => Some(LogicalKey::Mbutton), + //winuser::VK_XBUTTON1 => Some(LogicalKey::Xbutton1), + //winuser::VK_XBUTTON2 => Some(LogicalKey::Xbutton2), + winuser::VK_BACK => Some(LogicalKey::Back), + winuser::VK_TAB => Some(LogicalKey::Tab), + //winuser::VK_CLEAR => Some(LogicalKey::Clear), + winuser::VK_RETURN => Some(LogicalKey::Return), + winuser::VK_LSHIFT => Some(LogicalKey::LShift), + winuser::VK_RSHIFT => Some(LogicalKey::RShift), + winuser::VK_LCONTROL => Some(LogicalKey::LControl), + winuser::VK_RCONTROL => Some(LogicalKey::RControl), + winuser::VK_LMENU => Some(LogicalKey::LAlt), + winuser::VK_RMENU => Some(LogicalKey::RAlt), + winuser::VK_PAUSE => Some(LogicalKey::Pause), + winuser::VK_CAPITAL => Some(LogicalKey::Capital), + winuser::VK_KANA => Some(LogicalKey::Kana), + //winuser::VK_HANGUEL => Some(LogicalKey::Hanguel), + //winuser::VK_HANGUL => Some(LogicalKey::Hangul), + //winuser::VK_JUNJA => Some(LogicalKey::Junja), + //winuser::VK_FINAL => Some(LogicalKey::Final), + //winuser::VK_HANJA => Some(LogicalKey::Hanja), + winuser::VK_KANJI => Some(LogicalKey::Kanji), + winuser::VK_ESCAPE => Some(LogicalKey::Escape), + winuser::VK_CONVERT => Some(LogicalKey::Convert), + winuser::VK_NONCONVERT => Some(LogicalKey::NoConvert), + //winuser::VK_ACCEPT => Some(LogicalKey::Accept), + //winuser::VK_MODECHANGE => Some(LogicalKey::Modechange), + winuser::VK_SPACE => Some(LogicalKey::Space), + winuser::VK_PRIOR => Some(LogicalKey::PageUp), + winuser::VK_NEXT => Some(LogicalKey::PageDown), + winuser::VK_END => Some(LogicalKey::End), + winuser::VK_HOME => Some(LogicalKey::Home), + winuser::VK_LEFT => Some(LogicalKey::Left), + winuser::VK_UP => Some(LogicalKey::Up), + winuser::VK_RIGHT => Some(LogicalKey::Right), + winuser::VK_DOWN => Some(LogicalKey::Down), + //winuser::VK_SELECT => Some(LogicalKey::Select), + //winuser::VK_PRINT => Some(LogicalKey::Print), + //winuser::VK_EXECUTE => Some(LogicalKey::Execute), + winuser::VK_SNAPSHOT => Some(LogicalKey::Snapshot), + winuser::VK_INSERT => Some(LogicalKey::Insert), + winuser::VK_DELETE => Some(LogicalKey::Delete), + //winuser::VK_HELP => Some(LogicalKey::Help), + 0x30 => Some(LogicalKey::Key0), + 0x31 => Some(LogicalKey::Key1), + 0x32 => Some(LogicalKey::Key2), + 0x33 => Some(LogicalKey::Key3), + 0x34 => Some(LogicalKey::Key4), + 0x35 => Some(LogicalKey::Key5), + 0x36 => Some(LogicalKey::Key6), + 0x37 => Some(LogicalKey::Key7), + 0x38 => Some(LogicalKey::Key8), + 0x39 => Some(LogicalKey::Key9), + 0x41 => Some(LogicalKey::A), + 0x42 => Some(LogicalKey::B), + 0x43 => Some(LogicalKey::C), + 0x44 => Some(LogicalKey::D), + 0x45 => Some(LogicalKey::E), + 0x46 => Some(LogicalKey::F), + 0x47 => Some(LogicalKey::G), + 0x48 => Some(LogicalKey::H), + 0x49 => Some(LogicalKey::I), + 0x4A => Some(LogicalKey::J), + 0x4B => Some(LogicalKey::K), + 0x4C => Some(LogicalKey::L), + 0x4D => Some(LogicalKey::M), + 0x4E => Some(LogicalKey::N), + 0x4F => Some(LogicalKey::O), + 0x50 => Some(LogicalKey::P), + 0x51 => Some(LogicalKey::Q), + 0x52 => Some(LogicalKey::R), + 0x53 => Some(LogicalKey::S), + 0x54 => Some(LogicalKey::T), + 0x55 => Some(LogicalKey::U), + 0x56 => Some(LogicalKey::V), + 0x57 => Some(LogicalKey::W), + 0x58 => Some(LogicalKey::X), + 0x59 => Some(LogicalKey::Y), + 0x5A => Some(LogicalKey::Z), + winuser::VK_LWIN => Some(LogicalKey::LWin), + winuser::VK_RWIN => Some(LogicalKey::RWin), + winuser::VK_APPS => Some(LogicalKey::Apps), + winuser::VK_SLEEP => Some(LogicalKey::Sleep), + winuser::VK_NUMPAD0 => Some(LogicalKey::Numpad0), + winuser::VK_NUMPAD1 => Some(LogicalKey::Numpad1), + winuser::VK_NUMPAD2 => Some(LogicalKey::Numpad2), + winuser::VK_NUMPAD3 => Some(LogicalKey::Numpad3), + winuser::VK_NUMPAD4 => Some(LogicalKey::Numpad4), + winuser::VK_NUMPAD5 => Some(LogicalKey::Numpad5), + winuser::VK_NUMPAD6 => Some(LogicalKey::Numpad6), + winuser::VK_NUMPAD7 => Some(LogicalKey::Numpad7), + winuser::VK_NUMPAD8 => Some(LogicalKey::Numpad8), + winuser::VK_NUMPAD9 => Some(LogicalKey::Numpad9), + winuser::VK_MULTIPLY => Some(LogicalKey::Multiply), + winuser::VK_ADD => Some(LogicalKey::Add), + //winuser::VK_SEPARATOR => Some(LogicalKey::Separator), + winuser::VK_SUBTRACT => Some(LogicalKey::Subtract), + winuser::VK_DECIMAL => Some(LogicalKey::Decimal), + winuser::VK_DIVIDE => Some(LogicalKey::Divide), + winuser::VK_F1 => Some(LogicalKey::F1), + winuser::VK_F2 => Some(LogicalKey::F2), + winuser::VK_F3 => Some(LogicalKey::F3), + winuser::VK_F4 => Some(LogicalKey::F4), + winuser::VK_F5 => Some(LogicalKey::F5), + winuser::VK_F6 => Some(LogicalKey::F6), + winuser::VK_F7 => Some(LogicalKey::F7), + winuser::VK_F8 => Some(LogicalKey::F8), + winuser::VK_F9 => Some(LogicalKey::F9), + winuser::VK_F10 => Some(LogicalKey::F10), + winuser::VK_F11 => Some(LogicalKey::F11), + winuser::VK_F12 => Some(LogicalKey::F12), + winuser::VK_F13 => Some(LogicalKey::F13), + winuser::VK_F14 => Some(LogicalKey::F14), + winuser::VK_F15 => Some(LogicalKey::F15), + winuser::VK_F16 => Some(LogicalKey::F16), + winuser::VK_F17 => Some(LogicalKey::F17), + winuser::VK_F18 => Some(LogicalKey::F18), + winuser::VK_F19 => Some(LogicalKey::F19), + winuser::VK_F20 => Some(LogicalKey::F20), + winuser::VK_F21 => Some(LogicalKey::F21), + winuser::VK_F22 => Some(LogicalKey::F22), + winuser::VK_F23 => Some(LogicalKey::F23), + winuser::VK_F24 => Some(LogicalKey::F24), + winuser::VK_NUMLOCK => Some(LogicalKey::Numlock), + winuser::VK_SCROLL => Some(LogicalKey::Scroll), + winuser::VK_BROWSER_BACK => Some(LogicalKey::NavigateBackward), + winuser::VK_BROWSER_FORWARD => Some(LogicalKey::NavigateForward), + winuser::VK_BROWSER_REFRESH => Some(LogicalKey::WebRefresh), + winuser::VK_BROWSER_STOP => Some(LogicalKey::WebStop), + winuser::VK_BROWSER_SEARCH => Some(LogicalKey::WebSearch), + winuser::VK_BROWSER_FAVORITES => Some(LogicalKey::WebFavorites), + winuser::VK_BROWSER_HOME => Some(LogicalKey::WebHome), + winuser::VK_VOLUME_MUTE => Some(LogicalKey::Mute), + winuser::VK_VOLUME_DOWN => Some(LogicalKey::VolumeDown), + winuser::VK_VOLUME_UP => Some(LogicalKey::VolumeUp), + winuser::VK_MEDIA_NEXT_TRACK => Some(LogicalKey::NextTrack), + winuser::VK_MEDIA_PREV_TRACK => Some(LogicalKey::PrevTrack), + winuser::VK_MEDIA_STOP => Some(LogicalKey::MediaStop), + winuser::VK_MEDIA_PLAY_PAUSE => Some(LogicalKey::PlayPause), + winuser::VK_LAUNCH_MAIL => Some(LogicalKey::Mail), + winuser::VK_LAUNCH_MEDIA_SELECT => Some(LogicalKey::MediaSelect), + /*winuser::VK_LAUNCH_APP1 => Some(LogicalKey::Launch_app1), + winuser::VK_LAUNCH_APP2 => Some(LogicalKey::Launch_app2),*/ + winuser::VK_OEM_PLUS => Some(LogicalKey::Equals), + winuser::VK_OEM_COMMA => Some(LogicalKey::Comma), + winuser::VK_OEM_MINUS => Some(LogicalKey::Minus), + winuser::VK_OEM_PERIOD => Some(LogicalKey::Period), winuser::VK_OEM_1 => map_text_keys(vkey), winuser::VK_OEM_2 => map_text_keys(vkey), winuser::VK_OEM_3 => map_text_keys(vkey), @@ -320,19 +320,19 @@ pub fn vkey_to_winit_vkey(vkey: c_int) -> Option { winuser::VK_OEM_5 => map_text_keys(vkey), winuser::VK_OEM_6 => map_text_keys(vkey), winuser::VK_OEM_7 => map_text_keys(vkey), - /* winuser::VK_OEM_8 => Some(VirtualKeyCode::Oem_8), */ - winuser::VK_OEM_102 => Some(VirtualKeyCode::OEM102), - /*winuser::VK_PROCESSKEY => Some(VirtualKeyCode::Processkey), - winuser::VK_PACKET => Some(VirtualKeyCode::Packet), - winuser::VK_ATTN => Some(VirtualKeyCode::Attn), - winuser::VK_CRSEL => Some(VirtualKeyCode::Crsel), - winuser::VK_EXSEL => Some(VirtualKeyCode::Exsel), - winuser::VK_EREOF => Some(VirtualKeyCode::Ereof), - winuser::VK_PLAY => Some(VirtualKeyCode::Play), - winuser::VK_ZOOM => Some(VirtualKeyCode::Zoom), - winuser::VK_NONAME => Some(VirtualKeyCode::Noname), - winuser::VK_PA1 => Some(VirtualKeyCode::Pa1), - winuser::VK_OEM_CLEAR => Some(VirtualKeyCode::Oem_clear),*/ + /* winuser::VK_OEM_8 => Some(LogicalKey::Oem_8), */ + winuser::VK_OEM_102 => Some(LogicalKey::OEM102), + /*winuser::VK_PROCESSKEY => Some(LogicalKey::Processkey), + winuser::VK_PACKET => Some(LogicalKey::Packet), + winuser::VK_ATTN => Some(LogicalKey::Attn), + winuser::VK_CRSEL => Some(LogicalKey::Crsel), + winuser::VK_EXSEL => Some(LogicalKey::Exsel), + winuser::VK_EREOF => Some(LogicalKey::Ereof), + winuser::VK_PLAY => Some(LogicalKey::Play), + winuser::VK_ZOOM => Some(LogicalKey::Zoom), + winuser::VK_NONAME => Some(LogicalKey::Noname), + winuser::VK_PA1 => Some(LogicalKey::Pa1), + winuser::VK_OEM_CLEAR => Some(LogicalKey::Oem_clear),*/ _ => None, } } @@ -387,27 +387,28 @@ pub fn handle_extended_keys( pub fn process_key_params( wparam: WPARAM, lparam: LPARAM, -) -> Option<(ScanCode, Option)> { +) -> Option<(u32, Option, bool)> { let scancode = ((lparam >> 16) & 0xff) as UINT; let extended = (lparam & 0x01000000) != 0; + let is_repeat = (lparam & 0x7fff) != 0; handle_extended_keys(wparam as _, scancode, extended) - .map(|(vkey, scancode)| (scancode, vkey_to_winit_vkey(vkey))) + .map(|(vkey, scancode)| (scancode, vkey_to_winit_vkey(vkey), is_repeat)) } // This is needed as windows doesn't properly distinguish // some virtual key codes for different keyboard layouts -fn map_text_keys(win_virtual_key: i32) -> Option { +fn map_text_keys(win_virtual_key: i32) -> Option { let char_key = unsafe { winuser::MapVirtualKeyA(win_virtual_key as u32, winuser::MAPVK_VK_TO_CHAR) } & 0x7FFF; match char::from_u32(char_key) { - Some(';') => Some(VirtualKeyCode::Semicolon), - Some('/') => Some(VirtualKeyCode::Slash), - Some('`') => Some(VirtualKeyCode::Grave), - Some('[') => Some(VirtualKeyCode::LBracket), - Some(']') => Some(VirtualKeyCode::RBracket), - Some('\'') => Some(VirtualKeyCode::Apostrophe), - Some('\\') => Some(VirtualKeyCode::Backslash), + Some(';') => Some(LogicalKey::Semicolon), + Some('/') => Some(LogicalKey::Slash), + Some('`') => Some(LogicalKey::Grave), + Some('[') => Some(LogicalKey::LBracket), + Some(']') => Some(LogicalKey::RBracket), + Some('\'') => Some(LogicalKey::Apostrophe), + Some('\\') => Some(LogicalKey::Backslash), _ => None, } } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index a7deac50c5..e005ec6a84 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -24,14 +24,17 @@ use winapi::{ }, um::{ commctrl, libloaderapi, ole2, processthreadsapi, winbase, - winnt::{HANDLE, LONG, LPCSTR, SHORT}, + winnt::{HANDLE, LONG, LPCSTR}, winuser, }, }; use crate::{ - dpi::{PhysicalPosition, PhysicalSize}, - event::{DeviceEvent, Event, Force, KeyboardInput, Touch, TouchPhase, WindowEvent}, + dpi::{PhysicalPosition, PhysicalSize, PhysicalDelta, UnitlessDelta}, + event::{ + Event, Force, WindowEvent, RawPointerEvent, RawKeyboardEvent, PointerId, KeyPress, LogicalKey, + PointerPress, PointerButton, ModifiersState, RawPointerPress, RawKeyPress, + }, event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW}, platform_impl::platform::{ dark_mode::try_dark_mode, @@ -40,9 +43,9 @@ use crate::{ event::{self, handle_extended_keys, process_key_params, vkey_to_winit_vkey}, monitor, raw_input, util, window_state::{CursorFlags, WindowFlags, WindowState}, - wrap_device_id, WindowId, DEVICE_ID, + WindowId, TouchId, KeyboardDeviceId, PointerDeviceId, }, - window::{Fullscreen, WindowId as RootWindowId}, + window::{Fullscreen, Theme}, }; use runner::{EventLoopRunner, EventLoopRunnerShared}; @@ -706,8 +709,6 @@ unsafe fn process_control_flow(runner: &EventLoopRunner) { /// Emit a `ModifiersChanged` event whenever modifiers have changed. fn update_modifiers(window: HWND, subclass_input: &SubclassInput) { - use crate::event::WindowEvent::ModifiersChanged; - let modifiers = event::get_key_mods(); let mut window_state = subclass_input.window_state.lock(); if window_state.modifiers_state != modifiers { @@ -717,10 +718,10 @@ fn update_modifiers(window: HWND, subclass_input: &SubclassInput) { drop(window_state); unsafe { - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: ModifiersChanged(modifiers), - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::ModifiersChanged(modifiers) + )); } } } @@ -781,21 +782,19 @@ unsafe extern "system" fn public_window_callback( } winuser::WM_CLOSE => { - use crate::event::WindowEvent::CloseRequested; - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: CloseRequested, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::CloseRequested, + )); 0 } winuser::WM_DESTROY => { - use crate::event::WindowEvent::Destroyed; ole2::RevokeDragDrop(window); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: Destroyed, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::Destroyed, + )); subclass_input.event_loop_runner.remove_window(window); drop(subclass_input); @@ -816,7 +815,7 @@ unsafe extern "system" fn public_window_callback( } else { let managing_redraw = flush_paint_messages(Some(window), &subclass_input.event_loop_runner); - subclass_input.send_event(Event::RedrawRequested(RootWindowId(WindowId(window)))); + subclass_input.send_event(Event::RedrawRequested(WindowId(window).into())); if managing_redraw { subclass_input.event_loop_runner.redraw_events_cleared(); process_control_flow(&subclass_input.event_loop_runner); @@ -873,16 +872,14 @@ unsafe extern "system" fn public_window_callback( // WM_MOVE supplies client area positions, so we send Moved here instead. winuser::WM_WINDOWPOSCHANGED => { - use crate::event::WindowEvent::Moved; - let windowpos = lparam as *const winuser::WINDOWPOS; if (*windowpos).flags & winuser::SWP_NOMOVE != winuser::SWP_NOMOVE { let physical_position = PhysicalPosition::new((*windowpos).x as i32, (*windowpos).y as i32); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: Moved(physical_position), - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::Moved(physical_position), + )); } // This is necessary for us to still get sent WM_SIZE. @@ -890,15 +887,14 @@ unsafe extern "system" fn public_window_callback( } winuser::WM_SIZE => { - use crate::event::WindowEvent::Resized; let w = LOWORD(lparam as DWORD) as u32; let h = HIWORD(lparam as DWORD) as u32; let physical_size = PhysicalSize::new(w, h); - let event = Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: Resized(physical_size), - }; + let event = Event::WindowEvent( + WindowId(window).into(), + WindowEvent::Resized(physical_size), + ); { let mut w = subclass_input.window_state.lock(); @@ -917,7 +913,6 @@ unsafe extern "system" fn public_window_callback( } winuser::WM_CHAR | winuser::WM_SYSCHAR => { - use crate::event::WindowEvent::ReceivedCharacter; use std::char; let is_high_surrogate = 0xD800 <= wparam && wparam <= 0xDBFF; let is_low_surrogate = 0xDC00 <= wparam && wparam <= 0xDFFF; @@ -930,20 +925,20 @@ unsafe extern "system" fn public_window_callback( if let Some(high_surrogate) = high_surrogate { let pair = [high_surrogate, wparam as u16]; if let Some(Ok(chr)) = char::decode_utf16(pair.iter().copied()).next() { - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: ReceivedCharacter(chr), - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::CharReceived(chr), + )); } } } else { subclass_input.window_state.lock().high_surrogate = None; if let Some(chr) = char::from_u32(wparam as u32) { - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: ReceivedCharacter(chr), - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::CharReceived(chr), + )); } } 0 @@ -972,7 +967,6 @@ unsafe extern "system" fn public_window_callback( } winuser::WM_MOUSEMOVE => { - use crate::event::WindowEvent::{CursorEntered, CursorMoved}; let mouse_was_outside_window = { let mut w = subclass_input.window_state.lock(); @@ -984,12 +978,10 @@ unsafe extern "system" fn public_window_callback( }; if mouse_was_outside_window { - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: CursorEntered { - device_id: DEVICE_ID, - }, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerEntered(PointerId::MOUSE_ID), + )); // Calling TrackMouseEvent in order to receive mouse leave events. winuser::TrackMouseEvent(&mut winuser::TRACKMOUSEEVENT { @@ -1015,21 +1007,16 @@ unsafe extern "system" fn public_window_callback( if cursor_moved { update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: CursorMoved { - device_id: DEVICE_ID, - position, - modifiers: event::get_key_mods(), - }, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerMoved(PointerId::MOUSE_ID, position), + )); } 0 } winuser::WM_MOUSELEAVE => { - use crate::event::WindowEvent::CursorLeft; { let mut w = subclass_input.window_state.lock(); w.mouse @@ -1037,89 +1024,68 @@ unsafe extern "system" fn public_window_callback( .ok(); } - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: CursorLeft { - device_id: DEVICE_ID, - }, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerLeft(PointerId::MOUSE_ID), + )); 0 } winuser::WM_MOUSEWHEEL => { - use crate::event::MouseScrollDelta::LineDelta; - let value = (wparam >> 16) as i16; let value = value as i32; - let value = value as f32 / winuser::WHEEL_DELTA as f32; + let value = value as f64 / winuser::WHEEL_DELTA as f64; update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: WindowEvent::MouseWheel { - device_id: DEVICE_ID, - delta: LineDelta(0.0, value), - phase: TouchPhase::Moved, - modifiers: event::get_key_mods(), - }, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::ScrollLines(UnitlessDelta::new(0.0, value)), + )); 0 } winuser::WM_MOUSEHWHEEL => { - use crate::event::MouseScrollDelta::LineDelta; - let value = (wparam >> 16) as i16; let value = value as i32; - let value = value as f32 / winuser::WHEEL_DELTA as f32; + let value = value as f64 / winuser::WHEEL_DELTA as f64; update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: WindowEvent::MouseWheel { - device_id: DEVICE_ID, - delta: LineDelta(value, 0.0), - phase: TouchPhase::Moved, - modifiers: event::get_key_mods(), - }, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::ScrollLines(UnitlessDelta::new(value, 0.0)), + )); 0 } winuser::WM_KEYDOWN | winuser::WM_SYSKEYDOWN => { - use crate::event::{ElementState::Pressed, VirtualKeyCode}; if msg == winuser::WM_SYSKEYDOWN && wparam as i32 == winuser::VK_F4 { commctrl::DefSubclassProc(window, msg, wparam, lparam) } else { - if let Some((scancode, vkey)) = process_key_params(wparam, lparam) { + if let Some((scan_code, logical_key, is_repeat)) = process_key_params(wparam, lparam) { update_modifiers(window, subclass_input); - #[allow(deprecated)] - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: WindowEvent::KeyboardInput { - device_id: DEVICE_ID, - input: KeyboardInput { - state: Pressed, - scancode, - virtual_keycode: vkey, - modifiers: event::get_key_mods(), - }, + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::KeyPress(KeyPress { + logical_key, + scan_code, + is_down: true, + is_repeat, is_synthetic: false, - }, - }); + }), + )); // Windows doesn't emit a delete character by default, but in order to make it // consistent with the other platforms we'll emit a delete character here. - if vkey == Some(VirtualKeyCode::Delete) { - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: WindowEvent::ReceivedCharacter('\u{7F}'), - }); + if logical_key == Some(LogicalKey::Delete) { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::CharReceived('\u{7F}'), + )); } } 0 @@ -1127,199 +1093,188 @@ unsafe extern "system" fn public_window_callback( } winuser::WM_KEYUP | winuser::WM_SYSKEYUP => { - use crate::event::ElementState::Released; - if let Some((scancode, vkey)) = process_key_params(wparam, lparam) { + if let Some((scan_code, logical_key, _)) = process_key_params(wparam, lparam) { update_modifiers(window, subclass_input); - #[allow(deprecated)] - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: WindowEvent::KeyboardInput { - device_id: DEVICE_ID, - input: KeyboardInput { - state: Released, - scancode, - virtual_keycode: vkey, - modifiers: event::get_key_mods(), - }, + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::KeyPress(KeyPress { + logical_key, + scan_code, + is_down: false, + is_repeat: false, is_synthetic: false, - }, - }); + }), + )); } 0 } winuser::WM_LBUTTONDOWN => { - use crate::event::{ElementState::Pressed, MouseButton::Left, WindowEvent::MouseInput}; - capture_mouse(window, &mut *subclass_input.window_state.lock()); - update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: MouseInput { - device_id: DEVICE_ID, - state: Pressed, - button: Left, - modifiers: event::get_key_mods(), - }, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerPress( + PointerId::MOUSE_ID, + PointerPress { + button: PointerButton::MOUSE_LEFT, + is_down: true, + click_count: {println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); 0}, + } + ), + )); 0 } winuser::WM_LBUTTONUP => { - use crate::event::{ - ElementState::Released, MouseButton::Left, WindowEvent::MouseInput, - }; - release_mouse(&mut *subclass_input.window_state.lock()); - update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: MouseInput { - device_id: DEVICE_ID, - state: Released, - button: Left, - modifiers: event::get_key_mods(), - }, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerPress( + PointerId::MOUSE_ID, + PointerPress { + button: PointerButton::MOUSE_LEFT, + is_down: false, + click_count: 0, + } + ), + )); 0 } winuser::WM_RBUTTONDOWN => { - use crate::event::{ - ElementState::Pressed, MouseButton::Right, WindowEvent::MouseInput, - }; - capture_mouse(window, &mut *subclass_input.window_state.lock()); - update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: MouseInput { - device_id: DEVICE_ID, - state: Pressed, - button: Right, - modifiers: event::get_key_mods(), - }, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerPress( + PointerId::MOUSE_ID, + PointerPress { + button: PointerButton::MOUSE_RIGHT, + is_down: true, + click_count: {println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); 0}, + } + ), + )); 0 } winuser::WM_RBUTTONUP => { - use crate::event::{ - ElementState::Released, MouseButton::Right, WindowEvent::MouseInput, - }; - release_mouse(&mut *subclass_input.window_state.lock()); - update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: MouseInput { - device_id: DEVICE_ID, - state: Released, - button: Right, - modifiers: event::get_key_mods(), - }, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerPress( + PointerId::MOUSE_ID, + PointerPress { + button: PointerButton::MOUSE_RIGHT, + is_down: false, + click_count: 0, + } + ), + )); 0 } winuser::WM_MBUTTONDOWN => { - use crate::event::{ - ElementState::Pressed, MouseButton::Middle, WindowEvent::MouseInput, - }; - capture_mouse(window, &mut *subclass_input.window_state.lock()); - update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: MouseInput { - device_id: DEVICE_ID, - state: Pressed, - button: Middle, - modifiers: event::get_key_mods(), - }, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerPress( + PointerId::MOUSE_ID, + PointerPress { + button: PointerButton::MOUSE_MIDDLE, + is_down: true, + click_count: {println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); 0}, + } + ), + )); 0 } winuser::WM_MBUTTONUP => { - use crate::event::{ - ElementState::Released, MouseButton::Middle, WindowEvent::MouseInput, - }; - release_mouse(&mut *subclass_input.window_state.lock()); - update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: MouseInput { - device_id: DEVICE_ID, - state: Released, - button: Middle, - modifiers: event::get_key_mods(), - }, - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerPress( + PointerId::MOUSE_ID, + PointerPress { + button: PointerButton::MOUSE_MIDDLE, + is_down: false, + click_count: 0, + } + ), + )); 0 } winuser::WM_XBUTTONDOWN => { - use crate::event::{ - ElementState::Pressed, MouseButton::Other, WindowEvent::MouseInput, - }; - let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); - capture_mouse(window, &mut *subclass_input.window_state.lock()); - update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: MouseInput { - device_id: DEVICE_ID, - state: Pressed, - button: Other(xbutton as u8), - modifiers: event::get_key_mods(), - }, - }); + let button = match winuser::GET_XBUTTON_WPARAM(wparam) { + 1 => PointerButton::MOUSE_X1, + 2 => PointerButton::MOUSE_X2, + _ => { + warn!("invalid x-button passed"); + return 0 + } + }; + + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerPress( + PointerId::MOUSE_ID, + PointerPress { + button, + is_down: true, + click_count: {println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); 0}, + } + ), + )); 0 } winuser::WM_XBUTTONUP => { - use crate::event::{ - ElementState::Released, MouseButton::Other, WindowEvent::MouseInput, - }; - let xbutton = winuser::GET_XBUTTON_WPARAM(wparam); - release_mouse(&mut *subclass_input.window_state.lock()); - update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: MouseInput { - device_id: DEVICE_ID, - state: Released, - button: Other(xbutton as u8), - modifiers: event::get_key_mods(), - }, - }); + let button = match winuser::GET_XBUTTON_WPARAM(wparam) { + 1 => PointerButton::MOUSE_X1, + 2 => PointerButton::MOUSE_X2, + _ => { + warn!("invalid x-button passed"); + return 0 + } + }; + + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerPress( + PointerId::MOUSE_ID, + PointerPress { + button, + is_down: false, + click_count: 0, + } + ), + )); 0 } winuser::WM_TOUCH => { let pcount = LOWORD(wparam as DWORD) as usize; - let mut inputs = Vec::with_capacity(pcount); + let mut inputs = Vec::::with_capacity(pcount); inputs.set_len(pcount); let htouch = lparam as winuser::HTOUCHINPUT; if winuser::GetTouchInputInfo( @@ -1330,36 +1285,65 @@ unsafe extern "system" fn public_window_callback( ) > 0 { for input in &inputs { - let mut location = POINT { + let mut position = POINT { x: input.x / 100, y: input.y / 100, }; - if winuser::ScreenToClient(window, &mut location as *mut _) == 0 { + if winuser::ScreenToClient(window, &mut position as *mut _) == 0 { continue; } - let x = location.x as f64 + (input.x % 100) as f64 / 100f64; - let y = location.y as f64 + (input.y % 100) as f64 / 100f64; - let location = PhysicalPosition::new(x, y); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: WindowEvent::Touch(Touch { - phase: if input.dwFlags & winuser::TOUCHEVENTF_DOWN != 0 { - TouchPhase::Started - } else if input.dwFlags & winuser::TOUCHEVENTF_UP != 0 { - TouchPhase::Ended - } else if input.dwFlags & winuser::TOUCHEVENTF_MOVE != 0 { - TouchPhase::Moved - } else { - continue; - }, - location, - force: None, // WM_TOUCH doesn't support pressure information - id: input.dwID as u64, - device_id: DEVICE_ID, - }), - }); + let x = position.x as f64 + (input.x % 100) as f64 / 100f64; + let y = position.y as f64 + (input.y % 100) as f64 / 100f64; + let position = PhysicalPosition::new(x, y); + let pointer_id = PointerId::TouchId(TouchId(input.dwID).into()); + + if input.dwFlags & winuser::TOUCHEVENTF_DOWN != 0 { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerCreated(pointer_id), + )); + } + + println!("\t\tTODO: SUPPORT TOUCHEVENTF_INRANGE"); + + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerMoved(pointer_id, position), + )); + + if input.dwFlags & winuser::TOUCHEVENTF_DOWN != 0 { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerPress( + pointer_id, + PointerPress { + button: PointerButton::TOUCH_CONTACT, + is_down: true, + click_count: {println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); 0}, + }, + ), + )); + } + + if input.dwFlags & winuser::TOUCHEVENTF_UP != 0 { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerPress( + pointer_id, + PointerPress { + button: PointerButton::TOUCH_CONTACT, + is_down: false, + click_count: 0, + }, + ), + )); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerDestroyed(pointer_id), + )); + } } } winuser::CloseTouchInputHandle(htouch); @@ -1390,7 +1374,7 @@ unsafe extern "system" fn public_window_callback( } let pointer_info_count = (entries_count * pointers_count) as usize; - let mut pointer_infos = Vec::with_capacity(pointer_info_count); + let mut pointer_infos = Vec::::with_capacity(pointer_info_count); pointer_infos.set_len(pointer_info_count); if GetPointerFrameInfoHistory( pointer_id, @@ -1436,12 +1420,12 @@ unsafe extern "system" fn public_window_callback( let y = display_rect.top as f64 + pointer_info.ptHimetricLocation.y as f64 * himetric_to_pixel_ratio_y; - let mut location = POINT { + let mut position = POINT { x: x.floor() as i32, y: y.floor() as i32, }; - if winuser::ScreenToClient(window, &mut location as *mut _) == 0 { + if winuser::ScreenToClient(window, &mut position as *mut _) == 0 { continue; } @@ -1477,28 +1461,64 @@ unsafe extern "system" fn public_window_callback( _ => None, }; - let x = location.x as f64 + x.fract(); - let y = location.y as f64 + y.fract(); - let location = PhysicalPosition::new(x, y); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: WindowEvent::Touch(Touch { - phase: if pointer_info.pointerFlags & winuser::POINTER_FLAG_DOWN != 0 { - TouchPhase::Started - } else if pointer_info.pointerFlags & winuser::POINTER_FLAG_UP != 0 { - TouchPhase::Ended - } else if pointer_info.pointerFlags & winuser::POINTER_FLAG_UPDATE != 0 - { - TouchPhase::Moved - } else { - continue; - }, - location, - force, - id: pointer_info.pointerId as u64, - device_id: DEVICE_ID, - }), - }); + let x = position.x as f64 + x.fract(); + let y = position.y as f64 + y.fract(); + let position = PhysicalPosition::new(x, y); + let pointer_id = PointerId::TouchId(TouchId(pointer_info.pointerId).into()); + + if pointer_info.pointerFlags & winuser::POINTER_FLAG_NEW != 0 { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerCreated(pointer_id), + )); + } + + if let Some(force) = force { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerForce(pointer_id, force), + )); + } + + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerMoved(pointer_id, position), + )); + + if pointer_info.pointerFlags & winuser::POINTER_FLAG_DOWN != 0 { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerPress( + pointer_id, + PointerPress { + button: PointerButton::TOUCH_CONTACT, + is_down: true, + click_count: {println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); 0}, + }, + ), + )); + } + + if pointer_info.pointerFlags & winuser::POINTER_FLAG_UP != 0 { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerPress( + pointer_id, + PointerPress { + button: PointerButton::TOUCH_CONTACT, + is_down: false, + click_count: 0, + }, + ), + )); + } + + if pointer_info.pointerFlags & winuser::POINTER_FLAG_INRANGE == 0 { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerDestroyed(pointer_id), + )); + } } SkipPointerFrameMessages(pointer_id); @@ -1507,75 +1527,63 @@ unsafe extern "system" fn public_window_callback( } winuser::WM_SETFOCUS => { - use crate::event::{ElementState::Released, WindowEvent::Focused}; for windows_keycode in event::get_pressed_keys() { - let scancode = + let scan_code = winuser::MapVirtualKeyA(windows_keycode as _, winuser::MAPVK_VK_TO_VSC); - let virtual_keycode = event::vkey_to_winit_vkey(windows_keycode); + let logical_key = event::vkey_to_winit_vkey(windows_keycode); update_modifiers(window, subclass_input); - #[allow(deprecated)] - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: WindowEvent::KeyboardInput { - device_id: DEVICE_ID, - input: KeyboardInput { - scancode, - virtual_keycode, - state: Released, - modifiers: event::get_key_mods(), - }, + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::KeyPress(KeyPress { + logical_key, + scan_code, + is_down: true, + is_repeat: false, is_synthetic: true, - }, - }) + }), + )); } - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: Focused(true), - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::FocusGained, + )); 0 } winuser::WM_KILLFOCUS => { - use crate::event::{ - ElementState::Released, - ModifiersState, - WindowEvent::{Focused, ModifiersChanged}, - }; for windows_keycode in event::get_pressed_keys() { - let scancode = + let scan_code = winuser::MapVirtualKeyA(windows_keycode as _, winuser::MAPVK_VK_TO_VSC); - let virtual_keycode = event::vkey_to_winit_vkey(windows_keycode); - - #[allow(deprecated)] - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: WindowEvent::KeyboardInput { - device_id: DEVICE_ID, - input: KeyboardInput { - scancode, - virtual_keycode, - state: Released, - modifiers: event::get_key_mods(), - }, + let logical_key = event::vkey_to_winit_vkey(windows_keycode); + + update_modifiers(window, subclass_input); + + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::KeyPress(KeyPress { + logical_key, + scan_code, + is_down: false, + is_repeat: false, is_synthetic: true, - }, - }) + }), + )); } subclass_input.window_state.lock().modifiers_state = ModifiersState::empty(); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: ModifiersChanged(ModifiersState::empty()), - }); - - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: Focused(false), - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::ModifiersChanged(ModifiersState::empty()), + )); + + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::FocusLost, + )); 0 } @@ -1638,8 +1646,6 @@ unsafe extern "system" fn public_window_callback( // Only sent on Windows 8.1 or newer. On Windows 7 and older user has to log out to change // DPI, therefore all applications are closed while DPI is changing. winuser::WM_DPICHANGED => { - use crate::event::WindowEvent::ScaleFactorChanged; - // This message actually provides two DPI values - x and y. However MSDN says that // "you only need to use either the X-axis or the Y-axis value when scaling your // application since they are the same". @@ -1714,13 +1720,10 @@ unsafe extern "system" fn public_window_callback( false => old_physical_inner_size, }; - let _ = subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: ScaleFactorChanged { - scale_factor: new_scale_factor, - new_inner_size: &mut new_physical_inner_size, - }, - }); + let _ = subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::ScaleFactorChanged(new_scale_factor, &mut new_physical_inner_size), + )); let dragging_window: bool; @@ -1853,22 +1856,19 @@ unsafe extern "system" fn public_window_callback( } winuser::WM_SETTINGCHANGE => { - use crate::event::WindowEvent::ThemeChanged; - let is_dark_mode = try_dark_mode(window); let mut window_state = subclass_input.window_state.lock(); let changed = window_state.is_dark_mode != is_dark_mode; if changed { - use crate::window::Theme::*; - let theme = if is_dark_mode { Dark } else { Light }; + let theme = if is_dark_mode { Theme::Dark } else { Theme::Light }; window_state.is_dark_mode = is_dark_mode; mem::drop(window_state); - subclass_input.send_event(Event::WindowEvent { - window_id: RootWindowId(WindowId(window)), - event: ThemeChanged(theme), - }); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::ThemeChanged(theme), + )); } commctrl::DefSubclassProc(window, msg, wparam, lparam) @@ -1947,84 +1947,83 @@ unsafe extern "system" fn thread_event_target_callback( } winuser::WM_INPUT_DEVICE_CHANGE => { - let event = match wparam as _ { - winuser::GIDC_ARRIVAL => DeviceEvent::Added, - winuser::GIDC_REMOVAL => DeviceEvent::Removed, - _ => unreachable!(), - }; + let mut device_info: winuser::RID_DEVICE_INFO = mem::zeroed(); + device_info.cbSize = mem::size_of::() as _; - subclass_input.send_event(Event::DeviceEvent { - device_id: wrap_device_id(lparam as _), - event, - }); + let result = winuser::GetRawInputDeviceInfoW( + lparam as _, + winuser::RIDI_DEVICEINFO, + &mut device_info as *mut _ as *mut _, + ptr::null_mut(), + ); + assert!(result > 0); + + match device_info.dwType { + winuser::RIM_TYPEMOUSE => subclass_input.send_event(Event::RawPointerEvent( + PointerDeviceId(lparam as _).into(), + match wparam as _ { + winuser::GIDC_ARRIVAL => RawPointerEvent::Added, + winuser::GIDC_REMOVAL => RawPointerEvent::Removed, + _ => unreachable!(), + } + )), + winuser::RIM_TYPEKEYBOARD => subclass_input.send_event(Event::RawKeyboardEvent( + KeyboardDeviceId(lparam as _).into(), + match wparam as _ { + winuser::GIDC_ARRIVAL => RawKeyboardEvent::Added, + winuser::GIDC_REMOVAL => RawKeyboardEvent::Removed, + _ => unreachable!(), + } + )), + _ => (), + } 0 } winuser::WM_INPUT => { - use crate::event::{ - DeviceEvent::{Button, Key, Motion, MouseMotion, MouseWheel}, - ElementState::{Pressed, Released}, - MouseScrollDelta::LineDelta, - }; - if let Some(data) = raw_input::get_raw_input_data(lparam as _) { - let device_id = wrap_device_id(data.header.hDevice as _); - if data.header.dwType == winuser::RIM_TYPEMOUSE { + let pointer_id = PointerDeviceId(data.header.hDevice).into(); let mouse = data.data.mouse(); if util::has_flag(mouse.usFlags, winuser::MOUSE_MOVE_RELATIVE) { let x = mouse.lLastX as f64; let y = mouse.lLastY as f64; - if x != 0.0 { - subclass_input.send_event(Event::DeviceEvent { - device_id, - event: Motion { axis: 0, value: x }, - }); - } - - if y != 0.0 { - subclass_input.send_event(Event::DeviceEvent { - device_id, - event: Motion { axis: 1, value: y }, - }); - } - if x != 0.0 || y != 0.0 { - subclass_input.send_event(Event::DeviceEvent { - device_id, - event: MouseMotion { delta: (x, y) }, - }); + subclass_input.send_event(Event::RawPointerEvent( + pointer_id, + RawPointerEvent::MovedRelative(PhysicalDelta::new(x, y)) + )); } } if util::has_flag(mouse.usButtonFlags, winuser::RI_MOUSE_WHEEL) { - let delta = mouse.usButtonData as SHORT / winuser::WHEEL_DELTA; - subclass_input.send_event(Event::DeviceEvent { - device_id, - event: MouseWheel { - delta: LineDelta(0.0, delta as f32), - }, - }); + let delta = mouse.usButtonData as f64 / winuser::WHEEL_DELTA as f64; + subclass_input.send_event(Event::RawPointerEvent( + pointer_id, + RawPointerEvent::Wheel(UnitlessDelta::new(0.0, delta)), + )); + } + if util::has_flag(mouse.usButtonFlags, 0x0800 /*winuser::RI_MOUSE_HWHEEL*/) { + let delta = mouse.usButtonData as f64 / winuser::WHEEL_DELTA as f64; + subclass_input.send_event(Event::RawPointerEvent( + pointer_id, + RawPointerEvent::Wheel(UnitlessDelta::new(delta, 0.0)), + )); } let button_state = raw_input::get_raw_mouse_button_state(mouse.usButtonFlags); // Left, middle, and right, respectively. - for (index, state) in button_state.iter().enumerate() { - if let Some(state) = *state { - // This gives us consistency with X11, since there doesn't - // seem to be anything else reasonable to do for a mouse - // button ID. - let button = (index + 1) as _; - subclass_input.send_event(Event::DeviceEvent { - device_id, - event: Button { button, state }, - }); - } + for (button, is_down) in button_state.iter().cloned().flatten() { + subclass_input.send_event(Event::RawPointerEvent( + pointer_id, + RawPointerEvent::Press(RawPointerPress { button, is_down }), + )); } } else if data.header.dwType == winuser::RIM_TYPEKEYBOARD { + let keyboard_id = KeyboardDeviceId(data.header.hDevice).into(); let keyboard = data.data.keyboard(); let pressed = keyboard.Message == winuser::WM_KEYDOWN @@ -2033,27 +2032,25 @@ unsafe extern "system" fn thread_event_target_callback( || keyboard.Message == winuser::WM_SYSKEYUP; if pressed || released { - let state = if pressed { Pressed } else { Released }; + let is_down = pressed; - let scancode = keyboard.MakeCode as _; + let scan_code = keyboard.MakeCode as _; let extended = util::has_flag(keyboard.Flags, winuser::RI_KEY_E0 as _) | util::has_flag(keyboard.Flags, winuser::RI_KEY_E1 as _); - if let Some((vkey, scancode)) = - handle_extended_keys(keyboard.VKey as _, scancode, extended) + if let Some((vkey, scan_code)) = + handle_extended_keys(keyboard.VKey as _, scan_code, extended) { - let virtual_keycode = vkey_to_winit_vkey(vkey); - - #[allow(deprecated)] - subclass_input.send_event(Event::DeviceEvent { - device_id, - event: Key(KeyboardInput { - scancode, - state, - virtual_keycode, - modifiers: event::get_key_mods(), + let logical_key = vkey_to_winit_vkey(vkey); + + subclass_input.send_event(Event::RawKeyboardEvent( + keyboard_id, + RawKeyboardEvent::Press(RawKeyPress { + logical_key, + scan_code, + is_down, }), - }); + )); } } } diff --git a/src/platform_impl/windows/event_loop/runner.rs b/src/platform_impl/windows/event_loop/runner.rs index 258a40c08c..09f766b766 100644 --- a/src/platform_impl/windows/event_loop/runner.rs +++ b/src/platform_impl/windows/event_loop/runner.rs @@ -376,15 +376,11 @@ impl EventLoopRunner { impl BufferedEvent { pub fn from_event(event: Event<'_, T>) -> BufferedEvent { match event { - Event::WindowEvent { - event: - WindowEvent::ScaleFactorChanged { - scale_factor, - new_inner_size, - }, + Event::WindowEvent( window_id, - } => BufferedEvent::ScaleFactorChanged(window_id, scale_factor, *new_inner_size), - event => BufferedEvent::Event(event.to_static().unwrap()), + WindowEvent::ScaleFactorChanged(scale_factor, new_inner_size), + ) => BufferedEvent::ScaleFactorChanged(window_id, scale_factor, *new_inner_size), + event => BufferedEvent::Event(event.to_static().ok().unwrap()), } } @@ -392,13 +388,10 @@ impl BufferedEvent { match self { Self::Event(event) => dispatch(event), Self::ScaleFactorChanged(window_id, scale_factor, mut new_inner_size) => { - dispatch(Event::WindowEvent { + dispatch(Event::WindowEvent( window_id, - event: WindowEvent::ScaleFactorChanged { - scale_factor, - new_inner_size: &mut new_inner_size, - }, - }); + WindowEvent::ScaleFactorChanged(scale_factor, &mut new_inner_size), + )); util::set_inner_size_physical( (window_id.0).0, new_inner_size.width as _, diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 021c903b8d..6f5816e38f 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -1,6 +1,6 @@ #![cfg(target_os = "windows")] -use winapi::{self, shared::windef::HWND}; +use winapi::{self, shared::windef::HWND, um::winnt::HANDLE}; pub use self::{ event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget}, @@ -11,7 +11,6 @@ pub use self::{ pub use self::icon::WinIcon as PlatformIcon; -use crate::event::DeviceId as RootDeviceId; use crate::icon::Icon; #[derive(Clone, Default)] @@ -30,30 +29,68 @@ pub struct Cursor(pub *const winapi::ctypes::wchar_t); unsafe impl Send for Cursor {} unsafe impl Sync for Cursor {} -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct DeviceId(u32); +macro_rules! device_id { + ($name:ident) => { + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub(crate) struct $name(HANDLE); + + unsafe impl Send for $name {} + unsafe impl Sync for $name {} + + impl $name { + pub unsafe fn dummy() -> Self { + Self(std::ptr::null_mut()) + } + + pub fn persistent_identifier(&self) -> Option { + raw_input::get_raw_input_device_name(self.0) + } + + #[inline(always)] + pub fn handle(&self) -> HANDLE { + self.0 + } + } -impl DeviceId { + impl From<$name> for crate::event::$name { + fn from(platform_id: $name) -> Self { + Self(platform_id) + } + } + }; +} + +device_id!(PointerDeviceId); +device_id!(KeyboardDeviceId); + +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct MouseId; +impl MouseId { pub unsafe fn dummy() -> Self { - DeviceId(0) + MouseId } } - -impl DeviceId { - pub fn persistent_identifier(&self) -> Option { - if self.0 != 0 { - raw_input::get_raw_input_device_name(self.0 as _) - } else { - None - } +impl From for crate::event::MouseId { + fn from(platform_id: MouseId) -> Self { + Self(platform_id) } } -// Constant device ID, to be removed when this backend is updated to report real device IDs. -const DEVICE_ID: RootDeviceId = RootDeviceId(DeviceId(0)); +impl crate::event::PointerId { + const MOUSE_ID: Self = Self::MouseId(crate::event::MouseId(MouseId)); +} -fn wrap_device_id(id: u32) -> RootDeviceId { - RootDeviceId(DeviceId(id)) +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct TouchId(u32); +impl TouchId { + pub unsafe fn dummy() -> Self { + TouchId(!0) + } +} +impl From for crate::event::TouchId { + fn from(platform_id: TouchId) -> Self { + Self(platform_id) + } } pub type OsError = std::io::Error; @@ -71,6 +108,12 @@ impl WindowId { } } +impl From for crate::window::WindowId { + fn from(platform_id: WindowId) -> Self { + Self(platform_id) + } +} + #[macro_use] mod util; mod dark_mode; diff --git a/src/platform_impl/windows/raw_input.rs b/src/platform_impl/windows/raw_input.rs index 73b136a82f..cd574bae81 100644 --- a/src/platform_impl/windows/raw_input.rs +++ b/src/platform_impl/windows/raw_input.rs @@ -21,7 +21,10 @@ use winapi::{ }, }; -use crate::{event::ElementState, platform_impl::platform::util}; +use crate::{ + event::PointerButton, + platform_impl::platform::util, +}; #[allow(dead_code)] pub fn get_raw_input_device_list() -> Option> { @@ -189,33 +192,43 @@ fn button_flags_to_element_state( button_flags: USHORT, down_flag: USHORT, up_flag: USHORT, -) -> Option { +) -> Option { // We assume the same button won't be simultaneously pressed and released. if util::has_flag(button_flags, down_flag) { - Some(ElementState::Pressed) + Some(true) } else if util::has_flag(button_flags, up_flag) { - Some(ElementState::Released) + Some(false) } else { None } } -pub fn get_raw_mouse_button_state(button_flags: USHORT) -> [Option; 3] { +pub fn get_raw_mouse_button_state(button_flags: USHORT) -> [Option<(PointerButton, bool)>; 5] { [ button_flags_to_element_state( button_flags, - winuser::RI_MOUSE_LEFT_BUTTON_DOWN, - winuser::RI_MOUSE_LEFT_BUTTON_UP, - ), + winuser::RI_MOUSE_BUTTON_1_DOWN, + winuser::RI_MOUSE_BUTTON_1_UP, + ).map(|b| (PointerButton::BUTTON_1, b)), + button_flags_to_element_state( + button_flags, + winuser::RI_MOUSE_BUTTON_2_DOWN, + winuser::RI_MOUSE_BUTTON_2_UP, + ).map(|b| (PointerButton::BUTTON_2, b)), + button_flags_to_element_state( + button_flags, + winuser::RI_MOUSE_BUTTON_3_DOWN, + winuser::RI_MOUSE_BUTTON_3_UP, + ).map(|b| (PointerButton::BUTTON_3, b)), button_flags_to_element_state( button_flags, - winuser::RI_MOUSE_MIDDLE_BUTTON_DOWN, - winuser::RI_MOUSE_MIDDLE_BUTTON_UP, - ), + winuser::RI_MOUSE_BUTTON_4_DOWN, + winuser::RI_MOUSE_BUTTON_4_UP, + ).map(|b| (PointerButton::BUTTON_4, b)), button_flags_to_element_state( button_flags, - winuser::RI_MOUSE_RIGHT_BUTTON_DOWN, - winuser::RI_MOUSE_RIGHT_BUTTON_UP, - ), + winuser::RI_MOUSE_BUTTON_5_DOWN, + winuser::RI_MOUSE_BUTTON_5_UP, + ).map(|b| (PointerButton::BUTTON_5, b)), ] } diff --git a/src/window.rs b/src/window.rs index 113e7c042b..e5f9df0c9f 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,4 +1,46 @@ -//! The `Window` struct and associated types. +//! The [`Window`] struct and associated types. +//! +//! # Window creation +//! +//! [`Window`]s can be created either by calling the [`Window::new`] function or by creating a +//! [`WindowBuilder`], populating it with data, and calling the [`WindowBuilder::build`] method: +//! +//! ```no_run +//! let mut event_loop = EventLoop::new(); +//! let window = Window::new(&event_loop).unwrap(); +//! ``` +//! +//! ```no_run +//! let mut event_loop = EventLoop::new(); +//! let window = WindowBuilder::new() +//! .with_title("A fantastic window!") +//! .build(&event_loop) +//! .unwrap(); +//! ``` +//! +//! # Rendering +//! +//! Winit does not provide any tools to directly render onto windows. Instead, you should use +//! either the platform-specific handle retrieval methods provided in the `platform` module +//! +//! Applications should listen for `WindowEvent::CloseRequested` to handle the user attempting to +//! close the window. `CloseRequested` does not force the window to be closed immediately - the +//! `Window` will only close either when it is explicitly dropped or the application quits. +//! +//! ```no_run +//! event_loop.run(move |event, _, control_flow| { +//! *control_flow = ControlFlow::Wait; +//! +//! match event { +//! Event::WindowEvent { +//! event: WindowEvent::CloseRequested, +//! .. +//! } => *control_flow = ControlFlow::Exit, +//! _ => (), +//! } +//! }); +//! ``` + use std::fmt; use crate::{ @@ -13,30 +55,7 @@ pub use crate::icon::{BadIcon, Icon}; /// Represents a window. /// -/// # Example -/// -/// ```no_run -/// use winit::{ -/// event::{Event, WindowEvent}, -/// event_loop::{ControlFlow, EventLoop}, -/// window::Window, -/// }; -/// -/// let mut event_loop = EventLoop::new(); -/// let window = Window::new(&event_loop).unwrap(); -/// -/// event_loop.run(move |event, _, control_flow| { -/// *control_flow = ControlFlow::Wait; -/// -/// match event { -/// Event::WindowEvent { -/// event: WindowEvent::CloseRequested, -/// .. -/// } => *control_flow = ControlFlow::Exit, -/// _ => (), -/// } -/// }); -/// ``` +/// See the module-level docs for more info. pub struct Window { pub(crate) window: platform_impl::Window, } @@ -80,6 +99,8 @@ impl WindowId { } /// Object that allows you to build windows. +/// +/// See the module-level docs for more info. #[derive(Clone, Default)] pub struct WindowBuilder { /// The attributes to use to create the window. @@ -863,7 +884,7 @@ pub enum Fullscreen { Borderless(MonitorHandle), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Theme { Light, Dark, From 5f7cf2ae6ed1e916fe578eb5e6ea9ac43938a8cd Mon Sep 17 00:00:00 2001 From: Osspial Date: Sat, 16 May 2020 16:27:39 -0400 Subject: [PATCH 10/29] Reorder events.rs --- src/event.rs | 289 ++++++++++++++++++++++++++------------------------- 1 file changed, 145 insertions(+), 144 deletions(-) diff --git a/src/event.rs b/src/event.rs index 3ca22d3df7..4c3fef5eec 100644 --- a/src/event.rs +++ b/src/event.rs @@ -120,70 +120,6 @@ pub enum AppEvent { Resumed, } -impl<'a, T> Event<'a, T> { - pub fn map_nonuser_event(self) -> Result, Event<'a, T>> { - use self::Event::*; - match self { - UserEvent(_) => Err(self), - WindowEvent(window_id, event) => Ok(WindowEvent(window_id, event)), - RawPointerEvent(pointer_id, event) => Ok(RawPointerEvent(pointer_id, event)), - RawKeyboardEvent(keyboard_id, event) => Ok(RawKeyboardEvent(keyboard_id, event)), - AppEvent(app_event) => Ok(AppEvent(app_event)), - NewEvents(cause) => Ok(NewEvents(cause)), - MainEventsCleared => Ok(MainEventsCleared), - RedrawRequested(wid) => Ok(RedrawRequested(wid)), - RedrawEventsCleared => Ok(RedrawEventsCleared), - LoopDestroyed => Ok(LoopDestroyed), - } - } - - /// If the event doesn't contain a reference, turn it into an event with a `'static` lifetime. - /// Otherwise, return `None`. - pub fn to_static(self) -> Result, Event<'a, T>> { - use self::Event::*; - match self { - NewEvents(cause) => Ok(NewEvents(cause)), - WindowEvent(window_id, event) => event.to_static() - .map(|e| -> Event<'static, T> {WindowEvent(window_id, e)}) - .map_err(|e| -> Event<'a, T> {WindowEvent(window_id, e)}), - RawPointerEvent(pointer_id, event) => Ok(RawPointerEvent(pointer_id, event)), - RawKeyboardEvent(keyboard_id, event) => Ok(RawKeyboardEvent(keyboard_id, event)), - AppEvent(app_event) => Ok(AppEvent(app_event)), - UserEvent(e) => Ok(UserEvent(e)), - MainEventsCleared => Ok(MainEventsCleared), - RedrawRequested(wid) => Ok(RedrawRequested(wid)), - RedrawEventsCleared => Ok(RedrawEventsCleared), - LoopDestroyed => Ok(LoopDestroyed), - } - } -} - -/// Describes the reason the event loop is resuming. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum StartCause { - /// Sent if the time specified by `ControlFlow::WaitUntil` has been reached. Contains the - /// moment the timeout was requested and the requested resume time. The actual resume time is - /// guaranteed to be equal to or after the requested resume time. - ResumeTimeReached { - start: Instant, - requested_resume: Instant, - }, - - /// Sent if the OS has new events to send to the window, after a wait was requested. Contains - /// the moment the wait was requested and the resume time, if requested. - WaitCancelled { - start: Instant, - requested_resume: Option, - }, - - /// Sent if the event loop is being resumed after the loop's control flow was set to - /// `ControlFlow::Poll`. - Poll, - - /// Sent once, immediately after `run` is called. Indicates that the loop was just initialized. - Init, -} - /// Describes an event from a `Window`. #[derive(Debug, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -276,6 +212,76 @@ pub enum WindowEvent<'a> { ScaleFactorChanged(f64, &'a mut PhysicalSize), } +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum RawPointerEvent { + /// A device has been added. + Added, + /// A device has been removed. + Removed, + Press(RawPointerPress), + /// Relative change in physical position of a pointing device. + /// + /// This represents raw, unfiltered physical motion, NOT the position of the mouse. Accordingly, + /// the values provided here are the change in position of the mouse since the previous + /// `MovedRelative` event. + MovedRelative(PhysicalDelta), + /// Change in absolute position of a pointing device. + /// + /// The `PhysicalPosition` value is the new position of the cursor relative to the desktop. This + /// generally doesn't get output by standard mouse devices, but can get output from tablet devices. + MovedAbsolute(PhysicalPosition), + /// Change in rotation of mouse wheel. + Wheel(UnitlessDelta), +} + +/// Raw keyboard events. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum RawKeyboardEvent { + /// A keyboard device has been added. + Added, + /// A keyboard device has been removed. + Removed, + Press(RawKeyPress), +} + +impl<'a, T> Event<'a, T> { + pub fn map_nonuser_event(self) -> Result, Event<'a, T>> { + use self::Event::*; + match self { + UserEvent(_) => Err(self), + WindowEvent(window_id, event) => Ok(WindowEvent(window_id, event)), + RawPointerEvent(pointer_id, event) => Ok(RawPointerEvent(pointer_id, event)), + RawKeyboardEvent(keyboard_id, event) => Ok(RawKeyboardEvent(keyboard_id, event)), + AppEvent(app_event) => Ok(AppEvent(app_event)), + NewEvents(cause) => Ok(NewEvents(cause)), + MainEventsCleared => Ok(MainEventsCleared), + RedrawRequested(wid) => Ok(RedrawRequested(wid)), + RedrawEventsCleared => Ok(RedrawEventsCleared), + LoopDestroyed => Ok(LoopDestroyed), + } + } + + /// If the event doesn't contain a reference, turn it into an event with a `'static` lifetime. + /// Otherwise, return `None`. + pub fn to_static(self) -> Result, Event<'a, T>> { + use self::Event::*; + match self { + NewEvents(cause) => Ok(NewEvents(cause)), + WindowEvent(window_id, event) => event.to_static() + .map(|e| -> Event<'static, T> {WindowEvent(window_id, e)}) + .map_err(|e| -> Event<'a, T> {WindowEvent(window_id, e)}), + RawPointerEvent(pointer_id, event) => Ok(RawPointerEvent(pointer_id, event)), + RawKeyboardEvent(keyboard_id, event) => Ok(RawKeyboardEvent(keyboard_id, event)), + AppEvent(app_event) => Ok(AppEvent(app_event)), + UserEvent(e) => Ok(UserEvent(e)), + MainEventsCleared => Ok(MainEventsCleared), + RedrawRequested(wid) => Ok(RedrawRequested(wid)), + RedrawEventsCleared => Ok(RedrawEventsCleared), + LoopDestroyed => Ok(LoopDestroyed), + } + } +} + impl Clone for WindowEvent<'static> { fn clone(&self) -> Self { use self::WindowEvent::*; @@ -342,6 +348,33 @@ impl<'a> WindowEvent<'a> { } } +/// Describes the reason the event loop is resuming. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum StartCause { + /// Sent if the time specified by `ControlFlow::WaitUntil` has been reached. Contains the + /// moment the timeout was requested and the requested resume time. The actual resume time is + /// guaranteed to be equal to or after the requested resume time. + ResumeTimeReached { + start: Instant, + requested_resume: Instant, + }, + + /// Sent if the OS has new events to send to the window, after a wait was requested. Contains + /// the moment the wait was requested and the resume time, if requested. + WaitCancelled { + start: Instant, + requested_resume: Option, + }, + + /// Sent if the event loop is being resumed after the loop's control flow was set to + /// `ControlFlow::Poll`. + Poll, + + /// Sent once, immediately after `run` is called. Indicates that the loop was just initialized. + Init, +} + + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct KeyPress { pub(crate) logical_key: Option, @@ -443,36 +476,6 @@ impl RawPointerPress { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub enum PointerId { - MouseId(MouseId), - TouchId(TouchId), - // PenId(PenId), -} - -impl PointerId { - pub fn is_mouse_id(&self) -> bool { - match *self { - PointerId::MouseId(_) => true, - _ => false, - } - } - - pub fn is_touch_id(&self) -> bool { - match *self { - PointerId::TouchId(_) => true, - _ => false, - } - } - - // pub fn is_pen_id(&self) -> bool { - // match *self { - // PointerId::PenId(_) => true, - // _ => false, - // } - // } -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[repr(transparent)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -531,39 +534,14 @@ impl PointerButton { // pub fn is_button_6(&self) -> bool { *self == Self::BUTTON_6 } } -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum RawPointerEvent { - /// A device has been added. - Added, - /// A device has been removed. - Removed, - Press(RawPointerPress), - /// Relative change in physical position of a pointing device. - /// - /// This represents raw, unfiltered physical motion, NOT the position of the mouse. Accordingly, - /// the values provided here are the change in position of the mouse since the previous - /// `MovedRelative` event. - MovedRelative(PhysicalDelta), - /// Change in absolute position of a pointing device. - /// - /// The `PhysicalPosition` value is the new position of the cursor relative to the desktop. This - /// generally doesn't get output by standard mouse devices, but can get output from tablet devices. - MovedAbsolute(PhysicalPosition), - /// Change in rotation of mouse wheel. - Wheel(UnitlessDelta), -} - -/// Raw keyboard events. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum RawKeyboardEvent { - /// A keyboard device has been added. - Added, - /// A keyboard device has been removed. - Removed, - Press(RawKeyPress), +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum PointerId { + MouseId(MouseId), + TouchId(TouchId), + // PenId(PenId), } -/// A typed identifier for a mouse device. +/// A typed identifier for a pointer device. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct MouseId(pub(crate) platform_impl::MouseId); @@ -576,6 +554,29 @@ pub struct PointerDeviceId(pub(crate) platform_impl::PointerDeviceId); #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct KeyboardDeviceId(pub(crate) platform_impl::KeyboardDeviceId); +impl PointerId { + pub fn is_mouse_id(&self) -> bool { + match *self { + PointerId::MouseId(_) => true, + _ => false, + } + } + + pub fn is_touch_id(&self) -> bool { + match *self { + PointerId::TouchId(_) => true, + _ => false, + } + } + + // pub fn is_pen_id(&self) -> bool { + // match *self { + // PointerId::PenId(_) => true, + // _ => false, + // } + // } +} + impl MouseId { /// Returns a dummy `MouseId`, useful for unit testing. The only guarantee made about the return /// value of this function is that it will always be equal to itself and to future values returned @@ -890,25 +891,6 @@ pub enum LogicalKey { Cut, } -impl ModifiersState { - /// Returns `true` if the shift key is pressed. - pub fn shift(&self) -> bool { - self.intersects(Self::SHIFT) - } - /// Returns `true` if the control key is pressed. - pub fn ctrl(&self) -> bool { - self.intersects(Self::CTRL) - } - /// Returns `true` if the alt key is pressed. - pub fn alt(&self) -> bool { - self.intersects(Self::ALT) - } - /// Returns `true` if the logo key is pressed. - pub fn logo(&self) -> bool { - self.intersects(Self::LOGO) - } -} - bitflags! { /// Represents the current state of the keyboard modifiers /// @@ -936,6 +918,25 @@ bitflags! { } } +impl ModifiersState { + /// Returns `true` if the shift key is pressed. + pub fn shift(&self) -> bool { + self.intersects(Self::SHIFT) + } + /// Returns `true` if the control key is pressed. + pub fn ctrl(&self) -> bool { + self.intersects(Self::CTRL) + } + /// Returns `true` if the alt key is pressed. + pub fn alt(&self) -> bool { + self.intersects(Self::ALT) + } + /// Returns `true` if the logo key is pressed. + pub fn logo(&self) -> bool { + self.intersects(Self::LOGO) + } +} + #[cfg(feature = "serde")] mod modifiers_serde { use super::ModifiersState; From 6adde34ffcfb727717a85d56e7d504df4cd04d89 Mon Sep 17 00:00:00 2001 From: Osspial Date: Sat, 16 May 2020 18:23:23 -0400 Subject: [PATCH 11/29] Make examples, docs, and tests work --- examples/control_flow.rs | 25 +++---- examples/cursor.rs | 20 +----- examples/cursor_grab.rs | 44 +++++------- examples/custom_events.rs | 5 +- examples/fullscreen.rs | 24 +++---- examples/handling_close.rs | 90 ++++++++++-------------- examples/min_max_size.rs | 5 +- examples/minimize.rs | 21 ++---- examples/multithreaded.rs | 35 +++------- examples/multiwindow.rs | 13 +--- examples/request_redraw.rs | 11 +-- examples/request_redraw_threaded.rs | 5 +- examples/resizable.rs | 14 +--- examples/timer.rs | 5 +- examples/transparent.rs | 5 +- examples/web.rs | 6 +- examples/window.rs | 10 +-- examples/window_debug.rs | 104 +++++++++++----------------- examples/window_icon.rs | 18 +++-- examples/window_run_return.rs | 7 +- src/event.rs | 12 ++++ src/lib.rs | 15 ++-- src/window.rs | 14 ++-- tests/send_objects.rs | 3 +- 24 files changed, 192 insertions(+), 319 deletions(-) diff --git a/examples/control_flow.rs b/examples/control_flow.rs index 6d71541216..6dbb669405 100644 --- a/examples/control_flow.rs +++ b/examples/control_flow.rs @@ -1,7 +1,7 @@ use std::{thread, time}; use winit::{ - event::{Event, KeyboardInput, WindowEvent}, + event::{Event, LogicalKey, StartCause, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; @@ -37,7 +37,6 @@ fn main() { let mut close_requested = false; event_loop.run(move |event, _, control_flow| { - use winit::event::{ElementState, StartCause, VirtualKeyCode}; println!("{:?}", event); match event { Event::NewEvents(start_cause) => { @@ -46,36 +45,28 @@ fn main() { _ => false, } } - Event::WindowEvent { event, .. } => match event { + Event::WindowEvent(_, event) => match event { WindowEvent::CloseRequested => { close_requested = true; } - WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(virtual_code), - state: ElementState::Pressed, - .. - }, - .. - } => match virtual_code { - VirtualKeyCode::Key1 => { + WindowEvent::KeyPress(e) if e.is_down() => match e.logical_key() { + Some(LogicalKey::Key1) => { mode = Mode::Wait; println!("\nmode: {:?}\n", mode); } - VirtualKeyCode::Key2 => { + Some(LogicalKey::Key2) => { mode = Mode::WaitUntil; println!("\nmode: {:?}\n", mode); } - VirtualKeyCode::Key3 => { + Some(LogicalKey::Key3) => { mode = Mode::Poll; println!("\nmode: {:?}\n", mode); } - VirtualKeyCode::R => { + Some(LogicalKey::R) => { request_redraw = !request_redraw; println!("\nrequest_redraw: {}\n", request_redraw); } - VirtualKeyCode::Escape => { + Some(LogicalKey::Escape) => { close_requested = true; } _ => (), diff --git a/examples/cursor.rs b/examples/cursor.rs index de45adae33..9e93909a10 100644 --- a/examples/cursor.rs +++ b/examples/cursor.rs @@ -1,5 +1,5 @@ use winit::{ - event::{ElementState, Event, KeyboardInput, WindowEvent}, + event::{Event, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::{CursorIcon, WindowBuilder}, }; @@ -17,18 +17,7 @@ fn main() { *control_flow = ControlFlow::Wait; match event { - Event::WindowEvent { - event: - WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - .. - }, - .. - }, - .. - } => { + Event::WindowEvent(_, WindowEvent::KeyPress(e)) if e.is_down() => { println!("Setting cursor to \"{:?}\"", CURSORS[cursor_idx]); window.set_cursor_icon(CURSORS[cursor_idx]); if cursor_idx < CURSORS.len() - 1 { @@ -37,10 +26,7 @@ fn main() { cursor_idx = 0; } } - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { + Event::WindowEvent(_, WindowEvent::CloseRequested) => { *control_flow = ControlFlow::Exit; return; } diff --git a/examples/cursor_grab.rs b/examples/cursor_grab.rs index 317577e3c5..5a02c02541 100644 --- a/examples/cursor_grab.rs +++ b/examples/cursor_grab.rs @@ -1,5 +1,5 @@ use winit::{ - event::{DeviceEvent, ElementState, Event, KeyboardInput, ModifiersState, WindowEvent}, + event::{Event, LogicalKey, ModifiersState, RawPointerEvent, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; @@ -19,34 +19,28 @@ fn main() { *control_flow = ControlFlow::Wait; match event { - Event::WindowEvent { event, .. } => match event { + Event::WindowEvent(_, event) => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, - WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Released, - virtual_keycode: Some(key), - .. - }, - .. - } => { - use winit::event::VirtualKeyCode::*; - match key { - Escape => *control_flow = ControlFlow::Exit, - G => window.set_cursor_grab(!modifiers.shift()).unwrap(), - H => window.set_cursor_visible(modifiers.shift()), - _ => (), - } - } + WindowEvent::KeyPress(e) if e.is_down() => match e.logical_key() { + Some(LogicalKey::Escape) => *control_flow = ControlFlow::Exit, + Some(LogicalKey::G) => window.set_cursor_grab(!modifiers.shift()).unwrap(), + Some(LogicalKey::H) => window.set_cursor_visible(modifiers.shift()), + _ => (), + }, WindowEvent::ModifiersChanged(m) => modifiers = m, _ => (), }, - Event::DeviceEvent { event, .. } => match event { - DeviceEvent::MouseMotion { delta } => println!("mouse moved: {:?}", delta), - DeviceEvent::Button { button, state } => match state { - ElementState::Pressed => println!("mouse button {} pressed", button), - ElementState::Released => println!("mouse button {} released", button), - }, + Event::RawPointerEvent(_, event) => match event { + RawPointerEvent::MovedRelative(delta) => println!("pointer moved: {:?}", delta), + RawPointerEvent::MovedAbsolute(position) => { + println!("pointer moved to: {:?}", position) + } + RawPointerEvent::Press(e) if e.is_down() => { + println!("pointer button {:?} pressed", e.button()) + } + RawPointerEvent::Press(e) if e.is_up() => { + println!("pointer button {:?} released", e.button()) + } _ => (), }, _ => (), diff --git a/examples/custom_events.rs b/examples/custom_events.rs index c59299cab4..72787c0190 100644 --- a/examples/custom_events.rs +++ b/examples/custom_events.rs @@ -37,10 +37,7 @@ fn main() { match event { Event::UserEvent(event) => println!("user event: {:?}", event), - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => *control_flow = ControlFlow::Exit, + Event::WindowEvent(_, WindowEvent::CloseRequested) => *control_flow = ControlFlow::Exit, _ => (), } }); diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index 4cdb7b63ed..ec12b60208 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -1,5 +1,5 @@ use std::io::{stdin, stdout, Write}; -use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}; +use winit::event::{Event, LogicalKey, WindowEvent}; use winit::event_loop::{ControlFlow, EventLoop}; use winit::monitor::{MonitorHandle, VideoMode}; use winit::window::{Fullscreen, WindowBuilder}; @@ -34,33 +34,25 @@ fn main() { *control_flow = ControlFlow::Wait; match event { - Event::WindowEvent { event, .. } => match event { + Event::WindowEvent(_, event) => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, - WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(virtual_code), - state, - .. - }, - .. - } => match (virtual_code, state) { - (VirtualKeyCode::Escape, _) => *control_flow = ControlFlow::Exit, - (VirtualKeyCode::F, ElementState::Pressed) => { + WindowEvent::KeyPress(e) if e.is_down() => match e.logical_key() { + Some(LogicalKey::Escape) => *control_flow = ControlFlow::Exit, + Some(LogicalKey::F) => { if window.fullscreen().is_some() { window.set_fullscreen(None); } else { window.set_fullscreen(fullscreen.clone()); } } - (VirtualKeyCode::S, ElementState::Pressed) => { + Some(LogicalKey::S) => { println!("window.fullscreen {:?}", window.fullscreen()); } - (VirtualKeyCode::M, ElementState::Pressed) => { + Some(LogicalKey::M) => { is_maximized = !is_maximized; window.set_maximized(is_maximized); } - (VirtualKeyCode::D, ElementState::Pressed) => { + Some(LogicalKey::D) => { decorations = !decorations; window.set_decorations(decorations); } diff --git a/examples/handling_close.rs b/examples/handling_close.rs index cbd5705369..834cf6dc0d 100644 --- a/examples/handling_close.rs +++ b/examples/handling_close.rs @@ -1,5 +1,5 @@ use winit::{ - event::{Event, KeyboardInput, WindowEvent}, + event::{Event, LogicalKey, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; @@ -16,67 +16,51 @@ fn main() { let mut close_requested = false; event_loop.run(move |event, _, control_flow| { - use winit::event::{ - ElementState::Released, - VirtualKeyCode::{N, Y}, - }; *control_flow = ControlFlow::Wait; match event { - Event::WindowEvent { event, .. } => { - match event { - WindowEvent::CloseRequested => { - // `CloseRequested` is sent when the close button on the window is pressed (or - // through whatever other mechanisms the window manager provides for closing a - // window). If you don't handle this event, the close button won't actually do - // anything. + Event::WindowEvent(_, event) => match event { + WindowEvent::CloseRequested => { + // `CloseRequested` is sent when the close button on the window is pressed (or + // through whatever other mechanisms the window manager provides for closing a + // window). If you don't handle this event, the close button won't actually do + // anything. - // A common thing to do here is prompt the user if they have unsaved work. - // Creating a proper dialog box for that is far beyond the scope of this - // example, so here we'll just respond to the Y and N keys. - println!("Are you ready to bid your window farewell? [Y/N]"); - close_requested = true; + // A common thing to do here is prompt the user if they have unsaved work. + // Creating a proper dialog box for that is far beyond the scope of this + // example, so here we'll just respond to the Y and N keys. + println!("Are you ready to bid your window farewell? [Y/N]"); + close_requested = true; - // In applications where you can safely close the window without further - // action from the user, this is generally where you'd handle cleanup before - // closing the window. How to close the window is detailed in the handler for - // the Y key. - } - WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(virtual_code), - state: Released, - .. - }, - .. - } => { - match virtual_code { - Y => { - if close_requested { - // This is where you'll want to do any cleanup you need. - println!("Buh-bye!"); + // In applications where you can safely close the window without further + // action from the user, this is generally where you'd handle cleanup before + // closing the window. How to close the window is detailed in the handler for + // the Y key. + } + WindowEvent::KeyPress(e) if e.is_up() => match e.logical_key() { + Some(LogicalKey::Y) => { + if close_requested { + // This is where you'll want to do any cleanup you need. + println!("Buh-bye!"); - // For a single-window application like this, you'd normally just - // break out of the event loop here. If you wanted to keep running the - // event loop (i.e. if it's a multi-window application), you need to - // drop the window. That closes it, and results in `Destroyed` being - // sent. - *control_flow = ControlFlow::Exit; - } - } - N => { - if close_requested { - println!("Your window will continue to stay by your side."); - close_requested = false; - } - } - _ => (), + // For a single-window application like this, you'd normally just + // break out of the event loop here. If you wanted to keep running the + // event loop (i.e. if it's a multi-window application), you need to + // drop the window. That closes it, and results in `Destroyed` being + // sent. + *control_flow = ControlFlow::Exit; + } + } + Some(LogicalKey::N) => { + if close_requested { + println!("Your window will continue to stay by your side."); + close_requested = false; } } _ => (), - } - } + }, + _ => (), + }, _ => (), } }); diff --git a/examples/min_max_size.rs b/examples/min_max_size.rs index f4fd00c1bb..77e9d26301 100644 --- a/examples/min_max_size.rs +++ b/examples/min_max_size.rs @@ -19,10 +19,7 @@ fn main() { println!("{:?}", event); match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => *control_flow = ControlFlow::Exit, + Event::WindowEvent(_, WindowEvent::CloseRequested) => *control_flow = ControlFlow::Exit, _ => (), } }); diff --git a/examples/minimize.rs b/examples/minimize.rs index 871cfe2edb..bed582c3b3 100644 --- a/examples/minimize.rs +++ b/examples/minimize.rs @@ -1,6 +1,6 @@ extern crate winit; -use winit::event::{Event, VirtualKeyCode, WindowEvent}; +use winit::event::{Event, LogicalKey, WindowEvent}; use winit::event_loop::{ControlFlow, EventLoop}; use winit::window::WindowBuilder; @@ -17,22 +17,13 @@ fn main() { *control_flow = ControlFlow::Wait; match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => *control_flow = ControlFlow::Exit, + Event::WindowEvent(_, WindowEvent::CloseRequested) => *control_flow = ControlFlow::Exit, // Keyboard input event to handle minimize via a hotkey - Event::WindowEvent { - event: WindowEvent::KeyboardInput { input, .. }, - window_id, - } => { - if window_id == window.id() { - // Pressing the 'M' key will minimize the window - if input.virtual_keycode == Some(VirtualKeyCode::M) { - window.set_minimized(true); - } - } + Event::WindowEvent(window_id, WindowEvent::KeyPress(e)) + if e.is_down() && e.logical_key_is(LogicalKey::M) && window_id == window.id() => + { + window.set_minimized(true) } _ => (), } diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs index 60f9d802de..1ca91e2401 100644 --- a/examples/multithreaded.rs +++ b/examples/multithreaded.rs @@ -4,7 +4,7 @@ fn main() { use winit::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, - event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, + event::{Event, WindowEvent, ModifiersState}, event_loop::{ControlFlow, EventLoop}, window::{CursorIcon, Fullscreen, WindowBuilder}, }; @@ -23,6 +23,7 @@ fn main() { let mut video_modes: Vec<_> = window.current_monitor().video_modes().collect(); let mut video_mode_id = 0usize; + let mut modifiers = ModifiersState::empty(); let (tx, rx) = mpsc::channel(); window_senders.insert(window.id(), tx); @@ -47,21 +48,12 @@ fn main() { video_modes.iter().nth(video_mode_id).unwrap() ); } - } - #[allow(deprecated)] - WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Released, - virtual_keycode: Some(key), - modifiers, - .. - }, - .. - } => { + }, + WindowEvent::ModifiersChanged(mods) => modifiers = mods, + WindowEvent::KeyPress(e) if e.is_up() => if let Some(key) = e.logical_key() { window.set_title(&format!("{:?}", key)); let state = !modifiers.shift(); - use VirtualKeyCode::*; + use winit::event::LogicalKey::*; match key { A => window.set_always_on_top(state), C => window.set_cursor_icon(match state { @@ -152,23 +144,14 @@ fn main() { false => ControlFlow::Exit, }; match event { - Event::WindowEvent { event, window_id } => match event { + Event::WindowEvent(window_id, event) => match event { WindowEvent::CloseRequested - | WindowEvent::Destroyed - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Released, - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => { + | WindowEvent::Destroyed => { window_senders.remove(&window_id); } _ => { if let Some(tx) = window_senders.get(&window_id) { - if let Some(event) = event.to_static() { + if let Ok(event) = event.to_static() { tx.send(event).unwrap(); } } diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index 01c91bb646..35c1bcddef 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; use winit::{ - event::{ElementState, Event, KeyboardInput, WindowEvent}, + event::{Event, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::Window, }; @@ -19,7 +19,7 @@ fn main() { *control_flow = ControlFlow::Wait; match event { - Event::WindowEvent { event, window_id } => { + Event::WindowEvent(window_id, event) => { match event { WindowEvent::CloseRequested => { println!("Window {:?} has received the signal to close", window_id); @@ -31,14 +31,7 @@ fn main() { *control_flow = ControlFlow::Exit; } } - WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - .. - }, - .. - } => { + WindowEvent::KeyPress(e) if e.is_down() => { let window = Window::new(&event_loop).unwrap(); windows.insert(window.id(), window); } diff --git a/examples/request_redraw.rs b/examples/request_redraw.rs index 5d761ae479..46f5c1f0f7 100644 --- a/examples/request_redraw.rs +++ b/examples/request_redraw.rs @@ -1,5 +1,5 @@ use winit::{ - event::{ElementState, Event, WindowEvent}, + event::{Event, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; @@ -19,14 +19,9 @@ fn main() { *control_flow = ControlFlow::Wait; match event { - Event::WindowEvent { event, .. } => match event { + Event::WindowEvent(_, event) => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, - WindowEvent::MouseInput { - state: ElementState::Released, - .. - } => { - window.request_redraw(); - } + WindowEvent::PointerPress(_, e) if e.is_up() => window.request_redraw(), _ => (), }, Event::RedrawRequested(_) => { diff --git a/examples/request_redraw_threaded.rs b/examples/request_redraw_threaded.rs index 341612ca64..237788ce8d 100644 --- a/examples/request_redraw_threaded.rs +++ b/examples/request_redraw_threaded.rs @@ -26,10 +26,7 @@ fn main() { *control_flow = ControlFlow::Wait; match event { - Event::WindowEvent { event, .. } => match event { - WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, - _ => (), - }, + Event::WindowEvent(_, WindowEvent::CloseRequested) => *control_flow = ControlFlow::Exit, Event::RedrawRequested(_) => { println!("\nredrawing!\n"); } diff --git a/examples/resizable.rs b/examples/resizable.rs index 6a90391937..7ddf35e1ab 100644 --- a/examples/resizable.rs +++ b/examples/resizable.rs @@ -1,6 +1,6 @@ use winit::{ dpi::LogicalSize, - event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, + event::{Event, LogicalKey, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; @@ -22,17 +22,9 @@ fn main() { *control_flow = ControlFlow::Wait; match event { - Event::WindowEvent { event, .. } => match event { + Event::WindowEvent(_, event) => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, - WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(VirtualKeyCode::Space), - state: ElementState::Released, - .. - }, - .. - } => { + WindowEvent::KeyPress(e) if e.is_up() && e.logical_key_is(LogicalKey::Space) => { resizable = !resizable; println!("Resizable: {}", resizable); window.set_resizable(resizable); diff --git a/examples/timer.rs b/examples/timer.rs index 52a1444ec2..4e61751aba 100644 --- a/examples/timer.rs +++ b/examples/timer.rs @@ -28,10 +28,7 @@ fn main() { *control_flow = ControlFlow::WaitUntil(Instant::now() + timer_length); println!("\nTimer\n"); } - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => *control_flow = ControlFlow::Exit, + Event::WindowEvent(_, WindowEvent::CloseRequested) => *control_flow = ControlFlow::Exit, _ => (), } }); diff --git a/examples/transparent.rs b/examples/transparent.rs index 78e3c4da33..093c7f612f 100644 --- a/examples/transparent.rs +++ b/examples/transparent.rs @@ -21,10 +21,7 @@ fn main() { println!("{:?}", event); match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => *control_flow = ControlFlow::Exit, + Event::WindowEvent(_, WindowEvent::CloseRequested) => *control_flow = ControlFlow::Exit, _ => (), } }); diff --git a/examples/web.rs b/examples/web.rs index 46b024ccf2..f9b6baead4 100644 --- a/examples/web.rs +++ b/examples/web.rs @@ -49,10 +49,8 @@ pub fn main() { std_web::console!(log, "%s", format!("{:?}", event)); match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - window_id, - } if window_id == window.id() => *control_flow = ControlFlow::Exit, + Event::WindowEvent(window_id, WindowEvent::CloseRequested) + if window_id == window.id() => *control_flow = ControlFlow::Exit, Event::MainEventsCleared => { window.request_redraw(); } diff --git a/examples/window.rs b/examples/window.rs index c028a50f3f..286c54fc8a 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -19,13 +19,9 @@ fn main() { println!("{:?}", event); match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - window_id, - } if window_id == window.id() => *control_flow = ControlFlow::Exit, - Event::MainEventsCleared => { - window.request_redraw(); - } + Event::WindowEvent(window_id, WindowEvent::CloseRequested) + if window_id == window.id() => *control_flow = ControlFlow::Exit, + Event::MainEventsCleared => window.request_redraw(), _ => (), } }); diff --git a/examples/window_debug.rs b/examples/window_debug.rs index f6e960a794..5730c7f901 100644 --- a/examples/window_debug.rs +++ b/examples/window_debug.rs @@ -2,7 +2,7 @@ use winit::{ dpi::{LogicalSize, PhysicalSize}, - event::{DeviceEvent, ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, + event::{RawKeyboardEvent, Event, LogicalKey, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::{Fullscreen, WindowBuilder}, }; @@ -33,22 +33,14 @@ fn main() { *control_flow = ControlFlow::Wait; match event { - Event::DeviceEvent { - event: - DeviceEvent::Key(KeyboardInput { - virtual_keycode: Some(key), - state: ElementState::Pressed, - .. - }), - .. - } => match key { - VirtualKeyCode::M => { + Event::RawKeyboardEvent(_, RawKeyboardEvent::Press(e)) if e.is_down() => match e.logical_key() { + Some(LogicalKey::M) => { if minimized { minimized = !minimized; window.set_minimized(minimized); } } - VirtualKeyCode::V => { + Some(LogicalKey::V) => { if !visible { visible = !visible; window.set_visible(visible); @@ -56,61 +48,49 @@ fn main() { } _ => (), }, - Event::WindowEvent { - event: WindowEvent::KeyboardInput { input, .. }, - .. - } => match input { - KeyboardInput { - virtual_keycode: Some(key), - state: ElementState::Pressed, - .. - } => match key { - VirtualKeyCode::E => { - fn area(size: PhysicalSize) -> u32 { - size.width * size.height - } - - let monitor = window.current_monitor(); - if let Some(mode) = monitor - .video_modes() - .max_by(|a, b| area(a.size()).cmp(&area(b.size()))) - { - window.set_fullscreen(Some(Fullscreen::Exclusive(mode))); - } else { - eprintln!("no video modes available"); - } - } - VirtualKeyCode::F => { - if window.fullscreen().is_some() { - window.set_fullscreen(None); - } else { - let monitor = window.current_monitor(); - window.set_fullscreen(Some(Fullscreen::Borderless(monitor))); - } + Event::WindowEvent(_, WindowEvent::KeyPress(e)) if e.is_down() => match e.logical_key() { + Some(LogicalKey::E) => { + fn area(size: PhysicalSize) -> u32 { + size.width * size.height } - VirtualKeyCode::M => { - minimized = !minimized; - window.set_minimized(minimized); - } - VirtualKeyCode::Q => { - *control_flow = ControlFlow::Exit; - } - VirtualKeyCode::V => { - visible = !visible; - window.set_visible(visible); + + let monitor = window.current_monitor(); + if let Some(mode) = monitor + .video_modes() + .max_by(|a, b| area(a.size()).cmp(&area(b.size()))) + { + window.set_fullscreen(Some(Fullscreen::Exclusive(mode))); + } else { + eprintln!("no video modes available"); } - VirtualKeyCode::X => { - maximized = !maximized; - window.set_maximized(maximized); + } + Some(LogicalKey::F) => { + if window.fullscreen().is_some() { + window.set_fullscreen(None); + } else { + let monitor = window.current_monitor(); + window.set_fullscreen(Some(Fullscreen::Borderless(monitor))); } - _ => (), - }, + } + Some(LogicalKey::M) => { + minimized = !minimized; + window.set_minimized(minimized); + } + Some(LogicalKey::Q) => { + *control_flow = ControlFlow::Exit; + } + Some(LogicalKey::V) => { + visible = !visible; + window.set_visible(visible); + } + Some(LogicalKey::X) => { + maximized = !maximized; + window.set_maximized(maximized); + } _ => (), }, - Event::WindowEvent { - event: WindowEvent::CloseRequested, - window_id, - } if window_id == window.id() => *control_flow = ControlFlow::Exit, + Event::WindowEvent(window_id, WindowEvent::CloseRequested) + if window_id == window.id() => *control_flow = ControlFlow::Exit, _ => (), } }); diff --git a/examples/window_icon.rs b/examples/window_icon.rs index 734debf4d4..4b6bc6f6ea 100644 --- a/examples/window_icon.rs +++ b/examples/window_icon.rs @@ -1,7 +1,7 @@ extern crate image; use std::path::Path; use winit::{ - event::Event, + event::{Event, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::{Icon, WindowBuilder}, }; @@ -30,15 +30,13 @@ fn main() { event_loop.run(move |event, _, control_flow| { *control_flow = ControlFlow::Wait; - if let Event::WindowEvent { event, .. } = event { - use winit::event::WindowEvent::*; - match event { - CloseRequested => *control_flow = ControlFlow::Exit, - DroppedFile(path) => { - window.set_window_icon(Some(load_icon(&path))); - } - _ => (), - } + match event { + Event::WindowEvent(_, event) => match event { + WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, + WindowEvent::FileDropped(path) => window.set_window_icon(Some(load_icon(&path))), + _ => () + }, + _ => (), } }); } diff --git a/examples/window_run_return.rs b/examples/window_run_return.rs index 0112eb3e5b..6c17112ff5 100644 --- a/examples/window_run_return.rs +++ b/examples/window_run_return.rs @@ -30,16 +30,13 @@ fn main() { event_loop.run_return(|event, _, control_flow| { *control_flow = ControlFlow::Wait; - if let Event::WindowEvent { event, .. } = &event { + if let Event::WindowEvent(_, event) = &event { // Print only Window events to reduce noise println!("{:?}", event); } match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { + Event::WindowEvent(_, WindowEvent::CloseRequested) => { quit = true; } Event::MainEventsCleared => { diff --git a/src/event.rs b/src/event.rs index 4c3fef5eec..c406e2a434 100644 --- a/src/event.rs +++ b/src/event.rs @@ -419,6 +419,9 @@ impl KeyPress { pub fn is_down(&self) -> bool { self.is_down } + pub fn is_up(&self) -> bool { + !self.is_down + } /// Is `true` if the user has held down the key long enough to send duplicate events. /// /// Is always `false` if `is_down` is `false`. @@ -449,6 +452,9 @@ impl RawKeyPress { pub fn is_down(&self) -> bool { self.is_down } + pub fn is_up(&self) -> bool { + !self.is_down + } } impl PointerPress { @@ -458,6 +464,9 @@ impl PointerPress { pub fn is_down(&self) -> bool { self.is_down } + pub fn is_up(&self) -> bool { + !self.is_down + } /// The number of clicks the user has made in the same spot within the system's double-click /// interval. `1` is emitted on the first click, `2` is emitted on the second click, etc. /// @@ -474,6 +483,9 @@ impl RawPointerPress { pub fn is_down(&self) -> bool { self.is_down } + pub fn is_up(&self) -> bool { + !self.is_down + } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] diff --git a/src/lib.rs b/src/lib.rs index ce66665616..2037e6bc77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,9 +24,10 @@ //! Once a [`Window`] has been created, it will generate different *events*. A [`Window`] object can //! generate [`WindowEvent`]s when certain input events occur, such as a cursor moving over the //! window or a key getting pressed while the window is focused. Devices can generate -//! [`DeviceEvent`]s, which contain unfiltered event data that isn't specific to a certain window. -//! Some user activity, like mouse movement, can generate both a [`WindowEvent`] *and* a -//! [`DeviceEvent`]. You can also create and handle your own custom [`UserEvent`]s, if desired. +//! [`RawPointerEvent`]s and [`RawKeyboardEvent`]s, which contain unfiltered event data that isn't +//! specific to a certain window. Some user activity, like mouse movement, can generate both +//! [`WindowEvent`]s *and* raw events. You can also create and handle your own custom +//! [`UserEvent`]s, if desired. //! //! You can retreive events by calling [`EventLoop::run`][event_loop_run]. This function will //! dispatch events for every [`Window`] that was created with that particular [`EventLoop`], and @@ -62,10 +63,7 @@ //! *control_flow = ControlFlow::Wait; //! //! match event { -//! Event::WindowEvent { -//! event: WindowEvent::CloseRequested, -//! .. -//! } => { +//! Event::WindowEvent(_, WindowEvent::CloseRequested) => { //! println!("The close button was pressed; stopping"); //! *control_flow = ControlFlow::Exit //! }, @@ -123,7 +121,8 @@ //! [window_id_fn]: window::Window::id //! [`Event`]: event::Event //! [`WindowEvent`]: event::WindowEvent -//! [`DeviceEvent`]: event::DeviceEvent +//! [`RawKeyboardEvent`]: event::RawKeyboardEvent +//! [`RawPointerEvent`]: event::RawPointerEvent //! [`UserEvent`]: event::Event::UserEvent //! [`LoopDestroyed`]: event::Event::LoopDestroyed //! [`platform`]: platform diff --git a/src/window.rs b/src/window.rs index e5f9df0c9f..531e3fad14 100644 --- a/src/window.rs +++ b/src/window.rs @@ -6,11 +6,13 @@ //! [`WindowBuilder`], populating it with data, and calling the [`WindowBuilder::build`] method: //! //! ```no_run +//! # use winit::{event_loop::EventLoop, window::Window}; //! let mut event_loop = EventLoop::new(); //! let window = Window::new(&event_loop).unwrap(); //! ``` //! //! ```no_run +//! # use winit::{event_loop::EventLoop, window::WindowBuilder}; //! let mut event_loop = EventLoop::new(); //! let window = WindowBuilder::new() //! .with_title("A fantastic window!") @@ -28,14 +30,18 @@ //! `Window` will only close either when it is explicitly dropped or the application quits. //! //! ```no_run +//! # use winit::{ +//! # event_loop::{ControlFlow, EventLoop}, +//! # event::{Event, WindowEvent}, +//! # window::WindowBuilder +//! # }; +//! # let event_loop = EventLoop::new(); //! event_loop.run(move |event, _, control_flow| { //! *control_flow = ControlFlow::Wait; //! //! match event { -//! Event::WindowEvent { -//! event: WindowEvent::CloseRequested, -//! .. -//! } => *control_flow = ControlFlow::Exit, +//! Event::WindowEvent(_, WindowEvent::CloseRequested) +//! => *control_flow = ControlFlow::Exit, //! _ => (), //! } //! }); diff --git a/tests/send_objects.rs b/tests/send_objects.rs index 252b271a4b..742decadfe 100644 --- a/tests/send_objects.rs +++ b/tests/send_objects.rs @@ -22,6 +22,7 @@ fn window_send() { fn ids_send() { // ensures that the various `..Id` types implement `Send` needs_send::(); - needs_send::(); + needs_send::(); + needs_send::(); needs_send::(); } From 0c3bc38f1d100163656d1049c2280ab91fa957d0 Mon Sep 17 00:00:00 2001 From: Osspial Date: Sat, 16 May 2020 18:25:43 -0400 Subject: [PATCH 12/29] format all the things --- examples/multithreaded.rs | 165 +++++++++++----------- examples/web.rs | 5 +- examples/window.rs | 5 +- examples/window_debug.rs | 36 +++-- examples/window_icon.rs | 2 +- src/dpi.rs | 6 +- src/event.rs | 67 ++++++--- src/platform/windows.rs | 2 +- src/platform_impl/windows/drop_handler.rs | 2 +- src/platform_impl/windows/event.rs | 2 +- src/platform_impl/windows/event_loop.rs | 90 +++++++----- src/platform_impl/windows/raw_input.rs | 20 +-- 12 files changed, 233 insertions(+), 169 deletions(-) diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs index 1ca91e2401..13e1a62448 100644 --- a/examples/multithreaded.rs +++ b/examples/multithreaded.rs @@ -4,7 +4,7 @@ fn main() { use winit::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, - event::{Event, WindowEvent, ModifiersState}, + event::{Event, ModifiersState, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::{CursorIcon, Fullscreen, WindowBuilder}, }; @@ -48,89 +48,91 @@ fn main() { video_modes.iter().nth(video_mode_id).unwrap() ); } - }, + } WindowEvent::ModifiersChanged(mods) => modifiers = mods, - WindowEvent::KeyPress(e) if e.is_up() => if let Some(key) = e.logical_key() { - window.set_title(&format!("{:?}", key)); - let state = !modifiers.shift(); - use winit::event::LogicalKey::*; - match key { - A => window.set_always_on_top(state), - C => window.set_cursor_icon(match state { - true => CursorIcon::Progress, - false => CursorIcon::Default, - }), - D => window.set_decorations(!state), - // Cycle through video modes - Right | Left => { - video_mode_id = match key { - Left => video_mode_id.saturating_sub(1), - Right => (video_modes.len() - 1).min(video_mode_id + 1), - _ => unreachable!(), - }; - println!( - "Picking video mode: {}", - video_modes.iter().nth(video_mode_id).unwrap() - ); - } - F => window.set_fullscreen(match (state, modifiers.alt()) { - (true, false) => { - Some(Fullscreen::Borderless(window.current_monitor())) + WindowEvent::KeyPress(e) if e.is_up() => { + if let Some(key) = e.logical_key() { + window.set_title(&format!("{:?}", key)); + let state = !modifiers.shift(); + use winit::event::LogicalKey::*; + match key { + A => window.set_always_on_top(state), + C => window.set_cursor_icon(match state { + true => CursorIcon::Progress, + false => CursorIcon::Default, + }), + D => window.set_decorations(!state), + // Cycle through video modes + Right | Left => { + video_mode_id = match key { + Left => video_mode_id.saturating_sub(1), + Right => (video_modes.len() - 1).min(video_mode_id + 1), + _ => unreachable!(), + }; + println!( + "Picking video mode: {}", + video_modes.iter().nth(video_mode_id).unwrap() + ); } - (true, true) => Some(Fullscreen::Exclusive( - video_modes.iter().nth(video_mode_id).unwrap().clone(), - )), - (false, _) => None, - }), - G => window.set_cursor_grab(state).unwrap(), - H => window.set_cursor_visible(!state), - I => { - println!("Info:"); - println!("-> outer_position : {:?}", window.outer_position()); - println!("-> inner_position : {:?}", window.inner_position()); - println!("-> outer_size : {:?}", window.outer_size()); - println!("-> inner_size : {:?}", window.inner_size()); - println!("-> fullscreen : {:?}", window.fullscreen()); - } - L => window.set_min_inner_size(match state { - true => Some(WINDOW_SIZE), - false => None, - }), - M => window.set_maximized(state), - P => window.set_outer_position({ - let mut position = window.outer_position().unwrap(); - let sign = if state { 1 } else { -1 }; - position.x += 10 * sign; - position.y += 10 * sign; - position - }), - Q => window.request_redraw(), - R => window.set_resizable(state), - S => window.set_inner_size(match state { - true => PhysicalSize::new( - WINDOW_SIZE.width + 100, - WINDOW_SIZE.height + 100, - ), - false => WINDOW_SIZE, - }), - W => { - if let Size::Physical(size) = WINDOW_SIZE.into() { - window - .set_cursor_position(Position::Physical( - PhysicalPosition::new( - size.width as i32 / 2, - size.height as i32 / 2, - ), - )) - .unwrap() + F => window.set_fullscreen(match (state, modifiers.alt()) { + (true, false) => { + Some(Fullscreen::Borderless(window.current_monitor())) + } + (true, true) => Some(Fullscreen::Exclusive( + video_modes.iter().nth(video_mode_id).unwrap().clone(), + )), + (false, _) => None, + }), + G => window.set_cursor_grab(state).unwrap(), + H => window.set_cursor_visible(!state), + I => { + println!("Info:"); + println!("-> outer_position : {:?}", window.outer_position()); + println!("-> inner_position : {:?}", window.inner_position()); + println!("-> outer_size : {:?}", window.outer_size()); + println!("-> inner_size : {:?}", window.inner_size()); + println!("-> fullscreen : {:?}", window.fullscreen()); } + L => window.set_min_inner_size(match state { + true => Some(WINDOW_SIZE), + false => None, + }), + M => window.set_maximized(state), + P => window.set_outer_position({ + let mut position = window.outer_position().unwrap(); + let sign = if state { 1 } else { -1 }; + position.x += 10 * sign; + position.y += 10 * sign; + position + }), + Q => window.request_redraw(), + R => window.set_resizable(state), + S => window.set_inner_size(match state { + true => PhysicalSize::new( + WINDOW_SIZE.width + 100, + WINDOW_SIZE.height + 100, + ), + false => WINDOW_SIZE, + }), + W => { + if let Size::Physical(size) = WINDOW_SIZE.into() { + window + .set_cursor_position(Position::Physical( + PhysicalPosition::new( + size.width as i32 / 2, + size.height as i32 / 2, + ), + )) + .unwrap() + } + } + Z => { + window.set_visible(false); + thread::sleep(Duration::from_secs(1)); + window.set_visible(true); + } + _ => (), } - Z => { - window.set_visible(false); - thread::sleep(Duration::from_secs(1)); - window.set_visible(true); - } - _ => (), } } _ => (), @@ -145,8 +147,7 @@ fn main() { }; match event { Event::WindowEvent(window_id, event) => match event { - WindowEvent::CloseRequested - | WindowEvent::Destroyed => { + WindowEvent::CloseRequested | WindowEvent::Destroyed => { window_senders.remove(&window_id); } _ => { diff --git a/examples/web.rs b/examples/web.rs index f9b6baead4..5d425d0653 100644 --- a/examples/web.rs +++ b/examples/web.rs @@ -50,7 +50,10 @@ pub fn main() { match event { Event::WindowEvent(window_id, WindowEvent::CloseRequested) - if window_id == window.id() => *control_flow = ControlFlow::Exit, + if window_id == window.id() => + { + *control_flow = ControlFlow::Exit + } Event::MainEventsCleared => { window.request_redraw(); } diff --git a/examples/window.rs b/examples/window.rs index 286c54fc8a..c0abf376e0 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -20,7 +20,10 @@ fn main() { match event { Event::WindowEvent(window_id, WindowEvent::CloseRequested) - if window_id == window.id() => *control_flow = ControlFlow::Exit, + if window_id == window.id() => + { + *control_flow = ControlFlow::Exit + } Event::MainEventsCleared => window.request_redraw(), _ => (), } diff --git a/examples/window_debug.rs b/examples/window_debug.rs index 5730c7f901..a5d87696b3 100644 --- a/examples/window_debug.rs +++ b/examples/window_debug.rs @@ -2,7 +2,7 @@ use winit::{ dpi::{LogicalSize, PhysicalSize}, - event::{RawKeyboardEvent, Event, LogicalKey, WindowEvent}, + event::{Event, LogicalKey, RawKeyboardEvent, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::{Fullscreen, WindowBuilder}, }; @@ -33,22 +33,25 @@ fn main() { *control_flow = ControlFlow::Wait; match event { - Event::RawKeyboardEvent(_, RawKeyboardEvent::Press(e)) if e.is_down() => match e.logical_key() { - Some(LogicalKey::M) => { - if minimized { - minimized = !minimized; - window.set_minimized(minimized); + Event::RawKeyboardEvent(_, RawKeyboardEvent::Press(e)) if e.is_down() => { + match e.logical_key() { + Some(LogicalKey::M) => { + if minimized { + minimized = !minimized; + window.set_minimized(minimized); + } } - } - Some(LogicalKey::V) => { - if !visible { - visible = !visible; - window.set_visible(visible); + Some(LogicalKey::V) => { + if !visible { + visible = !visible; + window.set_visible(visible); + } } + _ => (), } - _ => (), - }, - Event::WindowEvent(_, WindowEvent::KeyPress(e)) if e.is_down() => match e.logical_key() { + } + Event::WindowEvent(_, WindowEvent::KeyPress(e)) if e.is_down() => match e.logical_key() + { Some(LogicalKey::E) => { fn area(size: PhysicalSize) -> u32 { size.width * size.height @@ -90,7 +93,10 @@ fn main() { _ => (), }, Event::WindowEvent(window_id, WindowEvent::CloseRequested) - if window_id == window.id() => *control_flow = ControlFlow::Exit, + if window_id == window.id() => + { + *control_flow = ControlFlow::Exit + } _ => (), } }); diff --git a/examples/window_icon.rs b/examples/window_icon.rs index 4b6bc6f6ea..07e1545c9c 100644 --- a/examples/window_icon.rs +++ b/examples/window_icon.rs @@ -34,7 +34,7 @@ fn main() { Event::WindowEvent(_, event) => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, WindowEvent::FileDropped(path) => window.set_window_icon(Some(load_icon(&path))), - _ => () + _ => (), }, _ => (), } diff --git a/src/dpi.rs b/src/dpi.rs index 8dd1d5638d..2d3bbf9ee5 100644 --- a/src/dpi.rs +++ b/src/dpi.rs @@ -341,7 +341,7 @@ macro_rules! dpi_type { }; } -dpi_type!{ +dpi_type! { let h = x; let v = y; @@ -353,7 +353,7 @@ dpi_type!{ pub enum Position; } -dpi_type!{ +dpi_type! { let h = width; let v = height; @@ -365,7 +365,7 @@ dpi_type!{ pub enum Size; } -dpi_type!{ +dpi_type! { let h = x; let v = y; diff --git a/src/event.rs b/src/event.rs index c406e2a434..8526ef20da 100644 --- a/src/event.rs +++ b/src/event.rs @@ -34,13 +34,10 @@ //! //! [event_loop_run]: crate::event_loop::EventLoop::run use instant::Instant; -use std::{ - path::PathBuf, - fmt, -}; +use std::{fmt, path::PathBuf}; use crate::{ - dpi::{PhysicalPosition, PhysicalSize, PhysicalDelta, UnitlessDelta}, + dpi::{PhysicalDelta, PhysicalPosition, PhysicalSize, UnitlessDelta}, platform_impl, window::{Theme, WindowId}, }; @@ -267,9 +264,10 @@ impl<'a, T> Event<'a, T> { use self::Event::*; match self { NewEvents(cause) => Ok(NewEvents(cause)), - WindowEvent(window_id, event) => event.to_static() - .map(|e| -> Event<'static, T> {WindowEvent(window_id, e)}) - .map_err(|e| -> Event<'a, T> {WindowEvent(window_id, e)}), + WindowEvent(window_id, event) => event + .to_static() + .map(|e| -> Event<'static, T> { WindowEvent(window_id, e) }) + .map_err(|e| -> Event<'a, T> { WindowEvent(window_id, e) }), RawPointerEvent(pointer_id, event) => Ok(RawPointerEvent(pointer_id, event)), RawKeyboardEvent(keyboard_id, event) => Ok(RawKeyboardEvent(keyboard_id, event)), AppEvent(app_event) => Ok(AppEvent(app_event)), @@ -310,7 +308,9 @@ impl Clone for WindowEvent<'static> { ScrollPixels(delta) => ScrollPixels(delta), ScrollEnded => ScrollEnded, ThemeChanged(theme) => ThemeChanged(theme), - ScaleFactorChanged(..) => unreachable!("Static event can't be about scale factor changing") + ScaleFactorChanged(..) => { + unreachable!("Static event can't be about scale factor changing") + } } } } @@ -374,7 +374,6 @@ pub enum StartCause { Init, } - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct KeyPress { pub(crate) logical_key: Option, @@ -528,21 +527,45 @@ impl PointerButton { pub const BUTTON_5: Self = Self(PointerButtonInner::Button5); // pub const BUTTON_6: Self = Self(PointerButtonInner::Button6); - pub fn as_u8(&self) -> u8 { self.0 as u8 } - pub fn is_mouse_left(&self) -> bool { *self == Self::MOUSE_LEFT } - pub fn is_mouse_right(&self) -> bool { *self == Self::MOUSE_RIGHT } - pub fn is_mouse_middle(&self) -> bool { *self == Self::MOUSE_MIDDLE } - pub fn is_mouse_x1(&self) -> bool { *self == Self::MOUSE_X1 } - pub fn is_mouse_x2(&self) -> bool { *self == Self::MOUSE_X2 } - pub fn is_touch_contact(&self) -> bool { *self == Self::TOUCH_CONTACT } + pub fn as_u8(&self) -> u8 { + self.0 as u8 + } + pub fn is_mouse_left(&self) -> bool { + *self == Self::MOUSE_LEFT + } + pub fn is_mouse_right(&self) -> bool { + *self == Self::MOUSE_RIGHT + } + pub fn is_mouse_middle(&self) -> bool { + *self == Self::MOUSE_MIDDLE + } + pub fn is_mouse_x1(&self) -> bool { + *self == Self::MOUSE_X1 + } + pub fn is_mouse_x2(&self) -> bool { + *self == Self::MOUSE_X2 + } + pub fn is_touch_contact(&self) -> bool { + *self == Self::TOUCH_CONTACT + } // pub fn is_pen_contact(&self) -> bool { *self == Self::PEN_CONTACT } // pub fn is_pen_barrel(&self) -> bool { *self == Self::PEN_BARREL } // pub fn is_pen_eraser(&self) -> bool { *self == Self::PEN_ERASER } - pub fn is_button_1(&self) -> bool { *self == Self::BUTTON_1 } - pub fn is_button_2(&self) -> bool { *self == Self::BUTTON_2 } - pub fn is_button_3(&self) -> bool { *self == Self::BUTTON_3 } - pub fn is_button_4(&self) -> bool { *self == Self::BUTTON_4 } - pub fn is_button_5(&self) -> bool { *self == Self::BUTTON_5 } + pub fn is_button_1(&self) -> bool { + *self == Self::BUTTON_1 + } + pub fn is_button_2(&self) -> bool { + *self == Self::BUTTON_2 + } + pub fn is_button_3(&self) -> bool { + *self == Self::BUTTON_3 + } + pub fn is_button_4(&self) -> bool { + *self == Self::BUTTON_4 + } + pub fn is_button_5(&self) -> bool { + *self == Self::BUTTON_5 + } // pub fn is_button_6(&self) -> bool { *self == Self::BUTTON_6 } } diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 8741b6754d..80c5d6df3a 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -9,7 +9,7 @@ use winapi::shared::windef::HWND; use crate::{ dpi::PhysicalSize, - event::{PointerDeviceId, KeyboardDeviceId}, + event::{KeyboardDeviceId, PointerDeviceId}, event_loop::EventLoop, monitor::MonitorHandle, platform_impl::{EventLoop as WindowsEventLoop, WinIcon}, diff --git a/src/platform_impl/windows/drop_handler.rs b/src/platform_impl/windows/drop_handler.rs index cbcda08e0f..902e8bfeea 100644 --- a/src/platform_impl/windows/drop_handler.rs +++ b/src/platform_impl/windows/drop_handler.rs @@ -127,7 +127,7 @@ impl FileDropHandler { if drop_handler.hovered_is_valid { drop_handler.send_event(Event::WindowEvent( WindowId(drop_handler.window).into(), - WindowEvent::FileHoverCancelled + WindowEvent::FileHoverCancelled, )); } diff --git a/src/platform_impl/windows/event.rs b/src/platform_impl/windows/event.rs index 4ccef008a2..2d54446bd2 100644 --- a/src/platform_impl/windows/event.rs +++ b/src/platform_impl/windows/event.rs @@ -5,7 +5,7 @@ use std::{ sync::atomic::{AtomicBool, AtomicPtr, Ordering}, }; -use crate::event::{ModifiersState, LogicalKey}; +use crate::event::{LogicalKey, ModifiersState}; use winapi::{ shared::minwindef::{HKL, HKL__, LPARAM, UINT, WPARAM}, diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index e005ec6a84..d59461f041 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -30,10 +30,10 @@ use winapi::{ }; use crate::{ - dpi::{PhysicalPosition, PhysicalSize, PhysicalDelta, UnitlessDelta}, + dpi::{PhysicalDelta, PhysicalPosition, PhysicalSize, UnitlessDelta}, event::{ - Event, Force, WindowEvent, RawPointerEvent, RawKeyboardEvent, PointerId, KeyPress, LogicalKey, - PointerPress, PointerButton, ModifiersState, RawPointerPress, RawKeyPress, + Event, Force, KeyPress, LogicalKey, ModifiersState, PointerButton, PointerId, PointerPress, + RawKeyPress, RawKeyboardEvent, RawPointerEvent, RawPointerPress, WindowEvent, }, event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW}, platform_impl::platform::{ @@ -43,7 +43,7 @@ use crate::{ event::{self, handle_extended_keys, process_key_params, vkey_to_winit_vkey}, monitor, raw_input, util, window_state::{CursorFlags, WindowFlags, WindowState}, - WindowId, TouchId, KeyboardDeviceId, PointerDeviceId, + KeyboardDeviceId, PointerDeviceId, TouchId, WindowId, }, window::{Fullscreen, Theme}, }; @@ -720,7 +720,7 @@ fn update_modifiers(window: HWND, subclass_input: &SubclassInput) { unsafe { subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::ModifiersChanged(modifiers) + WindowEvent::ModifiersChanged(modifiers), )); } } @@ -891,10 +891,8 @@ unsafe extern "system" fn public_window_callback( let h = HIWORD(lparam as DWORD) as u32; let physical_size = PhysicalSize::new(w, h); - let event = Event::WindowEvent( - WindowId(window).into(), - WindowEvent::Resized(physical_size), - ); + let event = + Event::WindowEvent(WindowId(window).into(), WindowEvent::Resized(physical_size)); { let mut w = subclass_input.window_state.lock(); @@ -1066,7 +1064,9 @@ unsafe extern "system" fn public_window_callback( if msg == winuser::WM_SYSKEYDOWN && wparam as i32 == winuser::VK_F4 { commctrl::DefSubclassProc(window, msg, wparam, lparam) } else { - if let Some((scan_code, logical_key, is_repeat)) = process_key_params(wparam, lparam) { + if let Some((scan_code, logical_key, is_repeat)) = + process_key_params(wparam, lparam) + { update_modifiers(window, subclass_input); subclass_input.send_event(Event::WindowEvent( @@ -1121,8 +1121,11 @@ unsafe extern "system" fn public_window_callback( PointerPress { button: PointerButton::MOUSE_LEFT, is_down: true, - click_count: {println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); 0}, - } + click_count: { + println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); + 0 + }, + }, ), )); 0 @@ -1140,7 +1143,7 @@ unsafe extern "system" fn public_window_callback( button: PointerButton::MOUSE_LEFT, is_down: false, click_count: 0, - } + }, ), )); 0 @@ -1157,8 +1160,11 @@ unsafe extern "system" fn public_window_callback( PointerPress { button: PointerButton::MOUSE_RIGHT, is_down: true, - click_count: {println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); 0}, - } + click_count: { + println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); + 0 + }, + }, ), )); 0 @@ -1176,7 +1182,7 @@ unsafe extern "system" fn public_window_callback( button: PointerButton::MOUSE_RIGHT, is_down: false, click_count: 0, - } + }, ), )); 0 @@ -1193,8 +1199,11 @@ unsafe extern "system" fn public_window_callback( PointerPress { button: PointerButton::MOUSE_MIDDLE, is_down: true, - click_count: {println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); 0}, - } + click_count: { + println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); + 0 + }, + }, ), )); 0 @@ -1212,7 +1221,7 @@ unsafe extern "system" fn public_window_callback( button: PointerButton::MOUSE_MIDDLE, is_down: false, click_count: 0, - } + }, ), )); 0 @@ -1227,7 +1236,7 @@ unsafe extern "system" fn public_window_callback( 2 => PointerButton::MOUSE_X2, _ => { warn!("invalid x-button passed"); - return 0 + return 0; } }; @@ -1238,8 +1247,11 @@ unsafe extern "system" fn public_window_callback( PointerPress { button, is_down: true, - click_count: {println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); 0}, - } + click_count: { + println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); + 0 + }, + }, ), )); 0 @@ -1254,7 +1266,7 @@ unsafe extern "system" fn public_window_callback( 2 => PointerButton::MOUSE_X2, _ => { warn!("invalid x-button passed"); - return 0 + return 0; } }; @@ -1266,7 +1278,7 @@ unsafe extern "system" fn public_window_callback( button, is_down: false, click_count: 0, - } + }, ), )); 0 @@ -1321,7 +1333,10 @@ unsafe extern "system" fn public_window_callback( PointerPress { button: PointerButton::TOUCH_CONTACT, is_down: true, - click_count: {println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); 0}, + click_count: { + println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); + 0 + }, }, ), )); @@ -1374,7 +1389,8 @@ unsafe extern "system" fn public_window_callback( } let pointer_info_count = (entries_count * pointers_count) as usize; - let mut pointer_infos = Vec::::with_capacity(pointer_info_count); + let mut pointer_infos = + Vec::::with_capacity(pointer_info_count); pointer_infos.set_len(pointer_info_count); if GetPointerFrameInfoHistory( pointer_id, @@ -1493,7 +1509,10 @@ unsafe extern "system" fn public_window_callback( PointerPress { button: PointerButton::TOUCH_CONTACT, is_down: true, - click_count: {println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); 0}, + click_count: { + println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); + 0 + }, }, ), )); @@ -1861,7 +1880,11 @@ unsafe extern "system" fn public_window_callback( let changed = window_state.is_dark_mode != is_dark_mode; if changed { - let theme = if is_dark_mode { Theme::Dark } else { Theme::Light }; + let theme = if is_dark_mode { + Theme::Dark + } else { + Theme::Light + }; window_state.is_dark_mode = is_dark_mode; mem::drop(window_state); @@ -1965,7 +1988,7 @@ unsafe extern "system" fn thread_event_target_callback( winuser::GIDC_ARRIVAL => RawPointerEvent::Added, winuser::GIDC_REMOVAL => RawPointerEvent::Removed, _ => unreachable!(), - } + }, )), winuser::RIM_TYPEKEYBOARD => subclass_input.send_event(Event::RawKeyboardEvent( KeyboardDeviceId(lparam as _).into(), @@ -1973,7 +1996,7 @@ unsafe extern "system" fn thread_event_target_callback( winuser::GIDC_ARRIVAL => RawKeyboardEvent::Added, winuser::GIDC_REMOVAL => RawKeyboardEvent::Removed, _ => unreachable!(), - } + }, )), _ => (), } @@ -1994,7 +2017,7 @@ unsafe extern "system" fn thread_event_target_callback( if x != 0.0 || y != 0.0 { subclass_input.send_event(Event::RawPointerEvent( pointer_id, - RawPointerEvent::MovedRelative(PhysicalDelta::new(x, y)) + RawPointerEvent::MovedRelative(PhysicalDelta::new(x, y)), )); } } @@ -2006,7 +2029,10 @@ unsafe extern "system" fn thread_event_target_callback( RawPointerEvent::Wheel(UnitlessDelta::new(0.0, delta)), )); } - if util::has_flag(mouse.usButtonFlags, 0x0800 /*winuser::RI_MOUSE_HWHEEL*/) { + if util::has_flag( + mouse.usButtonFlags, + 0x0800, /*winuser::RI_MOUSE_HWHEEL*/ + ) { let delta = mouse.usButtonData as f64 / winuser::WHEEL_DELTA as f64; subclass_input.send_event(Event::RawPointerEvent( pointer_id, diff --git a/src/platform_impl/windows/raw_input.rs b/src/platform_impl/windows/raw_input.rs index cd574bae81..ea7de2cee3 100644 --- a/src/platform_impl/windows/raw_input.rs +++ b/src/platform_impl/windows/raw_input.rs @@ -21,10 +21,7 @@ use winapi::{ }, }; -use crate::{ - event::PointerButton, - platform_impl::platform::util, -}; +use crate::{event::PointerButton, platform_impl::platform::util}; #[allow(dead_code)] pub fn get_raw_input_device_list() -> Option> { @@ -209,26 +206,31 @@ pub fn get_raw_mouse_button_state(button_flags: USHORT) -> [Option<(PointerButto button_flags, winuser::RI_MOUSE_BUTTON_1_DOWN, winuser::RI_MOUSE_BUTTON_1_UP, - ).map(|b| (PointerButton::BUTTON_1, b)), + ) + .map(|b| (PointerButton::BUTTON_1, b)), button_flags_to_element_state( button_flags, winuser::RI_MOUSE_BUTTON_2_DOWN, winuser::RI_MOUSE_BUTTON_2_UP, - ).map(|b| (PointerButton::BUTTON_2, b)), + ) + .map(|b| (PointerButton::BUTTON_2, b)), button_flags_to_element_state( button_flags, winuser::RI_MOUSE_BUTTON_3_DOWN, winuser::RI_MOUSE_BUTTON_3_UP, - ).map(|b| (PointerButton::BUTTON_3, b)), + ) + .map(|b| (PointerButton::BUTTON_3, b)), button_flags_to_element_state( button_flags, winuser::RI_MOUSE_BUTTON_4_DOWN, winuser::RI_MOUSE_BUTTON_4_UP, - ).map(|b| (PointerButton::BUTTON_4, b)), + ) + .map(|b| (PointerButton::BUTTON_4, b)), button_flags_to_element_state( button_flags, winuser::RI_MOUSE_BUTTON_5_DOWN, winuser::RI_MOUSE_BUTTON_5_UP, - ).map(|b| (PointerButton::BUTTON_5, b)), + ) + .map(|b| (PointerButton::BUTTON_5, b)), ] } From d06f58f9f7b10b38338b2fc906c2823c14b37c61 Mon Sep 17 00:00:00 2001 From: Osspial Date: Sat, 16 May 2020 18:30:49 -0400 Subject: [PATCH 13/29] Make serde work --- src/event.rs | 68 +++++++++++++++++----------------------------------- 1 file changed, 22 insertions(+), 46 deletions(-) diff --git a/src/event.rs b/src/event.rs index 8526ef20da..ebb4b79688 100644 --- a/src/event.rs +++ b/src/event.rs @@ -34,10 +34,13 @@ //! //! [event_loop_run]: crate::event_loop::EventLoop::run use instant::Instant; -use std::{fmt, path::PathBuf}; +use std::{ + path::PathBuf, + fmt, +}; use crate::{ - dpi::{PhysicalDelta, PhysicalPosition, PhysicalSize, UnitlessDelta}, + dpi::{PhysicalPosition, PhysicalSize, PhysicalDelta, UnitlessDelta}, platform_impl, window::{Theme, WindowId}, }; @@ -119,7 +122,6 @@ pub enum AppEvent { /// Describes an event from a `Window`. #[derive(Debug, PartialEq)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum WindowEvent<'a> { /// The size of the window has changed. Contains the client area's new dimensions. Resized(PhysicalSize), @@ -264,10 +266,9 @@ impl<'a, T> Event<'a, T> { use self::Event::*; match self { NewEvents(cause) => Ok(NewEvents(cause)), - WindowEvent(window_id, event) => event - .to_static() - .map(|e| -> Event<'static, T> { WindowEvent(window_id, e) }) - .map_err(|e| -> Event<'a, T> { WindowEvent(window_id, e) }), + WindowEvent(window_id, event) => event.to_static() + .map(|e| -> Event<'static, T> {WindowEvent(window_id, e)}) + .map_err(|e| -> Event<'a, T> {WindowEvent(window_id, e)}), RawPointerEvent(pointer_id, event) => Ok(RawPointerEvent(pointer_id, event)), RawKeyboardEvent(keyboard_id, event) => Ok(RawKeyboardEvent(keyboard_id, event)), AppEvent(app_event) => Ok(AppEvent(app_event)), @@ -308,9 +309,7 @@ impl Clone for WindowEvent<'static> { ScrollPixels(delta) => ScrollPixels(delta), ScrollEnded => ScrollEnded, ThemeChanged(theme) => ThemeChanged(theme), - ScaleFactorChanged(..) => { - unreachable!("Static event can't be about scale factor changing") - } + ScaleFactorChanged(..) => unreachable!("Static event can't be about scale factor changing") } } } @@ -374,6 +373,7 @@ pub enum StartCause { Init, } + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct KeyPress { pub(crate) logical_key: Option, @@ -527,45 +527,21 @@ impl PointerButton { pub const BUTTON_5: Self = Self(PointerButtonInner::Button5); // pub const BUTTON_6: Self = Self(PointerButtonInner::Button6); - pub fn as_u8(&self) -> u8 { - self.0 as u8 - } - pub fn is_mouse_left(&self) -> bool { - *self == Self::MOUSE_LEFT - } - pub fn is_mouse_right(&self) -> bool { - *self == Self::MOUSE_RIGHT - } - pub fn is_mouse_middle(&self) -> bool { - *self == Self::MOUSE_MIDDLE - } - pub fn is_mouse_x1(&self) -> bool { - *self == Self::MOUSE_X1 - } - pub fn is_mouse_x2(&self) -> bool { - *self == Self::MOUSE_X2 - } - pub fn is_touch_contact(&self) -> bool { - *self == Self::TOUCH_CONTACT - } + pub fn as_u8(&self) -> u8 { self.0 as u8 } + pub fn is_mouse_left(&self) -> bool { *self == Self::MOUSE_LEFT } + pub fn is_mouse_right(&self) -> bool { *self == Self::MOUSE_RIGHT } + pub fn is_mouse_middle(&self) -> bool { *self == Self::MOUSE_MIDDLE } + pub fn is_mouse_x1(&self) -> bool { *self == Self::MOUSE_X1 } + pub fn is_mouse_x2(&self) -> bool { *self == Self::MOUSE_X2 } + pub fn is_touch_contact(&self) -> bool { *self == Self::TOUCH_CONTACT } // pub fn is_pen_contact(&self) -> bool { *self == Self::PEN_CONTACT } // pub fn is_pen_barrel(&self) -> bool { *self == Self::PEN_BARREL } // pub fn is_pen_eraser(&self) -> bool { *self == Self::PEN_ERASER } - pub fn is_button_1(&self) -> bool { - *self == Self::BUTTON_1 - } - pub fn is_button_2(&self) -> bool { - *self == Self::BUTTON_2 - } - pub fn is_button_3(&self) -> bool { - *self == Self::BUTTON_3 - } - pub fn is_button_4(&self) -> bool { - *self == Self::BUTTON_4 - } - pub fn is_button_5(&self) -> bool { - *self == Self::BUTTON_5 - } + pub fn is_button_1(&self) -> bool { *self == Self::BUTTON_1 } + pub fn is_button_2(&self) -> bool { *self == Self::BUTTON_2 } + pub fn is_button_3(&self) -> bool { *self == Self::BUTTON_3 } + pub fn is_button_4(&self) -> bool { *self == Self::BUTTON_4 } + pub fn is_button_5(&self) -> bool { *self == Self::BUTTON_5 } // pub fn is_button_6(&self) -> bool { *self == Self::BUTTON_6 } } From 510f005a8dbb04538cce2c6c564b4dee933ced72 Mon Sep 17 00:00:00 2001 From: Osspial Date: Sat, 16 May 2020 22:46:26 -0400 Subject: [PATCH 14/29] Make serde tests work --- tests/serde_objects.rs | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/tests/serde_objects.rs b/tests/serde_objects.rs index ad729dcd1b..084ee971d2 100644 --- a/tests/serde_objects.rs +++ b/tests/serde_objects.rs @@ -2,11 +2,8 @@ use serde::{Deserialize, Serialize}; use winit::{ - dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize}, - event::{ - ElementState, KeyboardInput, ModifiersState, MouseButton, MouseScrollDelta, TouchPhase, - VirtualKeyCode, - }, + dpi::{Pixel, LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, PhysicalDelta, LogicalDelta, UnitlessDelta}, + event::{ModifiersState, PointerButton, LogicalKey}, window::CursorIcon, }; @@ -20,20 +17,17 @@ fn window_serde() { #[test] fn events_serde() { - needs_serde::(); - needs_serde::(); - needs_serde::(); - needs_serde::(); - needs_serde::(); - needs_serde::(); needs_serde::(); + needs_serde::(); + needs_serde::(); } -#[test] -fn dpi_serde() { - needs_serde::>(); - needs_serde::>(); - needs_serde::>(); - needs_serde::>(); - needs_serde::>(); +pub fn dpi_serde Deserialize<'a>>() { + needs_serde::>(); + needs_serde::>(); + needs_serde::>(); + needs_serde::>(); + needs_serde::>(); + needs_serde::>(); + needs_serde::>(); } From bb5dd6bbbfce58393c83cc13ac94ba1ecb3f1118 Mon Sep 17 00:00:00 2001 From: Osspial Date: Wed, 20 May 2020 17:13:49 -0400 Subject: [PATCH 15/29] Rename KeyPress to Key --- examples/control_flow.rs | 2 +- examples/cursor.rs | 2 +- examples/cursor_grab.rs | 2 +- examples/fullscreen.rs | 2 +- examples/handling_close.rs | 2 +- examples/minimize.rs | 2 +- examples/multithreaded.rs | 2 +- examples/multiwindow.rs | 2 +- examples/resizable.rs | 2 +- examples/window_debug.rs | 4 ++-- src/event.rs | 16 ++++++++-------- src/platform_impl/windows/event_loop.rs | 14 +++++++------- 12 files changed, 26 insertions(+), 26 deletions(-) diff --git a/examples/control_flow.rs b/examples/control_flow.rs index 6dbb669405..d145943355 100644 --- a/examples/control_flow.rs +++ b/examples/control_flow.rs @@ -49,7 +49,7 @@ fn main() { WindowEvent::CloseRequested => { close_requested = true; } - WindowEvent::KeyPress(e) if e.is_down() => match e.logical_key() { + WindowEvent::Key(e) if e.is_down() => match e.logical_key() { Some(LogicalKey::Key1) => { mode = Mode::Wait; println!("\nmode: {:?}\n", mode); diff --git a/examples/cursor.rs b/examples/cursor.rs index 9e93909a10..498e93b1d1 100644 --- a/examples/cursor.rs +++ b/examples/cursor.rs @@ -17,7 +17,7 @@ fn main() { *control_flow = ControlFlow::Wait; match event { - Event::WindowEvent(_, WindowEvent::KeyPress(e)) if e.is_down() => { + Event::WindowEvent(_, WindowEvent::Key(e)) if e.is_down() => { println!("Setting cursor to \"{:?}\"", CURSORS[cursor_idx]); window.set_cursor_icon(CURSORS[cursor_idx]); if cursor_idx < CURSORS.len() - 1 { diff --git a/examples/cursor_grab.rs b/examples/cursor_grab.rs index 5a02c02541..89d68da84d 100644 --- a/examples/cursor_grab.rs +++ b/examples/cursor_grab.rs @@ -21,7 +21,7 @@ fn main() { match event { Event::WindowEvent(_, event) => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, - WindowEvent::KeyPress(e) if e.is_down() => match e.logical_key() { + WindowEvent::Key(e) if e.is_down() => match e.logical_key() { Some(LogicalKey::Escape) => *control_flow = ControlFlow::Exit, Some(LogicalKey::G) => window.set_cursor_grab(!modifiers.shift()).unwrap(), Some(LogicalKey::H) => window.set_cursor_visible(modifiers.shift()), diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index ec12b60208..ef9afe076f 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -36,7 +36,7 @@ fn main() { match event { Event::WindowEvent(_, event) => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, - WindowEvent::KeyPress(e) if e.is_down() => match e.logical_key() { + WindowEvent::Key(e) if e.is_down() => match e.logical_key() { Some(LogicalKey::Escape) => *control_flow = ControlFlow::Exit, Some(LogicalKey::F) => { if window.fullscreen().is_some() { diff --git a/examples/handling_close.rs b/examples/handling_close.rs index 834cf6dc0d..a6446e4a74 100644 --- a/examples/handling_close.rs +++ b/examples/handling_close.rs @@ -37,7 +37,7 @@ fn main() { // closing the window. How to close the window is detailed in the handler for // the Y key. } - WindowEvent::KeyPress(e) if e.is_up() => match e.logical_key() { + WindowEvent::Key(e) if e.is_up() => match e.logical_key() { Some(LogicalKey::Y) => { if close_requested { // This is where you'll want to do any cleanup you need. diff --git a/examples/minimize.rs b/examples/minimize.rs index bed582c3b3..4808930998 100644 --- a/examples/minimize.rs +++ b/examples/minimize.rs @@ -20,7 +20,7 @@ fn main() { Event::WindowEvent(_, WindowEvent::CloseRequested) => *control_flow = ControlFlow::Exit, // Keyboard input event to handle minimize via a hotkey - Event::WindowEvent(window_id, WindowEvent::KeyPress(e)) + Event::WindowEvent(window_id, WindowEvent::Key(e)) if e.is_down() && e.logical_key_is(LogicalKey::M) && window_id == window.id() => { window.set_minimized(true) diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs index 13e1a62448..8402bbedc7 100644 --- a/examples/multithreaded.rs +++ b/examples/multithreaded.rs @@ -50,7 +50,7 @@ fn main() { } } WindowEvent::ModifiersChanged(mods) => modifiers = mods, - WindowEvent::KeyPress(e) if e.is_up() => { + WindowEvent::Key(e) if e.is_up() => { if let Some(key) = e.logical_key() { window.set_title(&format!("{:?}", key)); let state = !modifiers.shift(); diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index 35c1bcddef..9e570b8de0 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -31,7 +31,7 @@ fn main() { *control_flow = ControlFlow::Exit; } } - WindowEvent::KeyPress(e) if e.is_down() => { + WindowEvent::Key(e) if e.is_down() => { let window = Window::new(&event_loop).unwrap(); windows.insert(window.id(), window); } diff --git a/examples/resizable.rs b/examples/resizable.rs index 7ddf35e1ab..0269291ef1 100644 --- a/examples/resizable.rs +++ b/examples/resizable.rs @@ -24,7 +24,7 @@ fn main() { match event { Event::WindowEvent(_, event) => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, - WindowEvent::KeyPress(e) if e.is_up() && e.logical_key_is(LogicalKey::Space) => { + WindowEvent::Key(e) if e.is_up() && e.logical_key_is(LogicalKey::Space) => { resizable = !resizable; println!("Resizable: {}", resizable); window.set_resizable(resizable); diff --git a/examples/window_debug.rs b/examples/window_debug.rs index a5d87696b3..a5ce80e6be 100644 --- a/examples/window_debug.rs +++ b/examples/window_debug.rs @@ -33,7 +33,7 @@ fn main() { *control_flow = ControlFlow::Wait; match event { - Event::RawKeyboardEvent(_, RawKeyboardEvent::Press(e)) if e.is_down() => { + Event::RawKeyboardEvent(_, RawKeyboardEvent::Key(e)) if e.is_down() => { match e.logical_key() { Some(LogicalKey::M) => { if minimized { @@ -50,7 +50,7 @@ fn main() { _ => (), } } - Event::WindowEvent(_, WindowEvent::KeyPress(e)) if e.is_down() => match e.logical_key() + Event::WindowEvent(_, WindowEvent::Key(e)) if e.is_down() => match e.logical_key() { Some(LogicalKey::E) => { fn area(size: PhysicalSize) -> u32 { diff --git a/src/event.rs b/src/event.rs index ebb4b79688..214c8e235e 100644 --- a/src/event.rs +++ b/src/event.rs @@ -162,7 +162,7 @@ pub enum WindowEvent<'a> { /// The window received a unicode character. CharReceived(char), - KeyPress(KeyPress), + Key(KeyEvent), /// The keyboard modifiers have changed. /// @@ -240,7 +240,7 @@ pub enum RawKeyboardEvent { Added, /// A keyboard device has been removed. Removed, - Press(RawKeyPress), + Key(RawKeyEvent), } impl<'a, T> Event<'a, T> { @@ -295,7 +295,7 @@ impl Clone for WindowEvent<'static> { FocusGained => FocusGained, FocusLost => FocusLost, CharReceived(char) => CharReceived(char), - KeyPress(key_press) => KeyPress(key_press), + Key(key_press) => Key(key_press), ModifiersChanged(state) => ModifiersChanged(state), PointerCreated(id) => PointerCreated(id), PointerForce(id, force) => PointerForce(id, force), @@ -328,7 +328,7 @@ impl<'a> WindowEvent<'a> { FocusGained => Ok(FocusGained), FocusLost => Ok(FocusLost), CharReceived(char) => Ok(CharReceived(char)), - KeyPress(key_press) => Ok(KeyPress(key_press)), + Key(key_press) => Ok(Key(key_press)), ModifiersChanged(state) => Ok(ModifiersChanged(state)), PointerCreated(id) => Ok(PointerCreated(id)), PointerForce(id, force) => Ok(PointerForce(id, force)), @@ -375,7 +375,7 @@ pub enum StartCause { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct KeyPress { +pub struct KeyEvent { pub(crate) logical_key: Option, pub(crate) scan_code: u32, pub(crate) is_down: bool, @@ -384,7 +384,7 @@ pub struct KeyPress { } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct RawKeyPress { +pub struct RawKeyEvent { pub(crate) logical_key: Option, pub(crate) scan_code: u32, pub(crate) is_down: bool, @@ -403,7 +403,7 @@ pub struct RawPointerPress { pub(crate) is_down: bool, } -impl KeyPress { +impl KeyEvent { pub fn logical_key(&self) -> Option { self.logical_key } @@ -441,7 +441,7 @@ impl KeyPress { } } -impl RawKeyPress { +impl RawKeyEvent { pub fn logical_key(&self) -> Option { self.logical_key } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index d59461f041..c1b0eee382 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -32,8 +32,8 @@ use winapi::{ use crate::{ dpi::{PhysicalDelta, PhysicalPosition, PhysicalSize, UnitlessDelta}, event::{ - Event, Force, KeyPress, LogicalKey, ModifiersState, PointerButton, PointerId, PointerPress, - RawKeyPress, RawKeyboardEvent, RawPointerEvent, RawPointerPress, WindowEvent, + Event, Force, KeyEvent, LogicalKey, ModifiersState, PointerButton, PointerId, PointerPress, + RawKeyEvent, RawKeyboardEvent, RawPointerEvent, RawPointerPress, WindowEvent, }, event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW}, platform_impl::platform::{ @@ -1071,7 +1071,7 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::KeyPress(KeyPress { + WindowEvent::Key(KeyEvent { logical_key, scan_code, is_down: true, @@ -1098,7 +1098,7 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::KeyPress(KeyPress { + WindowEvent::Key(KeyEvent { logical_key, scan_code, is_down: false, @@ -1555,7 +1555,7 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::KeyPress(KeyPress { + WindowEvent::Key(KeyEvent { logical_key, scan_code, is_down: true, @@ -1583,7 +1583,7 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::KeyPress(KeyPress { + WindowEvent::Key(KeyEvent { logical_key, scan_code, is_down: false, @@ -2071,7 +2071,7 @@ unsafe extern "system" fn thread_event_target_callback( subclass_input.send_event(Event::RawKeyboardEvent( keyboard_id, - RawKeyboardEvent::Press(RawKeyPress { + RawKeyboardEvent::Key(RawKeyEvent { logical_key, scan_code, is_down, From 852b292a6ba2e265d3c74a415d544a855b4fad89 Mon Sep 17 00:00:00 2001 From: Osspial Date: Wed, 20 May 2020 17:17:47 -0400 Subject: [PATCH 16/29] Rename PointerPress to PointerButton --- examples/cursor_grab.rs | 4 +- examples/request_redraw.rs | 2 +- src/event.rs | 16 ++++---- src/platform_impl/windows/event_loop.rs | 54 ++++++++++++------------- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/examples/cursor_grab.rs b/examples/cursor_grab.rs index 89d68da84d..a0f4fecaba 100644 --- a/examples/cursor_grab.rs +++ b/examples/cursor_grab.rs @@ -35,10 +35,10 @@ fn main() { RawPointerEvent::MovedAbsolute(position) => { println!("pointer moved to: {:?}", position) } - RawPointerEvent::Press(e) if e.is_down() => { + RawPointerEvent::Button(e) if e.is_down() => { println!("pointer button {:?} pressed", e.button()) } - RawPointerEvent::Press(e) if e.is_up() => { + RawPointerEvent::Button(e) if e.is_up() => { println!("pointer button {:?} released", e.button()) } _ => (), diff --git a/examples/request_redraw.rs b/examples/request_redraw.rs index 46f5c1f0f7..8036a15153 100644 --- a/examples/request_redraw.rs +++ b/examples/request_redraw.rs @@ -21,7 +21,7 @@ fn main() { match event { Event::WindowEvent(_, event) => match event { WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, - WindowEvent::PointerPress(_, e) if e.is_up() => window.request_redraw(), + WindowEvent::PointerButton(_, e) if e.is_up() => window.request_redraw(), _ => (), }, Event::RedrawRequested(_) => { diff --git a/src/event.rs b/src/event.rs index 214c8e235e..76ac128596 100644 --- a/src/event.rs +++ b/src/event.rs @@ -177,7 +177,7 @@ pub enum WindowEvent<'a> { PointerCreated(PointerId), PointerForce(PointerId, Force), PointerMoved(PointerId, PhysicalPosition), - PointerPress(PointerId, PointerPress), + PointerButton(PointerId, PointerButtonEvent), PointerEntered(PointerId), PointerLeft(PointerId), PointerDestroyed(PointerId), @@ -217,7 +217,7 @@ pub enum RawPointerEvent { Added, /// A device has been removed. Removed, - Press(RawPointerPress), + Button(RawPointerButtonEvent), /// Relative change in physical position of a pointing device. /// /// This represents raw, unfiltered physical motion, NOT the position of the mouse. Accordingly, @@ -300,7 +300,7 @@ impl Clone for WindowEvent<'static> { PointerCreated(id) => PointerCreated(id), PointerForce(id, force) => PointerForce(id, force), PointerMoved(id, position) => PointerMoved(id, position), - PointerPress(id, pointer_press) => PointerPress(id, pointer_press), + PointerButton(id, pointer_button) => PointerButton(id, pointer_button), PointerEntered(id) => PointerEntered(id), PointerLeft(id) => PointerLeft(id), PointerDestroyed(id) => PointerDestroyed(id), @@ -333,7 +333,7 @@ impl<'a> WindowEvent<'a> { PointerCreated(id) => Ok(PointerCreated(id)), PointerForce(id, force) => Ok(PointerForce(id, force)), PointerMoved(id, position) => Ok(PointerMoved(id, position)), - PointerPress(id, pointer_press) => Ok(PointerPress(id, pointer_press)), + PointerButton(id, pointer_button) => Ok(PointerButton(id, pointer_button)), PointerEntered(id) => Ok(PointerEntered(id)), PointerLeft(id) => Ok(PointerLeft(id)), PointerDestroyed(id) => Ok(PointerDestroyed(id)), @@ -391,14 +391,14 @@ pub struct RawKeyEvent { } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct PointerPress { +pub struct PointerButtonEvent { pub(crate) button: PointerButton, pub(crate) is_down: bool, pub(crate) click_count: u32, } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct RawPointerPress { +pub struct RawPointerButtonEvent { pub(crate) button: PointerButton, pub(crate) is_down: bool, } @@ -456,7 +456,7 @@ impl RawKeyEvent { } } -impl PointerPress { +impl PointerButtonEvent { pub fn button(&self) -> PointerButton { self.button } @@ -475,7 +475,7 @@ impl PointerPress { } } -impl RawPointerPress { +impl RawPointerButtonEvent { pub fn button(&self) -> PointerButton { self.button } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index c1b0eee382..6952da7eb6 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -32,8 +32,8 @@ use winapi::{ use crate::{ dpi::{PhysicalDelta, PhysicalPosition, PhysicalSize, UnitlessDelta}, event::{ - Event, Force, KeyEvent, LogicalKey, ModifiersState, PointerButton, PointerId, PointerPress, - RawKeyEvent, RawKeyboardEvent, RawPointerEvent, RawPointerPress, WindowEvent, + Event, Force, KeyEvent, LogicalKey, ModifiersState, PointerButton, PointerId, PointerButtonEvent, + RawKeyEvent, RawKeyboardEvent, RawPointerEvent, RawPointerButtonEvent, WindowEvent, }, event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW}, platform_impl::platform::{ @@ -1116,9 +1116,9 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerPress( + WindowEvent::PointerButton( PointerId::MOUSE_ID, - PointerPress { + PointerButtonEvent { button: PointerButton::MOUSE_LEFT, is_down: true, click_count: { @@ -1137,9 +1137,9 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerPress( + WindowEvent::PointerButton( PointerId::MOUSE_ID, - PointerPress { + PointerButtonEvent { button: PointerButton::MOUSE_LEFT, is_down: false, click_count: 0, @@ -1155,9 +1155,9 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerPress( + WindowEvent::PointerButton( PointerId::MOUSE_ID, - PointerPress { + PointerButtonEvent { button: PointerButton::MOUSE_RIGHT, is_down: true, click_count: { @@ -1176,9 +1176,9 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerPress( + WindowEvent::PointerButton( PointerId::MOUSE_ID, - PointerPress { + PointerButtonEvent { button: PointerButton::MOUSE_RIGHT, is_down: false, click_count: 0, @@ -1194,9 +1194,9 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerPress( + WindowEvent::PointerButton( PointerId::MOUSE_ID, - PointerPress { + PointerButtonEvent { button: PointerButton::MOUSE_MIDDLE, is_down: true, click_count: { @@ -1215,9 +1215,9 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerPress( + WindowEvent::PointerButton( PointerId::MOUSE_ID, - PointerPress { + PointerButtonEvent { button: PointerButton::MOUSE_MIDDLE, is_down: false, click_count: 0, @@ -1242,9 +1242,9 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerPress( + WindowEvent::PointerButton( PointerId::MOUSE_ID, - PointerPress { + PointerButtonEvent { button, is_down: true, click_count: { @@ -1272,9 +1272,9 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerPress( + WindowEvent::PointerButton( PointerId::MOUSE_ID, - PointerPress { + PointerButtonEvent { button, is_down: false, click_count: 0, @@ -1328,9 +1328,9 @@ unsafe extern "system" fn public_window_callback( if input.dwFlags & winuser::TOUCHEVENTF_DOWN != 0 { subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerPress( + WindowEvent::PointerButton( pointer_id, - PointerPress { + PointerButtonEvent { button: PointerButton::TOUCH_CONTACT, is_down: true, click_count: { @@ -1345,9 +1345,9 @@ unsafe extern "system" fn public_window_callback( if input.dwFlags & winuser::TOUCHEVENTF_UP != 0 { subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerPress( + WindowEvent::PointerButton( pointer_id, - PointerPress { + PointerButtonEvent { button: PointerButton::TOUCH_CONTACT, is_down: false, click_count: 0, @@ -1504,9 +1504,9 @@ unsafe extern "system" fn public_window_callback( if pointer_info.pointerFlags & winuser::POINTER_FLAG_DOWN != 0 { subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerPress( + WindowEvent::PointerButton( pointer_id, - PointerPress { + PointerButtonEvent { button: PointerButton::TOUCH_CONTACT, is_down: true, click_count: { @@ -1521,9 +1521,9 @@ unsafe extern "system" fn public_window_callback( if pointer_info.pointerFlags & winuser::POINTER_FLAG_UP != 0 { subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerPress( + WindowEvent::PointerButton( pointer_id, - PointerPress { + PointerButtonEvent { button: PointerButton::TOUCH_CONTACT, is_down: false, click_count: 0, @@ -2045,7 +2045,7 @@ unsafe extern "system" fn thread_event_target_callback( for (button, is_down) in button_state.iter().cloned().flatten() { subclass_input.send_event(Event::RawPointerEvent( pointer_id, - RawPointerEvent::Press(RawPointerPress { button, is_down }), + RawPointerEvent::Button(RawPointerButtonEvent { button, is_down }), )); } } else if data.header.dwType == winuser::RIM_TYPEKEYBOARD { From 9f3fc7b67cc15d770acfd7f0778554280da08ebe Mon Sep 17 00:00:00 2001 From: Osspial Date: Wed, 20 May 2020 17:17:58 -0400 Subject: [PATCH 17/29] Format --- examples/window_debug.rs | 3 +- src/event.rs | 67 +++++++++++++++++-------- src/platform_impl/windows/event_loop.rs | 5 +- tests/serde_objects.rs | 7 ++- 4 files changed, 54 insertions(+), 28 deletions(-) diff --git a/examples/window_debug.rs b/examples/window_debug.rs index a5ce80e6be..49ce011927 100644 --- a/examples/window_debug.rs +++ b/examples/window_debug.rs @@ -50,8 +50,7 @@ fn main() { _ => (), } } - Event::WindowEvent(_, WindowEvent::Key(e)) if e.is_down() => match e.logical_key() - { + Event::WindowEvent(_, WindowEvent::Key(e)) if e.is_down() => match e.logical_key() { Some(LogicalKey::E) => { fn area(size: PhysicalSize) -> u32 { size.width * size.height diff --git a/src/event.rs b/src/event.rs index 76ac128596..cb889d12db 100644 --- a/src/event.rs +++ b/src/event.rs @@ -34,13 +34,10 @@ //! //! [event_loop_run]: crate::event_loop::EventLoop::run use instant::Instant; -use std::{ - path::PathBuf, - fmt, -}; +use std::{fmt, path::PathBuf}; use crate::{ - dpi::{PhysicalPosition, PhysicalSize, PhysicalDelta, UnitlessDelta}, + dpi::{PhysicalDelta, PhysicalPosition, PhysicalSize, UnitlessDelta}, platform_impl, window::{Theme, WindowId}, }; @@ -266,9 +263,10 @@ impl<'a, T> Event<'a, T> { use self::Event::*; match self { NewEvents(cause) => Ok(NewEvents(cause)), - WindowEvent(window_id, event) => event.to_static() - .map(|e| -> Event<'static, T> {WindowEvent(window_id, e)}) - .map_err(|e| -> Event<'a, T> {WindowEvent(window_id, e)}), + WindowEvent(window_id, event) => event + .to_static() + .map(|e| -> Event<'static, T> { WindowEvent(window_id, e) }) + .map_err(|e| -> Event<'a, T> { WindowEvent(window_id, e) }), RawPointerEvent(pointer_id, event) => Ok(RawPointerEvent(pointer_id, event)), RawKeyboardEvent(keyboard_id, event) => Ok(RawKeyboardEvent(keyboard_id, event)), AppEvent(app_event) => Ok(AppEvent(app_event)), @@ -309,7 +307,9 @@ impl Clone for WindowEvent<'static> { ScrollPixels(delta) => ScrollPixels(delta), ScrollEnded => ScrollEnded, ThemeChanged(theme) => ThemeChanged(theme), - ScaleFactorChanged(..) => unreachable!("Static event can't be about scale factor changing") + ScaleFactorChanged(..) => { + unreachable!("Static event can't be about scale factor changing") + } } } } @@ -373,7 +373,6 @@ pub enum StartCause { Init, } - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct KeyEvent { pub(crate) logical_key: Option, @@ -527,21 +526,45 @@ impl PointerButton { pub const BUTTON_5: Self = Self(PointerButtonInner::Button5); // pub const BUTTON_6: Self = Self(PointerButtonInner::Button6); - pub fn as_u8(&self) -> u8 { self.0 as u8 } - pub fn is_mouse_left(&self) -> bool { *self == Self::MOUSE_LEFT } - pub fn is_mouse_right(&self) -> bool { *self == Self::MOUSE_RIGHT } - pub fn is_mouse_middle(&self) -> bool { *self == Self::MOUSE_MIDDLE } - pub fn is_mouse_x1(&self) -> bool { *self == Self::MOUSE_X1 } - pub fn is_mouse_x2(&self) -> bool { *self == Self::MOUSE_X2 } - pub fn is_touch_contact(&self) -> bool { *self == Self::TOUCH_CONTACT } + pub fn as_u8(&self) -> u8 { + self.0 as u8 + } + pub fn is_mouse_left(&self) -> bool { + *self == Self::MOUSE_LEFT + } + pub fn is_mouse_right(&self) -> bool { + *self == Self::MOUSE_RIGHT + } + pub fn is_mouse_middle(&self) -> bool { + *self == Self::MOUSE_MIDDLE + } + pub fn is_mouse_x1(&self) -> bool { + *self == Self::MOUSE_X1 + } + pub fn is_mouse_x2(&self) -> bool { + *self == Self::MOUSE_X2 + } + pub fn is_touch_contact(&self) -> bool { + *self == Self::TOUCH_CONTACT + } // pub fn is_pen_contact(&self) -> bool { *self == Self::PEN_CONTACT } // pub fn is_pen_barrel(&self) -> bool { *self == Self::PEN_BARREL } // pub fn is_pen_eraser(&self) -> bool { *self == Self::PEN_ERASER } - pub fn is_button_1(&self) -> bool { *self == Self::BUTTON_1 } - pub fn is_button_2(&self) -> bool { *self == Self::BUTTON_2 } - pub fn is_button_3(&self) -> bool { *self == Self::BUTTON_3 } - pub fn is_button_4(&self) -> bool { *self == Self::BUTTON_4 } - pub fn is_button_5(&self) -> bool { *self == Self::BUTTON_5 } + pub fn is_button_1(&self) -> bool { + *self == Self::BUTTON_1 + } + pub fn is_button_2(&self) -> bool { + *self == Self::BUTTON_2 + } + pub fn is_button_3(&self) -> bool { + *self == Self::BUTTON_3 + } + pub fn is_button_4(&self) -> bool { + *self == Self::BUTTON_4 + } + pub fn is_button_5(&self) -> bool { + *self == Self::BUTTON_5 + } // pub fn is_button_6(&self) -> bool { *self == Self::BUTTON_6 } } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 6952da7eb6..6738195fe6 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -32,8 +32,9 @@ use winapi::{ use crate::{ dpi::{PhysicalDelta, PhysicalPosition, PhysicalSize, UnitlessDelta}, event::{ - Event, Force, KeyEvent, LogicalKey, ModifiersState, PointerButton, PointerId, PointerButtonEvent, - RawKeyEvent, RawKeyboardEvent, RawPointerEvent, RawPointerButtonEvent, WindowEvent, + Event, Force, KeyEvent, LogicalKey, ModifiersState, PointerButton, PointerButtonEvent, + PointerId, RawKeyEvent, RawKeyboardEvent, RawPointerButtonEvent, RawPointerEvent, + WindowEvent, }, event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW}, platform_impl::platform::{ diff --git a/tests/serde_objects.rs b/tests/serde_objects.rs index 084ee971d2..dcee06e882 100644 --- a/tests/serde_objects.rs +++ b/tests/serde_objects.rs @@ -2,8 +2,11 @@ use serde::{Deserialize, Serialize}; use winit::{ - dpi::{Pixel, LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, PhysicalDelta, LogicalDelta, UnitlessDelta}, - event::{ModifiersState, PointerButton, LogicalKey}, + dpi::{ + LogicalDelta, LogicalPosition, LogicalSize, PhysicalDelta, PhysicalPosition, PhysicalSize, + Pixel, UnitlessDelta, + }, + event::{LogicalKey, ModifiersState, PointerButton}, window::CursorIcon, }; From f03160783b6fa223355941436a9c6cb79dafca2b Mon Sep 17 00:00:00 2001 From: Osspial Date: Wed, 20 May 2020 17:57:34 -0400 Subject: [PATCH 18/29] Add constructors and setters to event structs --- src/event.rs | 97 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 5 deletions(-) diff --git a/src/event.rs b/src/event.rs index cb889d12db..7ca6f216ec 100644 --- a/src/event.rs +++ b/src/event.rs @@ -373,7 +373,7 @@ pub enum StartCause { Init, } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct KeyEvent { pub(crate) logical_key: Option, pub(crate) scan_code: u32, @@ -382,21 +382,21 @@ pub struct KeyEvent { pub(crate) is_synthetic: bool, } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct RawKeyEvent { pub(crate) logical_key: Option, pub(crate) scan_code: u32, pub(crate) is_down: bool, } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct PointerButtonEvent { pub(crate) button: PointerButton, pub(crate) is_down: bool, pub(crate) click_count: u32, } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct RawPointerButtonEvent { pub(crate) button: PointerButton, pub(crate) is_down: bool, @@ -440,6 +440,33 @@ impl KeyEvent { } } +impl KeyEvent { + pub fn new() -> Self { + Self::default() + } + + pub fn set_logical_key(&mut self, logical_key: Option) -> &mut Self { + self.logical_key = logical_key; + self + } + pub fn set_scan_code(&mut self, scan_code: u32) -> &mut Self { + self.scan_code = scan_code; + self + } + pub fn set_is_down(&mut self, is_down: bool) -> &mut Self { + self.is_down = is_down; + self + } + pub fn set_is_repeat(&mut self, is_repeat: bool) -> &mut Self { + self.is_repeat = is_repeat; + self + } + pub fn set_is_synthetic(&mut self, is_synthetic: bool) -> &mut Self { + self.is_synthetic = is_synthetic; + self + } +} + impl RawKeyEvent { pub fn logical_key(&self) -> Option { self.logical_key @@ -455,6 +482,25 @@ impl RawKeyEvent { } } +impl RawKeyEvent { + pub fn new() -> Self { + Self::default() + } + + pub fn set_logical_key(&mut self, logical_key: Option) -> &mut Self { + self.logical_key = logical_key; + self + } + pub fn set_scan_code(&mut self, scan_code: u32) -> &mut Self { + self.scan_code = scan_code; + self + } + pub fn set_is_down(&mut self, is_down: bool) -> &mut Self { + self.is_down = is_down; + self + } +} + impl PointerButtonEvent { pub fn button(&self) -> PointerButton { self.button @@ -474,6 +520,25 @@ impl PointerButtonEvent { } } +impl PointerButtonEvent { + pub fn new() -> Self { + Self::default() + } + + pub fn set_button(&mut self, button: PointerButton) -> &mut Self { + self.button = button; + self + } + pub fn set_is_down(&mut self, is_down: bool) -> &mut Self { + self.is_down = is_down; + self + } + pub fn set_click_count(&mut self, click_count: u32) -> &mut Self { + self.click_count = click_count; + self + } +} + impl RawPointerButtonEvent { pub fn button(&self) -> PointerButton { self.button @@ -486,7 +551,22 @@ impl RawPointerButtonEvent { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +impl RawPointerButtonEvent { + pub fn new() -> Self { + Self::default() + } + + pub fn set_button(&mut self, button: PointerButton) -> &mut Self { + self.button = button; + self + } + pub fn set_is_down(&mut self, is_down: bool) -> &mut Self { + self.is_down = is_down; + self + } +} + +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[repr(transparent)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(transparent))] @@ -506,6 +586,13 @@ enum PointerButtonInner { // Button6, } +impl Default for PointerButtonInner { + #[inline(always)] + fn default() -> Self { + PointerButtonInner::Button1 + } +} + impl PointerButton { pub const MOUSE_LEFT: Self = Self::BUTTON_1; pub const MOUSE_RIGHT: Self = Self::BUTTON_2; From 304cbf380b279c98fd554ab68366214f84eb8ddc Mon Sep 17 00:00:00 2001 From: Osspial Date: Wed, 20 May 2020 18:26:58 -0400 Subject: [PATCH 19/29] Reorder some things --- src/event.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/event.rs b/src/event.rs index 7ca6f216ec..eea15edf16 100644 --- a/src/event.rs +++ b/src/event.rs @@ -132,18 +132,18 @@ pub enum WindowEvent<'a> { /// The window has been destroyed. Destroyed, - /// A file has been dropped into the window. - /// - /// When the user drops multiple files at once, this event will be emitted for each file - /// separately. - FileDropped(PathBuf), - /// A file is being hovered over the window. /// /// When the user hovers multiple files at once, this event will be emitted for each file /// separately. FileHovered(PathBuf), + /// A file has been dropped into the window. + /// + /// When the user drops multiple files at once, this event will be emitted for each file + /// separately. + FileDropped(PathBuf), + /// A file was hovered, but has exited the window. /// /// There will be a single `HoveredFileCancelled` event triggered even if multiple files were @@ -156,11 +156,11 @@ pub enum WindowEvent<'a> { /// The window lost focus. FocusLost, + Key(KeyEvent), + /// The window received a unicode character. CharReceived(char), - Key(KeyEvent), - /// The keyboard modifiers have changed. /// /// This is tracked internally to avoid tracking errors arising from modifier key state changes when events from From 8ef7b1e794ce7b8c8af6d87ef292c501583b355f Mon Sep 17 00:00:00 2001 From: Osspial Date: Thu, 21 May 2020 13:34:30 -0400 Subject: [PATCH 20/29] Add PointerButton serialization styles support Also adds test to ensure serialization/deserialization backwards-compatibility with the old MouseButton type --- Cargo.toml | 3 + src/event.rs | 354 +++++++++++++++++++++++- src/platform_impl/windows/event_loop.rs | 2 +- 3 files changed, 345 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2f4903d9f2..750742b17a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,9 @@ bitflags = "1" [dev-dependencies] image = "0.23" simple_logger = "1" +ron = {version = "0.6"} +serde_json = {version = "1"} +bincode = {version = "1"} [target.'cfg(target_os = "android")'.dependencies] ndk = "0.1.0" diff --git a/src/event.rs b/src/event.rs index eea15edf16..6e836fd8f6 100644 --- a/src/event.rs +++ b/src/event.rs @@ -577,19 +577,22 @@ pub struct PointerButton(PointerButtonInner); #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(rename = "PointerButton"))] +#[cfg_attr(feature = "serde", serde(try_from = "pointer_button_serde::PointerButtonSerialize"))] +#[cfg_attr(feature = "serde", serde(into = "pointer_button_serde::PointerButtonSerialize"))] +#[allow(non_camel_case_types)] enum PointerButtonInner { - Button1, - Button2, - Button3, - Button4, - Button5, - // Button6, + BUTTON_1, + BUTTON_2, + BUTTON_3, + BUTTON_4, + BUTTON_5, + // BUTTON_6, } impl Default for PointerButtonInner { #[inline(always)] fn default() -> Self { - PointerButtonInner::Button1 + PointerButtonInner::BUTTON_1 } } @@ -606,12 +609,12 @@ impl PointerButton { // pub const PEN_BARREL: Self = Self::BUTTON_2; // pub const PEN_ERASER: Self = Self::BUTTON_6; - pub const BUTTON_1: Self = Self(PointerButtonInner::Button1); - pub const BUTTON_2: Self = Self(PointerButtonInner::Button2); - pub const BUTTON_3: Self = Self(PointerButtonInner::Button3); - pub const BUTTON_4: Self = Self(PointerButtonInner::Button4); - pub const BUTTON_5: Self = Self(PointerButtonInner::Button5); - // pub const BUTTON_6: Self = Self(PointerButtonInner::Button6); + pub const BUTTON_1: Self = Self(PointerButtonInner::BUTTON_1); + pub const BUTTON_2: Self = Self(PointerButtonInner::BUTTON_2); + pub const BUTTON_3: Self = Self(PointerButtonInner::BUTTON_3); + pub const BUTTON_4: Self = Self(PointerButtonInner::BUTTON_4); + pub const BUTTON_5: Self = Self(PointerButtonInner::BUTTON_5); + // pub const BUTTON_6: Self = Self(PointerButtonInner::BUTTON_6); pub fn as_u8(&self) -> u8 { self.0 as u8 @@ -653,6 +656,63 @@ impl PointerButton { *self == Self::BUTTON_5 } // pub fn is_button_6(&self) -> bool { *self == Self::BUTTON_6 } + + /// Serializes the `PointerButton` as the `BUTTON_*` constants. This is the default + /// serialization style, since it's pointer-type agnostic. + /// + /// For use with `#[serde(serialize_with = "path")]` + #[cfg(feature = "serde")] + pub fn serialize_agnostic(&self, serializer: S) -> Result + where S: serde::Serializer + { + serde::Serialize::serialize(&self.0.as_serialize_agnostic(), serializer) + } + + /// Tries to serialize the `PointerButton` as the `MOUSE_*` constants, falling back to + /// the `BUTTON_{NUM}` constants if the value doesn't map onto a mouse constant. + /// + /// For use with `#[serde(serialize_with = "path")]` + #[cfg(feature = "serde")] + pub fn serialize_mouse(&self, serializer: S) -> Result + where S: serde::Serializer + { + serde::Serialize::serialize(&self.0.as_serialize_mouse(), serializer) + } + + /// Tries to serialize the `PointerButton` as the `TOUCH_*` constants, falling back to + /// the `BUTTON_{NUM}` constants if the value doesn't map onto a touch constant. + /// + /// For use with `#[serde(serialize_with = "path")]` + #[cfg(feature = "serde")] + pub fn serialize_touch(&self, serializer: S) -> Result + where S: serde::Serializer + { + serde::Serialize::serialize(&self.0.as_serialize_touch(), serializer) + } + + // /// Tries to serialize the `PointerButton` as the `PEN_*` constants, falling back to + // /// the `BUTTON_{NUM}` constants if the value doesn't map onto a pen constant. + // /// + // /// For use with `#[serde(serialize_with = "path")]` + // #[cfg(feature = "serde")] + // pub fn serialize_pen(&self, serializer: S) -> Result + // where S: serde::Serializer + // { + // serde::Serialize::serialize(&self.0.as_serialize_pen(), serializer) + // } + + /// Serializes the `PointerButton` as a legacy Winit [`MouseButton`]. This is provided for + /// backwards-compatibility purposes. + /// + /// For use with `#[serde(serialize_with = "path")]` + /// + /// [`MouseButton`]: https://docs.rs/winit/0.22.2/winit/event/enum.MouseButton.html + #[cfg(feature = "serde")] + pub fn serialize_legacy(&self, serializer: S) -> Result + where S: serde::Serializer + { + serde::Serialize::serialize(&self.0.as_serialize_legacy(), serializer) + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] @@ -1108,3 +1168,271 @@ mod modifiers_serde { } } } + +#[cfg(feature = "serde")] +mod pointer_button_serde { + use super::PointerButtonInner; + use std::{ + convert::TryFrom, + fmt, + }; + use serde::{Serialize, Deserialize}; + + #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] + #[derive(Serialize, Deserialize)] + #[serde(rename = "PointerButton")] + #[allow(non_camel_case_types)] + pub enum PointerButtonSerialize { + // legacy style + Left, + Right, + Middle, + Other(u8), + + // input-agnostic style + BUTTON_1, + BUTTON_2, + BUTTON_3, + BUTTON_4, + BUTTON_5, + // BUTTON_6, + + // mouse style + MOUSE_LEFT, + MOUSE_RIGHT, + MOUSE_MIDDLE, + MOUSE_X1, + MOUSE_X2, + + // touch style + TOUCH_CONTACT, + + // pen style + // PenDown, + // PenBarrel, + // PenEraser, + } + + + pub struct OtherConvertError(u8); + + impl TryFrom for PointerButtonInner { + type Error = OtherConvertError; + fn try_from(serialize: PointerButtonSerialize) -> Result { + match serialize { + PointerButtonSerialize::TOUCH_CONTACT | + PointerButtonSerialize::BUTTON_1 | + PointerButtonSerialize::Left | + PointerButtonSerialize::MOUSE_LEFT => Ok(PointerButtonInner::BUTTON_1), + + PointerButtonSerialize::BUTTON_2 | + PointerButtonSerialize::Right | + PointerButtonSerialize::MOUSE_RIGHT => Ok(PointerButtonInner::BUTTON_2), + + PointerButtonSerialize::BUTTON_3 | + PointerButtonSerialize::Middle | + PointerButtonSerialize::MOUSE_MIDDLE => Ok(PointerButtonInner::BUTTON_3), + + PointerButtonSerialize::BUTTON_4 | + PointerButtonSerialize::Other(0) | + PointerButtonSerialize::MOUSE_X1 => Ok(PointerButtonInner::BUTTON_4), + + PointerButtonSerialize::BUTTON_5 | + PointerButtonSerialize::Other(1) | + PointerButtonSerialize::MOUSE_X2 => Ok(PointerButtonInner::BUTTON_5), + + // PointerButtonSerialize::BUTTON_6 | + // PointerButtonSerialize::Other(2) => Ok(PointerButtonInner::BUTTON_6), + + PointerButtonSerialize::Other(i) => Err(OtherConvertError(i)), + } + } + } + + impl From for PointerButtonSerialize { + fn from(inner: PointerButtonInner) -> PointerButtonSerialize { + inner.as_serialize_agnostic() + } + } + + impl PointerButtonInner { + pub fn as_serialize_agnostic(&self) -> PointerButtonSerialize { + match self { + PointerButtonInner::BUTTON_1 => PointerButtonSerialize::BUTTON_1, + PointerButtonInner::BUTTON_2 => PointerButtonSerialize::BUTTON_2, + PointerButtonInner::BUTTON_3 => PointerButtonSerialize::BUTTON_3, + PointerButtonInner::BUTTON_4 => PointerButtonSerialize::BUTTON_4, + PointerButtonInner::BUTTON_5 => PointerButtonSerialize::BUTTON_5, + } + } + + pub fn as_serialize_legacy(&self) -> PointerButtonSerialize { + match self { + PointerButtonInner::BUTTON_1 => PointerButtonSerialize::Left, + PointerButtonInner::BUTTON_2 => PointerButtonSerialize::Right, + PointerButtonInner::BUTTON_3 => PointerButtonSerialize::Middle, + PointerButtonInner::BUTTON_4 => PointerButtonSerialize::Other(0), + PointerButtonInner::BUTTON_5 => PointerButtonSerialize::Other(1), + } + } + + pub fn as_serialize_mouse(&self) -> PointerButtonSerialize { + match self { + PointerButtonInner::BUTTON_1 => PointerButtonSerialize::MOUSE_LEFT, + PointerButtonInner::BUTTON_2 => PointerButtonSerialize::MOUSE_RIGHT, + PointerButtonInner::BUTTON_3 => PointerButtonSerialize::MOUSE_MIDDLE, + PointerButtonInner::BUTTON_4 => PointerButtonSerialize::MOUSE_X1, + PointerButtonInner::BUTTON_5 => PointerButtonSerialize::MOUSE_X2, + } + } + + pub fn as_serialize_touch(&self) -> PointerButtonSerialize { + match self { + PointerButtonInner::BUTTON_1 => PointerButtonSerialize::TOUCH_CONTACT, + PointerButtonInner::BUTTON_2 => PointerButtonSerialize::BUTTON_2, + PointerButtonInner::BUTTON_3 => PointerButtonSerialize::BUTTON_3, + PointerButtonInner::BUTTON_4 => PointerButtonSerialize::BUTTON_4, + PointerButtonInner::BUTTON_5 => PointerButtonSerialize::BUTTON_5, + } + } + } + + impl fmt::Display for OtherConvertError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "could not deserialize Other({})", self.0) + } + } + + #[cfg(test)] + mod tests { + use crate::event::PointerButton; + use serde::{Serialize, Deserialize}; + + /// legacy mouse button struct + #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] + #[derive(Serialize, Deserialize)] + enum MouseButton { + Left, + Right, + Middle, + Other(u8), + } + + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] + #[serde(rename = "Serde")] + struct LegacySerde(MouseButton); + + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] + #[serde(rename = "Serde")] + struct NewSerde(#[serde(serialize_with = "PointerButton::serialize_legacy")] PointerButton); + + trait Serde { + type Error: std::fmt::Debug; + fn to_bytes(value: &T) -> Result, Self::Error> + where + T: Serialize; + fn from_bytes<'a, T>(s: &'a [u8]) -> Result + where + T: Deserialize<'a>; + } + + struct Ron; + impl Serde for Ron { + type Error = ron::Error; + fn to_bytes(value: &T) -> Result, Self::Error> + where + T: Serialize + { + ron::ser::to_string(value).map(|s| s.into_bytes()) + } + fn from_bytes<'a, T>(s: &'a [u8]) -> Result + where + T: Deserialize<'a> + { + ron::de::from_bytes(s) + } + } + + struct Bincode; + impl Serde for Bincode { + type Error = bincode::Error; + fn to_bytes(value: &T) -> Result, Self::Error> + where + T: Serialize + { + bincode::serialize(value) + } + fn from_bytes<'a, T>(s: &'a [u8]) -> Result + where + T: Deserialize<'a> + { + bincode::deserialize(s) + } + } + + struct Json; + impl Serde for Json { + type Error = serde_json::Error; + fn to_bytes(value: &T) -> Result, Self::Error> + where + T: Serialize + { + serde_json::to_vec(value) + } + fn from_bytes<'a, T>(s: &'a [u8]) -> Result + where + T: Deserialize<'a> + { + serde_json::from_slice(s) + } + } + + fn serde() { + let legacy = [ + LegacySerde(MouseButton::Left), + LegacySerde(MouseButton::Right), + LegacySerde(MouseButton::Middle), + LegacySerde(MouseButton::Other(0)), + LegacySerde(MouseButton::Other(1)), + ]; + let new = [ + NewSerde(PointerButton::MOUSE_LEFT), + NewSerde(PointerButton::MOUSE_RIGHT), + NewSerde(PointerButton::MOUSE_MIDDLE), + NewSerde(PointerButton::MOUSE_X1), + NewSerde(PointerButton::MOUSE_X2), + ]; + + let try_to_utf8 = |b: &[u8]| format!("\n\tstr: {}\n\tbytes: {:?}", std::str::from_utf8(b).unwrap_or_else(|_| ""), b); + for (l, n) in legacy.iter().cloned().zip(new.iter().cloned()) { + println!("legacy: {:?}, new: {:?}", l, n); + let legacy_serialized: Vec = S::to_bytes(&l).unwrap(); + let new_serialized: Vec = S::to_bytes(&n).unwrap(); + println!("legacy serialized: {}", try_to_utf8(&legacy_serialized)); + println!("new serialized: {}", try_to_utf8(&new_serialized)); + + let legacy_deserialized: LegacySerde = S::from_bytes(&new_serialized).unwrap(); + let new_deserialized: NewSerde = S::from_bytes(&legacy_serialized).unwrap(); + + assert_eq!(&legacy_serialized, &new_serialized); + assert_eq!(legacy_deserialized, l); + assert_eq!(new_deserialized, n); + } + } + + #[test] + fn serde_pointer_button_backwards_compatibility_ron() { + serde::(); + } + + #[test] + fn serde_pointer_button_backwards_compatibility_bincode() { + serde::(); + } + + #[test] + fn serde_pointer_button_backwards_compatibility_json() { + serde::(); + } + } +} diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 6738195fe6..2a6481158d 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -776,7 +776,7 @@ unsafe extern "system" fn public_window_callback( commctrl::DefSubclassProc(window, msg, wparam, lparam) } winuser::WM_NCLBUTTONDOWN => { - if wparam == winuser::HTCAPTION as _ { + if wparam == winuser::HTCAPTION as WPARAM { winuser::PostMessageW(window, winuser::WM_MOUSEMOVE, 0, 0); } commctrl::DefSubclassProc(window, msg, wparam, lparam) From b9e152a4a036057cad628367d277cb565a82f9dc Mon Sep 17 00:00:00 2001 From: Osspial Date: Fri, 22 May 2020 00:28:23 -0400 Subject: [PATCH 21/29] Add pen events to the public API --- Cargo.toml | 1 + src/event.rs | 462 ++++++++++++++++++++++++++++--- src/platform_impl/windows/mod.rs | 13 + 3 files changed, 444 insertions(+), 32 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 750742b17a..9a8219bfaa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ simple_logger = "1" ron = {version = "0.6"} serde_json = {version = "1"} bincode = {version = "1"} +assert_approx_eq = "1" [target.'cfg(target_os = "android")'.dependencies] ndk = "0.1.0" diff --git a/src/event.rs b/src/event.rs index 6e836fd8f6..b7e0ae515d 100644 --- a/src/event.rs +++ b/src/event.rs @@ -173,6 +173,8 @@ pub enum WindowEvent<'a> { PointerCreated(PointerId), PointerForce(PointerId, Force), + PointerTilt(PointerId, PointerTiltEvent), + PointerTwist(PointerId, f64), PointerMoved(PointerId, PhysicalPosition), PointerButton(PointerId, PointerButtonEvent), PointerEntered(PointerId), @@ -296,6 +298,8 @@ impl Clone for WindowEvent<'static> { Key(key_press) => Key(key_press), ModifiersChanged(state) => ModifiersChanged(state), PointerCreated(id) => PointerCreated(id), + PointerTilt(id, tilt) => PointerTilt(id, tilt), + PointerTwist(id, twist) => PointerTwist(id, twist), PointerForce(id, force) => PointerForce(id, force), PointerMoved(id, position) => PointerMoved(id, position), PointerButton(id, pointer_button) => PointerButton(id, pointer_button), @@ -331,6 +335,8 @@ impl<'a> WindowEvent<'a> { Key(key_press) => Ok(Key(key_press)), ModifiersChanged(state) => Ok(ModifiersChanged(state)), PointerCreated(id) => Ok(PointerCreated(id)), + PointerTilt(id, tilt) => Ok(PointerTilt(id, tilt)), + PointerTwist(id, twist) => Ok(PointerTwist(id, twist)), PointerForce(id, force) => Ok(PointerForce(id, force)), PointerMoved(id, position) => Ok(PointerMoved(id, position)), PointerButton(id, pointer_button) => Ok(PointerButton(id, pointer_button)), @@ -586,7 +592,7 @@ enum PointerButtonInner { BUTTON_3, BUTTON_4, BUTTON_5, - // BUTTON_6, + BUTTON_6, } impl Default for PointerButtonInner { @@ -605,16 +611,16 @@ impl PointerButton { pub const TOUCH_CONTACT: Self = Self::BUTTON_1; - // pub const PEN_DOWN: Self = Self::BUTTON_1; - // pub const PEN_BARREL: Self = Self::BUTTON_2; - // pub const PEN_ERASER: Self = Self::BUTTON_6; + pub const PEN_CONTACT: Self = Self::BUTTON_1; + pub const PEN_BARREL: Self = Self::BUTTON_2; + pub const PEN_ERASER: Self = Self::BUTTON_6; pub const BUTTON_1: Self = Self(PointerButtonInner::BUTTON_1); pub const BUTTON_2: Self = Self(PointerButtonInner::BUTTON_2); pub const BUTTON_3: Self = Self(PointerButtonInner::BUTTON_3); pub const BUTTON_4: Self = Self(PointerButtonInner::BUTTON_4); pub const BUTTON_5: Self = Self(PointerButtonInner::BUTTON_5); - // pub const BUTTON_6: Self = Self(PointerButtonInner::BUTTON_6); + pub const BUTTON_6: Self = Self(PointerButtonInner::BUTTON_6); pub fn as_u8(&self) -> u8 { self.0 as u8 @@ -637,9 +643,9 @@ impl PointerButton { pub fn is_touch_contact(&self) -> bool { *self == Self::TOUCH_CONTACT } - // pub fn is_pen_contact(&self) -> bool { *self == Self::PEN_CONTACT } - // pub fn is_pen_barrel(&self) -> bool { *self == Self::PEN_BARREL } - // pub fn is_pen_eraser(&self) -> bool { *self == Self::PEN_ERASER } + pub fn is_pen_contact(&self) -> bool { *self == Self::PEN_CONTACT } + pub fn is_pen_barrel(&self) -> bool { *self == Self::PEN_BARREL } + pub fn is_pen_eraser(&self) -> bool { *self == Self::PEN_ERASER } pub fn is_button_1(&self) -> bool { *self == Self::BUTTON_1 } @@ -655,7 +661,7 @@ impl PointerButton { pub fn is_button_5(&self) -> bool { *self == Self::BUTTON_5 } - // pub fn is_button_6(&self) -> bool { *self == Self::BUTTON_6 } + pub fn is_button_6(&self) -> bool { *self == Self::BUTTON_6 } /// Serializes the `PointerButton` as the `BUTTON_*` constants. This is the default /// serialization style, since it's pointer-type agnostic. @@ -690,16 +696,16 @@ impl PointerButton { serde::Serialize::serialize(&self.0.as_serialize_touch(), serializer) } - // /// Tries to serialize the `PointerButton` as the `PEN_*` constants, falling back to - // /// the `BUTTON_{NUM}` constants if the value doesn't map onto a pen constant. - // /// - // /// For use with `#[serde(serialize_with = "path")]` - // #[cfg(feature = "serde")] - // pub fn serialize_pen(&self, serializer: S) -> Result - // where S: serde::Serializer - // { - // serde::Serialize::serialize(&self.0.as_serialize_pen(), serializer) - // } + /// Tries to serialize the `PointerButton` as the `PEN_*` constants, falling back to + /// the `BUTTON_{NUM}` constants if the value doesn't map onto a pen constant. + /// + /// For use with `#[serde(serialize_with = "path")]` + #[cfg(feature = "serde")] + pub fn serialize_pen(&self, serializer: S) -> Result + where S: serde::Serializer + { + serde::Serialize::serialize(&self.0.as_serialize_pen(), serializer) + } /// Serializes the `PointerButton` as a legacy Winit [`MouseButton`]. This is provided for /// backwards-compatibility purposes. @@ -719,7 +725,7 @@ impl PointerButton { pub enum PointerId { MouseId(MouseId), TouchId(TouchId), - // PenId(PenId), + PenId(PenId), } /// A typed identifier for a pointer device. @@ -729,6 +735,9 @@ pub struct MouseId(pub(crate) platform_impl::MouseId); #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct TouchId(pub(crate) platform_impl::TouchId); +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct PenId(pub(crate) platform_impl::PenId); + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct PointerDeviceId(pub(crate) platform_impl::PointerDeviceId); @@ -750,12 +759,12 @@ impl PointerId { } } - // pub fn is_pen_id(&self) -> bool { - // match *self { - // PointerId::PenId(_) => true, - // _ => false, - // } - // } + pub fn is_pen_id(&self) -> bool { + match *self { + PointerId::PenId(_) => true, + _ => false, + } + } } impl MouseId { @@ -815,6 +824,12 @@ impl fmt::Debug for TouchId { } } +impl fmt::Debug for PenId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + self.0.fmt(f) + } +} + /// Describes the force of a touch event #[derive(Debug, Clone, Copy, PartialEq)] pub enum Force { @@ -871,6 +886,85 @@ impl Force { } } +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct PointerTiltEvent { + tilt_angle_x: f64, + tilt_angle_y: f64, +} + +impl PointerTiltEvent { + pub fn new_titlt_angle(tilt_angle_x: f64, tilt_angle_y: f64) -> PointerTiltEvent { + PointerTiltEvent { + tilt_angle_x, + tilt_angle_y, + } + } + + #[inline(always)] + pub fn tilt_angle_x(&self) -> f64 { + self.tilt_angle_x + } + + #[inline(always)] + pub fn tilt_angle_y(&self) -> f64 { + self.tilt_angle_y + } + + #[inline(always)] + pub fn tilt_angle(&self) -> f64 { + let tilt = f64::sqrt(self.tilt_angle_x.sin().powi(2) + self.tilt_angle_y.sin().powi(2)).asin(); + if tilt.is_nan() { + 0.0 + } else { + tilt + } + } + + #[inline(always)] + pub fn altitude_angle(&self) -> f64 { + std::f64::consts::PI/2.0 - self.tilt_angle() + } + + #[inline(always)] + pub fn tilt_vector_x(&self) -> f64 { + self.tilt_angle_x.sin() + } + + #[inline(always)] + pub fn tilt_vector_y(&self) -> f64 { + self.tilt_angle_y.sin() + } + + #[inline(always)] + pub fn tilt_vector_z(&self) -> f64 { + let z = f64::sqrt(1.0 - self.tilt_vector_x().powi(2) - self.tilt_vector_y().powi(2)); + if z.is_nan() { + 0.0 + } else { + z + } + } + + #[inline(always)] + pub fn azimuth_angle(&self) -> Option { + if self.tilt_angle_x == 0.0 && self.tilt_angle_y == 0.0 { + None + } else { + Some(f64::atan2(self.tilt_angle_x, self.tilt_angle_y)) + } + } + + #[inline(always)] + pub fn azimuth_vector_x(&self) -> f64 { + self.azimuth_angle().map(|a| a.sin()).unwrap_or(0.0) + } + + #[inline(always)] + pub fn azimuth_vector_y(&self) -> f64 { + self.azimuth_angle().map(|a| a.cos()).unwrap_or(0.0) + } +} + /// Symbolic name for a keyboard key. #[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)] #[repr(u32)] @@ -1195,7 +1289,7 @@ mod pointer_button_serde { BUTTON_3, BUTTON_4, BUTTON_5, - // BUTTON_6, + BUTTON_6, // mouse style MOUSE_LEFT, @@ -1208,9 +1302,9 @@ mod pointer_button_serde { TOUCH_CONTACT, // pen style - // PenDown, - // PenBarrel, - // PenEraser, + PEN_CONTACT, + PEN_BARREL, + PEN_ERASER, } @@ -1221,11 +1315,13 @@ mod pointer_button_serde { fn try_from(serialize: PointerButtonSerialize) -> Result { match serialize { PointerButtonSerialize::TOUCH_CONTACT | + PointerButtonSerialize::PEN_CONTACT | PointerButtonSerialize::BUTTON_1 | PointerButtonSerialize::Left | PointerButtonSerialize::MOUSE_LEFT => Ok(PointerButtonInner::BUTTON_1), PointerButtonSerialize::BUTTON_2 | + PointerButtonSerialize::PEN_BARREL | PointerButtonSerialize::Right | PointerButtonSerialize::MOUSE_RIGHT => Ok(PointerButtonInner::BUTTON_2), @@ -1241,8 +1337,9 @@ mod pointer_button_serde { PointerButtonSerialize::Other(1) | PointerButtonSerialize::MOUSE_X2 => Ok(PointerButtonInner::BUTTON_5), - // PointerButtonSerialize::BUTTON_6 | - // PointerButtonSerialize::Other(2) => Ok(PointerButtonInner::BUTTON_6), + PointerButtonSerialize::BUTTON_6 | + PointerButtonSerialize::Other(2) | + PointerButtonSerialize::PEN_ERASER => Ok(PointerButtonInner::BUTTON_6), PointerButtonSerialize::Other(i) => Err(OtherConvertError(i)), } @@ -1263,6 +1360,7 @@ mod pointer_button_serde { PointerButtonInner::BUTTON_3 => PointerButtonSerialize::BUTTON_3, PointerButtonInner::BUTTON_4 => PointerButtonSerialize::BUTTON_4, PointerButtonInner::BUTTON_5 => PointerButtonSerialize::BUTTON_5, + PointerButtonInner::BUTTON_6 => PointerButtonSerialize::BUTTON_6, } } @@ -1273,6 +1371,7 @@ mod pointer_button_serde { PointerButtonInner::BUTTON_3 => PointerButtonSerialize::Middle, PointerButtonInner::BUTTON_4 => PointerButtonSerialize::Other(0), PointerButtonInner::BUTTON_5 => PointerButtonSerialize::Other(1), + PointerButtonInner::BUTTON_6 => PointerButtonSerialize::BUTTON_6, } } @@ -1283,6 +1382,7 @@ mod pointer_button_serde { PointerButtonInner::BUTTON_3 => PointerButtonSerialize::MOUSE_MIDDLE, PointerButtonInner::BUTTON_4 => PointerButtonSerialize::MOUSE_X1, PointerButtonInner::BUTTON_5 => PointerButtonSerialize::MOUSE_X2, + PointerButtonInner::BUTTON_6 => PointerButtonSerialize::BUTTON_6, } } @@ -1293,6 +1393,18 @@ mod pointer_button_serde { PointerButtonInner::BUTTON_3 => PointerButtonSerialize::BUTTON_3, PointerButtonInner::BUTTON_4 => PointerButtonSerialize::BUTTON_4, PointerButtonInner::BUTTON_5 => PointerButtonSerialize::BUTTON_5, + PointerButtonInner::BUTTON_6 => PointerButtonSerialize::BUTTON_6, + } + } + + pub fn as_serialize_pen(&self) -> PointerButtonSerialize { + match self { + PointerButtonInner::BUTTON_1 => PointerButtonSerialize::PEN_CONTACT, + PointerButtonInner::BUTTON_2 => PointerButtonSerialize::PEN_BARREL, + PointerButtonInner::BUTTON_3 => PointerButtonSerialize::BUTTON_3, + PointerButtonInner::BUTTON_4 => PointerButtonSerialize::BUTTON_4, + PointerButtonInner::BUTTON_5 => PointerButtonSerialize::BUTTON_5, + PointerButtonInner::BUTTON_6 => PointerButtonSerialize::PEN_ERASER, } } } @@ -1436,3 +1548,289 @@ mod pointer_button_serde { } } } + +#[cfg(test)] +mod tests { + use super::PointerTiltEvent; + use std::f64::consts::PI; + use assert_approx_eq::assert_approx_eq; + + #[test] + fn pointer_tilt_azimuth() { + let half_angle = 0.707107; + + println!("up"); + let up = PointerTiltEvent { + tilt_angle_x: 0.0, + tilt_angle_y: 0.0, + }; + assert_eq!(None, up.azimuth_angle()); + + println!("north"); + let north = PointerTiltEvent { + tilt_angle_x: 0.0, + tilt_angle_y: PI / 2.0, + }; + assert_approx_eq!(0.0, north.azimuth_angle().unwrap()); + assert_approx_eq!(0.0, north.azimuth_vector_x()); + assert_approx_eq!(1.0, north.azimuth_vector_y()); + + println!("north_east"); + let north_east = PointerTiltEvent { + tilt_angle_x: PI / 4.0, + tilt_angle_y: PI / 4.0, + }; + assert_approx_eq!(PI / 4.0, north_east.azimuth_angle().unwrap()); + assert_approx_eq!(half_angle, north_east.azimuth_vector_x()); + assert_approx_eq!(half_angle, north_east.azimuth_vector_y()); + + println!("east"); + let east = PointerTiltEvent { + tilt_angle_x: PI / 2.0, + tilt_angle_y: 0.0, + }; + assert_approx_eq!(1.0 * PI / 2.0, east.azimuth_angle().unwrap()); + assert_approx_eq!(1.0, east.azimuth_vector_x()); + assert_approx_eq!(0.0, east.azimuth_vector_y()); + + println!("south_east"); + let south_east = PointerTiltEvent { + tilt_angle_x: PI / 4.0, + tilt_angle_y: -PI / 4.0, + }; + assert_approx_eq!(3.0 * PI / 4.0, south_east.azimuth_angle().unwrap()); + assert_approx_eq!(half_angle, south_east.azimuth_vector_x()); + assert_approx_eq!(-half_angle, south_east.azimuth_vector_y()); + + println!("south"); + let south = PointerTiltEvent { + tilt_angle_x: 0.0, + tilt_angle_y: -PI / 2.0, + }; + assert_approx_eq!(2.0 * PI / 2.0, south.azimuth_angle().unwrap()); + assert_approx_eq!(0.0, south.azimuth_vector_x()); + assert_approx_eq!(-1.0, south.azimuth_vector_y()); + + println!("south_west"); + let south_west = PointerTiltEvent { + tilt_angle_x: -PI / 4.0, + tilt_angle_y: -PI / 4.0, + }; + assert_approx_eq!(-3.0 * PI / 4.0, south_west.azimuth_angle().unwrap()); + assert_approx_eq!(-half_angle, south_west.azimuth_vector_x()); + assert_approx_eq!(-half_angle, south_west.azimuth_vector_y()); + + println!("west"); + let west = PointerTiltEvent { + tilt_angle_x: -PI / 2.0, + tilt_angle_y: 0.0, + }; + assert_approx_eq!(-1.0 * PI / 2.0, west.azimuth_angle().unwrap()); + assert_approx_eq!(-1.0, west.azimuth_vector_x()); + assert_approx_eq!(0.0, west.azimuth_vector_y()); + + println!("north_west"); + let north_west = PointerTiltEvent { + tilt_angle_x: -PI / 4.0, + tilt_angle_y: PI / 4.0, + }; + assert_approx_eq!(-PI / 4.0, north_west.azimuth_angle().unwrap()); + assert_approx_eq!(-half_angle, north_west.azimuth_vector_x()); + assert_approx_eq!(half_angle, north_west.azimuth_vector_y()); + } + + #[test] + fn pointer_tilt_vector() { + let tilt_vector = |te: PointerTiltEvent| [te.tilt_vector_x(), te.tilt_vector_y(), te.tilt_vector_z()]; + + let eps = 1.0e-6; + let assert_normalized = |v: [f64; 3]| { + let length = (v[0].powi(2) + v[1].powi(2) + v[2].powi(2)).sqrt(); + if (length - 1.0).abs() > eps { + assert_eq!(length, 1.0, "vector {:?} is not normalized", v); + } + }; + let assert_approx_eq = |left: [f64; 3], right: [f64; 3]| { + println!("testing left normalized"); + assert_normalized(left); + println!("testing right normalized"); + assert_normalized(right); + + let mut equals = true; + for i in 0..3 { + equals &= (left[i] - right[i]).abs() <= eps; + } + if !equals { + assert_eq!(left, right); + } + }; + + println!("up"); + let up = PointerTiltEvent { + tilt_angle_x: 0.0, + tilt_angle_y: 0.0, + }; + assert_approx_eq([0.0, 0.0, 1.0], tilt_vector(up)); + + println!("east"); + let east = PointerTiltEvent { + tilt_angle_x: PI / 2.0, + tilt_angle_y: 0.0, + }; + assert_approx_eq([1.0, 0.0, 0.0], tilt_vector(east)); + + println!("west"); + let west = PointerTiltEvent { + tilt_angle_x: -PI / 2.0, + tilt_angle_y: 0.0, + }; + assert_approx_eq([-1.0, 0.0, 0.0], tilt_vector(west)); + + println!("north"); + let north = PointerTiltEvent { + tilt_angle_x: 0.0, + tilt_angle_y: PI / 2.0, + }; + assert_approx_eq([0.0, 1.0, 0.0], tilt_vector(north)); + + println!("south"); + let south = PointerTiltEvent { + tilt_angle_x: 0.0, + tilt_angle_y: -PI / 2.0, + }; + assert_approx_eq([0.0, -1.0, 0.0], tilt_vector(south)); + + let half_angle = 0.707107; + let circle_corner = PI/4.0; + println!("north_east"); + let north_east = PointerTiltEvent { + tilt_angle_x: circle_corner, + tilt_angle_y: circle_corner, + }; + assert_approx_eq([half_angle, half_angle, 0.0], tilt_vector(north_east)); + + println!("half_east"); + let half_east = PointerTiltEvent { + tilt_angle_x: PI / 4.0, + tilt_angle_y: 0.0, + }; + assert_approx_eq([half_angle, 0.0, half_angle], tilt_vector(half_east)); + + println!("half_north"); + let half_north = PointerTiltEvent { + tilt_angle_x: 0.0, + tilt_angle_y: PI / 4.0, + }; + assert_approx_eq([0.0, half_angle, half_angle], tilt_vector(half_north)); + + println!("half_north_east"); + let half_north_east = PointerTiltEvent { + tilt_angle_x: PI / 6.0, + tilt_angle_y: PI / 6.0, + }; + assert_approx_eq([0.5, 0.5, half_angle], tilt_vector(half_north_east)); + } + + #[test] + fn pointer_tilt_angle() { + let angle_slight = PI / 6.0; + let angle_lots = PI / 3.0; + let angle_full = PI / 2.0; + let diagonal_angle = |a: f64| (a.sin().powi(2)/2.0).sqrt().asin(); + let diagonal_slight = diagonal_angle(angle_slight); + let diagonal_lots = diagonal_angle(angle_lots); + let diagonal_full = diagonal_angle(angle_full); + + println!("up"); + let up = PointerTiltEvent { + tilt_angle_x: 0.0, + tilt_angle_y: 0.0, + }; + assert_approx_eq!(0.0, up.tilt_angle()); + + println!("north_slight"); + let north_slight = PointerTiltEvent { + tilt_angle_x: 0.0, + tilt_angle_y: angle_slight, + }; + assert_approx_eq!(angle_slight, north_slight.tilt_angle()); + + println!("north_lots"); + let north_lots = PointerTiltEvent { + tilt_angle_x: 0.0, + tilt_angle_y: angle_lots, + }; + assert_approx_eq!(angle_lots, north_lots.tilt_angle()); + + println!("north_full"); + let north_full = PointerTiltEvent { + tilt_angle_x: 0.0, + tilt_angle_y: angle_full, + }; + assert_approx_eq!(angle_full, north_full.tilt_angle()); + + println!("north_east_slight"); + let north_east_slight = PointerTiltEvent { + tilt_angle_x: diagonal_slight, + tilt_angle_y: diagonal_slight, + }; + assert_approx_eq!(angle_slight, north_east_slight.tilt_angle()); + + println!("north_east_lots"); + let north_east_lots = PointerTiltEvent { + tilt_angle_x: -diagonal_lots, + tilt_angle_y: -diagonal_lots, + }; + assert_approx_eq!(angle_lots, north_east_lots.tilt_angle()); + + println!("south_east_full"); + let south_east_full = PointerTiltEvent { + tilt_angle_x: -diagonal_full, + tilt_angle_y: -diagonal_full, + }; + assert_approx_eq!(angle_full, south_east_full.tilt_angle()); + + + println!("south_slight"); + let south_slight = PointerTiltEvent { + tilt_angle_x: -0.0, + tilt_angle_y: -angle_slight, + }; + assert_approx_eq!(angle_slight, south_slight.tilt_angle()); + + println!("south_lots"); + let south_lots = PointerTiltEvent { + tilt_angle_x: -0.0, + tilt_angle_y: -angle_lots, + }; + assert_approx_eq!(angle_lots, south_lots.tilt_angle()); + + println!("south_full"); + let south_full = PointerTiltEvent { + tilt_angle_x: -0.0, + tilt_angle_y: -angle_full, + }; + assert_approx_eq!(angle_full, south_full.tilt_angle()); + + println!("south_west_slight"); + let south_west_slight = PointerTiltEvent { + tilt_angle_x: -diagonal_slight, + tilt_angle_y: -diagonal_slight, + }; + assert_approx_eq!(angle_slight, south_west_slight.tilt_angle()); + + println!("south_west_lots"); + let south_west_lots = PointerTiltEvent { + tilt_angle_x: -diagonal_lots, + tilt_angle_y: -diagonal_lots, + }; + assert_approx_eq!(angle_lots, south_west_lots.tilt_angle()); + + println!("south_west_full"); + let south_west_full = PointerTiltEvent { + tilt_angle_x: -diagonal_full, + tilt_angle_y: -diagonal_full, + }; + assert_approx_eq!(angle_full, south_west_full.tilt_angle()); + } +} diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 6f5816e38f..61cc451461 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -93,6 +93,19 @@ impl From for crate::event::TouchId { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct PenId(u32); +impl PenId { + pub unsafe fn dummy() -> Self { + PenId(!0) + } +} +impl From for crate::event::PenId { + fn from(platform_id: PenId) -> Self { + Self(platform_id) + } +} + pub type OsError = std::io::Error; #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] From b5bf39a0cb2ab710232f39b41c6a27d17efb7aac Mon Sep 17 00:00:00 2001 From: Osspial Date: Fri, 22 May 2020 13:27:39 -0400 Subject: [PATCH 22/29] Fully implement new pointer API on Windows --- src/event.rs | 15 +++- src/platform_impl/windows/event_loop.rs | 107 +++++++++++++++++------- 2 files changed, 89 insertions(+), 33 deletions(-) diff --git a/src/event.rs b/src/event.rs index b7e0ae515d..d55177f926 100644 --- a/src/event.rs +++ b/src/event.rs @@ -175,12 +175,14 @@ pub enum WindowEvent<'a> { PointerForce(PointerId, Force), PointerTilt(PointerId, PointerTiltEvent), PointerTwist(PointerId, f64), + PointerContactArea(PointerId, PhysicalSize), PointerMoved(PointerId, PhysicalPosition), PointerButton(PointerId, PointerButtonEvent), PointerEntered(PointerId), PointerLeft(PointerId), PointerDestroyed(PointerId), + // TODO: SHOULD SCROLL EVENTS BE ASSOCIATED WITH A POINTER? ScrollStarted, ScrollLines(UnitlessDelta), ScrollPixels(PhysicalDelta), @@ -301,6 +303,7 @@ impl Clone for WindowEvent<'static> { PointerTilt(id, tilt) => PointerTilt(id, tilt), PointerTwist(id, twist) => PointerTwist(id, twist), PointerForce(id, force) => PointerForce(id, force), + PointerContactArea(id, contact_area) => PointerContactArea(id, contact_area), PointerMoved(id, position) => PointerMoved(id, position), PointerButton(id, pointer_button) => PointerButton(id, pointer_button), PointerEntered(id) => PointerEntered(id), @@ -338,6 +341,7 @@ impl<'a> WindowEvent<'a> { PointerTilt(id, tilt) => Ok(PointerTilt(id, tilt)), PointerTwist(id, twist) => Ok(PointerTwist(id, twist)), PointerForce(id, force) => Ok(PointerForce(id, force)), + PointerContactArea(id, contact_area) => Ok(PointerContactArea(id, contact_area)), PointerMoved(id, position) => Ok(PointerMoved(id, position)), PointerButton(id, pointer_button) => Ok(PointerButton(id, pointer_button)), PointerEntered(id) => Ok(PointerEntered(id)), @@ -893,7 +897,7 @@ pub struct PointerTiltEvent { } impl PointerTiltEvent { - pub fn new_titlt_angle(tilt_angle_x: f64, tilt_angle_y: f64) -> PointerTiltEvent { + pub fn new_tilt_angle(tilt_angle_x: f64, tilt_angle_y: f64) -> PointerTiltEvent { PointerTiltEvent { tilt_angle_x, tilt_angle_y, @@ -912,7 +916,11 @@ impl PointerTiltEvent { #[inline(always)] pub fn tilt_angle(&self) -> f64 { - let tilt = f64::sqrt(self.tilt_angle_x.sin().powi(2) + self.tilt_angle_y.sin().powi(2)).asin(); + // As shown by `tilt_vector_(x|y)`, the length of the tilt vector on the XY plane is + // trivially relatable to the tilt angle. This computes the length of the XY vector and uses + // that to get the axis-independent tilt angle. + let tilt_xy_distance_from_center = f64::sqrt(self.tilt_vector_x().powi(2) + self.tilt_vector_y().powi(2)); + let tilt = f64::asin(tilt_xy_distance_from_center); if tilt.is_nan() { 0.0 } else { @@ -937,6 +945,9 @@ impl PointerTiltEvent { #[inline(always)] pub fn tilt_vector_z(&self) -> f64 { + // The tilt vector is a normalized three-component vector. Since we know the X and Y + // components of that vector, we can use a transformed version of the pythagorean theorem + // to get the Z component. let z = f64::sqrt(1.0 - self.tilt_vector_x().powi(2) - self.tilt_vector_y().powi(2)); if z.is_nan() { 0.0 diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 2a6481158d..8fef6bd365 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -34,7 +34,7 @@ use crate::{ event::{ Event, Force, KeyEvent, LogicalKey, ModifiersState, PointerButton, PointerButtonEvent, PointerId, RawKeyEvent, RawKeyboardEvent, RawPointerButtonEvent, RawPointerEvent, - WindowEvent, + WindowEvent, PointerTiltEvent, }, event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW}, platform_impl::platform::{ @@ -641,7 +641,7 @@ pub(crate) fn subclass_window(window: HWND, subclass_input: SubclassInput) fn normalize_pointer_pressure(pressure: u32) -> Option { match pressure { - 1..=1024 => Some(Force::Normalized(pressure as f64 / 1024.0)), + 0..=1024 => Some(Force::Normalized(pressure as f64 / 1024.0)), _ => None, } } @@ -1446,54 +1446,99 @@ unsafe extern "system" fn public_window_callback( continue; } - let force = match pointer_info.pointerType { + + + let x = position.x as f64 + x.fract(); + let y = position.y as f64 + y.fract(); + let position = PhysicalPosition::new(x, y); + let pointer_id = PointerId::TouchId(TouchId(pointer_info.pointerId).into()); + + if pointer_info.pointerFlags & winuser::POINTER_FLAG_NEW != 0 { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerCreated(pointer_id), + )); + } + + let pi = std::f64::consts::PI; + let deg_to_twist = |deg: u32| ((deg as f64 / 360.0) - 0.5) * pi; + let mut force = None; + let mut tilt = None; + let mut twist = None; + let mut contact_area = None; + match pointer_info.pointerType { winuser::PT_TOUCH => { let mut touch_info = mem::MaybeUninit::uninit(); - GET_POINTER_TOUCH_INFO.and_then(|GetPointerTouchInfo| { - match GetPointerTouchInfo( + if let Some(GetPointerTouchInfo) = *GET_POINTER_TOUCH_INFO { + let get_touch_info_result = GetPointerTouchInfo( pointer_info.pointerId, - touch_info.as_mut_ptr(), - ) { - 0 => None, - _ => normalize_pointer_pressure( - touch_info.assume_init().pressure, - ), + touch_info.as_mut_ptr() + ); + if 0 != get_touch_info_result { + let touch_info = touch_info.assume_init(); + if touch_info.touchMask & winuser::TOUCH_MASK_PRESSURE != 0 { + force = normalize_pointer_pressure(touch_info.pressure); + } + if touch_info.touchMask & winuser::TOUCH_MASK_ORIENTATION != 0 { + twist = Some(deg_to_twist(touch_info.orientation)); + } + if touch_info.touchMask & winuser::TOUCH_MASK_CONTACTAREA != 0 { + let rect = touch_info.rcContactRaw; + contact_area = Some(PhysicalSize::new(rect.right - rect.left, rect.bottom - rect.top).cast()); + } } - }) + } } winuser::PT_PEN => { let mut pen_info = mem::MaybeUninit::uninit(); - GET_POINTER_PEN_INFO.and_then(|GetPointerPenInfo| { - match GetPointerPenInfo( + if let Some(GetPointerPenInfo) = *GET_POINTER_PEN_INFO { + let get_pen_info_result = GetPointerPenInfo( pointer_info.pointerId, pen_info.as_mut_ptr(), - ) { - 0 => None, - _ => { - normalize_pointer_pressure(pen_info.assume_init().pressure) + ); + if 0 != get_pen_info_result { + let pen_info = pen_info.assume_init(); + if pen_info.penMask & winuser::PEN_MASK_PRESSURE != 0 { + force = normalize_pointer_pressure(pen_info.pressure); + } + if pen_info.penMask & winuser::PEN_MASK_ROTATION != 0 { + // TODO: WHAT DIRECTION IS 0? + twist = Some(deg_to_twist(pen_info.rotation)); + } + if pen_info.penMask & (winuser::PEN_MASK_TILT_X | winuser::PEN_MASK_TILT_Y) != 0 { + tilt = Some(PointerTiltEvent::new_tilt_angle( + pen_info.tiltX as f64 / 90.0 * (pi / 2.0), + pen_info.tiltY as f64 / 90.0 * (pi / 2.0), + )); } } - }) + } } - _ => None, - }; - - let x = position.x as f64 + x.fract(); - let y = position.y as f64 + y.fract(); - let position = PhysicalPosition::new(x, y); - let pointer_id = PointerId::TouchId(TouchId(pointer_info.pointerId).into()); + _ => (), + } - if pointer_info.pointerFlags & winuser::POINTER_FLAG_NEW != 0 { + if let Some(force) = force { subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerCreated(pointer_id), + WindowEvent::PointerForce(pointer_id, force), )); } - - if let Some(force) = force { + if let Some(tilt) = tilt { subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerForce(pointer_id, force), + WindowEvent::PointerTilt(pointer_id, tilt), + )); + } + if let Some(twist) = twist { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerTwist(pointer_id, twist), + )); + } + if let Some(contact_area) = contact_area { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerContactArea(pointer_id, contact_area), )); } From 851a7ea6d03030260b837d08df74c60af1f8ae4d Mon Sep 17 00:00:00 2001 From: Osspial Date: Fri, 22 May 2020 13:32:51 -0400 Subject: [PATCH 23/29] Distinguish between touch and pen IDs --- src/platform_impl/windows/event_loop.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 8fef6bd365..4de102e473 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -44,7 +44,7 @@ use crate::{ event::{self, handle_extended_keys, process_key_params, vkey_to_winit_vkey}, monitor, raw_input, util, window_state::{CursorFlags, WindowFlags, WindowState}, - KeyboardDeviceId, PointerDeviceId, TouchId, WindowId, + KeyboardDeviceId, PointerDeviceId, TouchId, WindowId, PenId, }, window::{Fullscreen, Theme}, }; @@ -1451,14 +1451,6 @@ unsafe extern "system" fn public_window_callback( let x = position.x as f64 + x.fract(); let y = position.y as f64 + y.fract(); let position = PhysicalPosition::new(x, y); - let pointer_id = PointerId::TouchId(TouchId(pointer_info.pointerId).into()); - - if pointer_info.pointerFlags & winuser::POINTER_FLAG_NEW != 0 { - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerCreated(pointer_id), - )); - } let pi = std::f64::consts::PI; let deg_to_twist = |deg: u32| ((deg as f64 / 360.0) - 0.5) * pi; @@ -1466,8 +1458,10 @@ unsafe extern "system" fn public_window_callback( let mut tilt = None; let mut twist = None; let mut contact_area = None; + let pointer_id: PointerId; match pointer_info.pointerType { winuser::PT_TOUCH => { + pointer_id = PointerId::TouchId(TouchId(pointer_info.pointerId).into()); let mut touch_info = mem::MaybeUninit::uninit(); if let Some(GetPointerTouchInfo) = *GET_POINTER_TOUCH_INFO { let get_touch_info_result = GetPointerTouchInfo( @@ -1490,6 +1484,7 @@ unsafe extern "system" fn public_window_callback( } } winuser::PT_PEN => { + pointer_id = PointerId::PenId(PenId(pointer_info.pointerId).into()); let mut pen_info = mem::MaybeUninit::uninit(); if let Some(GetPointerPenInfo) = *GET_POINTER_PEN_INFO { let get_pen_info_result = GetPointerPenInfo( @@ -1514,7 +1509,14 @@ unsafe extern "system" fn public_window_callback( } } } - _ => (), + _ => return 0, + } + + if pointer_info.pointerFlags & winuser::POINTER_FLAG_NEW != 0 { + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerCreated(pointer_id), + )); } if let Some(force) = force { From 61f293403be8a442913a77563796e5a614193a60 Mon Sep 17 00:00:00 2001 From: Osspial Date: Mon, 25 May 2020 16:38:55 -0400 Subject: [PATCH 24/29] Implement new pen API on Windows --- examples/window.rs | 15 +- src/event.rs | 46 +- src/platform_impl/windows/event.rs | 284 ++++++++++- src/platform_impl/windows/event_loop.rs | 554 ++++++++++------------ src/platform_impl/windows/util.rs | 23 +- src/platform_impl/windows/window_state.rs | 13 +- 6 files changed, 605 insertions(+), 330 deletions(-) diff --git a/examples/window.rs b/examples/window.rs index c0abf376e0..39ec7c8756 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -16,7 +16,7 @@ fn main() { event_loop.run(move |event, _, control_flow| { *control_flow = ControlFlow::Wait; - println!("{:?}", event); + // println!("{:?}", event); match event { Event::WindowEvent(window_id, WindowEvent::CloseRequested) @@ -24,6 +24,19 @@ fn main() { { *control_flow = ControlFlow::Exit } + Event::WindowEvent(_, e) => match e { + WindowEvent::PointerCreated(..) | + // WindowEvent::PointerForce(..) | + WindowEvent::PointerTilt(..) | + WindowEvent::PointerTwist(..) | + // WindowEvent::PointerContactArea(..) | + WindowEvent::PointerMoved(..) | + WindowEvent::PointerButton(..) | + WindowEvent::PointerEntered(..) | + WindowEvent::PointerLeft(..) | + WindowEvent::PointerDestroyed(..) => println!("{:?}", e), + _ => () + }, Event::MainEventsCleared => window.request_redraw(), _ => (), } diff --git a/src/event.rs b/src/event.rs index d55177f926..fd4a8a3717 100644 --- a/src/event.rs +++ b/src/event.rs @@ -172,22 +172,22 @@ pub enum WindowEvent<'a> { ModifiersChanged(ModifiersState), PointerCreated(PointerId), + PointerEntered(PointerId), PointerForce(PointerId, Force), PointerTilt(PointerId, PointerTiltEvent), PointerTwist(PointerId, f64), PointerContactArea(PointerId, PhysicalSize), PointerMoved(PointerId, PhysicalPosition), + // TODO: IMPLEMENT. IS THIS REASONABLE TO IMPLEMENT ON NON-WINDOWS PLATFORMS? + // PointerHovered(PointerId), PointerButton(PointerId, PointerButtonEvent), - PointerEntered(PointerId), + PointerScrollStarted(PointerId), + PointerScrollLines(PointerId, UnitlessDelta), + PointerScrollPixels(PointerId, PhysicalDelta), + PointerScrollEnded(PointerId), PointerLeft(PointerId), PointerDestroyed(PointerId), - // TODO: SHOULD SCROLL EVENTS BE ASSOCIATED WITH A POINTER? - ScrollStarted, - ScrollLines(UnitlessDelta), - ScrollPixels(PhysicalDelta), - ScrollEnded, - /// The system window theme has changed. /// /// Applications might wish to react to this to change the theme of the content of the window @@ -309,10 +309,10 @@ impl Clone for WindowEvent<'static> { PointerEntered(id) => PointerEntered(id), PointerLeft(id) => PointerLeft(id), PointerDestroyed(id) => PointerDestroyed(id), - ScrollStarted => ScrollStarted, - ScrollLines(delta) => ScrollLines(delta), - ScrollPixels(delta) => ScrollPixels(delta), - ScrollEnded => ScrollEnded, + PointerScrollStarted(id) => PointerScrollStarted(id), + PointerScrollLines(id, delta) => PointerScrollLines(id, delta), + PointerScrollPixels(id, delta) => PointerScrollPixels(id, delta), + PointerScrollEnded(id) => PointerScrollEnded(id), ThemeChanged(theme) => ThemeChanged(theme), ScaleFactorChanged(..) => { unreachable!("Static event can't be about scale factor changing") @@ -347,10 +347,10 @@ impl<'a> WindowEvent<'a> { PointerEntered(id) => Ok(PointerEntered(id)), PointerLeft(id) => Ok(PointerLeft(id)), PointerDestroyed(id) => Ok(PointerDestroyed(id)), - ScrollStarted => Ok(ScrollStarted), - ScrollLines(delta) => Ok(ScrollLines(delta)), - ScrollPixels(delta) => Ok(ScrollPixels(delta)), - ScrollEnded => Ok(ScrollEnded), + PointerScrollStarted(id) => Ok(PointerScrollStarted(id)), + PointerScrollLines(id, delta) => Ok(PointerScrollLines(id, delta)), + PointerScrollPixels(id, delta) => Ok(PointerScrollPixels(id, delta)), + PointerScrollEnded(id) => Ok(PointerScrollEnded(id)), ThemeChanged(theme) => Ok(ThemeChanged(theme)), ScaleFactorChanged(..) => Err(self), } @@ -403,7 +403,7 @@ pub struct RawKeyEvent { pub struct PointerButtonEvent { pub(crate) button: PointerButton, pub(crate) is_down: bool, - pub(crate) click_count: u32, + pub(crate) multi_click_count: u32, } #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] @@ -523,10 +523,8 @@ impl PointerButtonEvent { } /// The number of clicks the user has made in the same spot within the system's double-click /// interval. `1` is emitted on the first click, `2` is emitted on the second click, etc. - /// - /// Is always `0` if `is_down` is `false`. - pub fn click_count(&self) -> u32 { - self.click_count + pub fn multi_click_count(&self) -> u32 { + self.multi_click_count } } @@ -543,8 +541,8 @@ impl PointerButtonEvent { self.is_down = is_down; self } - pub fn set_click_count(&mut self, click_count: u32) -> &mut Self { - self.click_count = click_count; + pub fn set_multi_click_count(&mut self, multi_click_count: u32) -> &mut Self { + self.multi_click_count = multi_click_count; self } } @@ -580,7 +578,7 @@ impl RawPointerButtonEvent { #[repr(transparent)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(transparent))] -pub struct PointerButton(PointerButtonInner); +pub struct PointerButton(pub(crate) PointerButtonInner); /// We use an internal enum rather than exposing the variants directly so that the `BUTTON_n` /// constants are formatted and exposed in a similar style to the `{MOUSE|TOUCH|PEN}_n` constants. @@ -590,7 +588,7 @@ pub struct PointerButton(PointerButtonInner); #[cfg_attr(feature = "serde", serde(try_from = "pointer_button_serde::PointerButtonSerialize"))] #[cfg_attr(feature = "serde", serde(into = "pointer_button_serde::PointerButtonSerialize"))] #[allow(non_camel_case_types)] -enum PointerButtonInner { +pub(crate) enum PointerButtonInner { BUTTON_1, BUTTON_2, BUTTON_3, diff --git a/src/platform_impl/windows/event.rs b/src/platform_impl/windows/event.rs index 2d54446bd2..f53f85f1a6 100644 --- a/src/platform_impl/windows/event.rs +++ b/src/platform_impl/windows/event.rs @@ -5,11 +5,18 @@ use std::{ sync::atomic::{AtomicBool, AtomicPtr, Ordering}, }; -use crate::event::{LogicalKey, ModifiersState}; +use crate::{ + dpi::{PhysicalSize, PhysicalPosition}, + event::{LogicalKey, ModifiersState, Force, PointerTiltEvent, PointerButton, WindowEvent, PointerId, PointerButtonEvent}, +}; +use std::collections::hash_map::{HashMap, Entry}; use winapi::{ - shared::minwindef::{HKL, HKL__, LPARAM, UINT, WPARAM}, - um::winuser, + shared::{ + windef::HWND, + minwindef::{HKL, HKL__, LPARAM, UINT, WPARAM, DWORD}, + }, + um::{winuser, winreg}, }; fn key_pressed(vkey: c_int) -> bool { @@ -412,3 +419,274 @@ fn map_text_keys(win_virtual_key: i32) -> Option { _ => None, } } + +bitflags!{ + pub struct ButtonsDown: u8 { + const BUTTON_1 = 1 << 1; + const BUTTON_2 = 1 << 2; + const BUTTON_3 = 1 << 3; + const BUTTON_4 = 1 << 4; + const BUTTON_5 = 1 << 5; + const BUTTON_6 = 1 << 6; + } +} + +impl PointerButton { + pub(crate) fn into_flags(&self) -> ButtonsDown { + use crate::event::PointerButtonInner::*; + match self.0 { + BUTTON_1 => ButtonsDown::BUTTON_1, + BUTTON_2 => ButtonsDown::BUTTON_2, + BUTTON_3 => ButtonsDown::BUTTON_3, + BUTTON_4 => ButtonsDown::BUTTON_4, + BUTTON_5 => ButtonsDown::BUTTON_5, + BUTTON_6 => ButtonsDown::BUTTON_6, + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct PointerState { + pub in_window: bool, + pub force: Force, + pub tilt: PointerTiltEvent, + pub twist: f64, + pub contact_area: PhysicalSize, + pub position: PhysicalPosition, + pub buttons_down: ButtonsDown, +} + +#[derive(Default, Debug, Clone, Copy)] +struct FullPointerState { + state: PointerState, + last_button_down: Option, +} + +#[derive(Debug, Clone, Copy)] +struct LastButtonDown { + button: PointerButton, + time: DWORD, + position: PhysicalPosition, + multi_click_count: u32, +} + +impl Default for PointerState { + fn default() -> PointerState { + PointerState { + in_window: false, + force: Force::Normalized(0.0), + tilt: PointerTiltEvent::new_tilt_angle(0.0, 0.0), + twist: 0.0, + contact_area: PhysicalSize::new(1.0, 1.0), + position: PhysicalPosition::new(f64::NEG_INFINITY, f64::NEG_INFINITY), + buttons_down: ButtonsDown::empty(), + } + } +} + +#[derive(Clone)] +pub struct PointerTracker { + pointer_info: HashMap, + call_legacy_capture_fns: bool, +} + +impl PointerTracker { + pub fn new() -> PointerTracker { + PointerTracker { + pointer_info: HashMap::new(), + call_legacy_capture_fns: true, + } + } + + pub fn update_pointer_state( + &mut self, + pointer_id: PointerId, + message_time: i32, + window: HWND, + new_state: impl FnOnce(PointerState) -> PointerState, + mut send_event: impl FnMut(WindowEvent<'static>) + ) { + let entry = self.pointer_info.entry(pointer_id); + if let Entry::Vacant(_) = entry { + send_event(WindowEvent::PointerCreated(pointer_id)); + } + let message_time = message_time as DWORD; + + let full_pointer_state = entry.or_default(); + let new_state = new_state(full_pointer_state.state); + + let &mut FullPointerState { + state: PointerState { + ref mut in_window, + ref mut force, + ref mut tilt, + ref mut twist, + ref mut contact_area, + ref mut position, + ref mut buttons_down, + }, + ref mut last_button_down, + } = full_pointer_state; + + if *in_window != new_state.in_window && new_state.in_window { + *in_window = new_state.in_window; + send_event(WindowEvent::PointerEntered(pointer_id)); + + if self.call_legacy_capture_fns { + unsafe { + // Calling TrackMouseEvent in order to receive mouse leave events. + winuser::TrackMouseEvent(&mut winuser::TRACKMOUSEEVENT { + cbSize: std::mem::size_of::() as DWORD, + dwFlags: winuser::TME_LEAVE, + hwndTrack: window, + dwHoverTime: winuser::HOVER_DEFAULT, + }); + } + } + } + if *force != new_state.force { + *force = new_state.force; + send_event(WindowEvent::PointerForce(pointer_id, *force)) + } + if *tilt != new_state.tilt { + *tilt = new_state.tilt; + send_event(WindowEvent::PointerTilt(pointer_id, *tilt)) + } + if *twist != new_state.twist { + *twist = new_state.twist; + send_event(WindowEvent::PointerTwist(pointer_id, *twist)) + } + if *contact_area != new_state.contact_area { + *contact_area = new_state.contact_area; + send_event(WindowEvent::PointerContactArea(pointer_id, *contact_area)) + } + if *position != new_state.position { + *position = new_state.position; + send_event(WindowEvent::PointerMoved(pointer_id, *position)) + } + if *buttons_down != new_state.buttons_down { + let diff = *buttons_down ^ new_state.buttons_down; + if diff != ButtonsDown::empty() { + *buttons_down = new_state.buttons_down; + + if self.call_legacy_capture_fns && pointer_id == PointerId::MOUSE_ID { + unsafe { + match *buttons_down == ButtonsDown::empty() { + // Capture mouse input, allowing `window` to receive mouse events when + // the cursor is outside of the window. + false => {winuser::SetCapture(window);} + // Release mouse input, stopping windows on this thread from receiving + // mouse input when the cursor is outside the window. + true => {winuser::ReleaseCapture();} + } + } + } + + let buttons = [ + (PointerButton::BUTTON_1, ButtonsDown::BUTTON_1), + (PointerButton::BUTTON_2, ButtonsDown::BUTTON_2), + (PointerButton::BUTTON_3, ButtonsDown::BUTTON_3), + (PointerButton::BUTTON_4, ButtonsDown::BUTTON_4), + (PointerButton::BUTTON_5, ButtonsDown::BUTTON_5), + (PointerButton::BUTTON_6, ButtonsDown::BUTTON_6), + ]; + + let (double_click_time, cx_double_click, cy_double_click): (DWORD, f64, f64); + match pointer_id { + PointerId::TouchId(_) | + PointerId::PenId(_) => unsafe { + let sub_key = "Software\\Microsoft\\Wisp\\Pen\\SysEventParameters\0"; + let dist_value = "DblDist\0"; + let time_value = "DblTime\0"; + + let mut time: DWORD = 0; + let result = winreg::RegGetValueA( + winreg::HKEY_CURRENT_USER, + sub_key.as_ptr() as *const _, + time_value.as_ptr() as *const _, + winreg::RRF_RT_REG_DWORD, + ptr::null_mut(), + &mut time as *mut DWORD as *mut _, + &mut (std::mem::size_of::() as DWORD), + ); + double_click_time = match result { + 0 => time, + _ => winuser::GetDoubleClickTime(), + }; + + let mut dist: DWORD = 0; + let result = winreg::RegGetValueA( + winreg::HKEY_CURRENT_USER, + sub_key.as_ptr() as *const _, + dist_value.as_ptr() as *const _, + winreg::RRF_RT_REG_DWORD, + ptr::null_mut(), + &mut dist as *mut DWORD as *mut _, + &mut (std::mem::size_of::() as DWORD), + ); + cx_double_click = match result { + 0 => dist as f64, + _ => winuser::GetSystemMetrics(winuser::SM_CXDOUBLECLK) as f64, + }; + cy_double_click = cx_double_click; + }, + PointerId::MouseId(_) => unsafe { + double_click_time = winuser::GetDoubleClickTime(); + cx_double_click = winuser::GetSystemMetrics(winuser::SM_CXDOUBLECLK) as f64; + cy_double_click = winuser::GetSystemMetrics(winuser::SM_CYDOUBLECLK) as f64; + } + } + let scale_factor = unsafe{ winuser::GetDpiForWindow(window) as f64 / 96.0 }; + let cx_double_click = cx_double_click * scale_factor; + let cy_double_click = cy_double_click * scale_factor; + + let mut last_click_set = false; + for (pointer_button, button_flag) in buttons.iter().cloned() { + if diff.contains(button_flag) { + let multi_click_count = match last_button_down { + Some(lbd) if + lbd.button == pointer_button && + (message_time.saturating_sub(lbd.time)) < double_click_time && + (lbd.position.x - position.x).abs() < cx_double_click && + (lbd.position.y - position.y).abs() < cy_double_click + => { + lbd.multi_click_count + }, + _ => 0, + }; + let is_down = buttons_down.contains(button_flag); + + send_event(WindowEvent::PointerButton( + pointer_id, + PointerButtonEvent { + button: pointer_button, + is_down, + multi_click_count, + }, + )); + + if !last_click_set && !is_down { + last_click_set = true; + *last_button_down = Some(LastButtonDown { + button: pointer_button, + time: message_time, + position: *position, + multi_click_count: multi_click_count + 1, + }); + } + } + } + } + } + if *in_window != new_state.in_window && !new_state.in_window { + *in_window = new_state.in_window; + send_event(WindowEvent::PointerLeft(pointer_id)); + } + } + + pub fn destroy_pointer(&mut self, pointer_id: PointerId, mut send_event: impl FnMut(WindowEvent<'static>)) { + if self.pointer_info.remove(&pointer_id).is_some() { + send_event(WindowEvent::PointerDestroyed(pointer_id)); + } + } +} diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 4de102e473..5260a441c1 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -41,9 +41,9 @@ use crate::{ dark_mode::try_dark_mode, dpi::{become_dpi_aware, dpi_to_scale_factor, enable_non_client_dpi_scaling}, drop_handler::FileDropHandler, - event::{self, handle_extended_keys, process_key_params, vkey_to_winit_vkey}, + event::{self, handle_extended_keys, process_key_params, vkey_to_winit_vkey, PointerState, ButtonsDown}, monitor, raw_input, util, - window_state::{CursorFlags, WindowFlags, WindowState}, + window_state::{WindowFlags, WindowState}, KeyboardDeviceId, PointerDeviceId, TouchId, WindowId, PenId, }, window::{Fullscreen, Theme}, @@ -70,6 +70,9 @@ type GetPointerTouchInfo = type GetPointerPenInfo = unsafe extern "system" fn(pointId: UINT, penInfo: *mut winuser::POINTER_PEN_INFO) -> BOOL; +type GetPointerInfo = + unsafe extern "system" fn(pointId: UINT, penInfo: *mut winuser::POINTER_INFO) -> BOOL; + lazy_static! { static ref GET_POINTER_FRAME_INFO_HISTORY: Option = get_function!("user32.dll", GetPointerFrameInfoHistory); @@ -81,6 +84,8 @@ lazy_static! { get_function!("user32.dll", GetPointerTouchInfo); static ref GET_POINTER_PEN_INFO: Option = get_function!("user32.dll", GetPointerPenInfo); + static ref GET_POINTER_INFO: Option = + get_function!("user32.dll", GetPointerInfo); } pub(crate) struct SubclassInput { @@ -93,6 +98,59 @@ impl SubclassInput { unsafe fn send_event(&self, event: Event<'_, T>) { self.event_loop_runner.send_event(event); } + + unsafe fn lock_and_update_pointer_state( + &self, + pointer_id: PointerId, + message_time: i32, + window: HWND, + new_state: impl FnOnce(PointerState) -> PointerState, + ) { + let mut event_buffer = Vec::new(); + + { + let mut w = self.window_state.lock(); + w.mouse.pointer_tracker.update_pointer_state( + pointer_id, + message_time, + window, + new_state, + |event| event_buffer.push(event), + ); + w.mouse.cursor_flags().refresh_os_cursor(window).ok(); + } + + for event in event_buffer { + self.send_event(Event::WindowEvent( + WindowId(window).into(), + event, + )) + } + } + + unsafe fn lock_and_destroy_pointer( + &self, + pointer_id: PointerId, + window: HWND, + ) { + let mut event_opt = None; + + { + let mut w = self.window_state.lock(); + w.mouse.pointer_tracker.destroy_pointer( + pointer_id, + |event| assert!(event_opt.replace(event).is_none()), + ); + w.mouse.cursor_flags().refresh_os_cursor(window).ok(); + } + + for event in event_opt { + self.send_event(Event::WindowEvent( + WindowId(window).into(), + event, + )) + } + } } struct ThreadMsgTargetSubclassInput { @@ -607,22 +665,6 @@ fn subclass_event_target_window( } } -/// Capture mouse input, allowing `window` to receive mouse events when the cursor is outside of -/// the window. -unsafe fn capture_mouse(window: HWND, window_state: &mut WindowState) { - window_state.mouse.buttons_down += 1; - winuser::SetCapture(window); -} - -/// Release mouse input, stopping windows on this thread from receiving mouse input when the cursor -/// is outside the window. -unsafe fn release_mouse(window_state: &mut WindowState) { - window_state.mouse.buttons_down = window_state.mouse.buttons_down.saturating_sub(1); - if window_state.mouse.buttons_down == 0 { - winuser::ReleaseCapture(); - } -} - const WINDOW_SUBCLASS_ID: UINT_PTR = 0; const THREAD_EVENT_TARGET_SUBCLASS_ID: UINT_PTR = 1; pub(crate) fn subclass_window(window: HWND, subclass_input: SubclassInput) { @@ -966,67 +1008,35 @@ unsafe extern "system" fn public_window_callback( } winuser::WM_MOUSEMOVE => { - let mouse_was_outside_window = { - let mut w = subclass_input.window_state.lock(); - - let was_outside_window = !w.mouse.cursor_flags().contains(CursorFlags::IN_WINDOW); - w.mouse - .set_cursor_flags(window, |f| f.set(CursorFlags::IN_WINDOW, true)) - .ok(); - was_outside_window - }; - - if mouse_was_outside_window { - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerEntered(PointerId::MOUSE_ID), - )); - - // Calling TrackMouseEvent in order to receive mouse leave events. - winuser::TrackMouseEvent(&mut winuser::TRACKMOUSEEVENT { - cbSize: mem::size_of::() as DWORD, - dwFlags: winuser::TME_LEAVE, - hwndTrack: window, - dwHoverTime: winuser::HOVER_DEFAULT, - }); - } - let x = windowsx::GET_X_LPARAM(lparam) as f64; let y = windowsx::GET_Y_LPARAM(lparam) as f64; let position = PhysicalPosition::new(x, y); - let cursor_moved; - { - // handle spurious WM_MOUSEMOVE messages - // see https://devblogs.microsoft.com/oldnewthing/20031001-00/?p=42343 - // and http://debugandconquer.blogspot.com/2015/08/the-cause-of-spurious-mouse-move.html - let mut w = subclass_input.window_state.lock(); - cursor_moved = w.mouse.last_position != Some(position); - w.mouse.last_position = Some(position); - } - if cursor_moved { - update_modifiers(window, subclass_input); + update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerMoved(PointerId::MOUSE_ID, position), - )); - } + subclass_input.lock_and_update_pointer_state( + PointerId::MOUSE_ID, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + position, + in_window: true, + ..pointer_state + }, + ); 0 } winuser::WM_MOUSELEAVE => { - { - let mut w = subclass_input.window_state.lock(); - w.mouse - .set_cursor_flags(window, |f| f.set(CursorFlags::IN_WINDOW, false)) - .ok(); - } - - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerLeft(PointerId::MOUSE_ID), - )); + subclass_input.lock_and_update_pointer_state( + PointerId::MOUSE_ID, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + in_window: false, + ..pointer_state + }, + ); 0 } @@ -1040,7 +1050,15 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::ScrollLines(UnitlessDelta::new(0.0, value)), + WindowEvent::PointerScrollStarted(PointerId::MOUSE_ID), + )); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerScrollLines(PointerId::MOUSE_ID, UnitlessDelta::new(0.0, value)), + )); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerScrollEnded(PointerId::MOUSE_ID), )); 0 @@ -1055,7 +1073,15 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::ScrollLines(UnitlessDelta::new(value, 0.0)), + WindowEvent::PointerScrollStarted(PointerId::MOUSE_ID), + )); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerScrollLines(PointerId::MOUSE_ID, UnitlessDelta::new(value, 0.0)), + )); + subclass_input.send_event(Event::WindowEvent( + WindowId(window).into(), + WindowEvent::PointerScrollEnded(PointerId::MOUSE_ID), )); 0 @@ -1112,124 +1138,96 @@ unsafe extern "system" fn public_window_callback( } winuser::WM_LBUTTONDOWN => { - capture_mouse(window, &mut *subclass_input.window_state.lock()); update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerButton( - PointerId::MOUSE_ID, - PointerButtonEvent { - button: PointerButton::MOUSE_LEFT, - is_down: true, - click_count: { - println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); - 0 - }, - }, - ), - )); + subclass_input.lock_and_update_pointer_state( + PointerId::MOUSE_ID, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + buttons_down: pointer_state.buttons_down | PointerButton::MOUSE_LEFT.into_flags(), + ..pointer_state + }, + ); 0 } winuser::WM_LBUTTONUP => { - release_mouse(&mut *subclass_input.window_state.lock()); update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerButton( - PointerId::MOUSE_ID, - PointerButtonEvent { - button: PointerButton::MOUSE_LEFT, - is_down: false, - click_count: 0, - }, - ), - )); + subclass_input.lock_and_update_pointer_state( + PointerId::MOUSE_ID, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + buttons_down: pointer_state.buttons_down & !PointerButton::MOUSE_LEFT.into_flags(), + ..pointer_state + }, + ); 0 } winuser::WM_RBUTTONDOWN => { - capture_mouse(window, &mut *subclass_input.window_state.lock()); update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerButton( - PointerId::MOUSE_ID, - PointerButtonEvent { - button: PointerButton::MOUSE_RIGHT, - is_down: true, - click_count: { - println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); - 0 - }, - }, - ), - )); + subclass_input.lock_and_update_pointer_state( + PointerId::MOUSE_ID, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + buttons_down: pointer_state.buttons_down | PointerButton::MOUSE_RIGHT.into_flags(), + ..pointer_state + }, + ); 0 } winuser::WM_RBUTTONUP => { - release_mouse(&mut *subclass_input.window_state.lock()); update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerButton( - PointerId::MOUSE_ID, - PointerButtonEvent { - button: PointerButton::MOUSE_RIGHT, - is_down: false, - click_count: 0, - }, - ), - )); + subclass_input.lock_and_update_pointer_state( + PointerId::MOUSE_ID, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + buttons_down: pointer_state.buttons_down & !PointerButton::MOUSE_RIGHT.into_flags(), + ..pointer_state + }, + ); 0 } winuser::WM_MBUTTONDOWN => { - capture_mouse(window, &mut *subclass_input.window_state.lock()); update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerButton( - PointerId::MOUSE_ID, - PointerButtonEvent { - button: PointerButton::MOUSE_MIDDLE, - is_down: true, - click_count: { - println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); - 0 - }, - }, - ), - )); + subclass_input.lock_and_update_pointer_state( + PointerId::MOUSE_ID, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + buttons_down: pointer_state.buttons_down | PointerButton::MOUSE_MIDDLE.into_flags(), + ..pointer_state + }, + ); 0 } winuser::WM_MBUTTONUP => { - release_mouse(&mut *subclass_input.window_state.lock()); update_modifiers(window, subclass_input); - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerButton( - PointerId::MOUSE_ID, - PointerButtonEvent { - button: PointerButton::MOUSE_MIDDLE, - is_down: false, - click_count: 0, - }, - ), - )); + subclass_input.lock_and_update_pointer_state( + PointerId::MOUSE_ID, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + buttons_down: pointer_state.buttons_down & !PointerButton::MOUSE_MIDDLE.into_flags(), + ..pointer_state + }, + ); 0 } winuser::WM_XBUTTONDOWN => { - capture_mouse(window, &mut *subclass_input.window_state.lock()); update_modifiers(window, subclass_input); let button = match winuser::GET_XBUTTON_WPARAM(wparam) { @@ -1241,25 +1239,19 @@ unsafe extern "system" fn public_window_callback( } }; - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerButton( - PointerId::MOUSE_ID, - PointerButtonEvent { - button, - is_down: true, - click_count: { - println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); - 0 - }, - }, - ), - )); + subclass_input.lock_and_update_pointer_state( + PointerId::MOUSE_ID, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + buttons_down: pointer_state.buttons_down | button.into_flags(), + ..pointer_state + }, + ); 0 } winuser::WM_XBUTTONUP => { - release_mouse(&mut *subclass_input.window_state.lock()); update_modifiers(window, subclass_input); let button = match winuser::GET_XBUTTON_WPARAM(wparam) { @@ -1271,17 +1263,15 @@ unsafe extern "system" fn public_window_callback( } }; - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerButton( - PointerId::MOUSE_ID, - PointerButtonEvent { - button, - is_down: false, - click_count: 0, - }, - ), - )); + subclass_input.lock_and_update_pointer_state( + PointerId::MOUSE_ID, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + buttons_down: pointer_state.buttons_down & !button.into_flags(), + ..pointer_state + }, + ); 0 } @@ -1319,46 +1309,38 @@ unsafe extern "system" fn public_window_callback( )); } - println!("\t\tTODO: SUPPORT TOUCHEVENTF_INRANGE"); - + let mut button_and_mask = ButtonsDown::empty(); + button_and_mask.set( + !PointerButton::TOUCH_CONTACT.into_flags(), + input.dwFlags & winuser::TOUCHEVENTF_UP != 0 + ); + let mut button_or_mask = ButtonsDown::empty(); + button_or_mask.set( + PointerButton::TOUCH_CONTACT.into_flags(), + input.dwFlags & winuser::TOUCHEVENTF_DOWN != 0 + ); + let contact_area = Some(PhysicalSize::new(input.cxContact as f64, input.cyContact as f64)) + .filter(|_| input.dwMask & winuser::TOUCHINPUTMASKF_CONTACTAREA != 0); + + subclass_input.lock_and_update_pointer_state( + pointer_id, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + in_window: true, + position, + buttons_down: pointer_state.buttons_down & button_and_mask | button_or_mask, + contact_area: contact_area.unwrap_or(pointer_state.contact_area), + ..pointer_state + } + ); subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), WindowEvent::PointerMoved(pointer_id, position), )); - if input.dwFlags & winuser::TOUCHEVENTF_DOWN != 0 { - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerButton( - pointer_id, - PointerButtonEvent { - button: PointerButton::TOUCH_CONTACT, - is_down: true, - click_count: { - println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); - 0 - }, - }, - ), - )); - } - - if input.dwFlags & winuser::TOUCHEVENTF_UP != 0 { - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerButton( - pointer_id, - PointerButtonEvent { - button: PointerButton::TOUCH_CONTACT, - is_down: false, - click_count: 0, - }, - ), - )); - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerDestroyed(pointer_id), - )); + if input.dwFlags & winuser::TOUCHEVENTF_INRANGE == 0 { + subclass_input.lock_and_destroy_pointer(pointer_id, window); } } } @@ -1366,6 +1348,36 @@ unsafe extern "system" fn public_window_callback( 0 } + // WM_POINTERENTER and WM_POINTERLEAVE send events when the pointer enters/leaves the entire + // window area, **NOT** just the client area. We process `WM_NCPOINTERUPDATE` to handle the + // case where the pointer is in the window area but not the client area. + winuser::WM_POINTERENTER | winuser::WM_POINTERLEAVE | winuser::WM_NCPOINTERUPDATE => { + if let Some(GetPointerInfo) = *GET_POINTER_INFO { + let pointer_id = LOWORD(wparam as DWORD) as u32; + let mut pointer_info: winuser::POINTER_INFO = mem::zeroed(); + if GetPointerInfo(pointer_id, &mut pointer_info) == 0 { + return 0; + } + let pointer_id = match pointer_info.pointerType { + winuser::PT_TOUCH => PointerId::TouchId(TouchId(pointer_id).into()), + winuser::PT_PEN => PointerId::PenId(PenId(pointer_id).into()), + _ => PointerId::MOUSE_ID, + }; + + subclass_input.lock_and_update_pointer_state( + pointer_id, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + in_window: util::point_in_window_client(window, pointer_info.ptPixelLocation).unwrap_or(false), + ..pointer_state + } + ); + } + + 0 + } + winuser::WM_POINTERDOWN | winuser::WM_POINTERUPDATE | winuser::WM_POINTERUP => { if let ( Some(GetPointerFrameInfoHistory), @@ -1453,12 +1465,19 @@ unsafe extern "system" fn public_window_callback( let position = PhysicalPosition::new(x, y); let pi = std::f64::consts::PI; - let deg_to_twist = |deg: u32| ((deg as f64 / 360.0) - 0.5) * pi; + let deg_to_twist = |deg: u32| (deg as f64 / 360.0) * pi; let mut force = None; let mut tilt = None; let mut twist = None; let mut contact_area = None; let pointer_id: PointerId; + + let mut buttons_down = ButtonsDown::empty(); + buttons_down.set( + PointerButton::TOUCH_CONTACT.into_flags(), + pointer_info.pointerFlags & winuser::POINTER_FLAG_INCONTACT != 0 + ); + match pointer_info.pointerType { winuser::PT_TOUCH => { pointer_id = PointerId::TouchId(TouchId(pointer_info.pointerId).into()); @@ -1497,7 +1516,6 @@ unsafe extern "system" fn public_window_callback( force = normalize_pointer_pressure(pen_info.pressure); } if pen_info.penMask & winuser::PEN_MASK_ROTATION != 0 { - // TODO: WHAT DIRECTION IS 0? twist = Some(deg_to_twist(pen_info.rotation)); } if pen_info.penMask & (winuser::PEN_MASK_TILT_X | winuser::PEN_MASK_TILT_Y) != 0 { @@ -1506,85 +1524,37 @@ unsafe extern "system" fn public_window_callback( pen_info.tiltY as f64 / 90.0 * (pi / 2.0), )); } + buttons_down.set( + PointerButton::PEN_BARREL.into_flags(), + pen_info.penFlags & winuser::PEN_FLAG_BARREL != 0 + ); + buttons_down.set( + PointerButton::PEN_ERASER.into_flags(), + pen_info.penFlags & winuser::PEN_FLAG_ERASER != 0 + ); } } } _ => return 0, } - if pointer_info.pointerFlags & winuser::POINTER_FLAG_NEW != 0 { - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerCreated(pointer_id), - )); - } - - if let Some(force) = force { - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerForce(pointer_id, force), - )); - } - if let Some(tilt) = tilt { - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerTilt(pointer_id, tilt), - )); - } - if let Some(twist) = twist { - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerTwist(pointer_id, twist), - )); - } - if let Some(contact_area) = contact_area { - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerContactArea(pointer_id, contact_area), - )); - } - - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerMoved(pointer_id, position), - )); - - if pointer_info.pointerFlags & winuser::POINTER_FLAG_DOWN != 0 { - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerButton( - pointer_id, - PointerButtonEvent { - button: PointerButton::TOUCH_CONTACT, - is_down: true, - click_count: { - println!("\t\tTODO: IMPLEMENT CLICK_COUNT"); - 0 - }, - }, - ), - )); - } - - if pointer_info.pointerFlags & winuser::POINTER_FLAG_UP != 0 { - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerButton( - pointer_id, - PointerButtonEvent { - button: PointerButton::TOUCH_CONTACT, - is_down: false, - click_count: 0, - }, - ), - )); - } + subclass_input.lock_and_update_pointer_state( + pointer_id, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + in_window: true, + force: force.unwrap_or(pointer_state.force), + tilt: tilt.unwrap_or(pointer_state.tilt), + twist: twist.unwrap_or(pointer_state.twist), + contact_area: contact_area.unwrap_or(pointer_state.contact_area), + position, + buttons_down, + } + ); if pointer_info.pointerFlags & winuser::POINTER_FLAG_INRANGE == 0 { - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerDestroyed(pointer_id), - )); + subclass_input.lock_and_destroy_pointer(pointer_id, window); } } @@ -1656,12 +1626,8 @@ unsafe extern "system" fn public_window_callback( winuser::WM_SETCURSOR => { let set_cursor_to = { - let window_state = subclass_input.window_state.lock(); - if window_state - .mouse - .cursor_flags() - .contains(CursorFlags::IN_WINDOW) - { + if util::cursor_in_window_client(window).unwrap_or(false) { + let window_state = subclass_input.window_state.lock(); Some(window_state.mouse.cursor) } else { None diff --git a/src/platform_impl/windows/util.rs b/src/platform_impl/windows/util.rs index 5faaae3e68..53a27a3be9 100644 --- a/src/platform_impl/windows/util.rs +++ b/src/platform_impl/windows/util.rs @@ -11,7 +11,7 @@ use winapi::{ ctypes::wchar_t, shared::{ minwindef::{BOOL, DWORD, UINT}, - windef::{DPI_AWARENESS_CONTEXT, HMONITOR, HWND, LPRECT, RECT}, + windef::{DPI_AWARENESS_CONTEXT, HMONITOR, HWND, LPRECT, RECT, POINT}, }, um::{ libloaderapi::{GetProcAddress, LoadLibraryA}, @@ -159,6 +159,27 @@ pub fn set_cursor_hidden(hidden: bool) { } } +pub fn get_cursor_position() -> Result { + unsafe { + let mut point: POINT = mem::zeroed(); + win_to_err(|| winuser::GetCursorPos(&mut point)).map(|_| point) + } +} + +pub fn point_in_rect(rect: RECT, point: POINT) -> bool { + unsafe { + winuser::PtInRect(&rect, point) != 0 + } +} + +pub fn point_in_window_client(window: HWND, point: POINT) -> Result { + Ok(point_in_rect(get_client_rect(window)?, point)) +} + +pub fn cursor_in_window_client(window: HWND) -> Result { + point_in_window_client(window, get_cursor_position()?) +} + pub fn get_cursor_clip() -> Result { unsafe { let mut rect: RECT = mem::zeroed(); diff --git a/src/platform_impl/windows/window_state.rs b/src/platform_impl/windows/window_state.rs index 124090813c..bc92d10f46 100644 --- a/src/platform_impl/windows/window_state.rs +++ b/src/platform_impl/windows/window_state.rs @@ -1,8 +1,8 @@ use crate::{ - dpi::{PhysicalPosition, Size}, + dpi::Size, event::ModifiersState, icon::Icon, - platform_impl::platform::{event_loop, util}, + platform_impl::platform::{event_loop, util, event::PointerTracker}, window::{CursorIcon, Fullscreen, WindowAttributes}, }; use parking_lot::MutexGuard; @@ -46,15 +46,14 @@ pub struct SavedWindow { pub struct MouseProperties { pub cursor: CursorIcon, pub buttons_down: u32, + pub pointer_tracker: PointerTracker, cursor_flags: CursorFlags, - pub last_position: Option>, } bitflags! { pub struct CursorFlags: u8 { const GRABBED = 1 << 0; const HIDDEN = 1 << 1; - const IN_WINDOW = 1 << 2; } } bitflags! { @@ -107,7 +106,7 @@ impl WindowState { cursor: CursorIcon::default(), buttons_down: 0, cursor_flags: CursorFlags::empty(), - last_position: None, + pointer_tracker: PointerTracker::new(), }, min_size: attributes.min_inner_size, @@ -332,7 +331,7 @@ impl WindowFlags { } impl CursorFlags { - fn refresh_os_cursor(self, window: HWND) -> Result<(), io::Error> { + pub fn refresh_os_cursor(self, window: HWND) -> Result<(), io::Error> { let client_rect = util::get_client_rect(window)?; if util::is_focused(window) { @@ -358,7 +357,7 @@ impl CursorFlags { } } - let cursor_in_client = self.contains(CursorFlags::IN_WINDOW); + let cursor_in_client = util::point_in_rect(client_rect, util::get_cursor_position()?); if cursor_in_client { util::set_cursor_hidden(self.contains(CursorFlags::HIDDEN)); } else { From eea84e31dd404a330e7b1d366345ddc1c1e6a276 Mon Sep 17 00:00:00 2001 From: Osspial Date: Mon, 25 May 2020 16:48:26 -0400 Subject: [PATCH 25/29] Remove redundant pointermoved from wm_touch handler --- src/platform_impl/windows/event_loop.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 5260a441c1..680367c2ca 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -1334,10 +1334,6 @@ unsafe extern "system" fn public_window_callback( ..pointer_state } ); - subclass_input.send_event(Event::WindowEvent( - WindowId(window).into(), - WindowEvent::PointerMoved(pointer_id, position), - )); if input.dwFlags & winuser::TOUCHEVENTF_INRANGE == 0 { subclass_input.lock_and_destroy_pointer(pointer_id, window); From 4db1d6e265a42473de127cc2cdcbe858531b62c2 Mon Sep 17 00:00:00 2001 From: Osspial Date: Mon, 25 May 2020 16:51:36 -0400 Subject: [PATCH 26/29] Fix Pointer(Created|Entered) events being sent after PointerDestroyed --- examples/window.rs | 4 ++-- src/platform_impl/windows/event_loop.rs | 30 +++++++++++++------------ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/examples/window.rs b/examples/window.rs index 39ec7c8756..beb4097b83 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -26,10 +26,10 @@ fn main() { } Event::WindowEvent(_, e) => match e { WindowEvent::PointerCreated(..) | - // WindowEvent::PointerForce(..) | + WindowEvent::PointerForce(..) | WindowEvent::PointerTilt(..) | WindowEvent::PointerTwist(..) | - // WindowEvent::PointerContactArea(..) | + WindowEvent::PointerContactArea(..) | WindowEvent::PointerMoved(..) | WindowEvent::PointerButton(..) | WindowEvent::PointerEntered(..) | diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 680367c2ca..17c196298c 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -1354,21 +1354,23 @@ unsafe extern "system" fn public_window_callback( if GetPointerInfo(pointer_id, &mut pointer_info) == 0 { return 0; } - let pointer_id = match pointer_info.pointerType { - winuser::PT_TOUCH => PointerId::TouchId(TouchId(pointer_id).into()), - winuser::PT_PEN => PointerId::PenId(PenId(pointer_id).into()), - _ => PointerId::MOUSE_ID, - }; + if pointer_info.pointerFlags & winuser::POINTER_FLAG_INRANGE != 0 { + let pointer_id = match pointer_info.pointerType { + winuser::PT_TOUCH => PointerId::TouchId(TouchId(pointer_id).into()), + winuser::PT_PEN => PointerId::PenId(PenId(pointer_id).into()), + _ => PointerId::MOUSE_ID, + }; - subclass_input.lock_and_update_pointer_state( - pointer_id, - winuser::GetMessageTime(), - window, - |pointer_state| PointerState { - in_window: util::point_in_window_client(window, pointer_info.ptPixelLocation).unwrap_or(false), - ..pointer_state - } - ); + subclass_input.lock_and_update_pointer_state( + pointer_id, + winuser::GetMessageTime(), + window, + |pointer_state| PointerState { + in_window: util::point_in_window_client(window, pointer_info.ptPixelLocation).unwrap_or(false), + ..pointer_state + } + ); + } } 0 From 201de6ce4bc5d9df12f06915c5f0c6be3c76993a Mon Sep 17 00:00:00 2001 From: Osspial Date: Mon, 25 May 2020 16:54:33 -0400 Subject: [PATCH 27/29] Include scroll events in example --- examples/window.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/window.rs b/examples/window.rs index beb4097b83..97a9a20f5e 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -34,6 +34,10 @@ fn main() { WindowEvent::PointerButton(..) | WindowEvent::PointerEntered(..) | WindowEvent::PointerLeft(..) | + WindowEvent::PointerScrollStarted(..) | + WindowEvent::PointerScrollLines(..) | + WindowEvent::PointerScrollPixels(..) | + WindowEvent::PointerScrollEnded(..) | WindowEvent::PointerDestroyed(..) => println!("{:?}", e), _ => () }, From 253df57d74825acd017a4a13ec433bef687b4155 Mon Sep 17 00:00:00 2001 From: Osspial Date: Mon, 25 May 2020 17:19:11 -0400 Subject: [PATCH 28/29] Remove Pointer from Scroll events --- examples/window.rs | 8 ++++---- src/event.rs | 27 +++++++++++++------------ src/platform_impl/windows/event_loop.rs | 12 +++++------ 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/examples/window.rs b/examples/window.rs index 97a9a20f5e..8d4dc4dc3c 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -34,10 +34,10 @@ fn main() { WindowEvent::PointerButton(..) | WindowEvent::PointerEntered(..) | WindowEvent::PointerLeft(..) | - WindowEvent::PointerScrollStarted(..) | - WindowEvent::PointerScrollLines(..) | - WindowEvent::PointerScrollPixels(..) | - WindowEvent::PointerScrollEnded(..) | + WindowEvent::ScrollStarted | + WindowEvent::ScrollLines(..) | + WindowEvent::ScrollPixels(..) | + WindowEvent::ScrollEnded | WindowEvent::PointerDestroyed(..) => println!("{:?}", e), _ => () }, diff --git a/src/event.rs b/src/event.rs index fd4a8a3717..f9bfa7202a 100644 --- a/src/event.rs +++ b/src/event.rs @@ -181,12 +181,13 @@ pub enum WindowEvent<'a> { // TODO: IMPLEMENT. IS THIS REASONABLE TO IMPLEMENT ON NON-WINDOWS PLATFORMS? // PointerHovered(PointerId), PointerButton(PointerId, PointerButtonEvent), - PointerScrollStarted(PointerId), - PointerScrollLines(PointerId, UnitlessDelta), - PointerScrollPixels(PointerId, PhysicalDelta), - PointerScrollEnded(PointerId), - PointerLeft(PointerId), PointerDestroyed(PointerId), + PointerLeft(PointerId), + + ScrollStarted, + ScrollLines(UnitlessDelta), + ScrollPixels(PhysicalDelta), + ScrollEnded, /// The system window theme has changed. /// @@ -309,10 +310,10 @@ impl Clone for WindowEvent<'static> { PointerEntered(id) => PointerEntered(id), PointerLeft(id) => PointerLeft(id), PointerDestroyed(id) => PointerDestroyed(id), - PointerScrollStarted(id) => PointerScrollStarted(id), - PointerScrollLines(id, delta) => PointerScrollLines(id, delta), - PointerScrollPixels(id, delta) => PointerScrollPixels(id, delta), - PointerScrollEnded(id) => PointerScrollEnded(id), + ScrollStarted => ScrollStarted, + ScrollLines(delta) => ScrollLines(delta), + ScrollPixels(delta) => ScrollPixels(delta), + ScrollEnded => ScrollEnded, ThemeChanged(theme) => ThemeChanged(theme), ScaleFactorChanged(..) => { unreachable!("Static event can't be about scale factor changing") @@ -347,10 +348,10 @@ impl<'a> WindowEvent<'a> { PointerEntered(id) => Ok(PointerEntered(id)), PointerLeft(id) => Ok(PointerLeft(id)), PointerDestroyed(id) => Ok(PointerDestroyed(id)), - PointerScrollStarted(id) => Ok(PointerScrollStarted(id)), - PointerScrollLines(id, delta) => Ok(PointerScrollLines(id, delta)), - PointerScrollPixels(id, delta) => Ok(PointerScrollPixels(id, delta)), - PointerScrollEnded(id) => Ok(PointerScrollEnded(id)), + ScrollStarted => Ok(ScrollStarted), + ScrollLines(delta) => Ok(ScrollLines(delta)), + ScrollPixels(delta) => Ok(ScrollPixels(delta)), + ScrollEnded => Ok(ScrollEnded), ThemeChanged(theme) => Ok(ThemeChanged(theme)), ScaleFactorChanged(..) => Err(self), } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 17c196298c..099c55712d 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -1050,15 +1050,15 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerScrollStarted(PointerId::MOUSE_ID), + WindowEvent::ScrollStarted, )); subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerScrollLines(PointerId::MOUSE_ID, UnitlessDelta::new(0.0, value)), + WindowEvent::ScrollLines(UnitlessDelta::new(0.0, value)), )); subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerScrollEnded(PointerId::MOUSE_ID), + WindowEvent::ScrollEnded, )); 0 @@ -1073,15 +1073,15 @@ unsafe extern "system" fn public_window_callback( subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerScrollStarted(PointerId::MOUSE_ID), + WindowEvent::ScrollStarted, )); subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerScrollLines(PointerId::MOUSE_ID, UnitlessDelta::new(value, 0.0)), + WindowEvent::ScrollLines(UnitlessDelta::new(value, 0.0)), )); subclass_input.send_event(Event::WindowEvent( WindowId(window).into(), - WindowEvent::PointerScrollEnded(PointerId::MOUSE_ID), + WindowEvent::ScrollEnded, )); 0 From 23ce4445c2b01a0d43a3174d3041491105ebaef4 Mon Sep 17 00:00:00 2001 From: Osspial Date: Mon, 25 May 2020 17:46:58 -0400 Subject: [PATCH 29/29] Use WM_POINTER for mouse events --- examples/window.rs | 4 +- src/platform_impl/windows/event.rs | 17 +++++++- src/platform_impl/windows/event_loop.rs | 52 ++++++++++++++++++++++--- 3 files changed, 64 insertions(+), 9 deletions(-) diff --git a/examples/window.rs b/examples/window.rs index 8d4dc4dc3c..c8cf4a8859 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -41,7 +41,9 @@ fn main() { WindowEvent::PointerDestroyed(..) => println!("{:?}", e), _ => () }, - Event::MainEventsCleared => window.request_redraw(), + Event::MainEventsCleared => { + window.request_redraw() + }, _ => (), } }); diff --git a/src/platform_impl/windows/event.rs b/src/platform_impl/windows/event.rs index f53f85f1a6..b4402269be 100644 --- a/src/platform_impl/windows/event.rs +++ b/src/platform_impl/windows/event.rs @@ -1,3 +1,5 @@ +#![allow(non_snake_case)] + use std::{ char, os::raw::c_int, @@ -14,7 +16,7 @@ use std::collections::hash_map::{HashMap, Entry}; use winapi::{ shared::{ windef::HWND, - minwindef::{HKL, HKL__, LPARAM, UINT, WPARAM, DWORD}, + minwindef::{HKL, HKL__, LPARAM, UINT, WPARAM, DWORD, BOOL}, }, um::{winuser, winreg}, }; @@ -484,6 +486,14 @@ impl Default for PointerState { } } +type EnableMouseInPointer = + unsafe extern "system" fn(fEnable: BOOL) -> BOOL; + +lazy_static! { + static ref ENABLE_MOUSE_IN_POINTER: Option = + get_function!("user32.dll", EnableMouseInPointer); +} + #[derive(Clone)] pub struct PointerTracker { pointer_info: HashMap, @@ -494,7 +504,10 @@ impl PointerTracker { pub fn new() -> PointerTracker { PointerTracker { pointer_info: HashMap::new(), - call_legacy_capture_fns: true, + call_legacy_capture_fns: match *ENABLE_MOUSE_IN_POINTER { + Some(EnableMouseInPointer) => unsafe{ EnableMouseInPointer(1) == 0 }, + None => true, + }, } } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 099c55712d..3702d35271 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -32,7 +32,7 @@ use winapi::{ use crate::{ dpi::{PhysicalDelta, PhysicalPosition, PhysicalSize, UnitlessDelta}, event::{ - Event, Force, KeyEvent, LogicalKey, ModifiersState, PointerButton, PointerButtonEvent, + Event, Force, KeyEvent, LogicalKey, ModifiersState, PointerButton, PointerId, RawKeyEvent, RawKeyboardEvent, RawPointerButtonEvent, RawPointerEvent, WindowEvent, PointerTiltEvent, }, @@ -1460,7 +1460,7 @@ unsafe extern "system" fn public_window_callback( let x = position.x as f64 + x.fract(); let y = position.y as f64 + y.fract(); - let position = PhysicalPosition::new(x, y); + let mut position = PhysicalPosition::new(x, y); let pi = std::f64::consts::PI; let deg_to_twist = |deg: u32| (deg as f64 / 360.0) * pi; @@ -1471,14 +1471,16 @@ unsafe extern "system" fn public_window_callback( let pointer_id: PointerId; let mut buttons_down = ButtonsDown::empty(); - buttons_down.set( - PointerButton::TOUCH_CONTACT.into_flags(), - pointer_info.pointerFlags & winuser::POINTER_FLAG_INCONTACT != 0 - ); match pointer_info.pointerType { winuser::PT_TOUCH => { pointer_id = PointerId::TouchId(TouchId(pointer_info.pointerId).into()); + + buttons_down.set( + PointerButton::TOUCH_CONTACT.into_flags(), + pointer_info.pointerFlags & winuser::POINTER_FLAG_INCONTACT != 0 + ); + let mut touch_info = mem::MaybeUninit::uninit(); if let Some(GetPointerTouchInfo) = *GET_POINTER_TOUCH_INFO { let get_touch_info_result = GetPointerTouchInfo( @@ -1502,6 +1504,12 @@ unsafe extern "system" fn public_window_callback( } winuser::PT_PEN => { pointer_id = PointerId::PenId(PenId(pointer_info.pointerId).into()); + + buttons_down.set( + PointerButton::PEN_CONTACT.into_flags(), + pointer_info.pointerFlags & winuser::POINTER_FLAG_INCONTACT != 0 + ); + let mut pen_info = mem::MaybeUninit::uninit(); if let Some(GetPointerPenInfo) = *GET_POINTER_PEN_INFO { let get_pen_info_result = GetPointerPenInfo( @@ -1533,6 +1541,38 @@ unsafe extern "system" fn public_window_callback( } } } + winuser::PT_MOUSE | + winuser::PT_TOUCHPAD => { + pointer_id = PointerId::MOUSE_ID; + + // There can be some rounding errors when doing the mouse hiMetric math, + // and it doesn't make a whole lot of sense for a traditional mouse + // pointer to be on a non-integer point, so round off any fractional + // values that might've cropped up. + position.x = position.x.round(); + position.y = position.y.round(); + + buttons_down.set( + PointerButton::MOUSE_LEFT.into_flags(), + pointer_info.pointerFlags & winuser::POINTER_FLAG_FIRSTBUTTON != 0, + ); + buttons_down.set( + PointerButton::MOUSE_RIGHT.into_flags(), + pointer_info.pointerFlags & winuser::POINTER_FLAG_SECONDBUTTON != 0, + ); + buttons_down.set( + PointerButton::MOUSE_MIDDLE.into_flags(), + pointer_info.pointerFlags & winuser::POINTER_FLAG_THIRDBUTTON != 0, + ); + buttons_down.set( + PointerButton::MOUSE_X1.into_flags(), + pointer_info.pointerFlags & winuser::POINTER_FLAG_FOURTHBUTTON != 0, + ); + buttons_down.set( + PointerButton::MOUSE_X2.into_flags(), + pointer_info.pointerFlags & winuser::POINTER_FLAG_FIFTHBUTTON != 0, + ); + } _ => return 0, }