api: overhaul pointer API
- Rename `CursorMoved` to `PointerMoved`. - Rename `CursorEntered` to `PointerEntered`. - Rename `CursorLeft` to `PointerLeft`. - Rename `MouseInput` to `PointerButton`. - Add `position` to every `PointerEvent`. - Remove `Touch`, which is folded into the `Pointer*` events. - New `PointerType` added to `PointerEntered` and `PointerLeft`, signifying which pointer type is the source of this event. - New `PointerSource` added to `PointerMoved`, similar to `PointerType` but holding additional data. - New `ButtonSource` added to `PointerButton`, similar to `PointerType` but holding pointer type specific buttons. Use `ButtonSource::mouse_button()` to easily normalize any pointer button type to a generic mouse button. - In the same spirit rename `DeviceEvent::MouseMotion` to `PointerMotion`. - Remove `Force::Calibrated::altitude_angle`. Fixes #3833. Fixes #883. Fixes #336. Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
This commit is contained in:
parent
32cd1ad9a7
commit
eccd9e415d
25 changed files with 1236 additions and 869 deletions
|
|
@ -44,7 +44,7 @@ fn main() -> Result<(), impl std::error::Error> {
|
|||
self.windows.clear();
|
||||
event_loop.exit();
|
||||
},
|
||||
WindowEvent::CursorEntered { device_id: _ } => {
|
||||
WindowEvent::PointerEntered { device_id: _, .. } => {
|
||||
// On x11, println when the cursor entered in a window even if the child window
|
||||
// is created by some key inputs.
|
||||
// the child windows are always placed at (0, 0) with size (200, 200) in the
|
||||
|
|
|
|||
|
|
@ -446,20 +446,23 @@ impl ApplicationHandler for Application {
|
|||
}
|
||||
}
|
||||
},
|
||||
WindowEvent::MouseInput { button, state, .. } => {
|
||||
WindowEvent::PointerButton { button, state, .. } => {
|
||||
info!("Pointer button {button:?} {state:?}");
|
||||
let mods = window.modifiers;
|
||||
if let Some(action) =
|
||||
state.is_pressed().then(|| Self::process_mouse_binding(button, &mods)).flatten()
|
||||
if let Some(action) = state
|
||||
.is_pressed()
|
||||
.then(|| Self::process_mouse_binding(button.mouse_button(), &mods))
|
||||
.flatten()
|
||||
{
|
||||
self.handle_action_with_window(event_loop, window_id, action);
|
||||
}
|
||||
},
|
||||
WindowEvent::CursorLeft { .. } => {
|
||||
info!("Cursor left Window={window_id:?}");
|
||||
WindowEvent::PointerLeft { .. } => {
|
||||
info!("Pointer left Window={window_id:?}");
|
||||
window.cursor_left();
|
||||
},
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
info!("Moved cursor to {position:?}");
|
||||
WindowEvent::PointerMoved { position, .. } => {
|
||||
info!("Moved pointer to {position:?}");
|
||||
window.cursor_moved(position);
|
||||
},
|
||||
WindowEvent::ActivationTokenDone { token: _token, .. } => {
|
||||
|
|
@ -510,11 +513,10 @@ impl ApplicationHandler for Application {
|
|||
WindowEvent::TouchpadPressure { .. }
|
||||
| WindowEvent::HoveredFileCancelled
|
||||
| WindowEvent::KeyboardInput { .. }
|
||||
| WindowEvent::CursorEntered { .. }
|
||||
| WindowEvent::PointerEntered { .. }
|
||||
| WindowEvent::DroppedFile(_)
|
||||
| WindowEvent::HoveredFile(_)
|
||||
| WindowEvent::Destroyed
|
||||
| WindowEvent::Touch(_)
|
||||
| WindowEvent::Moved(_) => (),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,9 +56,6 @@ changelog entry.
|
|||
|
||||
Keep in mind that handles do not auto-upgrade after permissions are granted and have to be
|
||||
re-created to make full use of this feature.
|
||||
- Add `Touch::finger_id` with a new type `FingerId`.
|
||||
- On Web and Windows, add `FingerIdExt*::is_primary()`, exposing a way to determine
|
||||
the primary finger in a multi-touch interaction.
|
||||
- Implement `Clone`, `Copy`, `Debug`, `Deserialize`, `Eq`, `Hash`, `Ord`, `PartialEq`, `PartialOrd`
|
||||
and `Serialize` on many types.
|
||||
- Add `MonitorHandle::current_video_mode()`.
|
||||
|
|
@ -66,6 +63,8 @@ changelog entry.
|
|||
- On macOS, add `WindowExtMacOS::set_borderless_game` and `WindowAttributesExtMacOS::with_borderless_game`
|
||||
to fully disable the menu bar and dock in Borderless Fullscreen as commonly done in games.
|
||||
- Add `WindowId::into_raw()` and `from_raw()`.
|
||||
- Add `PointerKind`, `PointerSource`, `ButtonSource`, `FingerId` and `position` to all pointer
|
||||
events as part of the pointer event overhaul.
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
@ -127,6 +126,29 @@ changelog entry.
|
|||
To migrate, you can probably just replace all instances of `inner_size` with `surface_size` in your codebase.
|
||||
- Every event carrying a `DeviceId` now uses `Option<DeviceId>` instead. A `None` value signifies that the
|
||||
device can't be uniquely identified.
|
||||
- Pointer `WindowEvent`s were overhauled. The new events can handle any type of pointer, serving as
|
||||
a single pointer input source. Now your application can handle any pointer type without having to
|
||||
explicitly handle e.g. `Touch`:
|
||||
- Rename `CursorMoved` to `PointerMoved`.
|
||||
- Rename `CursorEntered` to `PointerEntered`.
|
||||
- Rename `CursorLeft` to `PointerLeft`.
|
||||
- Rename `MouseInput` to `PointerButton`.
|
||||
- Add `position` to every `PointerEvent`.
|
||||
- `PointerMoved` is **not sent** after `PointerEntered` anymore.
|
||||
- Remove `Touch`, which is folded into the `Pointer*` events.
|
||||
- New `PointerKind` added to `PointerEntered` and `PointerLeft`, signifying which pointer type is
|
||||
the source of this event.
|
||||
- New `PointerSource` added to `PointerMoved`, similar to `PointerKind` but holding additional
|
||||
data.
|
||||
- New `ButtonSource` added to `PointerButton`, similar to `PointerKind` but holding pointer type
|
||||
specific buttons. Use `ButtonSource::mouse_button()` to easily normalize any pointer button
|
||||
type to a generic mouse button.
|
||||
- New `FingerId` added to `PointerKind::Touch` and `PointerSource::Touch` able to uniquely
|
||||
identify a finger in a multi-touch interaction. Replaces the old `Touch::id`.
|
||||
- On Web and Windows, add `FingerIdExt*::is_primary()`, exposing a way to determine
|
||||
the primary finger in a multi-touch interaction.
|
||||
- In the same spirit rename `DeviceEvent::MouseMotion` to `PointerMotion`.
|
||||
- Remove `Force::Calibrated::altitude_angle`.
|
||||
|
||||
### Removed
|
||||
|
||||
|
|
@ -149,13 +171,15 @@ changelog entry.
|
|||
v0.5 support. v0.6 remains in place and is enabled by default.
|
||||
- Remove `DeviceEvent::Added` and `DeviceEvent::Removed`.
|
||||
- Remove `DeviceEvent::Motion` and `WindowEvent::AxisMotion`.
|
||||
- Remove `Touch::id` in favor of `Touch::finger_id`.
|
||||
- Remove `MonitorHandle::size()` and `refresh_rate_millihertz()` in favor of
|
||||
`MonitorHandle::current_video_mode()`.
|
||||
- On Android, remove all `MonitorHandle` support instead of emitting false data.
|
||||
- Remove `impl From<u64> for WindowId` and `impl From<WindowId> for u64`. Replaced with
|
||||
`WindowId::into_raw()` and `from_raw()`.
|
||||
- Remove `dummy()` from `WindowId` and `DeviceId`.
|
||||
- Remove `WindowEvent::Touch` and `Touch` in favor of the new `PointerKind`, `PointerSource` and
|
||||
`ButtonSource` as part of the new pointer event overhaul.
|
||||
- Remove `Force::altitude_angle`.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
|||
354
src/event.rs
354
src/event.rs
|
|
@ -226,53 +226,89 @@ pub enum WindowEvent {
|
|||
/// - **iOS / Android / Web / Orbital:** Unsupported.
|
||||
Ime(Ime),
|
||||
|
||||
/// The cursor has moved on the window.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
CursorMoved {
|
||||
/// The pointer has moved on the window.
|
||||
PointerMoved {
|
||||
device_id: Option<DeviceId>,
|
||||
|
||||
/// (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. For that,
|
||||
/// consider [`DeviceEvent::MouseMotion`].
|
||||
/// (x,y) coordinates 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 pointer acceleration, it
|
||||
/// should not be used to implement non-pointer-like interactions such as 3D camera
|
||||
/// control. For that, consider [`DeviceEvent::PointerMotion`].
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
position: PhysicalPosition<f64>,
|
||||
|
||||
source: PointerSource,
|
||||
},
|
||||
|
||||
/// The cursor has entered the window.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
CursorEntered { device_id: Option<DeviceId> },
|
||||
/// The pointer has entered the window.
|
||||
PointerEntered {
|
||||
device_id: Option<DeviceId>,
|
||||
|
||||
/// The cursor has left the window.
|
||||
/// The position of the pointer when it entered the window.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Orbital: Always emits `(0., 0.)`.
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
CursorLeft { device_id: Option<DeviceId> },
|
||||
position: PhysicalPosition<f64>,
|
||||
|
||||
kind: PointerKind,
|
||||
},
|
||||
|
||||
/// The pointer has left the window.
|
||||
PointerLeft {
|
||||
device_id: Option<DeviceId>,
|
||||
|
||||
/// The position of the pointer when it left the window. The position reported can be
|
||||
/// outside the bounds of the window.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Orbital/Windows:** Always emits [`None`].
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
position: Option<PhysicalPosition<f64>>,
|
||||
|
||||
kind: PointerKind,
|
||||
},
|
||||
|
||||
/// A mouse wheel movement or touchpad scroll occurred.
|
||||
MouseWheel { device_id: Option<DeviceId>, delta: MouseScrollDelta, phase: TouchPhase },
|
||||
|
||||
/// An mouse button press has been received.
|
||||
MouseInput { device_id: Option<DeviceId>, state: ElementState, button: MouseButton },
|
||||
PointerButton {
|
||||
device_id: Option<DeviceId>,
|
||||
state: ElementState,
|
||||
|
||||
/// The position of the pointer when the button was pressed.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Orbital: Always emits `(0., 0.)`.
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
position: PhysicalPosition<f64>,
|
||||
|
||||
button: ButtonSource,
|
||||
},
|
||||
|
||||
/// Two-finger pinch gesture, often used for magnification.
|
||||
///
|
||||
|
|
@ -346,18 +382,6 @@ pub enum WindowEvent {
|
|||
/// touchpad is being pressed) and stage (integer representing the click level).
|
||||
TouchpadPressure { device_id: Option<DeviceId>, pressure: f32, stage: i64 },
|
||||
|
||||
/// Touch event has been received
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
/// - **macOS:** Unsupported.
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
Touch(Touch),
|
||||
|
||||
/// The window's scale factor has changed.
|
||||
///
|
||||
/// The following user actions can cause DPI changes:
|
||||
|
|
@ -431,6 +455,129 @@ pub enum WindowEvent {
|
|||
RedrawRequested,
|
||||
}
|
||||
|
||||
/// Represents the kind type of a pointer event.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// **Wayland/X11:** [`Unknown`](Self::Unknown) device types are converted to known variants by the
|
||||
/// system.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum PointerKind {
|
||||
Mouse,
|
||||
/// See [`PointerSource::Touch`] for more details.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// **macOS:** Unsupported.
|
||||
Touch(FingerId),
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// Represents the pointer type and its data for a pointer event.
|
||||
///
|
||||
/// **Wayland/X11:** [`Unknown`](Self::Unknown) device types are converted to known variants by the
|
||||
/// system.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum PointerSource {
|
||||
Mouse,
|
||||
/// Represents a touch event.
|
||||
///
|
||||
/// Every time the user touches the screen, a [`WindowEvent::PointerEntered`] and a
|
||||
/// [`WindowEvent::PointerButton`] with [`ElementState::Pressed`] event with an unique
|
||||
/// identifier for the finger is emitted. When a finger is lifted, a
|
||||
/// [`WindowEvent::PointerButton`] with [`ElementState::Released`] and a
|
||||
/// [`WindowEvent::PointerLeft`] event is generated with the same [`FingerId`].
|
||||
///
|
||||
/// After a [`WindowEvent::PointerEntered`] event has been emitted, there may be zero or more
|
||||
/// [`WindowEvent::PointerMoved`] events when the finger is moved or the touch pressure
|
||||
/// changes.
|
||||
///
|
||||
/// A [`WindowEvent::PointerLeft`] without a [`WindowEvent::PointerButton`] with
|
||||
/// [`ElementState::Released`] event is emitted when the system has canceled tracking this
|
||||
/// touch, such as when the window loses focus, or on mobile devices if the user moves the
|
||||
/// device against their face.
|
||||
///
|
||||
/// The [`FingerId`] may be reused by the system after a [`WindowEvent::PointerLeft`] event.
|
||||
/// The user should assume that a new [`WindowEvent::PointerEntered`] event received with the
|
||||
/// same ID has nothing to do with the old finger and is a new finger.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// **macOS:** Unsupported.
|
||||
Touch {
|
||||
finger_id: FingerId,
|
||||
|
||||
/// Describes how hard the screen was pressed. May be [`None`] if the hardware does not
|
||||
/// support pressure sensitivity.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **MacOS / Orbital / Wayland / X11:** Always emits [`None`].
|
||||
/// - **Android:** Will never be [`None`]. If the device doesn't support pressure
|
||||
/// sensitivity, force will either be 0.0 or 1.0. Also see the
|
||||
/// [android documentation](https://developer.android.com/reference/android/view/MotionEvent#AXIS_PRESSURE).#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
/// - **Web:** Will never be [`None`]. If the device doesn't support pressure sensitivity,
|
||||
/// force will be 0.5 when a button is pressed or 0.0 otherwise.
|
||||
force: Option<Force>,
|
||||
},
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl From<PointerSource> for PointerKind {
|
||||
fn from(source: PointerSource) -> Self {
|
||||
match source {
|
||||
PointerSource::Mouse => Self::Mouse,
|
||||
PointerSource::Touch { finger_id, .. } => Self::Touch(finger_id),
|
||||
PointerSource::Unknown => Self::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the pointer type of a [`WindowEvent::PointerButton`].
|
||||
///
|
||||
/// **Wayland/X11:** [`Unknown`](Self::Unknown) device types are converted to known variants by the
|
||||
/// system.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum ButtonSource {
|
||||
Mouse(MouseButton),
|
||||
/// See [`PointerSource::Touch`] for more details.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// **macOS:** Unsupported.
|
||||
Touch {
|
||||
finger_id: FingerId,
|
||||
force: Option<Force>,
|
||||
},
|
||||
Unknown(u16),
|
||||
}
|
||||
|
||||
impl ButtonSource {
|
||||
/// Convert any [`ButtonSource`] to an equivalent [`MouseButton`]. If a pointer type has no
|
||||
/// special handling in an application, this method can be used to handle it like any generic
|
||||
/// mouse input.
|
||||
pub fn mouse_button(self) -> MouseButton {
|
||||
match self {
|
||||
ButtonSource::Mouse(mouse) => mouse,
|
||||
ButtonSource::Touch { .. } => MouseButton::Left,
|
||||
ButtonSource::Unknown(button) => match button {
|
||||
0 => MouseButton::Left,
|
||||
1 => MouseButton::Middle,
|
||||
2 => MouseButton::Right,
|
||||
3 => MouseButton::Back,
|
||||
4 => MouseButton::Forward,
|
||||
_ => MouseButton::Other(button),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MouseButton> for ButtonSource {
|
||||
fn from(mouse: MouseButton) -> Self {
|
||||
Self::Mouse(mouse)
|
||||
}
|
||||
}
|
||||
|
||||
/// Identifier of an input device.
|
||||
///
|
||||
/// Whenever you receive an event arising from a particular input device, this event contains a
|
||||
|
|
@ -459,7 +606,7 @@ impl FingerId {
|
|||
/// 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.
|
||||
/// (corresponding to GUI pointers and keyboard focus) the device IDs may not match.
|
||||
///
|
||||
/// Note that these events are delivered regardless of input focus.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
|
|
@ -467,7 +614,7 @@ pub enum DeviceEvent {
|
|||
/// Change in physical position of a pointing device.
|
||||
///
|
||||
/// This represents raw, unfiltered physical motion. Not to be confused with
|
||||
/// [`WindowEvent::CursorMoved`].
|
||||
/// [`WindowEvent::PointerMoved`].
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
|
|
@ -484,7 +631,7 @@ pub enum DeviceEvent {
|
|||
///
|
||||
#[rustfmt::skip]
|
||||
/// [`CursorGrabMode::Locked`]: crate::window::CursorGrabMode::Locked
|
||||
MouseMotion {
|
||||
PointerMotion {
|
||||
/// (x, y) change in position in unspecified units.
|
||||
///
|
||||
/// Different devices may use different units.
|
||||
|
|
@ -813,50 +960,6 @@ pub enum TouchPhase {
|
|||
Cancelled,
|
||||
}
|
||||
|
||||
/// Represents a touch event
|
||||
///
|
||||
/// Every time the user touches the screen, a new [`TouchPhase::Started`] event with an unique
|
||||
/// identifier for the finger is generated. When the finger is lifted, an [`TouchPhase::Ended`]
|
||||
/// event is generated with the same finger id.
|
||||
///
|
||||
/// After a `Started` 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 `Ended` event. The user
|
||||
/// should assume that a new `Started` event received with the same id has nothing
|
||||
/// to do with the old finger and is a new finger.
|
||||
///
|
||||
/// A [`TouchPhase::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.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Web:** Doesn't take into account CSS [`border`], [`padding`], or [`transform`].
|
||||
/// - **macOS:** Unsupported.
|
||||
///
|
||||
/// [`border`]: https://developer.mozilla.org/en-US/docs/Web/CSS/border
|
||||
/// [`padding`]: https://developer.mozilla.org/en-US/docs/Web/CSS/padding
|
||||
/// [`transform`]: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Touch {
|
||||
pub device_id: Option<DeviceId>,
|
||||
pub phase: TouchPhase,
|
||||
pub location: PhysicalPosition<f64>,
|
||||
/// 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+, **Windows** 8+, **Web**, and **Android**.
|
||||
/// - **Android**: This will never be [None]. If the device doesn't support pressure
|
||||
/// sensitivity, force will either be 0.0 or 1.0. Also see the
|
||||
/// [android documentation](https://developer.android.com/reference/android/view/MotionEvent#AXIS_PRESSURE).
|
||||
pub force: Option<Force>,
|
||||
/// Unique identifier of a finger.
|
||||
pub finger_id: FingerId,
|
||||
}
|
||||
|
||||
/// Describes the force of a touch event
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
|
|
@ -877,12 +980,6 @@ pub enum Force {
|
|||
/// The value of this field is sufficiently high to provide a wide
|
||||
/// dynamic range for values of the `force` field.
|
||||
max_possible_force: f64,
|
||||
/// The altitude (in radians) of the stylus.
|
||||
///
|
||||
/// A value of 0 radians indicates that the stylus is parallel to the
|
||||
/// surface. The value of this property is Pi/2 when the stylus is
|
||||
/// perpendicular to the surface.
|
||||
altitude_angle: Option<f64>,
|
||||
},
|
||||
/// If the platform reports the force as normalized, we have no way of
|
||||
/// knowing how much pressure 1.0 corresponds to – we know it's the maximum
|
||||
|
|
@ -899,13 +996,7 @@ impl Force {
|
|||
/// consistent across devices.
|
||||
pub fn normalized(&self) -> f64 {
|
||||
match self {
|
||||
Force::Calibrated { force, max_possible_force, altitude_angle } => {
|
||||
let force = match altitude_angle {
|
||||
Some(altitude_angle) => force / altitude_angle.sin(),
|
||||
None => *force,
|
||||
};
|
||||
force / max_possible_force
|
||||
},
|
||||
Force::Calibrated { force, max_possible_force } => force / max_possible_force,
|
||||
Force::Normalized(force) => *force,
|
||||
}
|
||||
}
|
||||
|
|
@ -1028,6 +1119,7 @@ mod tests {
|
|||
use crate::event::Event::*;
|
||||
use crate::event::Ime::Enabled;
|
||||
use crate::event::WindowEvent::*;
|
||||
use crate::event::{PointerKind, PointerSource};
|
||||
use crate::window::WindowId;
|
||||
|
||||
// Mainline events.
|
||||
|
|
@ -1050,19 +1142,41 @@ mod tests {
|
|||
with_window_event(HoveredFile("x.txt".into()));
|
||||
with_window_event(HoveredFileCancelled);
|
||||
with_window_event(Ime(Enabled));
|
||||
with_window_event(CursorMoved { device_id: None, position: (0, 0).into() });
|
||||
with_window_event(PointerMoved {
|
||||
device_id: None,
|
||||
position: (0, 0).into(),
|
||||
source: PointerSource::Mouse,
|
||||
});
|
||||
with_window_event(ModifiersChanged(event::Modifiers::default()));
|
||||
with_window_event(CursorEntered { device_id: None });
|
||||
with_window_event(CursorLeft { device_id: None });
|
||||
with_window_event(PointerEntered {
|
||||
device_id: None,
|
||||
position: (0, 0).into(),
|
||||
kind: PointerKind::Mouse,
|
||||
});
|
||||
with_window_event(PointerLeft {
|
||||
device_id: None,
|
||||
position: Some((0, 0).into()),
|
||||
kind: PointerKind::Mouse,
|
||||
});
|
||||
with_window_event(MouseWheel {
|
||||
device_id: None,
|
||||
delta: event::MouseScrollDelta::LineDelta(0.0, 0.0),
|
||||
phase: event::TouchPhase::Started,
|
||||
});
|
||||
with_window_event(MouseInput {
|
||||
with_window_event(PointerButton {
|
||||
device_id: None,
|
||||
state: event::ElementState::Pressed,
|
||||
button: event::MouseButton::Other(0),
|
||||
position: (0, 0).into(),
|
||||
button: event::MouseButton::Other(0).into(),
|
||||
});
|
||||
with_window_event(PointerButton {
|
||||
device_id: None,
|
||||
state: event::ElementState::Released,
|
||||
position: (0, 0).into(),
|
||||
button: event::ButtonSource::Touch {
|
||||
finger_id: fid,
|
||||
force: Some(event::Force::Normalized(0.0)),
|
||||
},
|
||||
});
|
||||
with_window_event(PinchGesture {
|
||||
device_id: None,
|
||||
|
|
@ -1081,13 +1195,6 @@ mod tests {
|
|||
phase: event::TouchPhase::Started,
|
||||
});
|
||||
with_window_event(TouchpadPressure { device_id: None, pressure: 0.0, stage: 0 });
|
||||
with_window_event(Touch(event::Touch {
|
||||
device_id: None,
|
||||
phase: event::TouchPhase::Started,
|
||||
location: (0.0, 0.0).into(),
|
||||
finger_id: fid,
|
||||
force: Some(event::Force::Normalized(0.0)),
|
||||
}));
|
||||
with_window_event(ThemeChanged(crate::window::Theme::Light));
|
||||
with_window_event(Occluded(true));
|
||||
}
|
||||
|
|
@ -1099,7 +1206,7 @@ mod tests {
|
|||
let with_device_event =
|
||||
|dev_ev| x(event::Event::DeviceEvent { device_id: None, event: dev_ev });
|
||||
|
||||
with_device_event(MouseMotion { delta: (0.0, 0.0).into() });
|
||||
with_device_event(PointerMotion { delta: (0.0, 0.0).into() });
|
||||
with_device_event(MouseWheel {
|
||||
delta: event::MouseScrollDelta::LineDelta(0.0, 0.0),
|
||||
});
|
||||
|
|
@ -1122,15 +1229,10 @@ mod tests {
|
|||
let force = event::Force::Normalized(0.0);
|
||||
assert_eq!(force.normalized(), 0.0);
|
||||
|
||||
let force2 =
|
||||
event::Force::Calibrated { force: 5.0, max_possible_force: 2.5, altitude_angle: None };
|
||||
let force2 = event::Force::Calibrated { force: 5.0, max_possible_force: 2.5 };
|
||||
assert_eq!(force2.normalized(), 2.0);
|
||||
|
||||
let force3 = event::Force::Calibrated {
|
||||
force: 5.0,
|
||||
max_possible_force: 2.5,
|
||||
altitude_angle: Some(std::f64::consts::PI / 2.0),
|
||||
};
|
||||
let force3 = event::Force::Calibrated { force: 5.0, max_possible_force: 2.5 };
|
||||
assert_eq!(force3.normalized(), 2.0);
|
||||
}
|
||||
|
||||
|
|
@ -1154,16 +1256,6 @@ mod tests {
|
|||
HashSet::new().insert(event::MouseButton::Left.clone());
|
||||
HashSet::new().insert(event::Ime::Enabled);
|
||||
|
||||
let _ = event::Touch {
|
||||
device_id: None,
|
||||
phase: event::TouchPhase::Started,
|
||||
location: (0.0, 0.0).into(),
|
||||
finger_id: fid,
|
||||
force: Some(event::Force::Normalized(0.0)),
|
||||
}
|
||||
.clone();
|
||||
let _ =
|
||||
event::Force::Calibrated { force: 0.0, max_possible_force: 0.0, altitude_angle: None }
|
||||
.clone();
|
||||
let _ = event::Force::Calibrated { force: 0.0, max_possible_force: 0.0 }.clone();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ impl rwh_06::HasDisplayHandle for dyn ActiveEventLoop + '_ {
|
|||
|
||||
/// A proxy for the underlying display handle.
|
||||
///
|
||||
/// The purpose of this type is to provide a cheaply clonable handle to the underlying
|
||||
/// The purpose of this type is to provide a cheaply cloneable handle to the underlying
|
||||
/// display handle. This is often used by graphics APIs to connect to the underlying APIs.
|
||||
/// It is difficult to keep a handle to the [`EventLoop`] type or the [`ActiveEventLoop`]
|
||||
/// type. In contrast, this type involves no lifetimes and can be persisted for as long as
|
||||
|
|
|
|||
|
|
@ -29,17 +29,16 @@
|
|||
//! The following APIs can't take them into account and will therefore provide inaccurate results:
|
||||
//! - [`WindowEvent::SurfaceResized`] and [`Window::(set_)surface_size()`]
|
||||
//! - [`WindowEvent::Occluded`]
|
||||
//! - [`WindowEvent::CursorMoved`], [`WindowEvent::CursorEntered`], [`WindowEvent::CursorLeft`], and
|
||||
//! [`WindowEvent::Touch`].
|
||||
//! - [`WindowEvent::PointerMoved`], [`WindowEvent::PointerEntered`] and
|
||||
//! [`WindowEvent::PointerLeft`].
|
||||
//! - [`Window::set_outer_position()`]
|
||||
//!
|
||||
//! [`WindowEvent::SurfaceResized`]: crate::event::WindowEvent::SurfaceResized
|
||||
//! [`Window::(set_)surface_size()`]: crate::window::Window::surface_size
|
||||
//! [`WindowEvent::Occluded`]: crate::event::WindowEvent::Occluded
|
||||
//! [`WindowEvent::CursorMoved`]: crate::event::WindowEvent::CursorMoved
|
||||
//! [`WindowEvent::CursorEntered`]: crate::event::WindowEvent::CursorEntered
|
||||
//! [`WindowEvent::CursorLeft`]: crate::event::WindowEvent::CursorLeft
|
||||
//! [`WindowEvent::Touch`]: crate::event::WindowEvent::Touch
|
||||
//! [`WindowEvent::PointerMoved`]: crate::event::WindowEvent::PointerMoved
|
||||
//! [`WindowEvent::PointerEntered`]: crate::event::WindowEvent::PointerEntered
|
||||
//! [`WindowEvent::PointerLeft`]: crate::event::WindowEvent::PointerLeft
|
||||
//! [`Window::set_outer_position()`]: crate::window::Window::set_outer_position
|
||||
|
||||
use std::cell::Ref;
|
||||
|
|
|
|||
|
|
@ -317,48 +317,115 @@ impl EventLoop {
|
|||
InputEvent::MotionEvent(motion_event) => {
|
||||
let window_id = window::WindowId(WindowId);
|
||||
let device_id = Some(event::DeviceId(DeviceId(motion_event.device_id())));
|
||||
let action = motion_event.action();
|
||||
|
||||
let phase = match motion_event.action() {
|
||||
MotionAction::Down | MotionAction::PointerDown => {
|
||||
Some(event::TouchPhase::Started)
|
||||
},
|
||||
MotionAction::Up | MotionAction::PointerUp => Some(event::TouchPhase::Ended),
|
||||
MotionAction::Move => Some(event::TouchPhase::Moved),
|
||||
MotionAction::Cancel => Some(event::TouchPhase::Cancelled),
|
||||
_ => {
|
||||
None // TODO mouse events
|
||||
},
|
||||
};
|
||||
if let Some(phase) = phase {
|
||||
let pointers: Box<dyn Iterator<Item = android_activity::input::Pointer<'_>>> =
|
||||
match phase {
|
||||
event::TouchPhase::Started | event::TouchPhase::Ended => {
|
||||
Box::new(std::iter::once(
|
||||
let pointers: Option<
|
||||
Box<dyn Iterator<Item = android_activity::input::Pointer<'_>>>,
|
||||
> = match action {
|
||||
MotionAction::Down
|
||||
| MotionAction::PointerDown
|
||||
| MotionAction::Up
|
||||
| MotionAction::PointerUp => Some(Box::new(std::iter::once(
|
||||
motion_event.pointer_at_index(motion_event.pointer_index()),
|
||||
))
|
||||
},
|
||||
event::TouchPhase::Moved | event::TouchPhase::Cancelled => {
|
||||
Box::new(motion_event.pointers())
|
||||
))),
|
||||
MotionAction::Move | MotionAction::Cancel => {
|
||||
Some(Box::new(motion_event.pointers()))
|
||||
},
|
||||
// TODO mouse events
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(pointers) = pointers {
|
||||
for pointer in pointers {
|
||||
let location =
|
||||
let tool_type = pointer.tool_type();
|
||||
let position =
|
||||
PhysicalPosition { x: pointer.x() as _, y: pointer.y() as _ };
|
||||
trace!(
|
||||
"Input event {device_id:?}, {phase:?}, loc={location:?}, \
|
||||
pointer={pointer:?}"
|
||||
"Input event {device_id:?}, {action:?}, loc={position:?}, \
|
||||
pointer={pointer:?}, tool_type={tool_type:?}"
|
||||
);
|
||||
let finger_id = event::FingerId(FingerId(pointer.pointer_id()));
|
||||
let force = Some(Force::Normalized(pointer.pressure() as f64));
|
||||
|
||||
let event = event::WindowEvent::Touch(event::Touch {
|
||||
match action {
|
||||
MotionAction::Down | MotionAction::PointerDown => {
|
||||
let event = event::WindowEvent::PointerEntered {
|
||||
device_id,
|
||||
phase,
|
||||
location,
|
||||
finger_id: event::FingerId(FingerId(pointer.pointer_id())),
|
||||
force: Some(Force::Normalized(pointer.pressure() as f64)),
|
||||
});
|
||||
|
||||
position,
|
||||
kind: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::PointerKind::Touch(finger_id)
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::PointerKind::Unknown,
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
let event = event::WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: event::ElementState::Pressed,
|
||||
position,
|
||||
button: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::ButtonSource::Touch { finger_id, force }
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::ButtonSource::Unknown(0),
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
},
|
||||
MotionAction::Move => {
|
||||
let event = event::WindowEvent::PointerMoved {
|
||||
device_id,
|
||||
position,
|
||||
source: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::PointerSource::Touch { finger_id, force }
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::PointerSource::Unknown,
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
},
|
||||
MotionAction::Up | MotionAction::PointerUp | MotionAction::Cancel => {
|
||||
if let MotionAction::Up | MotionAction::PointerUp = action {
|
||||
let event = event::WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: event::ElementState::Released,
|
||||
position,
|
||||
button: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::ButtonSource::Touch { finger_id, force }
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::ButtonSource::Unknown(0),
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
}
|
||||
|
||||
let event = event::WindowEvent::PointerLeft {
|
||||
device_id,
|
||||
position: Some(position),
|
||||
kind: match tool_type {
|
||||
android_activity::input::ToolType::Finger => {
|
||||
event::PointerKind::Touch(finger_id)
|
||||
},
|
||||
// TODO mouse events
|
||||
android_activity::input::ToolType::Mouse => continue,
|
||||
_ => event::PointerKind::Unknown,
|
||||
},
|
||||
};
|
||||
app.window_event(&self.window_target, window_id, event);
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ fn maybe_dispatch_device_event(app_state: &Rc<AppState>, event: &NSEvent) {
|
|||
|
||||
if delta_x != 0.0 || delta_y != 0.0 {
|
||||
app_state.maybe_queue_with_handler(move |app, event_loop| {
|
||||
app.device_event(event_loop, None, DeviceEvent::MouseMotion {
|
||||
app.device_event(event_loop, None, DeviceEvent::PointerMotion {
|
||||
delta: (delta_x, delta_y),
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ use super::event::{
|
|||
use super::window::WinitWindow;
|
||||
use crate::dpi::{LogicalPosition, LogicalSize};
|
||||
use crate::event::{
|
||||
DeviceEvent, ElementState, Ime, Modifiers, MouseButton, MouseScrollDelta, TouchPhase,
|
||||
WindowEvent,
|
||||
DeviceEvent, ElementState, Ime, Modifiers, MouseButton, MouseScrollDelta, PointerKind,
|
||||
PointerSource, TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState, NamedKey};
|
||||
use crate::platform::macos::OptionAsAlt;
|
||||
|
|
@ -638,19 +638,28 @@ declare_class!(
|
|||
}
|
||||
|
||||
#[method(mouseEntered:)]
|
||||
fn mouse_entered(&self, _event: &NSEvent) {
|
||||
fn mouse_entered(&self, event: &NSEvent) {
|
||||
trace_scope!("mouseEntered:");
|
||||
self.queue_event(WindowEvent::CursorEntered {
|
||||
|
||||
let position = self.mouse_view_point(event).to_physical(self.scale_factor());
|
||||
|
||||
self.queue_event(WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Mouse,
|
||||
});
|
||||
}
|
||||
|
||||
#[method(mouseExited:)]
|
||||
fn mouse_exited(&self, _event: &NSEvent) {
|
||||
fn mouse_exited(&self, event: &NSEvent) {
|
||||
trace_scope!("mouseExited:");
|
||||
|
||||
self.queue_event(WindowEvent::CursorLeft {
|
||||
let position = self.mouse_view_point(event).to_physical(self.scale_factor());
|
||||
|
||||
self.queue_event(WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Mouse,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1033,16 +1042,21 @@ impl WinitView {
|
|||
}
|
||||
|
||||
fn mouse_click(&self, event: &NSEvent, button_state: ElementState) {
|
||||
let position = self.mouse_view_point(event).to_physical(self.scale_factor());
|
||||
let button = mouse_button(event);
|
||||
|
||||
self.update_modifiers(event, false);
|
||||
|
||||
self.queue_event(WindowEvent::MouseInput { device_id: None, state: button_state, button });
|
||||
self.queue_event(WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: button_state,
|
||||
position,
|
||||
button: button.into(),
|
||||
});
|
||||
}
|
||||
|
||||
fn mouse_motion(&self, event: &NSEvent) {
|
||||
let window_point = unsafe { event.locationInWindow() };
|
||||
let view_point = self.convertPoint_fromView(window_point, None);
|
||||
let view_point = self.mouse_view_point(event);
|
||||
let frame = self.frame();
|
||||
|
||||
if view_point.x.is_sign_negative()
|
||||
|
|
@ -1057,15 +1071,21 @@ impl WinitView {
|
|||
}
|
||||
}
|
||||
|
||||
let view_point = LogicalPosition::new(view_point.x, view_point.y);
|
||||
|
||||
self.update_modifiers(event, false);
|
||||
|
||||
self.queue_event(WindowEvent::CursorMoved {
|
||||
self.queue_event(WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position: view_point.to_physical(self.scale_factor()),
|
||||
source: PointerSource::Mouse,
|
||||
});
|
||||
}
|
||||
|
||||
fn mouse_view_point(&self, event: &NSEvent) -> LogicalPosition<f64> {
|
||||
let window_point = unsafe { event.locationInWindow() };
|
||||
let view_point = self.convertPoint_fromView(window_point, None);
|
||||
|
||||
LogicalPosition::new(view_point.x, view_point.y)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the mouse button from the NSEvent.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ use super::window::WinitUIWindow;
|
|||
use super::FingerId;
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::event::{
|
||||
ElementState, Event, FingerId as RootFingerId, Force, KeyEvent, Touch, TouchPhase, WindowEvent,
|
||||
ButtonSource, ElementState, Event, FingerId as RootFingerId, Force, KeyEvent, PointerKind,
|
||||
PointerSource, TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKeyCode, PhysicalKey};
|
||||
use crate::platform_impl::KeyEventExtra;
|
||||
|
|
@ -483,25 +484,18 @@ impl WinitView {
|
|||
for touch in touches {
|
||||
let logical_location = touch.locationInView(None);
|
||||
let touch_type = touch.r#type();
|
||||
let force = if os_supports_force {
|
||||
let force = if let UITouchType::Pencil = touch_type {
|
||||
None
|
||||
} else if os_supports_force {
|
||||
let trait_collection = self.traitCollection();
|
||||
let touch_capability = trait_collection.forceTouchCapability();
|
||||
// Both the OS _and_ the device need to be checked for force touch support.
|
||||
if touch_capability == UIForceTouchCapability::Available
|
||||
|| touch_type == UITouchType::Pencil
|
||||
{
|
||||
if touch_capability == UIForceTouchCapability::Available {
|
||||
let force = touch.force();
|
||||
let max_possible_force = touch.maximumPossibleForce();
|
||||
let altitude_angle: Option<f64> = if touch_type == UITouchType::Pencil {
|
||||
let angle = touch.altitudeAngle();
|
||||
Some(angle as _)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Some(Force::Calibrated {
|
||||
force: force as _,
|
||||
max_possible_force: max_possible_force as _,
|
||||
altitude_angle,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
|
@ -511,32 +505,91 @@ impl WinitView {
|
|||
};
|
||||
let touch_id = touch as *const UITouch as usize;
|
||||
let phase = touch.phase();
|
||||
let phase = match phase {
|
||||
UITouchPhase::Began => TouchPhase::Started,
|
||||
UITouchPhase::Moved => TouchPhase::Moved,
|
||||
// 2 is UITouchPhase::Stationary and is not expected here
|
||||
UITouchPhase::Ended => TouchPhase::Ended,
|
||||
UITouchPhase::Cancelled => TouchPhase::Cancelled,
|
||||
_ => panic!("unexpected touch phase: {phase:?}"),
|
||||
};
|
||||
|
||||
let physical_location = {
|
||||
let position = {
|
||||
let scale_factor = self.contentScaleFactor();
|
||||
PhysicalPosition::from_logical::<(f64, f64), f64>(
|
||||
(logical_location.x as _, logical_location.y as _),
|
||||
scale_factor as f64,
|
||||
)
|
||||
};
|
||||
let window_id = RootWindowId(window.id());
|
||||
let finger_id = RootFingerId(FingerId(touch_id));
|
||||
|
||||
match phase {
|
||||
UITouchPhase::Began => {
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: RootWindowId(window.id()),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
finger_id: RootFingerId(FingerId(touch_id)),
|
||||
location: physical_location,
|
||||
force,
|
||||
phase,
|
||||
}),
|
||||
position,
|
||||
kind: if let UITouchType::Pencil = touch_type {
|
||||
PointerKind::Unknown
|
||||
} else {
|
||||
PointerKind::Touch(finger_id)
|
||||
},
|
||||
},
|
||||
}));
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button: if let UITouchType::Pencil = touch_type {
|
||||
ButtonSource::Unknown(0)
|
||||
} else {
|
||||
ButtonSource::Touch { finger_id, force }
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
UITouchPhase::Moved => {
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position,
|
||||
source: if let UITouchType::Pencil = touch_type {
|
||||
PointerSource::Unknown
|
||||
} else {
|
||||
PointerSource::Touch { finger_id, force }
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
// 2 is UITouchPhase::Stationary and is not expected here
|
||||
UITouchPhase::Ended | UITouchPhase::Cancelled => {
|
||||
if let UITouchPhase::Ended = phase {
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button: if let UITouchType::Pencil = touch_type {
|
||||
ButtonSource::Unknown(0)
|
||||
} else {
|
||||
ButtonSource::Touch { finger_id, force }
|
||||
},
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: if let UITouchType::Pencil = touch_type {
|
||||
PointerKind::Unknown
|
||||
} else {
|
||||
PointerKind::Touch(finger_id)
|
||||
},
|
||||
},
|
||||
}));
|
||||
},
|
||||
_ => panic!("unexpected touch phase: {phase:?}"),
|
||||
}
|
||||
}
|
||||
let mtm = MainThreadMarker::new().unwrap();
|
||||
app_state::handle_nonuser_events(mtm, touch_events);
|
||||
|
|
|
|||
|
|
@ -638,7 +638,7 @@ pub fn keysym_to_key(keysym: u32) -> Key {
|
|||
// keysyms::ISO_Release_Margin_Left => NamedKey::IsoReleaseMarginLeft,
|
||||
// keysyms::ISO_Release_Margin_Right => NamedKey::IsoReleaseMarginRight,
|
||||
// keysyms::ISO_Release_Both_Margins => NamedKey::IsoReleaseBothMargins,
|
||||
// keysyms::ISO_Fast_Cursor_Left => NamedKey::IsoFastCursorLeft,
|
||||
// keysyms::ISO_Fast_Cursor_Left => NamedKey::IsoFastPointerLeft,
|
||||
// keysyms::ISO_Fast_Cursor_Right => NamedKey::IsoFastCursorRight,
|
||||
// keysyms::ISO_Fast_Cursor_Up => NamedKey::IsoFastCursorUp,
|
||||
// keysyms::ISO_Fast_Cursor_Down => NamedKey::IsoFastCursorDown,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use sctk::seat::pointer::{
|
|||
use sctk::seat::SeatState;
|
||||
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition};
|
||||
use crate::event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent};
|
||||
use crate::event::{ElementState, MouseButton, MouseScrollDelta, PointerSource, PointerKind, TouchPhase, WindowEvent};
|
||||
|
||||
use crate::platform_impl::wayland::state::WinitState;
|
||||
use crate::platform_impl::wayland::{self, WindowId};
|
||||
|
|
@ -123,7 +123,11 @@ impl PointerHandler for WinitState {
|
|||
// Regular events on the main surface.
|
||||
PointerEventKind::Enter { .. } => {
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::CursorEntered { device_id: None },
|
||||
WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
|
||||
|
|
@ -131,11 +135,6 @@ impl PointerHandler for WinitState {
|
|||
|
||||
// Set the currently focused surface.
|
||||
pointer.winit_data().inner.lock().unwrap().surface = Some(window_id);
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::CursorMoved { device_id: None, position },
|
||||
window_id,
|
||||
);
|
||||
},
|
||||
PointerEventKind::Leave { .. } => {
|
||||
window.pointer_left(Arc::downgrade(themed_pointer));
|
||||
|
|
@ -143,12 +142,22 @@ impl PointerHandler for WinitState {
|
|||
// Remove the active surface.
|
||||
pointer.winit_data().inner.lock().unwrap().surface = None;
|
||||
|
||||
self.events_sink
|
||||
.push_window_event(WindowEvent::CursorLeft { device_id: None }, window_id);
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
},
|
||||
PointerEventKind::Motion { .. } => {
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::CursorMoved { device_id: None, position },
|
||||
WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position,
|
||||
source: PointerSource::Mouse,
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
},
|
||||
|
|
@ -164,7 +173,12 @@ impl PointerHandler for WinitState {
|
|||
ElementState::Released
|
||||
};
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::MouseInput { device_id: None, state, button },
|
||||
WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state,
|
||||
position,
|
||||
button: button.into(),
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ impl Dispatch<ZwpRelativePointerV1, GlobalData, WinitState> for RelativePointerS
|
|||
};
|
||||
state
|
||||
.events_sink
|
||||
.push_device_event(DeviceEvent::MouseMotion { delta: (dx_unaccel, dy_unaccel) });
|
||||
.push_device_event(DeviceEvent::PointerMotion { delta: (dx_unaccel, dy_unaccel) });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use sctk::seat::touch::{TouchData, TouchHandler};
|
|||
use tracing::warn;
|
||||
|
||||
use crate::dpi::LogicalPosition;
|
||||
use crate::event::{Touch, TouchPhase, WindowEvent};
|
||||
use crate::event::{ButtonSource, ElementState, PointerKind, PointerSource, WindowEvent};
|
||||
use crate::platform_impl::wayland::state::WinitState;
|
||||
use crate::platform_impl::wayland::{self, FingerId};
|
||||
|
||||
|
|
@ -42,16 +42,25 @@ impl TouchHandler for WinitState {
|
|||
let location = LogicalPosition::<f64>::from(position);
|
||||
seat_state.touch_map.insert(id, TouchPoint { surface, location });
|
||||
|
||||
let position = location.to_physical(scale_factor);
|
||||
let finger_id =
|
||||
crate::event::FingerId(crate::platform_impl::FingerId::Wayland(FingerId(id)));
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::Touch(Touch {
|
||||
WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
phase: TouchPhase::Started,
|
||||
location: location.to_physical(scale_factor),
|
||||
force: None,
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
)),
|
||||
}),
|
||||
position,
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button: ButtonSource::Touch { finger_id, force: None },
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
}
|
||||
|
|
@ -85,16 +94,25 @@ impl TouchHandler for WinitState {
|
|||
None => return,
|
||||
};
|
||||
|
||||
let position = touch_point.location.to_physical(scale_factor);
|
||||
let finger_id =
|
||||
crate::event::FingerId(crate::platform_impl::FingerId::Wayland(FingerId(id)));
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::Touch(Touch {
|
||||
WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
phase: TouchPhase::Ended,
|
||||
location: touch_point.location.to_physical(scale_factor),
|
||||
force: None,
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
)),
|
||||
}),
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button: ButtonSource::Touch { finger_id, force: None },
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
}
|
||||
|
|
@ -131,15 +149,16 @@ impl TouchHandler for WinitState {
|
|||
touch_point.location = LogicalPosition::<f64>::from(position);
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::Touch(Touch {
|
||||
WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
phase: TouchPhase::Moved,
|
||||
location: touch_point.location.to_physical(scale_factor),
|
||||
force: None,
|
||||
position: touch_point.location.to_physical(scale_factor),
|
||||
source: PointerSource::Touch {
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
)),
|
||||
}),
|
||||
force: None,
|
||||
},
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
}
|
||||
|
|
@ -160,18 +179,16 @@ impl TouchHandler for WinitState {
|
|||
None => return,
|
||||
};
|
||||
|
||||
let location = touch_point.location.to_physical(scale_factor);
|
||||
let position = touch_point.location.to_physical(scale_factor);
|
||||
|
||||
self.events_sink.push_window_event(
|
||||
WindowEvent::Touch(Touch {
|
||||
WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
phase: TouchPhase::Cancelled,
|
||||
location,
|
||||
force: None,
|
||||
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
|
||||
FingerId(id),
|
||||
position: Some(position),
|
||||
kind: PointerKind::Touch(crate::event::FingerId(
|
||||
crate::platform_impl::FingerId::Wayland(FingerId(id)),
|
||||
)),
|
||||
}),
|
||||
},
|
||||
window_id,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ use xkbcommon_dl::xkb_mod_mask_t;
|
|||
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::event::{
|
||||
DeviceEvent, ElementState, Event, Ime, MouseButton, MouseScrollDelta, RawKeyEvent,
|
||||
SurfaceSizeWriter, Touch, TouchPhase, WindowEvent,
|
||||
ButtonSource, DeviceEvent, ElementState, Event, Ime, MouseButton, MouseScrollDelta,
|
||||
PointerKind, PointerSource, RawKeyEvent, SurfaceSizeWriter, TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::keyboard::ModifiersState;
|
||||
use crate::platform_impl::common::xkb::{self, XkbState};
|
||||
|
|
@ -238,15 +238,8 @@ impl EventProcessor {
|
|||
self.xinput2_unfocused(xev, &mut callback);
|
||||
},
|
||||
xinput2::XI_TouchBegin | xinput2::XI_TouchUpdate | xinput2::XI_TouchEnd => {
|
||||
let phase = match evtype {
|
||||
xinput2::XI_TouchBegin => TouchPhase::Started,
|
||||
xinput2::XI_TouchUpdate => TouchPhase::Moved,
|
||||
xinput2::XI_TouchEnd => TouchPhase::Ended,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let xev: &XIDeviceEvent = unsafe { xev.as_event() };
|
||||
self.xinput2_touch(xev, phase, &mut callback);
|
||||
self.xinput2_touch(xev, evtype, &mut callback);
|
||||
},
|
||||
xinput2::XI_RawButtonPress | xinput2::XI_RawButtonRelease => {
|
||||
let state = match evtype {
|
||||
|
|
@ -1025,16 +1018,27 @@ impl EventProcessor {
|
|||
return;
|
||||
}
|
||||
|
||||
let position = PhysicalPosition::new(event.event_x, event.event_y);
|
||||
|
||||
let event = match event.detail as u32 {
|
||||
xlib::Button1 => {
|
||||
WindowEvent::MouseInput { device_id, state, button: MouseButton::Left }
|
||||
xlib::Button1 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Left.into(),
|
||||
},
|
||||
xlib::Button2 => {
|
||||
WindowEvent::MouseInput { device_id, state, button: MouseButton::Middle }
|
||||
xlib::Button2 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Middle.into(),
|
||||
},
|
||||
|
||||
xlib::Button3 => {
|
||||
WindowEvent::MouseInput { device_id, state, button: MouseButton::Right }
|
||||
xlib::Button3 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Right.into(),
|
||||
},
|
||||
|
||||
// Suppress emulated scroll wheel clicks, since we handle the real motion events for
|
||||
|
|
@ -1052,10 +1056,25 @@ impl EventProcessor {
|
|||
},
|
||||
phase: TouchPhase::Moved,
|
||||
},
|
||||
8 => WindowEvent::MouseInput { device_id, state, button: MouseButton::Back },
|
||||
8 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Back.into(),
|
||||
},
|
||||
|
||||
9 => WindowEvent::MouseInput { device_id, state, button: MouseButton::Forward },
|
||||
x => WindowEvent::MouseInput { device_id, state, button: MouseButton::Other(x as u16) },
|
||||
9 => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Forward.into(),
|
||||
},
|
||||
x => WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state,
|
||||
position,
|
||||
button: MouseButton::Other(x as u16).into(),
|
||||
},
|
||||
};
|
||||
|
||||
let event = Event::WindowEvent { window_id, event };
|
||||
|
|
@ -1084,7 +1103,11 @@ impl EventProcessor {
|
|||
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id,
|
||||
position,
|
||||
source: PointerSource::Mouse,
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
} else if cursor_moved.is_none() {
|
||||
|
|
@ -1167,13 +1190,13 @@ impl EventProcessor {
|
|||
let device_id = Some(device_id);
|
||||
let position = PhysicalPosition::new(event.event_x, event.event_y);
|
||||
|
||||
let event =
|
||||
Event::WindowEvent { window_id, event: WindowEvent::CursorEntered { device_id } };
|
||||
callback(&self.target, event);
|
||||
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id,
|
||||
position,
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
|
|
@ -1193,8 +1216,10 @@ impl EventProcessor {
|
|||
if self.window_exists(window) {
|
||||
let event = Event::WindowEvent {
|
||||
window_id: mkwid(window),
|
||||
event: WindowEvent::CursorLeft {
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: Some(mkdid(event.deviceid as xinput::DeviceId)),
|
||||
position: Some(PhysicalPosition::new(event.event_x, event.event_y)),
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
|
|
@ -1253,7 +1278,7 @@ impl EventProcessor {
|
|||
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
event: WindowEvent::PointerMoved { device_id, position, source: PointerSource::Mouse },
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
|
|
@ -1309,7 +1334,7 @@ impl EventProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
fn xinput2_touch<F>(&mut self, xev: &XIDeviceEvent, phase: TouchPhase, mut callback: F)
|
||||
fn xinput2_touch<F>(&mut self, xev: &XIDeviceEvent, phase: i32, mut callback: F)
|
||||
where
|
||||
F: FnMut(&ActiveEventLoop, Event),
|
||||
{
|
||||
|
|
@ -1320,29 +1345,81 @@ impl EventProcessor {
|
|||
if self.window_exists(window) {
|
||||
let window_id = mkwid(window);
|
||||
let id = xev.detail as u32;
|
||||
let location = PhysicalPosition::new(xev.event_x, xev.event_y);
|
||||
let position = PhysicalPosition::new(xev.event_x, xev.event_y);
|
||||
|
||||
// Mouse cursor position changes when touch events are received.
|
||||
// Only the first concurrently active touch ID moves the mouse cursor.
|
||||
if is_first_touch(&mut self.first_touch, &mut self.num_touch, id, phase) {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::CursorMoved { device_id: None, position: location.cast() },
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position: position.cast(),
|
||||
source: PointerSource::Mouse,
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
|
||||
let device_id = Some(mkdid(xev.deviceid as xinput::DeviceId));
|
||||
let finger_id = mkfid(id);
|
||||
|
||||
match phase {
|
||||
xinput2::XI_TouchBegin => {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::Touch(Touch {
|
||||
device_id: Some(mkdid(xev.deviceid as xinput::DeviceId)),
|
||||
phase,
|
||||
location,
|
||||
force: None, // TODO
|
||||
finger_id: mkfid(id),
|
||||
}),
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id,
|
||||
position,
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
};
|
||||
callback(&self.target, event)
|
||||
callback(&self.target, event);
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button: ButtonSource::Touch { finger_id, force: None },
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
},
|
||||
xinput2::XI_TouchUpdate => {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id,
|
||||
position,
|
||||
source: PointerSource::Touch { finger_id, force: None },
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
},
|
||||
xinput2::XI_TouchEnd => {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button: ButtonSource::Touch { finger_id, force: None },
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
};
|
||||
callback(&self.target, event);
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1398,7 +1475,7 @@ impl EventProcessor {
|
|||
if let Some(mouse_delta) = mouse_delta.consume() {
|
||||
let event = Event::DeviceEvent {
|
||||
device_id: did,
|
||||
event: DeviceEvent::MouseMotion { delta: mouse_delta },
|
||||
event: DeviceEvent::PointerMotion { delta: mouse_delta },
|
||||
};
|
||||
callback(&self.target, event);
|
||||
}
|
||||
|
|
@ -1762,15 +1839,15 @@ impl EventProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_first_touch(first: &mut Option<u32>, num: &mut u32, id: u32, phase: TouchPhase) -> bool {
|
||||
fn is_first_touch(first: &mut Option<u32>, num: &mut u32, id: u32, phase: i32) -> bool {
|
||||
match phase {
|
||||
TouchPhase::Started => {
|
||||
xinput2::XI_TouchBegin => {
|
||||
if *num == 0 {
|
||||
*first = Some(id);
|
||||
}
|
||||
*num += 1;
|
||||
},
|
||||
TouchPhase::Cancelled | TouchPhase::Ended => {
|
||||
xinput2::XI_TouchEnd => {
|
||||
if *first == Some(id) {
|
||||
*first = None;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -407,11 +407,15 @@ impl EventLoop {
|
|||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::CursorMoved { device_id: None, position: (x, y).into() },
|
||||
event::WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position: (x, y).into(),
|
||||
source: event::PointerSource::Mouse,
|
||||
},
|
||||
);
|
||||
},
|
||||
EventOption::MouseRelative(MouseRelativeEvent { dx, dy }) => {
|
||||
app.device_event(window_target, None, event::DeviceEvent::MouseMotion {
|
||||
app.device_event(window_target, None, event::DeviceEvent::PointerMotion {
|
||||
delta: (dx as f64, dy as f64),
|
||||
});
|
||||
},
|
||||
|
|
@ -420,7 +424,12 @@ impl EventLoop {
|
|||
app.window_event(
|
||||
window_target,
|
||||
RootWindowId(window_id),
|
||||
event::WindowEvent::MouseInput { device_id: None, state, button },
|
||||
event::WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state,
|
||||
position: dpi::PhysicalPosition::default(),
|
||||
button: button.into(),
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
@ -469,9 +478,17 @@ impl EventLoop {
|
|||
// TODO: Screen, Clipboard, Drop
|
||||
EventOption::Hover(HoverEvent { entered }) => {
|
||||
let event = if entered {
|
||||
event::WindowEvent::CursorEntered { device_id: None }
|
||||
event::WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position: dpi::PhysicalPosition::default(),
|
||||
kind: event::PointerKind::Mouse,
|
||||
}
|
||||
} else {
|
||||
event::WindowEvent::CursorLeft { device_id: None }
|
||||
event::WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: None,
|
||||
kind: event::PointerKind::Mouse,
|
||||
}
|
||||
};
|
||||
|
||||
app.window_event(window_target, RootWindowId(window_id), event);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceId(u32);
|
||||
use crate::event::FingerId as RootFingerId;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeviceId(pub(crate) u32);
|
||||
|
||||
impl DeviceId {
|
||||
pub fn new(pointer_id: i32) -> Option<Self> {
|
||||
|
|
@ -34,3 +36,9 @@ impl FingerId {
|
|||
self.primary
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FingerId> for RootFingerId {
|
||||
fn from(id: FingerId) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ impl Shared {
|
|||
|
||||
runner.send_event(Event::DeviceEvent {
|
||||
device_id,
|
||||
event: DeviceEvent::Button { button: button.to_id(), state },
|
||||
event: DeviceEvent::Button { button: button.to_id().into(), state },
|
||||
});
|
||||
|
||||
return;
|
||||
|
|
@ -310,7 +310,7 @@ impl Shared {
|
|||
|
||||
Event::DeviceEvent {
|
||||
device_id,
|
||||
event: DeviceEvent::MouseMotion { delta: (delta.x, delta.y) },
|
||||
event: DeviceEvent::PointerMotion { delta: (delta.x, delta.y) },
|
||||
}
|
||||
}));
|
||||
}),
|
||||
|
|
@ -346,7 +346,7 @@ impl Shared {
|
|||
runner.send_event(Event::DeviceEvent {
|
||||
device_id: DeviceId::new(event.pointer_id()).map(RootDeviceId),
|
||||
event: DeviceEvent::Button {
|
||||
button: button.to_id(),
|
||||
button: button.to_id().into(),
|
||||
state: ElementState::Pressed,
|
||||
},
|
||||
});
|
||||
|
|
@ -365,7 +365,7 @@ impl Shared {
|
|||
runner.send_event(Event::DeviceEvent {
|
||||
device_id: DeviceId::new(event.pointer_id()).map(RootDeviceId),
|
||||
event: DeviceEvent::Button {
|
||||
button: button.to_id(),
|
||||
button: button.to_id().into(),
|
||||
state: ElementState::Released,
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ use super::window::WindowId;
|
|||
use super::{backend, runner, EventLoopProxy};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::event::{
|
||||
DeviceId as RootDeviceId, ElementState, Event, FingerId as RootFingerId, KeyEvent, Touch,
|
||||
TouchPhase, WindowEvent,
|
||||
DeviceId as RootDeviceId, ElementState, Event, KeyEvent, TouchPhase, WindowEvent,
|
||||
};
|
||||
use crate::event_loop::{
|
||||
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
|
||||
|
|
@ -200,12 +199,12 @@ impl ActiveEventLoop {
|
|||
);
|
||||
|
||||
let has_focus = canvas.has_focus.clone();
|
||||
canvas.on_cursor_leave({
|
||||
canvas.on_pointer_leave({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id| {
|
||||
move |active_modifiers, device_id, position, kind| {
|
||||
let focus = (has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
|
|
@ -214,23 +213,23 @@ impl ActiveEventLoop {
|
|||
}
|
||||
});
|
||||
|
||||
let pointer = pointer_id.map(|device_id| Event::WindowEvent {
|
||||
runner.send_events(focus.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorLeft { device_id: device_id.map(RootDeviceId) },
|
||||
});
|
||||
|
||||
if focus.is_some() || pointer.is_some() {
|
||||
runner.send_events(focus.into_iter().chain(pointer))
|
||||
}
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
position: Some(position),
|
||||
kind,
|
||||
},
|
||||
})))
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_cursor_enter({
|
||||
canvas.on_pointer_enter({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id| {
|
||||
move |active_modifiers, device_id, position, kind| {
|
||||
let focus = (has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
|
|
@ -239,51 +238,29 @@ impl ActiveEventLoop {
|
|||
}
|
||||
});
|
||||
|
||||
let pointer = pointer_id.map(|device_id| Event::WindowEvent {
|
||||
runner.send_events(focus.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorEntered { device_id: device_id.map(RootDeviceId) },
|
||||
});
|
||||
|
||||
if focus.is_some() || pointer.is_some() {
|
||||
runner.send_events(focus.into_iter().chain(pointer))
|
||||
}
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
position,
|
||||
kind,
|
||||
},
|
||||
})))
|
||||
}
|
||||
});
|
||||
|
||||
canvas.on_cursor_move(
|
||||
canvas.on_pointer_move(
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, pointer_id, events| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(events.flat_map(|position| {
|
||||
move |pointer_id, events| {
|
||||
runner.send_events(events.flat_map(|(active_modifiers, position, source)| {
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
|
||||
iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
})
|
||||
})));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, finger_id, events| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
let modifiers = (has_focus.get() && modifiers.get() != active_modifiers)
|
||||
.then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
|
|
@ -291,18 +268,11 @@ impl ActiveEventLoop {
|
|||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(events.map(
|
||||
|(location, force)| Event::WindowEvent {
|
||||
modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
phase: TouchPhase::Moved,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
},
|
||||
)));
|
||||
event: WindowEvent::PointerMoved { device_id, position, source },
|
||||
}))
|
||||
}));
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -310,11 +280,7 @@ impl ActiveEventLoop {
|
|||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers,
|
||||
device_id,
|
||||
position: crate::dpi::PhysicalPosition<f64>,
|
||||
buttons,
|
||||
button| {
|
||||
move |active_modifiers, device_id, position, state, button| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
|
|
@ -326,31 +292,15 @@ impl ActiveEventLoop {
|
|||
|
||||
let device_id = device_id.map(RootDeviceId);
|
||||
|
||||
let state = if buttons.contains(button.into()) {
|
||||
ElementState::Pressed
|
||||
} else {
|
||||
ElementState::Released
|
||||
};
|
||||
|
||||
// A chorded button event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(modifiers.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
runner.send_events(modifiers.into_iter().chain([Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput { device_id, state, button },
|
||||
},
|
||||
]));
|
||||
event: WindowEvent::PointerButton { device_id, state, position, button },
|
||||
}]));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
canvas.on_mouse_press(
|
||||
{
|
||||
canvas.on_pointer_press({
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
|
|
@ -364,57 +314,19 @@ impl ActiveEventLoop {
|
|||
});
|
||||
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
|
||||
// A mouse down event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(modifiers.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
runner.send_events(modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput {
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Pressed,
|
||||
position,
|
||||
button,
|
||||
},
|
||||
},
|
||||
]));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, finger_id, location, force| {
|
||||
let modifiers = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
})));
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
phase: TouchPhase::Started,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
},
|
||||
)))
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
canvas.on_mouse_release(
|
||||
{
|
||||
canvas.on_pointer_release({
|
||||
let runner = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
|
@ -431,56 +343,18 @@ impl ActiveEventLoop {
|
|||
|
||||
let device_id = pointer_id.map(RootDeviceId);
|
||||
|
||||
// A mouse up event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(modifiers.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
runner.send_events(modifiers.into_iter().chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved { device_id, position },
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput {
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id,
|
||||
state: ElementState::Released,
|
||||
position,
|
||||
button,
|
||||
},
|
||||
},
|
||||
]));
|
||||
}
|
||||
},
|
||||
{
|
||||
let runner_touch = self.runner.clone();
|
||||
let has_focus = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers, device_id, finger_id, location, force| {
|
||||
let modifiers =
|
||||
(has_focus.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
})));
|
||||
}
|
||||
});
|
||||
|
||||
runner_touch.send_events(modifiers.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
phase: TouchPhase::Ended,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
},
|
||||
)));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
canvas.on_mouse_wheel(move |delta, active_modifiers| {
|
||||
|
|
@ -505,20 +379,6 @@ impl ActiveEventLoop {
|
|||
)));
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_touch_cancel(move |device_id, finger_id, location, force| {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
finger_id: RootFingerId(finger_id),
|
||||
device_id: device_id.map(RootDeviceId),
|
||||
phase: TouchPhase::Cancelled,
|
||||
force: Some(force),
|
||||
location,
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_dark_mode(move |is_dark_mode| {
|
||||
let theme = if is_dark_mode { Theme::Dark } else { Theme::Light };
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use web_sys::{
|
|||
};
|
||||
|
||||
use super::super::cursor::CursorHandler;
|
||||
use super::super::event::{DeviceId, FingerId};
|
||||
use super::super::event::DeviceId;
|
||||
use super::super::main_thread::MainThreadMarker;
|
||||
use super::super::WindowId;
|
||||
use super::animation_frame::AnimationFrameHandler;
|
||||
|
|
@ -20,10 +20,12 @@ use super::event_handle::EventListenerHandle;
|
|||
use super::intersection_handle::IntersectionObserverHandle;
|
||||
use super::media_query_handle::MediaQueryListHandle;
|
||||
use super::pointer::PointerHandler;
|
||||
use super::{event, fullscreen, ButtonsState, ResizeScaleHandle};
|
||||
use super::{event, fullscreen, ResizeScaleHandle};
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
|
||||
use crate::error::RequestError;
|
||||
use crate::event::{Force, MouseButton, MouseScrollDelta, SurfaceSizeWriter};
|
||||
use crate::event::{
|
||||
ButtonSource, ElementState, MouseScrollDelta, PointerKind, PointerSource, SurfaceSizeWriter,
|
||||
};
|
||||
use crate::keyboard::{Key, KeyLocation, ModifiersState, PhysicalKey};
|
||||
use crate::platform_impl::Fullscreen;
|
||||
use crate::window::{WindowAttributes, WindowId as RootWindowId};
|
||||
|
|
@ -328,83 +330,62 @@ impl Canvas {
|
|||
}));
|
||||
}
|
||||
|
||||
pub fn on_cursor_leave<F>(&self, handler: F)
|
||||
pub fn on_pointer_leave<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<Option<DeviceId>>),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_cursor_leave(&self.common, handler)
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_leave(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_cursor_enter<F>(&self, handler: F)
|
||||
pub fn on_pointer_enter<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<Option<DeviceId>>),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_cursor_enter(&self.common, handler)
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_enter(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_mouse_release<M, T>(&self, mouse_handler: M, touch_handler: T)
|
||||
pub fn on_pointer_release<C>(&self, handler: C)
|
||||
where
|
||||
M: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_mouse_release(
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_release(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_pointer_press<C>(&self, handler: C)
|
||||
where
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_press(
|
||||
&self.common,
|
||||
mouse_handler,
|
||||
touch_handler,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_mouse_press<M, T>(&self, mouse_handler: M, touch_handler: T)
|
||||
where
|
||||
M: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_mouse_press(
|
||||
&self.common,
|
||||
mouse_handler,
|
||||
touch_handler,
|
||||
handler,
|
||||
Rc::clone(&self.prevent_default),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_cursor_move<M, T, B>(&self, mouse_handler: M, touch_handler: T, button_handler: B)
|
||||
pub fn on_pointer_move<C, B>(&self, cursor_handler: C, button_handler: B)
|
||||
where
|
||||
M: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, &mut dyn Iterator<Item = PhysicalPosition<f64>>),
|
||||
T: 'static
|
||||
C: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
FingerId,
|
||||
&mut dyn Iterator<Item = (PhysicalPosition<f64>, Force)>,
|
||||
&mut dyn Iterator<Item = (ModifiersState, PhysicalPosition<f64>, PointerSource)>,
|
||||
),
|
||||
B: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
PhysicalPosition<f64>,
|
||||
ButtonsState,
|
||||
MouseButton,
|
||||
ElementState,
|
||||
ButtonSource,
|
||||
),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_cursor_move(
|
||||
self.handlers.borrow_mut().pointer_handler.on_pointer_move(
|
||||
&self.common,
|
||||
mouse_handler,
|
||||
touch_handler,
|
||||
cursor_handler,
|
||||
button_handler,
|
||||
Rc::clone(&self.prevent_default),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn on_touch_cancel<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
self.handlers.borrow_mut().pointer_handler.on_touch_cancel(&self.common, handler)
|
||||
}
|
||||
|
||||
pub fn on_mouse_wheel<F>(&self, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(MouseScrollDelta, ModifiersState),
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ use wasm_bindgen::prelude::wasm_bindgen;
|
|||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use web_sys::{KeyboardEvent, MouseEvent, Navigator, PointerEvent, WheelEvent};
|
||||
|
||||
use super::super::FingerId;
|
||||
use super::Engine;
|
||||
use crate::event::{MouseButton, MouseScrollDelta};
|
||||
use crate::event::{MouseButton, MouseScrollDelta, PointerKind};
|
||||
use crate::keyboard::{Key, KeyLocation, ModifiersState, NamedKey, PhysicalKey};
|
||||
|
||||
bitflags::bitflags! {
|
||||
|
|
@ -68,14 +69,14 @@ pub fn mouse_button(event: &MouseEvent) -> Option<MouseButton> {
|
|||
}
|
||||
|
||||
impl MouseButton {
|
||||
pub fn to_id(self) -> u32 {
|
||||
pub fn to_id(self) -> u16 {
|
||||
match self {
|
||||
MouseButton::Left => 0,
|
||||
MouseButton::Right => 1,
|
||||
MouseButton::Middle => 2,
|
||||
MouseButton::Back => 3,
|
||||
MouseButton::Forward => 4,
|
||||
MouseButton::Other(value) => value.into(),
|
||||
MouseButton::Other(value) => value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -160,6 +161,14 @@ pub fn mouse_scroll_delta(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pointer_type(event: &PointerEvent, pointer_id: i32) -> PointerKind {
|
||||
match event.pointer_type().as_str() {
|
||||
"mouse" => PointerKind::Mouse,
|
||||
"touch" => PointerKind::Touch(FingerId::new(pointer_id, event.is_primary()).into()),
|
||||
_ => PointerKind::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn key_code(event: &KeyboardEvent) -> PhysicalKey {
|
||||
let code = event.code();
|
||||
PhysicalKey::from_key_code_attribute_value(&code)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ use wasm_bindgen::JsCast;
|
|||
use web_sys::{Document, HtmlCanvasElement, Navigator, PageTransitionEvent, VisibilityState};
|
||||
|
||||
pub use self::canvas::{Canvas, Style};
|
||||
pub use self::event::ButtonsState;
|
||||
pub use self::event_handle::EventListenerHandle;
|
||||
pub use self::resize_scaling::ResizeScaleHandle;
|
||||
pub use self::schedule::Schedule;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use event::ButtonsState;
|
||||
use web_sys::PointerEvent;
|
||||
|
||||
use super::super::event::{DeviceId, FingerId};
|
||||
use super::super::event::DeviceId;
|
||||
use super::canvas::Common;
|
||||
use super::event;
|
||||
use super::event_handle::EventListenerHandle;
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::event::{Force, MouseButton};
|
||||
use crate::event::{ButtonSource, ElementState, Force, PointerKind, PointerSource};
|
||||
use crate::keyboard::ModifiersState;
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -34,88 +33,78 @@ impl PointerHandler {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn on_cursor_leave<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
pub fn on_pointer_leave<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<Option<DeviceId>>),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_cursor_leave =
|
||||
Some(canvas_common.add_event("pointerout", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
|
||||
// touch events are handled separately
|
||||
// handling them here would produce duplicate mouse events, inconsistent with
|
||||
// other platforms.
|
||||
let device_id =
|
||||
(event.pointer_type() != "touch").then(|| DeviceId::new(event.pointer_id()));
|
||||
|
||||
handler(modifiers, device_id);
|
||||
let pointer_id = event.pointer_id();
|
||||
let device_id = DeviceId::new(pointer_id);
|
||||
let position =
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window));
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
handler(modifiers, device_id, position, kind);
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_cursor_enter<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
pub fn on_pointer_enter<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ModifiersState, Option<Option<DeviceId>>),
|
||||
F: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, PointerKind),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_cursor_enter =
|
||||
Some(canvas_common.add_event("pointerover", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
|
||||
// touch events are handled separately
|
||||
// handling them here would produce duplicate mouse events, inconsistent with
|
||||
// other platforms.
|
||||
let device_id =
|
||||
(event.pointer_type() != "touch").then(|| DeviceId::new(event.pointer_id()));
|
||||
|
||||
handler(modifiers, device_id);
|
||||
let pointer_id = event.pointer_id();
|
||||
let device_id = DeviceId::new(pointer_id);
|
||||
let position =
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window));
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
handler(modifiers, device_id, position, kind);
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_mouse_release<M, T>(
|
||||
&mut self,
|
||||
canvas_common: &Common,
|
||||
mut mouse_handler: M,
|
||||
mut touch_handler: T,
|
||||
) where
|
||||
M: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
pub fn on_pointer_release<C>(&mut self, canvas_common: &Common, mut handler: C)
|
||||
where
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_pointer_release =
|
||||
Some(canvas_common.add_event("pointerup", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
|
||||
match event.pointer_type().as_str() {
|
||||
"touch" => {
|
||||
let pointer_id = event.pointer_id();
|
||||
touch_handler(
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
|
||||
let button = event::mouse_button(&event).expect("no mouse button pressed");
|
||||
|
||||
let source = match kind {
|
||||
PointerKind::Mouse => ButtonSource::Mouse(button),
|
||||
PointerKind::Touch(finger_id) => ButtonSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
},
|
||||
PointerKind::Unknown => ButtonSource::Unknown(button.to_id()),
|
||||
};
|
||||
|
||||
handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
source,
|
||||
)
|
||||
},
|
||||
_ => mouse_handler(
|
||||
modifiers,
|
||||
DeviceId::new(event.pointer_id()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
event::mouse_button(&event).expect("no mouse button released"),
|
||||
),
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_mouse_press<M, T>(
|
||||
pub fn on_pointer_press<C>(
|
||||
&mut self,
|
||||
canvas_common: &Common,
|
||||
mut mouse_handler: M,
|
||||
mut touch_handler: T,
|
||||
mut handler: C,
|
||||
prevent_default: Rc<Cell<bool>>,
|
||||
) where
|
||||
M: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, MouseButton),
|
||||
T: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
C: 'static + FnMut(ModifiersState, Option<DeviceId>, PhysicalPosition<f64>, ButtonSource),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
let canvas = canvas_common.raw().clone();
|
||||
|
|
@ -129,75 +118,65 @@ impl PointerHandler {
|
|||
}
|
||||
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_type = &event.pointer_type();
|
||||
|
||||
match pointer_type.as_str() {
|
||||
"touch" => {
|
||||
let pointer_id = event.pointer_id();
|
||||
touch_handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
);
|
||||
},
|
||||
_ => {
|
||||
let pointer_id = event.pointer_id();
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
let button = event::mouse_button(&event).expect("no mouse button pressed");
|
||||
|
||||
mouse_handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
event::mouse_button(&event).expect("no mouse button pressed"),
|
||||
);
|
||||
|
||||
if pointer_type == "mouse" {
|
||||
let source = match kind {
|
||||
PointerKind::Mouse => {
|
||||
// Error is swallowed here since the error would occur every time the
|
||||
// mouse is clicked when the cursor is
|
||||
// grabbed, and there is probably not a
|
||||
// situation where this could fail, that we
|
||||
// care if it fails.
|
||||
let _e = canvas.set_pointer_capture(pointer_id);
|
||||
}
|
||||
|
||||
ButtonSource::Mouse(button)
|
||||
},
|
||||
}
|
||||
PointerKind::Touch(finger_id) => ButtonSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
},
|
||||
PointerKind::Unknown => ButtonSource::Unknown(button.to_id()),
|
||||
};
|
||||
|
||||
handler(
|
||||
modifiers,
|
||||
DeviceId::new(pointer_id),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
source,
|
||||
)
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_cursor_move<M, T, B>(
|
||||
pub fn on_pointer_move<C, B>(
|
||||
&mut self,
|
||||
canvas_common: &Common,
|
||||
mut mouse_handler: M,
|
||||
mut touch_handler: T,
|
||||
mut cursor_handler: C,
|
||||
mut button_handler: B,
|
||||
prevent_default: Rc<Cell<bool>>,
|
||||
) where
|
||||
M: 'static
|
||||
+ FnMut(ModifiersState, Option<DeviceId>, &mut dyn Iterator<Item = PhysicalPosition<f64>>),
|
||||
T: 'static
|
||||
C: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
FingerId,
|
||||
&mut dyn Iterator<Item = (PhysicalPosition<f64>, Force)>,
|
||||
&mut dyn Iterator<Item = (ModifiersState, PhysicalPosition<f64>, PointerSource)>,
|
||||
),
|
||||
B: 'static
|
||||
+ FnMut(
|
||||
ModifiersState,
|
||||
Option<DeviceId>,
|
||||
PhysicalPosition<f64>,
|
||||
ButtonsState,
|
||||
MouseButton,
|
||||
ElementState,
|
||||
ButtonSource,
|
||||
),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
let canvas = canvas_common.raw().clone();
|
||||
self.on_cursor_move =
|
||||
Some(canvas_common.add_event("pointermove", move |event: PointerEvent| {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
let pointer_id = event.pointer_id();
|
||||
let device_id = DeviceId::new(pointer_id);
|
||||
let kind = event::pointer_type(&event, pointer_id);
|
||||
|
||||
// chorded button event
|
||||
if let Some(button) = event::mouse_button(&event) {
|
||||
|
|
@ -208,11 +187,34 @@ impl PointerHandler {
|
|||
let _ = canvas.focus();
|
||||
}
|
||||
|
||||
let state = if event::mouse_buttons(&event).contains(button.into()) {
|
||||
ElementState::Pressed
|
||||
} else {
|
||||
ElementState::Released
|
||||
};
|
||||
|
||||
let button = match kind {
|
||||
PointerKind::Mouse => ButtonSource::Mouse(button),
|
||||
PointerKind::Touch(finger_id) => {
|
||||
let button_id = button.to_id();
|
||||
|
||||
if button_id != 1 {
|
||||
tracing::error!("unexpected touch button id: {button_id}");
|
||||
}
|
||||
|
||||
ButtonSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
}
|
||||
},
|
||||
PointerKind::Unknown => todo!(),
|
||||
};
|
||||
|
||||
button_handler(
|
||||
modifiers,
|
||||
event::mouse_modifiers(&event),
|
||||
device_id,
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
event::mouse_buttons(&event),
|
||||
state,
|
||||
button,
|
||||
);
|
||||
|
||||
|
|
@ -221,44 +223,24 @@ impl PointerHandler {
|
|||
|
||||
// pointer move event
|
||||
let scale = super::scale_factor(&window);
|
||||
match event.pointer_type().as_str() {
|
||||
"touch" => touch_handler(
|
||||
modifiers,
|
||||
|
||||
cursor_handler(
|
||||
device_id,
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
&mut event::pointer_move_event(event).map(|event| {
|
||||
(
|
||||
event::mouse_modifiers(&event),
|
||||
event::mouse_position(&event).to_physical(scale),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
match kind {
|
||||
PointerKind::Mouse => PointerSource::Mouse,
|
||||
PointerKind::Touch(finger_id) => PointerSource::Touch {
|
||||
finger_id,
|
||||
force: Some(Force::Normalized(event.pressure().into())),
|
||||
},
|
||||
PointerKind::Unknown => PointerSource::Unknown,
|
||||
},
|
||||
)
|
||||
}),
|
||||
),
|
||||
_ => mouse_handler(
|
||||
modifiers,
|
||||
device_id,
|
||||
&mut event::pointer_move_event(event)
|
||||
.map(|event| event::mouse_position(&event).to_physical(scale)),
|
||||
),
|
||||
};
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn on_touch_cancel<F>(&mut self, canvas_common: &Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(Option<DeviceId>, FingerId, PhysicalPosition<f64>, Force),
|
||||
{
|
||||
let window = canvas_common.window.clone();
|
||||
self.on_touch_cancel =
|
||||
Some(canvas_common.add_event("pointercancel", move |event: PointerEvent| {
|
||||
if event.pointer_type() == "touch" {
|
||||
let pointer_id = event.pointer_id();
|
||||
handler(
|
||||
DeviceId::new(pointer_id),
|
||||
FingerId::new(pointer_id, event.is_primary()),
|
||||
event::mouse_position(&event).to_physical(super::scale_factor(&window)),
|
||||
Force::Normalized(event.pressure() as f64),
|
||||
);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@ use windows_sys::Win32::UI::WindowsAndMessaging::{
|
|||
GetMenu, GetMessageW, KillTimer, LoadCursorW, PeekMessageW, PostMessageW, RegisterClassExW,
|
||||
RegisterWindowMessageA, SetCursor, SetTimer, SetWindowPos, TranslateMessage, CREATESTRUCTW,
|
||||
GWL_STYLE, GWL_USERDATA, HTCAPTION, HTCLIENT, MINMAXINFO, MNC_CLOSE, MSG, NCCALCSIZE_PARAMS,
|
||||
PM_REMOVE, PT_PEN, PT_TOUCH, RI_MOUSE_HWHEEL, RI_MOUSE_WHEEL, SC_MINIMIZE, SC_RESTORE,
|
||||
SIZE_MAXIMIZED, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, SWP_NOZORDER, WHEEL_DELTA, WINDOWPOS,
|
||||
WMSZ_BOTTOM, WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT, WMSZ_LEFT, WMSZ_RIGHT, WMSZ_TOP, WMSZ_TOPLEFT,
|
||||
PM_REMOVE, PT_TOUCH, RI_MOUSE_HWHEEL, RI_MOUSE_WHEEL, SC_MINIMIZE, SC_RESTORE, SIZE_MAXIMIZED,
|
||||
SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, SWP_NOZORDER, WHEEL_DELTA, WINDOWPOS, WMSZ_BOTTOM,
|
||||
WMSZ_BOTTOMLEFT, WMSZ_BOTTOMRIGHT, WMSZ_LEFT, WMSZ_RIGHT, WMSZ_TOP, WMSZ_TOPLEFT,
|
||||
WMSZ_TOPRIGHT, WM_CAPTURECHANGED, WM_CLOSE, WM_CREATE, WM_DESTROY, WM_DPICHANGED,
|
||||
WM_ENTERSIZEMOVE, WM_EXITSIZEMOVE, WM_GETMINMAXINFO, WM_IME_COMPOSITION, WM_IME_ENDCOMPOSITION,
|
||||
WM_IME_SETCONTEXT, WM_IME_STARTCOMPOSITION, WM_INPUT, WM_KEYDOWN, WM_KEYUP, WM_KILLFOCUS,
|
||||
|
|
@ -58,7 +58,7 @@ use crate::application::ApplicationHandler;
|
|||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::error::{EventLoopError, RequestError};
|
||||
use crate::event::{
|
||||
Event, FingerId as RootFingerId, Force, Ime, RawKeyEvent, SurfaceSizeWriter, Touch, TouchPhase,
|
||||
Event, FingerId as RootFingerId, Force, Ime, RawKeyEvent, SurfaceSizeWriter, TouchPhase,
|
||||
WindowEvent,
|
||||
};
|
||||
use crate::event_loop::{
|
||||
|
|
@ -1520,7 +1520,8 @@ unsafe fn public_window_callback_inner(
|
|||
},
|
||||
|
||||
WM_MOUSEMOVE => {
|
||||
use crate::event::WindowEvent::{CursorEntered, CursorLeft, CursorMoved};
|
||||
use crate::event::WindowEvent::{PointerEntered, PointerLeft, PointerMoved};
|
||||
use crate::event::{PointerKind, PointerSource};
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
|
|
@ -1541,7 +1542,11 @@ unsafe fn public_window_callback_inner(
|
|||
drop(w);
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CursorEntered { device_id: None },
|
||||
event: PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
});
|
||||
|
||||
// Calling TrackMouseEvent in order to receive mouse leave events.
|
||||
|
|
@ -1562,7 +1567,11 @@ unsafe fn public_window_callback_inner(
|
|||
drop(w);
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CursorLeft { device_id: None },
|
||||
event: PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Mouse,
|
||||
},
|
||||
});
|
||||
},
|
||||
PointerMoveKind::None => drop(w),
|
||||
|
|
@ -1581,7 +1590,7 @@ unsafe fn public_window_callback_inner(
|
|||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CursorMoved { device_id: None, position },
|
||||
event: PointerMoved { device_id: None, position, source: PointerSource::Mouse },
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1589,7 +1598,9 @@ unsafe fn public_window_callback_inner(
|
|||
},
|
||||
|
||||
WM_MOUSELEAVE => {
|
||||
use crate::event::WindowEvent::CursorLeft;
|
||||
use crate::event::PointerKind::Mouse;
|
||||
use crate::event::WindowEvent::PointerLeft;
|
||||
|
||||
{
|
||||
let mut w = userdata.window_state_lock();
|
||||
w.mouse.set_cursor_flags(window, |f| f.set(CursorFlags::IN_WINDOW, false)).ok();
|
||||
|
|
@ -1597,7 +1608,7 @@ unsafe fn public_window_callback_inner(
|
|||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: CursorLeft { device_id: None },
|
||||
event: PointerLeft { device_id: None, position: None, kind: Mouse },
|
||||
});
|
||||
|
||||
result = ProcResult::Value(0);
|
||||
|
|
@ -1660,15 +1671,24 @@ unsafe fn public_window_callback_inner(
|
|||
WM_LBUTTONDOWN => {
|
||||
use crate::event::ElementState::Pressed;
|
||||
use crate::event::MouseButton::Left;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
|
||||
unsafe { capture_mouse(window, &mut userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: None, state: Pressed, button: Left },
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: Left.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
|
|
@ -1676,15 +1696,24 @@ unsafe fn public_window_callback_inner(
|
|||
WM_LBUTTONUP => {
|
||||
use crate::event::ElementState::Released;
|
||||
use crate::event::MouseButton::Left;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
|
||||
unsafe { release_mouse(userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: None, state: Released, button: Left },
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: Left.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
|
|
@ -1692,15 +1721,24 @@ unsafe fn public_window_callback_inner(
|
|||
WM_RBUTTONDOWN => {
|
||||
use crate::event::ElementState::Pressed;
|
||||
use crate::event::MouseButton::Right;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
|
||||
unsafe { capture_mouse(window, &mut userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: None, state: Pressed, button: Right },
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: Right.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
|
|
@ -1708,15 +1746,24 @@ unsafe fn public_window_callback_inner(
|
|||
WM_RBUTTONUP => {
|
||||
use crate::event::ElementState::Released;
|
||||
use crate::event::MouseButton::Right;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
|
||||
unsafe { release_mouse(userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: None, state: Released, button: Right },
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: Right.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
|
|
@ -1724,15 +1771,24 @@ unsafe fn public_window_callback_inner(
|
|||
WM_MBUTTONDOWN => {
|
||||
use crate::event::ElementState::Pressed;
|
||||
use crate::event::MouseButton::Middle;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
|
||||
unsafe { capture_mouse(window, &mut userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: None, state: Pressed, button: Middle },
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: Middle.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
|
|
@ -1740,15 +1796,24 @@ unsafe fn public_window_callback_inner(
|
|||
WM_MBUTTONUP => {
|
||||
use crate::event::ElementState::Released;
|
||||
use crate::event::MouseButton::Middle;
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
|
||||
unsafe { release_mouse(userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput { device_id: None, state: Released, button: Middle },
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: Middle.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
},
|
||||
|
|
@ -1756,23 +1821,29 @@ unsafe fn public_window_callback_inner(
|
|||
WM_XBUTTONDOWN => {
|
||||
use crate::event::ElementState::Pressed;
|
||||
use crate::event::MouseButton::{Back, Forward, Other};
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
let xbutton = super::get_xbutton_wparam(wparam as u32);
|
||||
|
||||
unsafe { capture_mouse(window, &mut userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput {
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: match xbutton {
|
||||
1 => Back,
|
||||
2 => Forward,
|
||||
_ => Other(xbutton),
|
||||
},
|
||||
}
|
||||
.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
|
|
@ -1781,23 +1852,29 @@ unsafe fn public_window_callback_inner(
|
|||
WM_XBUTTONUP => {
|
||||
use crate::event::ElementState::Released;
|
||||
use crate::event::MouseButton::{Back, Forward, Other};
|
||||
use crate::event::WindowEvent::MouseInput;
|
||||
use crate::event::WindowEvent::PointerButton;
|
||||
let xbutton = super::get_xbutton_wparam(wparam as u32);
|
||||
|
||||
unsafe { release_mouse(userdata.window_state_lock()) };
|
||||
|
||||
update_modifiers(window, userdata);
|
||||
|
||||
let x = super::get_x_lparam(lparam as u32) as i32;
|
||||
let y = super::get_y_lparam(lparam as u32) as i32;
|
||||
let position = PhysicalPosition::new(x as f64, y as f64);
|
||||
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: MouseInput {
|
||||
event: PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: match xbutton {
|
||||
1 => Back,
|
||||
2 => Forward,
|
||||
_ => Other(xbutton),
|
||||
},
|
||||
}
|
||||
.into(),
|
||||
},
|
||||
});
|
||||
result = ProcResult::Value(0);
|
||||
|
|
@ -1815,6 +1892,10 @@ unsafe fn public_window_callback_inner(
|
|||
},
|
||||
|
||||
WM_TOUCH => {
|
||||
use crate::event::ButtonSource::Touch;
|
||||
use crate::event::ElementState::{Pressed, Released};
|
||||
use crate::event::{PointerKind, PointerSource};
|
||||
|
||||
let pcount = super::loword(wparam as u32) as usize;
|
||||
let mut inputs = Vec::with_capacity(pcount);
|
||||
let htouch = lparam;
|
||||
|
|
@ -1828,36 +1909,70 @@ unsafe fn public_window_callback_inner(
|
|||
} {
|
||||
unsafe { inputs.set_len(pcount) };
|
||||
for input in &inputs {
|
||||
let mut location = POINT { x: input.x / 100, y: input.y / 100 };
|
||||
let mut position = POINT { x: input.x / 100, y: input.y / 100 };
|
||||
|
||||
if unsafe { ScreenToClient(window, &mut location) } == false.into() {
|
||||
if unsafe { ScreenToClient(window, &mut position) } == false.into() {
|
||||
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);
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
phase: if util::has_flag(input.dwFlags, TOUCHEVENTF_DOWN) {
|
||||
TouchPhase::Started
|
||||
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_UP) {
|
||||
TouchPhase::Ended
|
||||
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_MOVE) {
|
||||
TouchPhase::Moved
|
||||
} else {
|
||||
continue;
|
||||
},
|
||||
location,
|
||||
force: None, // WM_TOUCH doesn't support pressure information
|
||||
finger_id: RootFingerId(FingerId {
|
||||
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 window_id = CoreWindowId(WindowId(window));
|
||||
let finger_id = RootFingerId(FingerId {
|
||||
id: input.dwID,
|
||||
primary: util::has_flag(input.dwFlags, TOUCHEVENTF_PRIMARY),
|
||||
}),
|
||||
device_id: None,
|
||||
}),
|
||||
});
|
||||
|
||||
if util::has_flag(input.dwFlags, TOUCHEVENTF_DOWN) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: Touch { finger_id, force: None },
|
||||
},
|
||||
});
|
||||
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_UP) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: Touch { finger_id, force: None },
|
||||
},
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: PointerKind::Touch(finger_id),
|
||||
},
|
||||
});
|
||||
} else if util::has_flag(input.dwFlags, TOUCHEVENTF_MOVE) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position,
|
||||
source: PointerSource::Touch { finger_id, force: None },
|
||||
},
|
||||
});
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe { CloseTouchInputHandle(htouch) };
|
||||
|
|
@ -1865,6 +1980,9 @@ unsafe fn public_window_callback_inner(
|
|||
},
|
||||
|
||||
WM_POINTERDOWN | WM_POINTERUPDATE | WM_POINTERUP => {
|
||||
use crate::event::ElementState::{Pressed, Released};
|
||||
use crate::event::{ButtonSource, PointerKind, PointerSource};
|
||||
|
||||
if let (
|
||||
Some(GetPointerFrameInfoHistory),
|
||||
Some(SkipPointerFrameMessages),
|
||||
|
|
@ -1949,15 +2067,11 @@ unsafe fn public_window_callback_inner(
|
|||
continue;
|
||||
}
|
||||
|
||||
let force = match pointer_info.pointerType {
|
||||
PT_TOUCH => {
|
||||
let force = if let PT_TOUCH = pointer_info.pointerType {
|
||||
let mut touch_info = mem::MaybeUninit::uninit();
|
||||
util::GET_POINTER_TOUCH_INFO.and_then(|GetPointerTouchInfo| {
|
||||
match unsafe {
|
||||
GetPointerTouchInfo(
|
||||
pointer_info.pointerId,
|
||||
touch_info.as_mut_ptr(),
|
||||
)
|
||||
GetPointerTouchInfo(pointer_info.pointerId, touch_info.as_mut_ptr())
|
||||
} {
|
||||
0 => None,
|
||||
_ => normalize_pointer_pressure(unsafe {
|
||||
|
|
@ -1965,51 +2079,88 @@ unsafe fn public_window_callback_inner(
|
|||
}),
|
||||
}
|
||||
})
|
||||
},
|
||||
PT_PEN => {
|
||||
let mut pen_info = mem::MaybeUninit::uninit();
|
||||
util::GET_POINTER_PEN_INFO.and_then(|GetPointerPenInfo| {
|
||||
match unsafe {
|
||||
GetPointerPenInfo(pointer_info.pointerId, pen_info.as_mut_ptr())
|
||||
} {
|
||||
0 => None,
|
||||
_ => normalize_pointer_pressure(unsafe {
|
||||
pen_info.assume_init().pressure
|
||||
}),
|
||||
}
|
||||
})
|
||||
},
|
||||
_ => None,
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let x = location.x as f64 + x.fract();
|
||||
let y = location.y as f64 + y.fract();
|
||||
let location = PhysicalPosition::new(x, y);
|
||||
let position = PhysicalPosition::new(x, y);
|
||||
|
||||
let window_id = CoreWindowId(WindowId(window));
|
||||
let finger_id = RootFingerId(FingerId {
|
||||
id: pointer_info.pointerId,
|
||||
primary: util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_PRIMARY),
|
||||
});
|
||||
|
||||
if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_DOWN) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id: CoreWindowId(WindowId(window)),
|
||||
event: WindowEvent::Touch(Touch {
|
||||
phase: if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_DOWN) {
|
||||
TouchPhase::Started
|
||||
window_id,
|
||||
event: WindowEvent::PointerEntered {
|
||||
device_id: None,
|
||||
position,
|
||||
kind: if let PT_TOUCH = pointer_info.pointerType {
|
||||
PointerKind::Touch(finger_id)
|
||||
} else {
|
||||
PointerKind::Unknown
|
||||
},
|
||||
},
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: Pressed,
|
||||
position,
|
||||
button: if let PT_TOUCH = pointer_info.pointerType {
|
||||
ButtonSource::Touch { finger_id, force }
|
||||
} else {
|
||||
ButtonSource::Unknown(0)
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UP) {
|
||||
TouchPhase::Ended
|
||||
} else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UPDATE)
|
||||
{
|
||||
TouchPhase::Moved
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerButton {
|
||||
device_id: None,
|
||||
state: Released,
|
||||
position,
|
||||
button: if let PT_TOUCH = pointer_info.pointerType {
|
||||
ButtonSource::Touch { finger_id, force }
|
||||
} else {
|
||||
ButtonSource::Unknown(0)
|
||||
},
|
||||
},
|
||||
});
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerLeft {
|
||||
device_id: None,
|
||||
position: Some(position),
|
||||
kind: if let PT_TOUCH = pointer_info.pointerType {
|
||||
PointerKind::Touch(finger_id)
|
||||
} else {
|
||||
PointerKind::Unknown
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UPDATE) {
|
||||
userdata.send_event(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::PointerMoved {
|
||||
device_id: None,
|
||||
position,
|
||||
source: if let PT_TOUCH = pointer_info.pointerType {
|
||||
PointerSource::Touch { finger_id, force }
|
||||
} else {
|
||||
PointerSource::Unknown
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
continue;
|
||||
},
|
||||
location,
|
||||
force,
|
||||
finger_id: RootFingerId(FingerId {
|
||||
id: pointer_info.pointerId,
|
||||
primary: util::has_flag(
|
||||
pointer_info.pointerFlags,
|
||||
POINTER_FLAG_PRIMARY,
|
||||
),
|
||||
}),
|
||||
device_id: None,
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
unsafe { SkipPointerFrameMessages(pointer_id) };
|
||||
|
|
@ -2431,7 +2582,7 @@ unsafe extern "system" fn thread_event_target_callback(
|
|||
}
|
||||
|
||||
unsafe fn handle_raw_input(userdata: &ThreadMsgTargetData, data: RAWINPUT) {
|
||||
use crate::event::DeviceEvent::{Button, Key, MouseMotion, MouseWheel};
|
||||
use crate::event::DeviceEvent::{Button, Key, MouseWheel, PointerMotion};
|
||||
use crate::event::ElementState::{Pressed, Released};
|
||||
use crate::event::MouseScrollDelta::LineDelta;
|
||||
|
||||
|
|
@ -2447,7 +2598,7 @@ unsafe fn handle_raw_input(userdata: &ThreadMsgTargetData, data: RAWINPUT) {
|
|||
if x != 0.0 || y != 0.0 {
|
||||
userdata.send_event(Event::DeviceEvent {
|
||||
device_id,
|
||||
event: MouseMotion { delta: (x, y) },
|
||||
event: PointerMotion { delta: (x, y) },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use windows_sys::Win32::UI::HiDpi::{
|
|||
DPI_AWARENESS_CONTEXT, MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS,
|
||||
};
|
||||
use windows_sys::Win32::UI::Input::KeyboardAndMouse::GetActiveWindow;
|
||||
use windows_sys::Win32::UI::Input::Pointer::{POINTER_INFO, POINTER_PEN_INFO, POINTER_TOUCH_INFO};
|
||||
use windows_sys::Win32::UI::Input::Pointer::{POINTER_INFO, POINTER_TOUCH_INFO};
|
||||
use windows_sys::Win32::UI::WindowsAndMessaging::{
|
||||
ClipCursor, GetClientRect, GetClipCursor, GetSystemMetrics, GetWindowPlacement, GetWindowRect,
|
||||
IsIconic, ShowCursor, IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM,
|
||||
|
|
@ -244,9 +244,6 @@ pub type GetPointerDeviceRects = unsafe extern "system" fn(
|
|||
pub type GetPointerTouchInfo =
|
||||
unsafe extern "system" fn(pointerId: u32, touchInfo: *mut POINTER_TOUCH_INFO) -> BOOL;
|
||||
|
||||
pub type GetPointerPenInfo =
|
||||
unsafe extern "system" fn(pointId: u32, penInfo: *mut POINTER_PEN_INFO) -> BOOL;
|
||||
|
||||
pub(crate) static GET_DPI_FOR_WINDOW: Lazy<Option<GetDpiForWindow>> =
|
||||
Lazy::new(|| get_function!("user32.dll", GetDpiForWindow));
|
||||
pub(crate) static ADJUST_WINDOW_RECT_EX_FOR_DPI: Lazy<Option<AdjustWindowRectExForDpi>> =
|
||||
|
|
@ -269,5 +266,3 @@ pub(crate) static GET_POINTER_DEVICE_RECTS: Lazy<Option<GetPointerDeviceRects>>
|
|||
Lazy::new(|| get_function!("user32.dll", GetPointerDeviceRects));
|
||||
pub(crate) static GET_POINTER_TOUCH_INFO: Lazy<Option<GetPointerTouchInfo>> =
|
||||
Lazy::new(|| get_function!("user32.dll", GetPointerTouchInfo));
|
||||
pub(crate) static GET_POINTER_PEN_INFO: Lazy<Option<GetPointerPenInfo>> =
|
||||
Lazy::new(|| get_function!("user32.dll", GetPointerPenInfo));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue