incular_platform/pointer.rs
1use incular_core::{PointerDeviceKind, PointerPhase, PointerSampleMetadata};
2
3/// Native device details that enrich a Winit pointer sample without changing
4/// its logical contact identity or phase. This is used only when an OS adapter
5/// can supply semantics Winit intentionally omits (for example Win32 pen kind,
6/// tilt, and eraser state).
7#[derive(Clone, Copy, Debug, PartialEq)]
8pub struct NativePointerSample {
9 /// Backend-local opaque physical-device token when available. This must
10 /// never contain a raw native handle. Shared desktop coordination remaps
11 /// the token into the same process-local ID namespace used for Winit
12 /// devices before a portable [`incular_core::InputEvent`] is emitted.
13 /// `None` preserves the stable Winit device ID rather than manufacturing
14 /// one.
15 pub device: Option<u64>,
16 pub kind: PointerDeviceKind,
17 pub sample: PointerSampleMetadata,
18 /// Native contact state when the device distinguishes hover from contact.
19 /// `None` preserves the ordinary Winit touch semantics.
20 pub in_contact: Option<bool>,
21}
22
23/// Portable metadata attached to one native pointer sample before its physical
24/// position is normalized into logical window coordinates.
25#[derive(Clone, Copy, Debug, PartialEq)]
26pub struct PointerMetadata {
27 pub pointer: u64,
28 pub device: u64,
29 pub kind: PointerDeviceKind,
30 pub buttons: u32,
31 pub button: Option<u32>,
32 pub sample: PointerSampleMetadata,
33 pub phase: PointerPhase,
34}
35
36/// Native cursor grab policy for one window.
37#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
38pub enum CursorGrabMode {
39 /// Release any pointer confinement or lock owned by the window.
40 #[default]
41 None,
42 /// Keep the pointer inside the window while preserving absolute motion.
43 Confined,
44 /// Lock the pointer for relative-motion style interaction.
45 Locked,
46}
47
48/// Finite logical cursor position relative to a window's client area.
49///
50/// The validated wrapper prevents NaN/infinity from reaching native APIs whose
51/// integer/physical conversion behavior is platform-dependent.
52#[derive(Clone, Copy, Debug, PartialEq)]
53pub struct LogicalWindowPosition {
54 x: f64,
55 y: f64,
56}
57
58impl LogicalWindowPosition {
59 pub fn new(x: f64, y: f64) -> Result<Self, LogicalWindowPositionError> {
60 if !x.is_finite() || !y.is_finite() {
61 return Err(LogicalWindowPositionError);
62 }
63 Ok(Self { x, y })
64 }
65
66 #[must_use]
67 pub const fn x(self) -> f64 {
68 self.x
69 }
70
71 #[must_use]
72 pub const fn y(self) -> f64 {
73 self.y
74 }
75}
76
77#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, thiserror::Error)]
78#[error("logical window position must contain finite coordinates")]
79pub struct LogicalWindowPositionError;