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