Skip to main content

agg_gui/
touch_points.rs

1//! # Active touch points — per-finger positions for widgets
2//!
3//! The multi-touch pipeline aggregates fingers into pinch/rotate
4//! gestures ([`crate::touch_state`]) and emulates a primary-finger
5//! mouse ([`crate::touch_emulation`]). Widgets that act as virtual
6//! gamepads — several on-screen buttons held by different fingers at
7//! once — need the raw per-finger positions instead. [`App`'s]
8//! touch entry points publish the active set here after every touch
9//! event; widgets poll [`active`] during paint/update and hit-test
10//! the points against their own controls.
11//!
12//! Positions are in the same app-local coordinate space widgets see
13//! mouse events in (Y-up, keyboard-lift applied).
14//!
15//! [`App`'s]: crate::widget::App
16
17use std::sync::Mutex;
18
19use crate::geometry::Point;
20
21/// One active finger: platform touch id + current position.
22#[derive(Clone, Copy, Debug, PartialEq)]
23pub struct TouchPoint {
24    pub id: u64,
25    pub pos: Point,
26}
27
28static POINTS: Mutex<Vec<TouchPoint>> = Mutex::new(Vec::new());
29
30/// App side: replace the published set (called after every touch
31/// start/move/end/cancel).
32pub fn publish(points: Vec<TouchPoint>) {
33    *POINTS.lock().unwrap() = points;
34}
35
36/// Widget side: the currently-active fingers. Empty when no touch is
37/// down (or the platform has no touchscreen).
38pub fn active() -> Vec<TouchPoint> {
39    POINTS.lock().unwrap().clone()
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    #[test]
47    fn publish_replaces_the_active_set() {
48        publish(vec![TouchPoint {
49            id: 7,
50            pos: Point::new(10.0, 20.0),
51        }]);
52        assert_eq!(active().len(), 1);
53        assert_eq!(active()[0].id, 7);
54        publish(Vec::new());
55        assert!(active().is_empty());
56    }
57}