Skip to content

Commit 33ee69f

Browse files
committed
Add relative motion pointer events.
1 parent 6382e63 commit 33ee69f

File tree

2 files changed

+158
-16
lines changed

2 files changed

+158
-16
lines changed

ui-events-winit/src/lib.rs

Lines changed: 97 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,22 @@ pub use web_time::Instant;
3838
use ui_events::{
3939
keyboard::KeyboardEvent,
4040
pointer::{
41-
PointerButtonEvent, PointerEvent, PointerId, PointerInfo, PointerScrollEvent, PointerState,
42-
PointerType, PointerUpdate,
41+
PointerButtonEvent, PointerEvent, PointerId, PointerInfo, PointerRelativeFrame,
42+
PointerRelativeMotion, PointerScrollEvent, PointerState, PointerType, PointerUpdate,
4343
},
4444
ScrollDelta,
4545
};
4646
use winit::{
47-
event::{ElementState, Force, MouseScrollDelta, Touch, TouchPhase, WindowEvent},
47+
dpi::PhysicalPosition,
48+
event::{DeviceEvent, ElementState, Force, MouseScrollDelta, Touch, TouchPhase, WindowEvent},
4849
keyboard::ModifiersState,
4950
};
5051

5152
/// Manages stateful transformations of winit [`WindowEvent`].
5253
///
5354
/// Store a single instance of this per window, then call [`WindowEventReducer::reduce`]
5455
/// on each [`WindowEvent`] for that window.
55-
/// Use the [`WindowEventTranslation`] value to receive [`PointerEvent`]s and [`KeyboardEvent`]s.
56+
/// Use the [`EventTranslation`] value to receive [`PointerEvent`]s and [`KeyboardEvent`]s.
5657
///
5758
/// This handles:
5859
/// - [`ModifiersChanged`][`WindowEvent::ModifiersChanged`]
@@ -78,7 +79,7 @@ pub struct WindowEventReducer {
7879
#[allow(clippy::cast_possible_truncation)]
7980
impl WindowEventReducer {
8081
/// Process a [`WindowEvent`].
81-
pub fn reduce(&mut self, we: &WindowEvent) -> Option<WindowEventTranslation> {
82+
pub fn reduce(&mut self, we: &WindowEvent) -> Option<EventTranslation> {
8283
const PRIMARY_MOUSE: PointerInfo = PointerInfo {
8384
pointer_id: Some(PointerId::PRIMARY),
8485
// TODO: Maybe transmute device.
@@ -98,19 +99,19 @@ impl WindowEventReducer {
9899
self.primary_state.modifiers = keyboard::from_winit_modifier_state(self.modifiers);
99100
None
100101
}
101-
WindowEvent::KeyboardInput { event, .. } => Some(WindowEventTranslation::Keyboard(
102+
WindowEvent::KeyboardInput { event, .. } => Some(EventTranslation::Keyboard(
102103
keyboard::from_winit_keyboard_event(event.clone(), self.modifiers),
103104
)),
104-
WindowEvent::CursorEntered { .. } => Some(WindowEventTranslation::Pointer(
105+
WindowEvent::CursorEntered { .. } => Some(EventTranslation::Pointer(
105106
PointerEvent::Enter(PRIMARY_MOUSE),
106107
)),
107-
WindowEvent::CursorLeft { .. } => Some(WindowEventTranslation::Pointer(
108-
PointerEvent::Leave(PRIMARY_MOUSE),
109-
)),
108+
WindowEvent::CursorLeft { .. } => Some(EventTranslation::Pointer(PointerEvent::Leave(
109+
PRIMARY_MOUSE,
110+
))),
110111
WindowEvent::CursorMoved { position, .. } => {
111112
self.primary_state.position = *position;
112113

113-
Some(WindowEventTranslation::Pointer(self.counter.attach_count(
114+
Some(EventTranslation::Pointer(self.counter.attach_count(
114115
PointerEvent::Move(PointerUpdate {
115116
pointer: PRIMARY_MOUSE,
116117
current: self.primary_state.clone(),
@@ -129,7 +130,7 @@ impl WindowEventReducer {
129130
self.primary_state.buttons.insert(button);
130131
}
131132

132-
Some(WindowEventTranslation::Pointer(self.counter.attach_count(
133+
Some(EventTranslation::Pointer(self.counter.attach_count(
133134
PointerEvent::Down(PointerButtonEvent {
134135
pointer: PRIMARY_MOUSE,
135136
button,
@@ -147,15 +148,15 @@ impl WindowEventReducer {
147148
self.primary_state.buttons.remove(button);
148149
}
149150

150-
Some(WindowEventTranslation::Pointer(self.counter.attach_count(
151+
Some(EventTranslation::Pointer(self.counter.attach_count(
151152
PointerEvent::Up(PointerButtonEvent {
152153
pointer: PRIMARY_MOUSE,
153154
button,
154155
state: self.primary_state.clone(),
155156
}),
156157
)))
157158
}
158-
WindowEvent::MouseWheel { delta, .. } => Some(WindowEventTranslation::Pointer(
159+
WindowEvent::MouseWheel { delta, .. } => Some(EventTranslation::Pointer(
159160
PointerEvent::Scroll(PointerScrollEvent {
160161
pointer: PRIMARY_MOUSE,
161162
delta: match *delta {
@@ -196,7 +197,7 @@ impl WindowEventReducer {
196197
..Default::default()
197198
};
198199

199-
Some(WindowEventTranslation::Pointer(self.counter.attach_count(
200+
Some(EventTranslation::Pointer(self.counter.attach_count(
200201
match phase {
201202
Started => PointerEvent::Down(PointerButtonEvent {
202203
pointer,
@@ -221,11 +222,48 @@ impl WindowEventReducer {
221222
_ => None,
222223
}
223224
}
225+
226+
/// Process a [`DeviceEvent`].
227+
pub fn reduce_device_event(&mut self, de: &DeviceEvent) -> Option<EventTranslation> {
228+
match de {
229+
DeviceEvent::MouseMotion { delta: (x, y) } => {
230+
const PRIMARY_MOUSE: PointerInfo = PointerInfo {
231+
pointer_id: Some(PointerId::PRIMARY),
232+
persistent_device_id: None,
233+
pointer_type: PointerType::Mouse,
234+
};
235+
236+
let time = Instant::now()
237+
.duration_since(*self.first_instant.get_or_insert_with(Instant::now))
238+
.as_nanos() as u64;
239+
240+
self.primary_state.time = time;
241+
242+
let frame = PointerRelativeFrame {
243+
time,
244+
distance: PhysicalPosition { x: *x, y: *y },
245+
buttons: self.primary_state.buttons,
246+
modifiers: self.primary_state.modifiers,
247+
count: 0,
248+
};
249+
250+
Some(EventTranslation::Pointer(PointerEvent::RelativeMotion(
251+
PointerRelativeMotion {
252+
pointer: PRIMARY_MOUSE,
253+
total: frame.clone(),
254+
frames: vec![frame],
255+
predicted: vec![],
256+
},
257+
)))
258+
}
259+
_ => None,
260+
}
261+
}
224262
}
225263

226264
/// Result of [`WindowEventReducer::reduce`].
227265
#[derive(Debug)]
228-
pub enum WindowEventTranslation {
266+
pub enum EventTranslation {
229267
/// Resulting [`KeyboardEvent`].
230268
Keyboard(KeyboardEvent),
231269
/// Resulting [`PointerEvent`].
@@ -345,6 +383,49 @@ impl TapCounter {
345383
})
346384
}
347385
}
386+
PointerEvent::RelativeMotion(PointerRelativeMotion {
387+
pointer,
388+
mut total,
389+
mut frames,
390+
mut predicted,
391+
}) => {
392+
if let Some(TapState { count, .. }) = self
393+
.taps
394+
.iter()
395+
.find(
396+
|TapState {
397+
pointer_id,
398+
down_time,
399+
up_time,
400+
..
401+
}| {
402+
*pointer_id == pointer.pointer_id && down_time == up_time
403+
},
404+
)
405+
.cloned()
406+
{
407+
total.count = count;
408+
for event in frames.iter_mut() {
409+
event.count = count;
410+
}
411+
for event in predicted.iter_mut() {
412+
event.count = count;
413+
}
414+
PointerEvent::RelativeMotion(PointerRelativeMotion {
415+
pointer,
416+
total,
417+
frames,
418+
predicted,
419+
})
420+
} else {
421+
PointerEvent::RelativeMotion(PointerRelativeMotion {
422+
pointer,
423+
total,
424+
frames,
425+
predicted,
426+
})
427+
}
428+
}
348429
PointerEvent::Cancel(p) => {
349430
self.taps
350431
.retain(|TapState { pointer_id, .. }| *pointer_id != p.pointer_id);

ui-events/src/pointer/mod.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,28 @@ impl Default for PointerState {
185185
}
186186
}
187187

188+
/// A relative pointer motion frame.
189+
///
190+
/// This is generally only applicable to a mouse or similar device,
191+
/// so touch/pen specific fields are excluded.
192+
#[derive(Clone, Debug, Default, PartialEq)]
193+
pub struct PointerRelativeFrame {
194+
/// `u64` nanoseconds real time.
195+
///
196+
/// The base time is not important, except by convention, and should
197+
/// generally be the same at least for states originating from the
198+
/// same device.
199+
pub time: u64,
200+
/// Distance traveled from the previous state.
201+
pub distance: PhysicalPosition<f64>,
202+
/// Pressed buttons.
203+
pub buttons: PointerButtons,
204+
/// Modifiers state.
205+
pub modifiers: Modifiers,
206+
/// Click or tap count associated with the pointer.
207+
pub count: u8,
208+
}
209+
188210
/// A pointer update, along with coalesced and predicted states.
189211
#[derive(Clone, Debug, PartialEq)]
190212
pub struct PointerUpdate {
@@ -214,6 +236,40 @@ impl PointerUpdate {
214236
}
215237
}
216238

239+
/// A relative pointer motion update.
240+
#[derive(Clone, Debug, PartialEq)]
241+
pub struct PointerRelativeMotion {
242+
/// Identifying information about pointer.
243+
pub pointer: PointerInfo,
244+
/// Cumulative motion over the frames.
245+
///
246+
/// The timestamp is for the last integrated frame.
247+
pub total: PointerRelativeFrame,
248+
/// All integrated frames in this motion update.
249+
///
250+
/// These primarily come from event coalescing.
251+
/// Coalescing is application-specific.
252+
/// On the web, the browser does its own coalescing, whereas
253+
/// on other platforms you may do your own, or forego it
254+
/// altogether, delivering every frame.
255+
///
256+
/// This includes the most recent frame.
257+
pub frames: Vec<PointerRelativeFrame>,
258+
/// Predicted frames, ordered by `time`.
259+
///
260+
/// Some platforms provide predicted frames directly,
261+
/// and you may choose to add your own predictor.
262+
pub predicted: Vec<PointerRelativeFrame>,
263+
}
264+
265+
impl PointerRelativeMotion {
266+
/// Returns `true` if this is the primary pointer.
267+
#[inline(always)]
268+
pub fn is_primary_pointer(&self) -> bool {
269+
self.pointer.is_primary_pointer()
270+
}
271+
}
272+
217273
/// An event representing a [`PointerButton`] that was pressed or released.
218274
#[derive(Clone, Debug)]
219275
pub struct PointerButtonEvent {
@@ -250,6 +306,10 @@ pub enum PointerEvent {
250306
Up(PointerButtonEvent),
251307
/// Pointer moved.
252308
Move(PointerUpdate),
309+
/// Pointer device moved but pointer position did not.
310+
///
311+
/// This is usually during a locking or confining grab.
312+
RelativeMotion(PointerRelativeMotion),
253313
/// Pointer motion was cancelled.
254314
///
255315
/// Usually this is a touch which was taken over somewhere else.
@@ -273,6 +333,7 @@ impl PointerEvent {
273333
Self::Down(PointerButtonEvent { pointer, .. })
274334
| Self::Up(PointerButtonEvent { pointer, .. })
275335
| Self::Move(PointerUpdate { pointer, .. })
336+
| Self::RelativeMotion(PointerRelativeMotion { pointer, .. })
276337
| Self::Cancel(pointer)
277338
| Self::Enter(pointer)
278339
| Self::Leave(pointer)

0 commit comments

Comments
 (0)