Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Introduce FingerId #3783

Merged
merged 1 commit into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ changelog entry.
well.
- On Android, add `{Active,}EventLoopExtAndroid::android_app()` to access the app used to create the loop.
- Add `ActiveEventLoop::system_theme()`, returning the current system theme.
- 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.

### Changed

Expand Down Expand Up @@ -110,6 +113,7 @@ 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`.

### Fixed

Expand Down
28 changes: 25 additions & 3 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,26 @@ impl DeviceId {
}
}

/// Identifier of a finger in a touch event.
///
/// Whenever a touch event is received it contains a `FingerId` which uniquely identifies the finger
/// used for the current interaction.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FingerId(pub(crate) platform_impl::FingerId);

impl FingerId {
/// Returns a dummy id, useful for unit testing.
///
/// # Notes
///
/// The only guarantee made about the return value of this function is that
/// it will always be equal to itself and to future values returned by this function.
/// No other guarantees are made. This may be equal to a real `FingerId`.
pub const fn dummy() -> Self {
FingerId(platform_impl::FingerId::dummy())
}
}

/// Represents raw hardware events that are not associated with any particular window.
///
/// Useful for interactions that diverge significantly from a conventional 2D GUI, such as 3D camera
Expand Down Expand Up @@ -846,7 +866,7 @@ pub struct Touch {
/// [android documentation](https://developer.android.com/reference/android/view/MotionEvent#AXIS_PRESSURE).
pub force: Option<Force>,
/// Unique identifier of a finger.
pub id: u64,
pub finger_id: FingerId,
}

/// Describes the force of a touch event
Expand Down Expand Up @@ -1012,6 +1032,7 @@ mod tests {
#[allow(unused_mut)]
let mut x = $closure;
let did = event::DeviceId::dummy();
let fid = event::FingerId::dummy();

#[allow(deprecated)]
{
Expand Down Expand Up @@ -1075,7 +1096,7 @@ mod tests {
device_id: did,
phase: event::TouchPhase::Started,
location: (0.0, 0.0).into(),
id: 0,
finger_id: fid,
force: Some(event::Force::Normalized(0.0)),
}));
with_window_event(ThemeChanged(crate::window::Theme::Light));
Expand Down Expand Up @@ -1133,6 +1154,7 @@ mod tests {
let _ = event::StartCause::Init.clone();

let did = crate::event::DeviceId::dummy().clone();
let fid = crate::event::FingerId::dummy().clone();
HashSet::new().insert(did);
let mut set = [did, did, did];
set.sort_unstable();
Expand All @@ -1148,7 +1170,7 @@ mod tests {
device_id: did,
phase: event::TouchPhase::Started,
location: (0.0, 0.0).into(),
id: 0,
finger_id: fid,
force: Some(event::Force::Normalized(0.0)),
}
.clone();
Expand Down
14 changes: 14 additions & 0 deletions src/platform/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ use web_sys::HtmlCanvasElement;
use crate::application::ApplicationHandler;
use crate::cursor::CustomCursorSource;
use crate::error::NotSupportedError;
use crate::event::FingerId;
use crate::event_loop::{ActiveEventLoop, EventLoop};
use crate::monitor::MonitorHandle;
use crate::platform_impl::PlatformCustomCursorSource;
Expand Down Expand Up @@ -763,3 +764,16 @@ impl Display for OrientationLockError {
}

impl Error for OrientationLockError {}

/// Additional methods on [`FingerId`] that are specific to Web.
pub trait FingerIdExtWeb {
/// Indicates if the finger represents the first contact in a multi-touch interaction.
#[allow(clippy::wrong_self_convention)]
fn is_primary(self) -> bool;
}

impl FingerIdExtWeb for FingerId {
fn is_primary(self) -> bool {
self.0.is_primary()
}
}
16 changes: 15 additions & 1 deletion src/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::ffi::c_void;
use std::path::Path;

use crate::dpi::PhysicalSize;
use crate::event::DeviceId;
use crate::event::{DeviceId, FingerId};
use crate::event_loop::EventLoopBuilder;
use crate::monitor::MonitorHandle;
use crate::window::{BadIcon, Icon, Window, WindowAttributes};
Expand Down Expand Up @@ -668,6 +668,20 @@ impl DeviceIdExtWindows for DeviceId {
}
}

/// Additional methods on `FingerId` that are specific to Windows.
pub trait FingerIdExtWindows {
/// Indicates if the finger represents the first contact in a multi-touch interaction.
#[allow(clippy::wrong_self_convention)]
fn is_primary(self) -> bool;
}

impl FingerIdExtWindows for FingerId {
#[inline]
fn is_primary(self) -> bool {
self.0.is_primary()
}
}

/// Additional methods on `Icon` that are specific to Windows.
pub trait IconExtWindows: Sized {
/// Create an icon from a file path.
Expand Down
11 changes: 10 additions & 1 deletion src/platform_impl/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ impl EventLoop {
device_id,
phase,
location,
id: pointer.pointer_id() as u64,
finger_id: event::FingerId(FingerId(pointer.pointer_id())),
force: Some(Force::Normalized(pointer.pressure() as f64)),
});

Expand Down Expand Up @@ -705,6 +705,15 @@ impl DeviceId {
}
}

#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct FingerId(i32);

impl FingerId {
pub const fn dummy() -> Self {
FingerId(0)
}
}

#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct PlatformSpecificWindowAttributes;

Expand Down
9 changes: 9 additions & 0 deletions src/platform_impl/apple/appkit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ impl DeviceId {
// Constant device ID; to be removed when if backend is updated to report real device IDs.
pub(crate) const DEVICE_ID: RootDeviceId = RootDeviceId(DeviceId);

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FingerId;

impl FingerId {
pub const fn dummy() -> Self {
FingerId
}
}

#[derive(Debug)]
pub enum OsError {
CGError(core_graphics::base::CGError),
Expand Down
9 changes: 9 additions & 0 deletions src/platform_impl/apple/uikit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ impl DeviceId {

pub(crate) const DEVICE_ID: RootDeviceId = RootDeviceId(DeviceId);

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FingerId(usize);

impl FingerId {
pub const fn dummy() -> Self {
FingerId(0)
}
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct KeyEventExtra {}

Expand Down
8 changes: 4 additions & 4 deletions src/platform_impl/apple/uikit/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ use objc2_ui_kit::{

use super::app_state::{self, EventWrapper};
use super::window::WinitUIWindow;
use super::DEVICE_ID;
use super::{FingerId, DEVICE_ID};
use crate::dpi::PhysicalPosition;
use crate::event::{Event, Force, Touch, TouchPhase, WindowEvent};
use crate::event::{Event, FingerId as RootFingerId, Force, Touch, TouchPhase, WindowEvent};
use crate::window::{WindowAttributes, WindowId as RootWindowId};

pub struct WinitViewState {
Expand Down Expand Up @@ -480,7 +480,7 @@ impl WinitView {
} else {
None
};
let touch_id = touch as *const UITouch as u64;
let touch_id = touch as *const UITouch as usize;
let phase = touch.phase();
let phase = match phase {
UITouchPhase::Began => TouchPhase::Started,
Expand All @@ -502,7 +502,7 @@ impl WinitView {
window_id: RootWindowId(window.id()),
event: WindowEvent::Touch(Touch {
device_id: DEVICE_ID,
id: touch_id,
finger_id: RootFingerId(FingerId(touch_id)),
location: physical_location,
force,
phase,
Expand Down
17 changes: 17 additions & 0 deletions src/platform_impl/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,23 @@ impl DeviceId {
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum FingerId {
#[cfg(x11_platform)]
X(x11::FingerId),
#[cfg(wayland_platform)]
Wayland(wayland::FingerId),
}

impl FingerId {
pub const fn dummy() -> Self {
#[cfg(wayland_platform)]
return FingerId::Wayland(wayland::FingerId::dummy());
#[cfg(all(not(wayland_platform), x11_platform))]
return FingerId::X(x11::FingerId::dummy());
}
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum MonitorHandle {
#[cfg(x11_platform)]
Expand Down
9 changes: 9 additions & 0 deletions src/platform_impl/linux/wayland/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ impl DeviceId {
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FingerId(i32);

impl FingerId {
pub const fn dummy() -> Self {
FingerId(0)
}
}

/// Get the WindowId out of the surface.
#[inline]
fn make_wid(surface: &WlSurface) -> WindowId {
Expand Down
18 changes: 13 additions & 5 deletions src/platform_impl/linux/wayland/seat/touch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use tracing::warn;
use crate::dpi::LogicalPosition;
use crate::event::{Touch, TouchPhase, WindowEvent};
use crate::platform_impl::wayland::state::WinitState;
use crate::platform_impl::wayland::{self, DeviceId};
use crate::platform_impl::wayland::{self, DeviceId, FingerId};

impl TouchHandler for WinitState {
fn down(
Expand Down Expand Up @@ -50,7 +50,9 @@ impl TouchHandler for WinitState {
phase: TouchPhase::Started,
location: location.to_physical(scale_factor),
force: None,
id: id as u64,
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
FingerId(id),
)),
}),
window_id,
);
Expand Down Expand Up @@ -93,7 +95,9 @@ impl TouchHandler for WinitState {
phase: TouchPhase::Ended,
location: touch_point.location.to_physical(scale_factor),
force: None,
id: id as u64,
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
FingerId(id),
)),
}),
window_id,
);
Expand Down Expand Up @@ -138,7 +142,9 @@ impl TouchHandler for WinitState {
phase: TouchPhase::Moved,
location: touch_point.location.to_physical(scale_factor),
force: None,
id: id as u64,
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
FingerId(id),
)),
}),
window_id,
);
Expand Down Expand Up @@ -170,7 +176,9 @@ impl TouchHandler for WinitState {
phase: TouchPhase::Cancelled,
location,
force: None,
id: id as u64,
finger_id: crate::event::FingerId(crate::platform_impl::FingerId::Wayland(
FingerId(id),
)),
}),
window_id,
);
Expand Down
12 changes: 6 additions & 6 deletions src/platform_impl/linux/x11/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ use crate::platform_impl::platform::x11::ActiveEventLoop;
use crate::platform_impl::x11::atoms::*;
use crate::platform_impl::x11::util::cookie::GenericEventCookie;
use crate::platform_impl::x11::{
mkdid, mkwid, util, CookieResultExt, Device, DeviceId, DeviceInfo, Dnd, DndState, ImeReceiver,
ScrollOrientation, UnownedWindow, WindowId,
mkdid, mkfid, mkwid, util, CookieResultExt, Device, DeviceId, DeviceInfo, Dnd, DndState,
ImeReceiver, ScrollOrientation, UnownedWindow, WindowId,
};

/// The maximum amount of X modifiers to replay.
Expand All @@ -60,7 +60,7 @@ pub struct EventProcessor {
//
// Used to detect key repeats.
pub held_key_press: Option<u32>,
pub first_touch: Option<u64>,
pub first_touch: Option<u32>,
// Currently focused window belonging to this process
pub active_window: Option<xproto::Window>,
/// Latest modifiers we've sent for the user to trigger change in event.
Expand Down Expand Up @@ -1313,7 +1313,7 @@ impl EventProcessor {
let window = xev.event as xproto::Window;
if self.window_exists(window) {
let window_id = mkwid(window);
let id = xev.detail as u64;
let id = xev.detail as u32;
let location = PhysicalPosition::new(xev.event_x, xev.event_y);

// Mouse cursor position changes when touch events are received.
Expand All @@ -1336,7 +1336,7 @@ impl EventProcessor {
phase,
location,
force: None, // TODO
id,
finger_id: mkfid(id),
}),
};
callback(&self.target, event)
Expand Down Expand Up @@ -1761,7 +1761,7 @@ impl EventProcessor {
}
}

fn is_first_touch(first: &mut Option<u64>, num: &mut u32, id: u64, phase: TouchPhase) -> bool {
fn is_first_touch(first: &mut Option<u32>, num: &mut u32, id: u32, phase: TouchPhase) -> bool {
match phase {
TouchPhase::Started => {
if *num == 0 {
Expand Down
14 changes: 14 additions & 0 deletions src/platform_impl/linux/x11/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,16 @@ impl DeviceId {
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FingerId(u32);

impl FingerId {
#[allow(unused)]
pub const fn dummy() -> Self {
FingerId(0)
}
}

pub(crate) struct Window(Arc<UnownedWindow>);

impl Deref for Window {
Expand Down Expand Up @@ -1027,6 +1037,10 @@ fn mkdid(w: xinput::DeviceId) -> crate::event::DeviceId {
crate::event::DeviceId(crate::platform_impl::DeviceId::X(DeviceId(w)))
}

fn mkfid(w: u32) -> crate::event::FingerId {
crate::event::FingerId(crate::platform_impl::FingerId::X(FingerId(w)))
}

#[derive(Debug)]
pub struct Device {
_name: String,
Expand Down
Loading
Loading