Skip to main content

lgui_core/core/input/
event.rs

1use std::{collections::HashMap, ops::Range, path::PathBuf};
2
3use super::{
4    normalized_f32_bits, AnimProperty, AnimationRegistry, EventPolicy, HitResult, HostTree, Point,
5    UiId,
6};
7
8pub use keyboard_types::{
9    Code as PhysicalKey, Key as LogicalKey, KeyState, KeyboardEvent, Location as KeyLocation,
10    Modifiers as KeyModifiers, NamedKey,
11};
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14pub enum PointerButton {
15    Left,
16    Right,
17    Middle,
18    Back,
19    Forward,
20    Other(u16),
21}
22
23#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
24pub struct PointerId(pub u64);
25
26#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
27pub enum PointerKind {
28    #[default]
29    Mouse,
30    Touch,
31    Pen,
32    Unknown,
33}
34
35#[derive(Clone, Copy, Debug, PartialEq, Eq)]
36pub struct PointerData {
37    pub id: PointerId,
38    pub kind: PointerKind,
39    pub point: Point,
40    pub pressure: Option<u16>,
41    pub primary: bool,
42}
43
44impl PointerData {
45    pub const fn mouse(point: Point) -> Self {
46        Self {
47            id: PointerId(0),
48            kind: PointerKind::Mouse,
49            point,
50            pressure: None,
51            primary: true,
52        }
53    }
54}
55
56#[derive(Clone, Copy, Debug, PartialEq, Eq)]
57pub enum TouchPhase {
58    Started,
59    Moved,
60    Ended,
61    Cancelled,
62}
63
64#[derive(Clone, Copy, Debug, PartialEq, Eq)]
65pub enum WheelUnit {
66    Lines,
67    Pixels,
68}
69
70#[derive(Clone, Copy, Debug)]
71pub struct WheelDelta {
72    pub x: f32,
73    pub y: f32,
74    pub unit: WheelUnit,
75    pub phase: TouchPhase,
76}
77
78impl PartialEq for WheelDelta {
79    fn eq(&self, other: &Self) -> bool {
80        normalized_f32_bits(self.x) == normalized_f32_bits(other.x)
81            && normalized_f32_bits(self.y) == normalized_f32_bits(other.y)
82            && self.unit == other.unit
83            && self.phase == other.phase
84    }
85}
86
87impl Eq for WheelDelta {}
88
89impl WheelDelta {
90    pub const fn lines(x: f32, y: f32) -> Self {
91        Self {
92            x,
93            y,
94            unit: WheelUnit::Lines,
95            phase: TouchPhase::Moved,
96        }
97    }
98
99    pub const fn pixels(x: f32, y: f32) -> Self {
100        Self {
101            x,
102            y,
103            unit: WheelUnit::Pixels,
104            phase: TouchPhase::Moved,
105        }
106    }
107}
108
109#[derive(Clone, Debug, PartialEq)]
110pub enum InputEvent {
111    PointerMove(PointerData),
112    PointerDown {
113        pointer: PointerData,
114        button: PointerButton,
115    },
116    PointerUp {
117        pointer: PointerData,
118        button: PointerButton,
119    },
120    PointerEnter(PointerData),
121    Wheel {
122        point: Point,
123        delta: WheelDelta,
124    },
125    TextInput(String),
126    Ime(ImeEvent),
127    Keyboard(KeyboardEvent),
128    PointerLeave(PointerData),
129    Touch {
130        pointer: PointerData,
131        phase: TouchPhase,
132    },
133    Platform(PlatformEvent),
134    Semantic(SemanticInput),
135}
136
137#[derive(Clone, Debug, PartialEq)]
138pub enum SemanticInput {
139    Click(UiId),
140    Focus(UiId),
141    Blur(UiId),
142    SetValue {
143        target: UiId,
144        value: String,
145    },
146    Action {
147        target: UiId,
148        action: super::SemanticAction,
149    },
150}
151
152#[derive(Clone, Copy, Debug, PartialEq, Eq)]
153pub enum PlatformTheme {
154    Light,
155    Dark,
156}
157
158#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
159pub struct WindowStateEvent {
160    pub focused: bool,
161    pub minimized: bool,
162    pub maximized: bool,
163    pub fullscreen: bool,
164}
165
166#[derive(Clone, Debug, PartialEq)]
167pub enum PlatformEvent {
168    Focused(bool),
169    FileHovered(PathBuf),
170    FileDropped(PathBuf),
171    FileHoverCancelled,
172    ScaleFactorChanged(f64),
173    ThemeChanged(PlatformTheme),
174    WindowStateChanged(WindowStateEvent),
175}
176
177#[derive(Clone, Debug, PartialEq, Eq)]
178pub enum ImeEvent {
179    Enabled,
180    Preedit {
181        text: String,
182        cursor: Option<Range<usize>>,
183    },
184    Commit(String),
185    Disabled,
186}
187
188#[derive(Clone, Debug, PartialEq, Eq)]
189pub enum UiEvent {
190    HoverChanged {
191        previous: Option<UiId>,
192        current: Option<HitResult>,
193    },
194    PressedChanged {
195        previous: Option<UiId>,
196        current: Option<HitResult>,
197    },
198    Clicked(HitResult),
199    Wheel {
200        hit: HitResult,
201        delta: WheelDelta,
202    },
203    TextInput {
204        target: UiId,
205        text: String,
206    },
207    ImeStarted {
208        target: UiId,
209    },
210    ImeUpdated {
211        target: UiId,
212        text: String,
213        cursor: Option<Range<usize>>,
214    },
215    ImeEnded {
216        target: UiId,
217    },
218    Keyboard {
219        target: UiId,
220        event: KeyboardEvent,
221    },
222    PointerPressed {
223        hit: HitResult,
224        pointer: PointerData,
225    },
226    PointerMoved {
227        hit: HitResult,
228        pointer: PointerData,
229    },
230    PointerDragged {
231        hit: HitResult,
232        pointer: PointerData,
233    },
234    PointerReleased {
235        hit: HitResult,
236        pointer: PointerData,
237    },
238    FocusChanged {
239        previous: Option<UiId>,
240        current: Option<HitResult>,
241    },
242    PointerLeft {
243        previous: Option<UiId>,
244    },
245    SemanticValue {
246        target: UiId,
247        value: String,
248    },
249    SemanticAction {
250        target: UiId,
251        action: super::SemanticAction,
252    },
253}
254
255#[derive(Clone, Debug, Default, PartialEq, Eq)]
256pub struct UiInteractionState {
257    pub hovered: Option<UiId>,
258    pub pressed: Option<UiId>,
259    pub focused: Option<UiId>,
260}
261
262impl UiInteractionState {
263    pub fn flags_for(&self, id: &UiId) -> InteractionFlags {
264        InteractionFlags {
265            hovered: self.hovered.as_ref() == Some(id),
266            pressed: self.pressed.as_ref() == Some(id),
267            focused: self.focused.as_ref() == Some(id),
268        }
269    }
270}
271
272#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
273pub struct InteractionFlags {
274    pub hovered: bool,
275    pub pressed: bool,
276    pub focused: bool,
277}
278
279mod animation;
280mod dispatcher;
281
282pub use animation::apply_events_to_animations;
283pub use dispatcher::UiEventDispatcher;
284
285#[cfg(test)]
286#[path = "event_test.rs"]
287mod tests;