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, Secondary, Tertiary, }
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum PointerEventPass {
24 Initial,
27 Main,
31 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,
53 pub origin: Vec2,
55 pub pressure: f32,
56 pub modifiers: Modifiers,
57 pub consumed: Rc<Cell<bool>>,
60}
61
62impl PointerEvent {
63 pub fn new(
64 id: PointerId,
65 kind: PointerKind,
66 event: PointerEventKind,
67 position: Vec2,
68 pressure: f32,
69 modifiers: Modifiers,
70 ) -> Self {
71 Self {
72 id,
73 kind,
74 event,
75 position,
76 origin: Vec2::ZERO,
77 pressure,
78 modifiers,
79 consumed: Rc::new(Cell::new(false)),
80 }
81 }
82
83 pub fn position_in_window(&self) -> Vec2 {
85 self.position + self.origin
86 }
87
88 pub fn consume(&self) {
92 self.consumed.set(true);
93 }
94
95 pub fn is_consumed(&self) -> bool {
97 self.consumed.get()
98 }
99}
100
101#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
102pub struct Modifiers {
103 pub shift: bool,
104 pub ctrl: bool,
105 pub alt: bool,
106 pub meta: bool, pub command: bool, }
109
110#[derive(Clone, Debug, PartialEq, Eq, Hash)]
111pub enum Key {
112 Character(char),
113 Enter,
114 Tab,
115 Backspace,
116 Delete,
117 Insert,
118 Escape,
119 ArrowLeft,
120 ArrowRight,
121 ArrowUp,
122 ArrowDown,
123 Home,
124 End,
125 PageUp,
126 PageDown,
127 Space,
128 F(u8), Unknown,
130}
131
132#[derive(Clone, Copy, Debug, PartialEq, Eq)]
133pub enum KeyEventType {
134 Down,
136 Up,
138 Unknown,
140}
141
142#[derive(Clone, Debug)]
143pub struct KeyEvent {
144 pub key: Key,
145 pub modifiers: Modifiers,
146 pub is_repeat: bool,
147 pub event_type: KeyEventType,
149 pub utf16_code_point: u16,
152}
153
154#[derive(Clone, Debug)]
155pub struct TextInputEvent {
156 pub text: String,
157}
158
159#[derive(Clone, Debug)]
160pub enum ImeEvent {
161 Start,
163 Update {
165 text: String,
166 cursor: Option<(usize, usize)>, },
168 Commit(String),
170 Cancel,
172}
173
174#[derive(Clone, Debug)]
175pub enum InputEvent {
176 Pointer(PointerEvent),
177 Key(KeyEvent),
178 Text(TextInputEvent),
179 Ime(ImeEvent),
180}
181
182#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
187pub enum InputMode {
188 #[default]
189 Touch,
190 Keyboard,
192}
193
194thread_local! {
195 static INPUT_MODE: Cell<InputMode> = const { Cell::new(InputMode::Touch) };
196}
197
198#[inline]
203pub fn input_mode() -> InputMode {
204 crate::locals::local_input_mode().unwrap_or_else(|| INPUT_MODE.get())
205}
206
207#[inline]
210pub fn set_input_mode_default(mode: InputMode) {
211 INPUT_MODE.set(mode);
212}
213
214pub fn request_input_mode(mode: InputMode) -> bool {
218 let prev = INPUT_MODE.get();
219 if prev == mode {
220 return false;
221 }
222 INPUT_MODE.set(mode);
223 crate::frame_clock::request_frame();
224 true
225}
226
227#[inline]
229pub fn is_focus_visible(focused: bool) -> bool {
230 focused && input_mode() == InputMode::Keyboard
231}
232
233#[cfg(test)]
234mod input_mode_tests {
235 use super::*;
236 use crate::frame_clock::take_frame_request;
237 use crate::modifier::{Interaction, MutableInteractionSource};
238
239 #[test]
240 fn request_input_mode_changes_and_requests_frame() {
241 set_input_mode_default(InputMode::Touch);
242 let _ = take_frame_request();
243
244 assert!(!request_input_mode(InputMode::Touch));
245 assert!(!take_frame_request());
246
247 assert!(request_input_mode(InputMode::Keyboard));
248 assert_eq!(input_mode(), InputMode::Keyboard);
249 assert!(take_frame_request());
250
251 assert!(request_input_mode(InputMode::Touch));
252 assert_eq!(input_mode(), InputMode::Touch);
253 set_input_mode_default(InputMode::Touch);
254 }
255
256 #[test]
257 fn focus_visible_requires_keyboard_mode() {
258 set_input_mode_default(InputMode::Touch);
259 let src = MutableInteractionSource::new();
260 src.emit(Interaction::Focus);
261 assert!(src.source().collect_is_focused());
262 assert!(!src.source().collect_is_focus_visible());
263
264 set_input_mode_default(InputMode::Keyboard);
265 assert!(src.source().collect_is_focus_visible());
266
267 set_input_mode_default(InputMode::Touch);
268 src.emit(Interaction::Unfocus);
269 }
270
271 #[test]
272 fn with_input_mode_overrides_global() {
273 set_input_mode_default(InputMode::Touch);
274 crate::locals::with_input_mode(InputMode::Keyboard, || {
275 assert_eq!(input_mode(), InputMode::Keyboard);
276 });
277 assert_eq!(input_mode(), InputMode::Touch);
278 }
279}