Skip to main content

agg_gui/widget/app/
touch.rs

1//! Touch-input forwarding methods on [`App`] — start/move/end/cancel
2//! plus the active-finger count. Split out of `app.rs` (800-line
3//! guardrail). Each entry point feeds two consumers: the multi-touch
4//! gesture recogniser in [`crate::touch_state`] (same screen→world
5//! conversion — Y-flip + keyboard lift — the mouse path uses), and the
6//! primary-finger mouse emulation in [`crate::touch_emulation`], whose
7//! commands are replayed through `App::on_mouse_*` in raw screen
8//! coordinates. Platform shells therefore forward raw touches ONLY —
9//! synthesizing mouse events shell-side would double-fire them.
10
11use super::super::keyboard_scroll;
12use crate::event::Modifiers;
13use crate::touch_emulation::EmuCmd;
14use crate::widget::App;
15
16impl App {
17    pub fn on_touch_start(
18        &mut self,
19        device: crate::touch_state::TouchDeviceId,
20        id: crate::touch_state::TouchId,
21        screen_x: f64,
22        screen_y: f64,
23        force: Option<f32>,
24    ) {
25        let pos = keyboard_scroll::lift_to_world(self.flip_y(screen_x, screen_y));
26        self.touch_state.on_start(device, id, pos, force);
27        crate::touch_state::note_touch_event();
28        let cmds = self.touch_mouse_emu.on_start(device, id, screen_x, screen_y);
29        self.apply_emu_cmds(cmds);
30    }
31    pub fn on_touch_move(
32        &mut self,
33        device: crate::touch_state::TouchDeviceId,
34        id: crate::touch_state::TouchId,
35        screen_x: f64,
36        screen_y: f64,
37        force: Option<f32>,
38    ) {
39        let pos = keyboard_scroll::lift_to_world(self.flip_y(screen_x, screen_y));
40        self.touch_state.on_move(device, id, pos, force);
41        crate::touch_state::note_touch_event();
42        let cmds = self.touch_mouse_emu.on_move(device, id, screen_x, screen_y);
43        self.apply_emu_cmds(cmds);
44    }
45    pub fn on_touch_end(
46        &mut self,
47        device: crate::touch_state::TouchDeviceId,
48        id: crate::touch_state::TouchId,
49    ) {
50        self.touch_state.on_end_or_cancel(device, id);
51        crate::touch_state::note_touch_event();
52        let cmds = self.touch_mouse_emu.on_end(device, id);
53        self.apply_emu_cmds(cmds);
54    }
55    pub fn on_touch_cancel(
56        &mut self,
57        device: crate::touch_state::TouchDeviceId,
58        id: crate::touch_state::TouchId,
59    ) {
60        self.touch_state.on_end_or_cancel(device, id);
61        crate::touch_state::note_touch_event();
62        let cmds = self.touch_mouse_emu.on_cancel(device, id);
63        self.apply_emu_cmds(cmds);
64    }
65
66    /// Replay emulation commands through the regular mouse entry points.
67    /// `note_touch_event()` has already run by the time this is called,
68    /// so widgets can tell these synthetic events apart from real mouse
69    /// input via [`crate::touch_state::last_touch_event_age`].
70    fn apply_emu_cmds(&mut self, cmds: Vec<EmuCmd>) {
71        for cmd in cmds {
72            match cmd {
73                EmuCmd::MouseMove(x, y) => self.on_mouse_move(x, y),
74                EmuCmd::MouseDown(x, y, btn) => {
75                    self.on_mouse_down(x, y, btn, Modifiers::default())
76                }
77                EmuCmd::MouseUp(x, y, btn) => self.on_mouse_up(x, y, btn, Modifiers::default()),
78                EmuCmd::MouseLeave => self.on_mouse_leave(),
79            }
80        }
81    }
82
83    /// Current number of fingers down across all devices.  Used by
84    /// widgets that want to know the gesture has *begun* before the
85    /// first frame has had a chance to produce a delta (where
86    /// `current_multi_touch()` may still be `None`).
87    pub fn active_touch_count(&self) -> usize {
88        self.touch_state.active_count()
89    }
90}