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, PartialEq, Eq, Hash)]
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 window_position: Vec2,
57 pub pressure: f32,
58 pub modifiers: Modifiers,
59 pub consumed: Rc<Cell<bool>>,
62}
63
64impl PointerEvent {
65 pub fn new(
66 id: PointerId,
67 kind: PointerKind,
68 event: PointerEventKind,
69 position: Vec2,
70 pressure: f32,
71 modifiers: Modifiers,
72 ) -> Self {
73 Self {
74 id,
75 kind,
76 event,
77 position,
78 origin: Vec2::ZERO,
79 window_position: position,
80 pressure,
81 modifiers,
82 consumed: Rc::new(Cell::new(false)),
83 }
84 }
85
86 pub fn position_in_window(&self) -> Vec2 {
88 self.window_position
89 }
90
91 pub fn consume(&self) {
95 self.consumed.set(true);
96 }
97
98 pub fn is_consumed(&self) -> bool {
100 self.consumed.get()
101 }
102}
103
104#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
105pub struct Modifiers {
106 pub shift: bool,
107 pub ctrl: bool,
108 pub alt: bool,
109 pub meta: bool, pub command: bool, }
112
113#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
115pub enum PhysicalKey {
116 KeyA,
117 KeyB,
118 KeyC,
119 KeyD,
120 KeyE,
121 KeyF,
122 KeyG,
123 KeyH,
124 KeyI,
125 KeyJ,
126 KeyK,
127 KeyL,
128 KeyM,
129 KeyN,
130 KeyO,
131 KeyP,
132 KeyQ,
133 KeyR,
134 KeyS,
135 KeyT,
136 KeyU,
137 KeyV,
138 KeyW,
139 KeyX,
140 KeyY,
141 KeyZ,
142 Digit0,
143 Digit1,
144 Digit2,
145 Digit3,
146 Digit4,
147 Digit5,
148 Digit6,
149 Digit7,
150 Digit8,
151 Digit9,
152 Minus,
153 Equal,
154 BracketLeft,
155 BracketRight,
156 Backslash,
157 Semicolon,
158 Quote,
159 Backquote,
160 Comma,
161 Period,
162 Slash,
163 IntlBackslash,
164 IntlRo,
165 IntlYen,
166 Escape,
167 F1,
168 F2,
169 F3,
170 F4,
171 F5,
172 F6,
173 F7,
174 F8,
175 F9,
176 F10,
177 F11,
178 F12,
179 PrintScreen,
180 ScrollLock,
181 Pause,
182 Insert,
183 Home,
184 PageUp,
185 Delete,
186 End,
187 PageDown,
188 ArrowRight,
189 ArrowLeft,
190 ArrowDown,
191 ArrowUp,
192 NumLock,
193 NumpadDivide,
194 NumpadMultiply,
195 NumpadSubtract,
196 NumpadAdd,
197 NumpadEnter,
198 NumpadDecimal,
199 Numpad0,
200 Numpad1,
201 Numpad2,
202 Numpad3,
203 Numpad4,
204 Numpad5,
205 Numpad6,
206 Numpad7,
207 Numpad8,
208 Numpad9,
209 Backspace,
210 Tab,
211 Space,
212 CapsLock,
213 Enter,
214 ShiftLeft,
215 ShiftRight,
216 ControlLeft,
217 ControlRight,
218 AltLeft,
219 AltRight,
220 SuperLeft,
221 SuperRight,
222 ContextMenu,
223 Unidentified,
224}
225
226impl PhysicalKey {
227 pub fn name(self) -> &'static str {
229 match self {
230 PhysicalKey::KeyA => "KeyA",
231 PhysicalKey::KeyB => "KeyB",
232 PhysicalKey::KeyC => "KeyC",
233 PhysicalKey::KeyD => "KeyD",
234 PhysicalKey::KeyE => "KeyE",
235 PhysicalKey::KeyF => "KeyF",
236 PhysicalKey::KeyG => "KeyG",
237 PhysicalKey::KeyH => "KeyH",
238 PhysicalKey::KeyI => "KeyI",
239 PhysicalKey::KeyJ => "KeyJ",
240 PhysicalKey::KeyK => "KeyK",
241 PhysicalKey::KeyL => "KeyL",
242 PhysicalKey::KeyM => "KeyM",
243 PhysicalKey::KeyN => "KeyN",
244 PhysicalKey::KeyO => "KeyO",
245 PhysicalKey::KeyP => "KeyP",
246 PhysicalKey::KeyQ => "KeyQ",
247 PhysicalKey::KeyR => "KeyR",
248 PhysicalKey::KeyS => "KeyS",
249 PhysicalKey::KeyT => "KeyT",
250 PhysicalKey::KeyU => "KeyU",
251 PhysicalKey::KeyV => "KeyV",
252 PhysicalKey::KeyW => "KeyW",
253 PhysicalKey::KeyX => "KeyX",
254 PhysicalKey::KeyY => "KeyY",
255 PhysicalKey::KeyZ => "KeyZ",
256 PhysicalKey::Digit0 => "Digit0",
257 PhysicalKey::Digit1 => "Digit1",
258 PhysicalKey::Digit2 => "Digit2",
259 PhysicalKey::Digit3 => "Digit3",
260 PhysicalKey::Digit4 => "Digit4",
261 PhysicalKey::Digit5 => "Digit5",
262 PhysicalKey::Digit6 => "Digit6",
263 PhysicalKey::Digit7 => "Digit7",
264 PhysicalKey::Digit8 => "Digit8",
265 PhysicalKey::Digit9 => "Digit9",
266 PhysicalKey::Minus => "Minus",
267 PhysicalKey::Equal => "Equal",
268 PhysicalKey::BracketLeft => "BracketLeft",
269 PhysicalKey::BracketRight => "BracketRight",
270 PhysicalKey::Backslash => "Backslash",
271 PhysicalKey::Semicolon => "Semicolon",
272 PhysicalKey::Quote => "Quote",
273 PhysicalKey::Backquote => "Backquote",
274 PhysicalKey::Comma => "Comma",
275 PhysicalKey::Period => "Period",
276 PhysicalKey::Slash => "Slash",
277 PhysicalKey::IntlBackslash => "IntlBackslash",
278 PhysicalKey::IntlRo => "IntlRo",
279 PhysicalKey::IntlYen => "IntlYen",
280 PhysicalKey::Escape => "Escape",
281 PhysicalKey::F1 => "F1",
282 PhysicalKey::F2 => "F2",
283 PhysicalKey::F3 => "F3",
284 PhysicalKey::F4 => "F4",
285 PhysicalKey::F5 => "F5",
286 PhysicalKey::F6 => "F6",
287 PhysicalKey::F7 => "F7",
288 PhysicalKey::F8 => "F8",
289 PhysicalKey::F9 => "F9",
290 PhysicalKey::F10 => "F10",
291 PhysicalKey::F11 => "F11",
292 PhysicalKey::F12 => "F12",
293 PhysicalKey::PrintScreen => "PrintScreen",
294 PhysicalKey::ScrollLock => "ScrollLock",
295 PhysicalKey::Pause => "Pause",
296 PhysicalKey::Insert => "Insert",
297 PhysicalKey::Home => "Home",
298 PhysicalKey::PageUp => "PageUp",
299 PhysicalKey::Delete => "Delete",
300 PhysicalKey::End => "End",
301 PhysicalKey::PageDown => "PageDown",
302 PhysicalKey::ArrowRight => "ArrowRight",
303 PhysicalKey::ArrowLeft => "ArrowLeft",
304 PhysicalKey::ArrowDown => "ArrowDown",
305 PhysicalKey::ArrowUp => "ArrowUp",
306 PhysicalKey::NumLock => "NumLock",
307 PhysicalKey::NumpadDivide => "NumpadDivide",
308 PhysicalKey::NumpadMultiply => "NumpadMultiply",
309 PhysicalKey::NumpadSubtract => "NumpadSubtract",
310 PhysicalKey::NumpadAdd => "NumpadAdd",
311 PhysicalKey::NumpadEnter => "NumpadEnter",
312 PhysicalKey::NumpadDecimal => "NumpadDecimal",
313 PhysicalKey::Numpad0 => "Numpad0",
314 PhysicalKey::Numpad1 => "Numpad1",
315 PhysicalKey::Numpad2 => "Numpad2",
316 PhysicalKey::Numpad3 => "Numpad3",
317 PhysicalKey::Numpad4 => "Numpad4",
318 PhysicalKey::Numpad5 => "Numpad5",
319 PhysicalKey::Numpad6 => "Numpad6",
320 PhysicalKey::Numpad7 => "Numpad7",
321 PhysicalKey::Numpad8 => "Numpad8",
322 PhysicalKey::Numpad9 => "Numpad9",
323 PhysicalKey::Backspace => "Backspace",
324 PhysicalKey::Tab => "Tab",
325 PhysicalKey::Space => "Space",
326 PhysicalKey::CapsLock => "CapsLock",
327 PhysicalKey::Enter => "Enter",
328 PhysicalKey::ShiftLeft => "ShiftLeft",
329 PhysicalKey::ShiftRight => "ShiftRight",
330 PhysicalKey::ControlLeft => "ControlLeft",
331 PhysicalKey::ControlRight => "ControlRight",
332 PhysicalKey::AltLeft => "AltLeft",
333 PhysicalKey::AltRight => "AltRight",
334 PhysicalKey::SuperLeft => "SuperLeft",
335 PhysicalKey::SuperRight => "SuperRight",
336 PhysicalKey::ContextMenu => "ContextMenu",
337 PhysicalKey::Unidentified => "Unidentified",
338 }
339 }
340
341 pub fn from_name(name: &str) -> Self {
345 match name {
346 "KeyA" => PhysicalKey::KeyA,
347 "KeyB" => PhysicalKey::KeyB,
348 "KeyC" => PhysicalKey::KeyC,
349 "KeyD" => PhysicalKey::KeyD,
350 "KeyE" => PhysicalKey::KeyE,
351 "KeyF" => PhysicalKey::KeyF,
352 "KeyG" => PhysicalKey::KeyG,
353 "KeyH" => PhysicalKey::KeyH,
354 "KeyI" => PhysicalKey::KeyI,
355 "KeyJ" => PhysicalKey::KeyJ,
356 "KeyK" => PhysicalKey::KeyK,
357 "KeyL" => PhysicalKey::KeyL,
358 "KeyM" => PhysicalKey::KeyM,
359 "KeyN" => PhysicalKey::KeyN,
360 "KeyO" => PhysicalKey::KeyO,
361 "KeyP" => PhysicalKey::KeyP,
362 "KeyQ" => PhysicalKey::KeyQ,
363 "KeyR" => PhysicalKey::KeyR,
364 "KeyS" => PhysicalKey::KeyS,
365 "KeyT" => PhysicalKey::KeyT,
366 "KeyU" => PhysicalKey::KeyU,
367 "KeyV" => PhysicalKey::KeyV,
368 "KeyW" => PhysicalKey::KeyW,
369 "KeyX" => PhysicalKey::KeyX,
370 "KeyY" => PhysicalKey::KeyY,
371 "KeyZ" => PhysicalKey::KeyZ,
372 "Digit0" => PhysicalKey::Digit0,
373 "Digit1" => PhysicalKey::Digit1,
374 "Digit2" => PhysicalKey::Digit2,
375 "Digit3" => PhysicalKey::Digit3,
376 "Digit4" => PhysicalKey::Digit4,
377 "Digit5" => PhysicalKey::Digit5,
378 "Digit6" => PhysicalKey::Digit6,
379 "Digit7" => PhysicalKey::Digit7,
380 "Digit8" => PhysicalKey::Digit8,
381 "Digit9" => PhysicalKey::Digit9,
382 "Minus" => PhysicalKey::Minus,
383 "Equal" => PhysicalKey::Equal,
384 "BracketLeft" => PhysicalKey::BracketLeft,
385 "BracketRight" => PhysicalKey::BracketRight,
386 "Backslash" => PhysicalKey::Backslash,
387 "Semicolon" => PhysicalKey::Semicolon,
388 "Quote" => PhysicalKey::Quote,
389 "Backquote" => PhysicalKey::Backquote,
390 "Comma" => PhysicalKey::Comma,
391 "Period" => PhysicalKey::Period,
392 "Slash" => PhysicalKey::Slash,
393 "IntlBackslash" => PhysicalKey::IntlBackslash,
394 "IntlRo" => PhysicalKey::IntlRo,
395 "IntlYen" => PhysicalKey::IntlYen,
396 "Escape" => PhysicalKey::Escape,
397 "F1" => PhysicalKey::F1,
398 "F2" => PhysicalKey::F2,
399 "F3" => PhysicalKey::F3,
400 "F4" => PhysicalKey::F4,
401 "F5" => PhysicalKey::F5,
402 "F6" => PhysicalKey::F6,
403 "F7" => PhysicalKey::F7,
404 "F8" => PhysicalKey::F8,
405 "F9" => PhysicalKey::F9,
406 "F10" => PhysicalKey::F10,
407 "F11" => PhysicalKey::F11,
408 "F12" => PhysicalKey::F12,
409 "PrintScreen" => PhysicalKey::PrintScreen,
410 "ScrollLock" => PhysicalKey::ScrollLock,
411 "Pause" => PhysicalKey::Pause,
412 "Insert" => PhysicalKey::Insert,
413 "Home" => PhysicalKey::Home,
414 "PageUp" => PhysicalKey::PageUp,
415 "Delete" => PhysicalKey::Delete,
416 "End" => PhysicalKey::End,
417 "PageDown" => PhysicalKey::PageDown,
418 "ArrowRight" => PhysicalKey::ArrowRight,
419 "ArrowLeft" => PhysicalKey::ArrowLeft,
420 "ArrowDown" => PhysicalKey::ArrowDown,
421 "ArrowUp" => PhysicalKey::ArrowUp,
422 "NumLock" => PhysicalKey::NumLock,
423 "NumpadDivide" => PhysicalKey::NumpadDivide,
424 "NumpadMultiply" => PhysicalKey::NumpadMultiply,
425 "NumpadSubtract" => PhysicalKey::NumpadSubtract,
426 "NumpadAdd" => PhysicalKey::NumpadAdd,
427 "NumpadEnter" => PhysicalKey::NumpadEnter,
428 "NumpadDecimal" => PhysicalKey::NumpadDecimal,
429 "Numpad0" => PhysicalKey::Numpad0,
430 "Numpad1" => PhysicalKey::Numpad1,
431 "Numpad2" => PhysicalKey::Numpad2,
432 "Numpad3" => PhysicalKey::Numpad3,
433 "Numpad4" => PhysicalKey::Numpad4,
434 "Numpad5" => PhysicalKey::Numpad5,
435 "Numpad6" => PhysicalKey::Numpad6,
436 "Numpad7" => PhysicalKey::Numpad7,
437 "Numpad8" => PhysicalKey::Numpad8,
438 "Numpad9" => PhysicalKey::Numpad9,
439 "Backspace" => PhysicalKey::Backspace,
440 "Tab" => PhysicalKey::Tab,
441 "Space" => PhysicalKey::Space,
442 "CapsLock" => PhysicalKey::CapsLock,
443 "Enter" => PhysicalKey::Enter,
444 "ShiftLeft" => PhysicalKey::ShiftLeft,
445 "ShiftRight" => PhysicalKey::ShiftRight,
446 "ControlLeft" => PhysicalKey::ControlLeft,
447 "ControlRight" => PhysicalKey::ControlRight,
448 "AltLeft" => PhysicalKey::AltLeft,
449 "AltRight" => PhysicalKey::AltRight,
450 "SuperLeft" | "MetaLeft" => PhysicalKey::SuperLeft,
451 "SuperRight" | "MetaRight" => PhysicalKey::SuperRight,
452 "ContextMenu" => PhysicalKey::ContextMenu,
453 _ => PhysicalKey::Unidentified,
454 }
455 }
456}
457
458#[derive(Clone, Debug, PartialEq, Eq, Hash)]
459pub enum Key {
460 Character(char),
461 Enter,
462 Tab,
463 Backspace,
464 Delete,
465 Insert,
466 Escape,
467 ArrowLeft,
468 ArrowRight,
469 ArrowUp,
470 ArrowDown,
471 Home,
472 End,
473 PageUp,
474 PageDown,
475 Space,
476 ShiftLeft,
477 ShiftRight,
478 F(u8), Unknown,
480}
481
482#[derive(Clone, Copy, Debug, PartialEq, Eq)]
483pub enum KeyEventType {
484 Down,
486 Up,
488 Unknown,
490}
491
492#[derive(Clone, Debug)]
493pub struct KeyEvent {
494 pub key: Key,
495 pub modifiers: Modifiers,
496 pub is_repeat: bool,
497 pub event_type: KeyEventType,
499 pub utf16_code_point: u16,
502 pub physical: Option<PhysicalKey>,
504}
505
506#[derive(Clone, Debug)]
507pub struct TextInputEvent {
508 pub text: String,
509}
510
511#[derive(Clone, Debug)]
512pub enum ImeEvent {
513 Start,
515 Update {
517 text: String,
518 cursor: Option<(usize, usize)>, },
520 Commit(String),
522 Cancel,
524}
525
526#[derive(Clone, Debug)]
527pub enum InputEvent {
528 Pointer(PointerEvent),
529 Key(KeyEvent),
530 Text(TextInputEvent),
531 Ime(ImeEvent),
532 Gamepad(GamepadEvent),
533}
534
535#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
538pub struct GamepadId(pub u32);
539
540#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
543pub enum GamepadButton {
544 South,
546 East,
548 West,
550 North,
552 Start,
553 Select,
554 LeftShoulder,
555 RightShoulder,
556 LeftStick,
557 RightStick,
558 DPadUp,
559 DPadDown,
560 DPadLeft,
561 DPadRight,
562}
563
564#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
566pub enum GamepadAxis {
567 LeftStickX,
568 LeftStickY,
569 RightStickX,
570 RightStickY,
571 LeftTrigger,
572 RightTrigger,
573}
574
575#[derive(Clone, Debug)]
576pub enum GamepadEvent {
577 Connected {
578 id: GamepadId,
579 name: String,
580 },
581 Disconnected {
582 id: GamepadId,
583 },
584 Button {
585 id: GamepadId,
586 button: GamepadButton,
587 pressed: bool,
588 },
589 Axis {
590 id: GamepadId,
591 axis: GamepadAxis,
592 value: f32,
594 },
595}
596
597impl GamepadEvent {
598 pub fn id(&self) -> GamepadId {
599 match *self {
600 GamepadEvent::Connected { id, .. } => id,
601 GamepadEvent::Disconnected { id } => id,
602 GamepadEvent::Button { id, .. } => id,
603 GamepadEvent::Axis { id, .. } => id,
604 }
605 }
606}
607
608#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
609pub enum InputMode {
610 #[default]
611 Touch,
612 Keyboard,
614}
615
616thread_local! {
617 static INPUT_MODE: Cell<InputMode> = const { Cell::new(InputMode::Touch) };
618}
619
620#[inline]
625pub fn input_mode() -> InputMode {
626 crate::locals::local_input_mode().unwrap_or_else(default_input_mode)
627}
628
629pub(crate) fn default_input_mode() -> InputMode {
630 INPUT_MODE.get()
631}
632
633#[inline]
635pub fn set_input_mode_default(mode: InputMode) {
636 INPUT_MODE.set(mode);
637 crate::request_frame();
638}
639
640pub fn request_input_mode(mode: InputMode) -> bool {
644 let prev = INPUT_MODE.get();
645 if prev == mode {
646 return false;
647 }
648 INPUT_MODE.set(mode);
649 crate::frame_clock::request_frame();
650 true
651}
652
653#[inline]
655pub fn is_focus_visible(focused: bool) -> bool {
656 focused && input_mode() == InputMode::Keyboard
657}
658
659#[cfg(test)]
660mod input_mode_tests {
661 use super::*;
662 use crate::frame_clock::take_frame_request;
663 use crate::modifier::{Interaction, MutableInteractionSource};
664
665 #[test]
666 fn request_input_mode_changes_and_requests_frame() {
667 set_input_mode_default(InputMode::Touch);
668 let _ = take_frame_request();
669
670 assert!(!request_input_mode(InputMode::Touch));
671 assert!(!take_frame_request());
672
673 assert!(request_input_mode(InputMode::Keyboard));
674 assert_eq!(input_mode(), InputMode::Keyboard);
675 assert!(take_frame_request());
676
677 assert!(request_input_mode(InputMode::Touch));
678 assert_eq!(input_mode(), InputMode::Touch);
679 set_input_mode_default(InputMode::Touch);
680 }
681
682 #[test]
683 fn focus_visible_requires_keyboard_mode() {
684 set_input_mode_default(InputMode::Touch);
685 let src = MutableInteractionSource::new();
686 src.emit(Interaction::Focus);
687 assert!(src.source().collect_is_focused());
688 assert!(!src.source().collect_is_focus_visible());
689
690 set_input_mode_default(InputMode::Keyboard);
691 assert!(src.source().collect_is_focus_visible());
692
693 set_input_mode_default(InputMode::Touch);
694 src.emit(Interaction::Unfocus);
695 }
696
697 #[test]
698 fn with_input_mode_overrides_global() {
699 set_input_mode_default(InputMode::Touch);
700 crate::locals::with_input_mode(InputMode::Keyboard, || {
701 assert_eq!(input_mode(), InputMode::Keyboard);
702 });
703 assert_eq!(input_mode(), InputMode::Touch);
704 }
705}