Skip to main content

repose_core/
input.rs

1use crate::Vec2;
2use std::cell::Cell;
3use std::rc::Rc;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6pub struct PointerId(pub u64);
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum PointerKind {
10    Mouse,
11    Touch,
12    Pen,
13}
14
15#[derive(Clone, Copy, Debug)]
16pub enum PointerButton {
17    Primary,   // Left mouse, touch
18    Secondary, // Right mouse
19    Tertiary,  // Middle mouse
20}
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum PointerEventPass {
24    /// Top-down pass: ancestor → descendant. Allows ancestors to preview or
25    /// intercept events before descendants see them.
26    Initial,
27    /// Bottom-up pass: descendant → ancestor. The primary pass where gesture
28    /// handlers react to and consume events. A child that consumes its event
29    /// prevents the parent from reacting (Compose's requireUnconsumed).
30    Main,
31    /// Top-down pass: ancestor → descendant. Allows descendants to learn
32    /// about events consumed by ancestors during the Main pass.
33    Final,
34}
35
36#[derive(Clone, Copy, Debug)]
37pub enum PointerEventKind {
38    Down(PointerButton),
39    Up(PointerButton),
40    Move,
41    Cancel,
42    Enter,
43    Leave,
44}
45
46#[derive(Clone, Debug)]
47pub struct PointerEvent {
48    pub id: PointerId,
49    pub kind: PointerKind,
50    pub event: PointerEventKind,
51    pub position: Vec2,
52    pub pressure: f32,
53    pub modifiers: Modifiers,
54    /// Shared consumed state -> every clone of this event points to the same
55    /// Cell. Calling `consume()` on any clone marks it consumed for all clones.
56    pub consumed: Rc<Cell<bool>>,
57}
58
59impl PointerEvent {
60    pub fn new(
61        id: PointerId,
62        kind: PointerKind,
63        event: PointerEventKind,
64        position: Vec2,
65        pressure: f32,
66        modifiers: Modifiers,
67    ) -> Self {
68        Self {
69            id,
70            kind,
71            event,
72            position,
73            pressure,
74            modifiers,
75            consumed: Rc::new(Cell::new(false)),
76        }
77    }
78
79    /// Mark this event as consumed. Once consumed, subsequent handlers in the
80    /// same pass should skip processing it (equivalent to Compose's
81    /// `PointerInputChange.consume()`).
82    pub fn consume(&self) {
83        self.consumed.set(true);
84    }
85
86    /// Returns `true` if `consume()` was called on this event or any clone of it.
87    pub fn is_consumed(&self) -> bool {
88        self.consumed.get()
89    }
90}
91
92#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
93pub struct Modifiers {
94    pub shift: bool,
95    pub ctrl: bool,
96    pub alt: bool,
97    pub meta: bool,    // Cmd on Mac, Win key on Windows
98    pub command: bool, // egui like (Cmd on macOS, Ctrl elsewhere)
99}
100
101#[derive(Clone, Debug, PartialEq, Eq, Hash)]
102pub enum Key {
103    Character(char),
104    Enter,
105    Tab,
106    Backspace,
107    Delete,
108    Escape,
109    ArrowLeft,
110    ArrowRight,
111    ArrowUp,
112    ArrowDown,
113    Home,
114    End,
115    PageUp,
116    PageDown,
117    Space,
118    F(u8), // F1-F12
119    Unknown,
120}
121
122#[derive(Clone, Copy, Debug, PartialEq, Eq)]
123pub enum KeyEventType {
124    /// Key pressed down.
125    Down,
126    /// Key released.
127    Up,
128    /// Unknown or unsupported event type.
129    Unknown,
130}
131
132#[derive(Clone, Debug)]
133pub struct KeyEvent {
134    pub key: Key,
135    pub modifiers: Modifiers,
136    pub is_repeat: bool,
137    /// Whether this is a key-down or key-up event.
138    pub event_type: KeyEventType,
139    /// UTF-16 code point for character keys, or 0 for non-characters.
140    /// Matches Compose's `utf16CodePoint`.
141    pub utf16_code_point: u16,
142}
143
144#[derive(Clone, Debug)]
145pub struct TextInputEvent {
146    pub text: String,
147}
148
149#[derive(Clone, Debug)]
150pub enum ImeEvent {
151    /// IME composition started
152    Start,
153    /// Composition text updated
154    Update {
155        text: String,
156        cursor: Option<(usize, usize)>, // (start, end) of composition range
157    },
158    /// Composition committed (finalized)
159    Commit(String),
160    /// Composition cancelled
161    Cancel,
162}
163
164#[derive(Clone, Debug)]
165pub enum InputEvent {
166    Pointer(PointerEvent),
167    Key(KeyEvent),
168    Text(TextInputEvent),
169    Ime(ImeEvent),
170}