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