ui_events/
lib.rs

1// Copyright 2025 the UI Events Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Cross-platform input event types modeled after W3C UI Events.
5//!
6//! This crate provides small, portable data types for working with pointer
7//! (mouse, touch, pen) and keyboard input in a platform-agnostic way.
8//! It aims to closely follow W3C terminology while remaining practical for native
9//! application development.
10//!
11//! ## What you get:
12//!
13//! - Pointer events: button down/up, move, enter/leave, scroll, gestures
14//! - Rich pointer state: position, pressure, tilt, contact size, modifiers
15//! - Keyboard types re-exported from [`keyboard-types`]
16//! - A stable vocabulary you can adapt from windowing backends
17//!
18//! This crate is intentionally focused on data structures — it does not open
19//! windows or read events.
20//! For integrations, see the adapter crates:
21//!
22//! - [`ui-events-winit`]: Convert between `winit` and `ui-events`.
23//! - [`ui-events-web`]: Convert between Web (`web-sys`) DOM events and `ui-events`.
24//!
25//! ## Coordinate system and units
26//!
27//! - Positions are in physical pixels (`dpi::PhysicalPosition<f64>`), with the
28//!   Y axis increasing downward.
29//! - Use [`PointerState::logical_position`](pointer::PointerState::logical_position)
30//!   to obtain logical coordinates using a scale factor.
31//! - Scroll deltas are expressed via [`ScrollDelta`]; see its docs for details
32//!   on page/line/pixel semantics.
33//!
34//! ## Primary pointer
35//!
36//! Some interactions need a notion of a “primary” pointer (e.g. left mouse button, first touch).
37//! The reserved id [`PointerId::PRIMARY`](pointer::PointerId::PRIMARY) marks this.
38//! Helper methods like [`PointerEvent::is_primary_pointer`](pointer::PointerEvent::is_primary_pointer)
39//! and [`PointerInfo::is_primary_pointer`](pointer::PointerInfo::is_primary_pointer) are provided for convenience.
40//!
41//! ## Feature flags
42//!
43//! - `std` (default): Use the Rust standard library.
44//! - `kurbo`: Add convenience methods for converting positions to `kurbo::Point`.
45//!
46//! ## Examples
47//!
48//! Basic matching on pointer events:
49//!
50//! ```
51//! use ui_events::pointer::{PointerEvent, PointerButton, PointerButtonEvent, PointerInfo, PointerState, PointerType};
52//! use ui_events::ScrollDelta;
53//! use keyboard_types::Modifiers;
54//! use dpi::{PhysicalPosition, PhysicalSize};
55//!
56//! fn handle_event(ev: PointerEvent) {
57//!     match ev {
58//!         PointerEvent::Down(PointerButtonEvent { button, state, .. }) => {
59//!             if button == Some(PointerButton::Primary) {
60//!                 // Start a drag, for example
61//!                 let pos = state.position;
62//!                 let _ = (pos.x, pos.y);
63//!             }
64//!         }
65//!         PointerEvent::Move(upd) => {
66//!             let logical = upd.current.logical_position();
67//!             let _ = (logical.x, logical.y);
68//!         }
69//!         PointerEvent::Scroll(s) => {
70//!             match s.delta {
71//!                 ScrollDelta::PageDelta(x, y) => { let _ = (x, y); }
72//!                 ScrollDelta::LineDelta(x, y) => { let _ = (x, y); }
73//!                 ScrollDelta::PixelDelta(p) => { let _ = (p.x, p.y); }
74//!             }
75//!         }
76//!         _ => {}
77//!     }
78//! }
79//!
80//! // Construct a minimal primary-pointer Down event
81//! let ev = PointerEvent::Down(PointerButtonEvent{
82//!     button: Some(PointerButton::Primary),
83//!     pointer: PointerInfo{
84//!         pointer_id: Some(ui_events::pointer::PointerId::PRIMARY),
85//!         persistent_device_id: None,
86//!         pointer_type: PointerType::Mouse,
87//!     },
88//!     state: PointerState{
89//!         time: 0,
90//!         position: PhysicalPosition { x: 10.0, y: 20.0 },
91//!         buttons: Default::default(),
92//!         modifiers: Modifiers::empty(),
93//!         count: 1,
94//!         contact_geometry: PhysicalSize { width: 1.0, height: 1.0 },
95//!         orientation: Default::default(),
96//!         pressure: 0.5,
97//!         tangential_pressure: 0.0,
98//!         scale_factor: 2.0,
99//!     },
100//! });
101//! handle_event(ev);
102//! ```
103//!
104//! ## See also
105//!
106//! - [`ui-events-winit`]
107//! - [`ui-events-web`]
108//! - [`keyboard-types`]
109//!
110//! [`keyboard-types`]: https://docs.rs/keyboard-types/
111//! [`ui-events-winit`]: https://docs.rs/ui-events-winit/
112//! [`ui-events-web`]: https://docs.rs/ui-events-web/
113//! [`winit`]: https://docs.rs/winit/
114// LINEBENDER LINT SET - lib.rs - v3
115// See https://linebender.org/wiki/canonical-lints/
116// These lints shouldn't apply to examples or tests.
117#![cfg_attr(not(test), warn(unused_crate_dependencies))]
118// These lints shouldn't apply to examples.
119#![warn(clippy::print_stdout, clippy::print_stderr)]
120// Targeting e.g. 32-bit means structs containing usize can give false positives for 64-bit.
121#![cfg_attr(target_pointer_width = "64", warn(clippy::trivially_copy_pass_by_ref))]
122// END LINEBENDER LINT SET
123#![no_std]
124
125pub mod keyboard;
126pub mod pointer;
127
128mod scroll;
129
130pub use scroll::ScrollDelta;