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, Copy, Debug, PartialEq, Eq, Hash)]
577pub enum SensorKind {
578 Gyroscope,
580 Accelerometer,
582}
583
584#[derive(Clone, Copy, Debug, PartialEq)]
586pub struct SensorSample {
587 pub kind: SensorKind,
588 pub data: [f32; 3],
590}
591
592pub fn normalize_device_name(name: &str) -> String {
595 name.chars()
596 .filter(|c| c.is_alphanumeric())
597 .flat_map(char::to_lowercase)
598 .collect()
599}
600
601impl SensorSample {
602 pub fn gyroscope(x: f32, y: f32, z: f32) -> Self {
603 Self {
604 kind: SensorKind::Gyroscope,
605 data: [x, y, z],
606 }
607 }
608
609 pub fn accelerometer(x: f32, y: f32, z: f32) -> Self {
610 Self {
611 kind: SensorKind::Accelerometer,
612 data: [x, y, z],
613 }
614 }
615}
616
617#[derive(Clone, Debug)]
618pub enum GamepadEvent {
619 Connected {
620 id: GamepadId,
621 name: String,
622 vendor_id: u16,
624 product_id: u16,
625 },
626 Disconnected {
627 id: GamepadId,
628 },
629 Button {
630 id: GamepadId,
631 button: GamepadButton,
632 pressed: bool,
633 },
634 Axis {
635 id: GamepadId,
636 axis: GamepadAxis,
637 value: f32,
639 },
640}
641
642impl GamepadEvent {
643 pub fn id(&self) -> GamepadId {
644 match *self {
645 GamepadEvent::Connected { id, .. } => id,
646 GamepadEvent::Disconnected { id } => id,
647 GamepadEvent::Button { id, .. } => id,
648 GamepadEvent::Axis { id, .. } => id,
649 }
650 }
651}
652
653#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
654pub enum InputMode {
655 #[default]
656 Touch,
657 Keyboard,
659}
660
661thread_local! {
662 static INPUT_MODE: Cell<InputMode> = const { Cell::new(InputMode::Touch) };
663}
664
665#[inline]
670pub fn input_mode() -> InputMode {
671 crate::locals::local_input_mode().unwrap_or_else(default_input_mode)
672}
673
674pub(crate) fn default_input_mode() -> InputMode {
675 INPUT_MODE.get()
676}
677
678#[inline]
680pub fn set_input_mode_default(mode: InputMode) {
681 INPUT_MODE.set(mode);
682 crate::request_frame();
683}
684
685pub fn request_input_mode(mode: InputMode) -> bool {
689 let prev = INPUT_MODE.get();
690 if prev == mode {
691 return false;
692 }
693 INPUT_MODE.set(mode);
694 crate::frame_clock::request_frame();
695 true
696}
697
698#[inline]
700pub fn is_focus_visible(focused: bool) -> bool {
701 focused && input_mode() == InputMode::Keyboard
702}
703
704#[cfg(test)]
705mod input_mode_tests {
706 use super::*;
707 use crate::frame_clock::take_frame_request;
708 use crate::modifier::{Interaction, MutableInteractionSource};
709
710 #[test]
711 fn request_input_mode_changes_and_requests_frame() {
712 set_input_mode_default(InputMode::Touch);
713 let _ = take_frame_request();
714
715 assert!(!request_input_mode(InputMode::Touch));
716 assert!(!take_frame_request());
717
718 assert!(request_input_mode(InputMode::Keyboard));
719 assert_eq!(input_mode(), InputMode::Keyboard);
720 assert!(take_frame_request());
721
722 assert!(request_input_mode(InputMode::Touch));
723 assert_eq!(input_mode(), InputMode::Touch);
724 set_input_mode_default(InputMode::Touch);
725 }
726
727 #[test]
728 fn focus_visible_requires_keyboard_mode() {
729 set_input_mode_default(InputMode::Touch);
730 let src = MutableInteractionSource::new();
731 src.emit(Interaction::Focus);
732 assert!(src.source().collect_is_focused());
733 assert!(!src.source().collect_is_focus_visible());
734
735 set_input_mode_default(InputMode::Keyboard);
736 assert!(src.source().collect_is_focus_visible());
737
738 set_input_mode_default(InputMode::Touch);
739 src.emit(Interaction::Unfocus);
740 }
741
742 #[test]
743 fn with_input_mode_overrides_global() {
744 set_input_mode_default(InputMode::Touch);
745 crate::locals::with_input_mode(InputMode::Keyboard, || {
746 assert_eq!(input_mode(), InputMode::Keyboard);
747 });
748 assert_eq!(input_mode(), InputMode::Touch);
749 }
750}