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 ControlLeft,
493 ControlRight,
494 AltLeft,
495 AltRight,
496 MetaLeft,
497 MetaRight,
498 CapsLock,
499 NumLock,
500 ScrollLock,
501 Pause,
502 PrintScreen,
503 ContextMenu,
504 Numpad(char),
505 NumpadEnter,
506 MediaPlay,
507 MediaPause,
508 MediaPlayPause,
509 MediaStop,
510 MediaNext,
511 MediaPrevious,
512 VolumeUp,
513 VolumeDown,
514 VolumeMute,
515 F(u8), Unknown,
517}
518
519#[derive(Clone, Copy, Debug, PartialEq, Eq)]
520pub enum KeyEventType {
521 Down,
523 Up,
525 Unknown,
527}
528
529#[derive(Clone, Debug)]
530pub struct KeyEvent {
531 pub key: Key,
532 pub modifiers: Modifiers,
533 pub is_repeat: bool,
534 pub event_type: KeyEventType,
536 pub utf16_code_point: u16,
539 pub physical: Option<PhysicalKey>,
541}
542
543impl KeyEvent {
544 pub fn is_ctrl_pressed(&self) -> bool {
545 self.modifiers.ctrl
546 }
547 pub fn is_alt_pressed(&self) -> bool {
548 self.modifiers.alt
549 }
550 pub fn is_shift_pressed(&self) -> bool {
551 self.modifiers.shift
552 }
553 pub fn is_meta_pressed(&self) -> bool {
554 self.modifiers.meta
555 }
556}
557
558#[derive(Clone, Debug)]
559pub struct TextInputEvent {
560 pub text: String,
561}
562
563#[derive(Clone, Debug)]
564pub enum ImeEvent {
565 Start,
567 Update {
569 text: String,
570 cursor: Option<(usize, usize)>, },
572 Commit(String),
574 Cancel,
576}
577
578#[derive(Clone, Debug)]
579pub enum InputEvent {
580 Pointer(PointerEvent),
581 Key(KeyEvent),
582 Text(TextInputEvent),
583 Ime(ImeEvent),
584 Gamepad(GamepadEvent),
585}
586
587#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
590pub struct GamepadId(pub u32);
591
592#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
595pub enum GamepadButton {
596 South,
598 East,
600 West,
602 North,
604 Start,
605 Select,
606 LeftShoulder,
607 RightShoulder,
608 LeftStick,
609 RightStick,
610 DPadUp,
611 DPadDown,
612 DPadLeft,
613 DPadRight,
614}
615
616#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
618pub enum GamepadAxis {
619 LeftStickX,
620 LeftStickY,
621 RightStickX,
622 RightStickY,
623 LeftTrigger,
624 RightTrigger,
625}
626
627#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
629pub enum SensorKind {
630 Gyroscope,
632 Accelerometer,
634}
635
636#[derive(Clone, Copy, Debug, PartialEq)]
638pub struct SensorSample {
639 pub kind: SensorKind,
640 pub data: [f32; 3],
642}
643
644pub fn normalize_device_name(name: &str) -> String {
647 name.chars()
648 .filter(|c| c.is_alphanumeric())
649 .flat_map(char::to_lowercase)
650 .collect()
651}
652
653impl SensorSample {
654 pub fn gyroscope(x: f32, y: f32, z: f32) -> Self {
655 Self {
656 kind: SensorKind::Gyroscope,
657 data: [x, y, z],
658 }
659 }
660
661 pub fn accelerometer(x: f32, y: f32, z: f32) -> Self {
662 Self {
663 kind: SensorKind::Accelerometer,
664 data: [x, y, z],
665 }
666 }
667}
668
669#[derive(Clone, Debug)]
670pub enum GamepadEvent {
671 Connected {
672 id: GamepadId,
673 name: String,
674 vendor_id: u16,
676 product_id: u16,
677 },
678 Disconnected {
679 id: GamepadId,
680 },
681 Button {
682 id: GamepadId,
683 button: GamepadButton,
684 pressed: bool,
685 },
686 Axis {
687 id: GamepadId,
688 axis: GamepadAxis,
689 value: f32,
691 },
692}
693
694impl GamepadEvent {
695 pub fn id(&self) -> GamepadId {
696 match *self {
697 GamepadEvent::Connected { id, .. } => id,
698 GamepadEvent::Disconnected { id } => id,
699 GamepadEvent::Button { id, .. } => id,
700 GamepadEvent::Axis { id, .. } => id,
701 }
702 }
703}
704
705#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
706pub enum InputMode {
707 #[default]
708 Touch,
709 Keyboard,
711}
712
713thread_local! {
714 static INPUT_MODE: Cell<InputMode> = const { Cell::new(InputMode::Touch) };
715}
716
717#[inline]
722pub fn input_mode() -> InputMode {
723 crate::locals::local_input_mode().unwrap_or_else(default_input_mode)
724}
725
726pub(crate) fn default_input_mode() -> InputMode {
727 INPUT_MODE.get()
728}
729
730#[inline]
732pub fn set_input_mode_default(mode: InputMode) {
733 INPUT_MODE.set(mode);
734 crate::request_frame();
735}
736
737pub fn request_input_mode(mode: InputMode) -> bool {
741 let prev = INPUT_MODE.get();
742 if prev == mode {
743 return false;
744 }
745 INPUT_MODE.set(mode);
746 crate::frame_clock::request_frame();
747 true
748}
749
750#[inline]
752pub fn is_focus_visible(focused: bool) -> bool {
753 focused && input_mode() == InputMode::Keyboard
754}
755
756#[cfg(test)]
757mod input_mode_tests {
758 use super::*;
759 use crate::frame_clock::take_frame_request;
760 use crate::modifier::{Interaction, MutableInteractionSource};
761
762 #[test]
763 fn request_input_mode_changes_and_requests_frame() {
764 set_input_mode_default(InputMode::Touch);
765 let _ = take_frame_request();
766
767 assert!(!request_input_mode(InputMode::Touch));
768 assert!(!take_frame_request());
769
770 assert!(request_input_mode(InputMode::Keyboard));
771 assert_eq!(input_mode(), InputMode::Keyboard);
772 assert!(take_frame_request());
773
774 assert!(request_input_mode(InputMode::Touch));
775 assert_eq!(input_mode(), InputMode::Touch);
776 set_input_mode_default(InputMode::Touch);
777 }
778
779 #[test]
780 fn focus_visible_requires_keyboard_mode() {
781 set_input_mode_default(InputMode::Touch);
782 let src = MutableInteractionSource::new();
783 src.emit(Interaction::Focus);
784 assert!(src.source().collect_is_focused());
785 assert!(!src.source().collect_is_focus_visible());
786
787 set_input_mode_default(InputMode::Keyboard);
788 assert!(src.source().collect_is_focus_visible());
789
790 set_input_mode_default(InputMode::Touch);
791 src.emit(Interaction::Unfocus);
792 }
793
794 #[test]
795 fn with_input_mode_overrides_global() {
796 set_input_mode_default(InputMode::Touch);
797 crate::locals::with_input_mode(InputMode::Keyboard, || {
798 assert_eq!(input_mode(), InputMode::Keyboard);
799 });
800 assert_eq!(input_mode(), InputMode::Touch);
801 }
802}