1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3use kbd::hotkey::Hotkey;
121use kbd::hotkey::Modifier;
122use kbd::key::Key;
123use winit::event::KeyEvent;
124use winit::keyboard::KeyCode;
125use winit::keyboard::ModifiersState;
126use winit::keyboard::PhysicalKey;
127
128mod private {
129 pub trait Sealed {}
130 impl Sealed for winit::keyboard::KeyCode {}
131 impl Sealed for winit::keyboard::PhysicalKey {}
132 impl Sealed for winit::keyboard::ModifiersState {}
133 impl Sealed for winit::event::KeyEvent {}
134}
135
136pub trait WinitKeyExt: private::Sealed {
143 #[must_use]
157 fn to_key(&self) -> Option<Key>;
158}
159
160impl WinitKeyExt for KeyCode {
161 #[allow(clippy::too_many_lines)]
162 fn to_key(&self) -> Option<Key> {
163 match self {
164 KeyCode::KeyA => Some(Key::A),
166 KeyCode::KeyB => Some(Key::B),
167 KeyCode::KeyC => Some(Key::C),
168 KeyCode::KeyD => Some(Key::D),
169 KeyCode::KeyE => Some(Key::E),
170 KeyCode::KeyF => Some(Key::F),
171 KeyCode::KeyG => Some(Key::G),
172 KeyCode::KeyH => Some(Key::H),
173 KeyCode::KeyI => Some(Key::I),
174 KeyCode::KeyJ => Some(Key::J),
175 KeyCode::KeyK => Some(Key::K),
176 KeyCode::KeyL => Some(Key::L),
177 KeyCode::KeyM => Some(Key::M),
178 KeyCode::KeyN => Some(Key::N),
179 KeyCode::KeyO => Some(Key::O),
180 KeyCode::KeyP => Some(Key::P),
181 KeyCode::KeyQ => Some(Key::Q),
182 KeyCode::KeyR => Some(Key::R),
183 KeyCode::KeyS => Some(Key::S),
184 KeyCode::KeyT => Some(Key::T),
185 KeyCode::KeyU => Some(Key::U),
186 KeyCode::KeyV => Some(Key::V),
187 KeyCode::KeyW => Some(Key::W),
188 KeyCode::KeyX => Some(Key::X),
189 KeyCode::KeyY => Some(Key::Y),
190 KeyCode::KeyZ => Some(Key::Z),
191
192 KeyCode::Digit0 => Some(Key::DIGIT0),
194 KeyCode::Digit1 => Some(Key::DIGIT1),
195 KeyCode::Digit2 => Some(Key::DIGIT2),
196 KeyCode::Digit3 => Some(Key::DIGIT3),
197 KeyCode::Digit4 => Some(Key::DIGIT4),
198 KeyCode::Digit5 => Some(Key::DIGIT5),
199 KeyCode::Digit6 => Some(Key::DIGIT6),
200 KeyCode::Digit7 => Some(Key::DIGIT7),
201 KeyCode::Digit8 => Some(Key::DIGIT8),
202 KeyCode::Digit9 => Some(Key::DIGIT9),
203
204 KeyCode::F1 => Some(Key::F1),
206 KeyCode::F2 => Some(Key::F2),
207 KeyCode::F3 => Some(Key::F3),
208 KeyCode::F4 => Some(Key::F4),
209 KeyCode::F5 => Some(Key::F5),
210 KeyCode::F6 => Some(Key::F6),
211 KeyCode::F7 => Some(Key::F7),
212 KeyCode::F8 => Some(Key::F8),
213 KeyCode::F9 => Some(Key::F9),
214 KeyCode::F10 => Some(Key::F10),
215 KeyCode::F11 => Some(Key::F11),
216 KeyCode::F12 => Some(Key::F12),
217 KeyCode::F13 => Some(Key::F13),
218 KeyCode::F14 => Some(Key::F14),
219 KeyCode::F15 => Some(Key::F15),
220 KeyCode::F16 => Some(Key::F16),
221 KeyCode::F17 => Some(Key::F17),
222 KeyCode::F18 => Some(Key::F18),
223 KeyCode::F19 => Some(Key::F19),
224 KeyCode::F20 => Some(Key::F20),
225 KeyCode::F21 => Some(Key::F21),
226 KeyCode::F22 => Some(Key::F22),
227 KeyCode::F23 => Some(Key::F23),
228 KeyCode::F24 => Some(Key::F24),
229 KeyCode::F25 => Some(Key::F25),
230 KeyCode::F26 => Some(Key::F26),
231 KeyCode::F27 => Some(Key::F27),
232 KeyCode::F28 => Some(Key::F28),
233 KeyCode::F29 => Some(Key::F29),
234 KeyCode::F30 => Some(Key::F30),
235 KeyCode::F31 => Some(Key::F31),
236 KeyCode::F32 => Some(Key::F32),
237 KeyCode::F33 => Some(Key::F33),
238 KeyCode::F34 => Some(Key::F34),
239 KeyCode::F35 => Some(Key::F35),
240
241 KeyCode::Enter => Some(Key::ENTER),
243 KeyCode::Escape => Some(Key::ESCAPE),
244 KeyCode::Space => Some(Key::SPACE),
245 KeyCode::Tab => Some(Key::TAB),
246 KeyCode::Delete => Some(Key::DELETE),
247 KeyCode::Backspace => Some(Key::BACKSPACE),
248 KeyCode::Insert => Some(Key::INSERT),
249 KeyCode::CapsLock => Some(Key::CAPS_LOCK),
250 KeyCode::Home => Some(Key::HOME),
251 KeyCode::End => Some(Key::END),
252 KeyCode::PageUp => Some(Key::PAGE_UP),
253 KeyCode::PageDown => Some(Key::PAGE_DOWN),
254 KeyCode::ArrowUp => Some(Key::ARROW_UP),
255 KeyCode::ArrowDown => Some(Key::ARROW_DOWN),
256 KeyCode::ArrowLeft => Some(Key::ARROW_LEFT),
257 KeyCode::ArrowRight => Some(Key::ARROW_RIGHT),
258
259 KeyCode::Minus => Some(Key::MINUS),
261 KeyCode::Equal => Some(Key::EQUAL),
262 KeyCode::BracketLeft => Some(Key::BRACKET_LEFT),
263 KeyCode::BracketRight => Some(Key::BRACKET_RIGHT),
264 KeyCode::Backslash => Some(Key::BACKSLASH),
265 KeyCode::Semicolon => Some(Key::SEMICOLON),
266 KeyCode::Quote => Some(Key::QUOTE),
267 KeyCode::Backquote => Some(Key::BACKQUOTE),
268 KeyCode::Comma => Some(Key::COMMA),
269 KeyCode::Period => Some(Key::PERIOD),
270 KeyCode::Slash => Some(Key::SLASH),
271
272 KeyCode::Numpad0 => Some(Key::NUMPAD0),
274 KeyCode::Numpad1 => Some(Key::NUMPAD1),
275 KeyCode::Numpad2 => Some(Key::NUMPAD2),
276 KeyCode::Numpad3 => Some(Key::NUMPAD3),
277 KeyCode::Numpad4 => Some(Key::NUMPAD4),
278 KeyCode::Numpad5 => Some(Key::NUMPAD5),
279 KeyCode::Numpad6 => Some(Key::NUMPAD6),
280 KeyCode::Numpad7 => Some(Key::NUMPAD7),
281 KeyCode::Numpad8 => Some(Key::NUMPAD8),
282 KeyCode::Numpad9 => Some(Key::NUMPAD9),
283 KeyCode::NumpadDecimal => Some(Key::NUMPAD_DECIMAL),
284 KeyCode::NumpadAdd => Some(Key::NUMPAD_ADD),
285 KeyCode::NumpadSubtract => Some(Key::NUMPAD_SUBTRACT),
286 KeyCode::NumpadMultiply => Some(Key::NUMPAD_MULTIPLY),
287 KeyCode::NumpadDivide => Some(Key::NUMPAD_DIVIDE),
288 KeyCode::NumpadEnter => Some(Key::NUMPAD_ENTER),
289 KeyCode::NumpadEqual => Some(Key::NUMPAD_EQUAL),
290 KeyCode::NumpadComma => Some(Key::NUMPAD_COMMA),
291 KeyCode::NumpadBackspace => Some(Key::NUMPAD_BACKSPACE),
292 KeyCode::NumpadClear => Some(Key::NUMPAD_CLEAR),
293 KeyCode::NumpadClearEntry => Some(Key::NUMPAD_CLEAR_ENTRY),
294 KeyCode::NumpadHash => Some(Key::NUMPAD_HASH),
295 KeyCode::NumpadMemoryAdd => Some(Key::NUMPAD_MEMORY_ADD),
296 KeyCode::NumpadMemoryClear => Some(Key::NUMPAD_MEMORY_CLEAR),
297 KeyCode::NumpadMemoryRecall => Some(Key::NUMPAD_MEMORY_RECALL),
298 KeyCode::NumpadMemoryStore => Some(Key::NUMPAD_MEMORY_STORE),
299 KeyCode::NumpadMemorySubtract => Some(Key::NUMPAD_MEMORY_SUBTRACT),
300 KeyCode::NumpadParenLeft => Some(Key::NUMPAD_PAREN_LEFT),
301 KeyCode::NumpadParenRight => Some(Key::NUMPAD_PAREN_RIGHT),
302 KeyCode::NumpadStar => Some(Key::NUMPAD_STAR),
303
304 KeyCode::ControlLeft => Some(Key::CONTROL_LEFT),
307 KeyCode::ControlRight => Some(Key::CONTROL_RIGHT),
308 KeyCode::ShiftLeft => Some(Key::SHIFT_LEFT),
309 KeyCode::ShiftRight => Some(Key::SHIFT_RIGHT),
310 KeyCode::AltLeft => Some(Key::ALT_LEFT),
311 KeyCode::AltRight => Some(Key::ALT_RIGHT),
312 KeyCode::SuperLeft | KeyCode::Meta => Some(Key::META_LEFT),
313 KeyCode::SuperRight => Some(Key::META_RIGHT),
314
315 KeyCode::AudioVolumeUp => Some(Key::AUDIO_VOLUME_UP),
317 KeyCode::AudioVolumeDown => Some(Key::AUDIO_VOLUME_DOWN),
318 KeyCode::AudioVolumeMute => Some(Key::AUDIO_VOLUME_MUTE),
319 KeyCode::MediaPlayPause => Some(Key::MEDIA_PLAY_PAUSE),
320 KeyCode::MediaStop => Some(Key::MEDIA_STOP),
321 KeyCode::MediaTrackNext => Some(Key::MEDIA_TRACK_NEXT),
322 KeyCode::MediaTrackPrevious => Some(Key::MEDIA_TRACK_PREVIOUS),
323 KeyCode::MediaSelect => Some(Key::MEDIA_SELECT),
324
325 KeyCode::BrowserBack => Some(Key::BROWSER_BACK),
327 KeyCode::BrowserFavorites => Some(Key::BROWSER_FAVORITES),
328 KeyCode::BrowserForward => Some(Key::BROWSER_FORWARD),
329 KeyCode::BrowserHome => Some(Key::BROWSER_HOME),
330 KeyCode::BrowserRefresh => Some(Key::BROWSER_REFRESH),
331 KeyCode::BrowserSearch => Some(Key::BROWSER_SEARCH),
332 KeyCode::BrowserStop => Some(Key::BROWSER_STOP),
333
334 KeyCode::PrintScreen => Some(Key::PRINT_SCREEN),
336 KeyCode::ScrollLock => Some(Key::SCROLL_LOCK),
337 KeyCode::Pause => Some(Key::PAUSE),
338 KeyCode::NumLock => Some(Key::NUM_LOCK),
339 KeyCode::ContextMenu => Some(Key::CONTEXT_MENU),
340 KeyCode::Power => Some(Key::POWER),
341 KeyCode::Sleep => Some(Key::SLEEP),
342 KeyCode::WakeUp => Some(Key::WAKE_UP),
343 KeyCode::Eject => Some(Key::EJECT),
344
345 KeyCode::Copy => Some(Key::COPY),
347 KeyCode::Cut => Some(Key::CUT),
348 KeyCode::Paste => Some(Key::PASTE),
349 KeyCode::Undo => Some(Key::UNDO),
350 KeyCode::Find => Some(Key::FIND),
351 KeyCode::Help => Some(Key::HELP),
352 KeyCode::Open => Some(Key::OPEN),
353 KeyCode::Select => Some(Key::SELECT),
354 KeyCode::Again => Some(Key::AGAIN),
355 KeyCode::Props => Some(Key::PROPS),
356 KeyCode::Abort => Some(Key::ABORT),
357 KeyCode::Resume => Some(Key::RESUME),
358 KeyCode::Suspend => Some(Key::SUSPEND),
359
360 KeyCode::Fn => Some(Key::FN),
362 KeyCode::FnLock => Some(Key::FN_LOCK),
363 KeyCode::Hyper => Some(Key::HYPER),
364 KeyCode::Turbo => Some(Key::TURBO),
365
366 KeyCode::Convert => Some(Key::CONVERT),
368 KeyCode::NonConvert => Some(Key::NON_CONVERT),
369 KeyCode::KanaMode => Some(Key::KANA_MODE),
370 KeyCode::Hiragana => Some(Key::HIRAGANA),
371 KeyCode::Katakana => Some(Key::KATAKANA),
372 KeyCode::Lang1 => Some(Key::LANG1),
373 KeyCode::Lang2 => Some(Key::LANG2),
374 KeyCode::Lang3 => Some(Key::LANG3),
375 KeyCode::Lang4 => Some(Key::LANG4),
376 KeyCode::Lang5 => Some(Key::LANG5),
377 KeyCode::IntlBackslash => Some(Key::INTL_BACKSLASH),
378 KeyCode::IntlRo => Some(Key::INTL_RO),
379 KeyCode::IntlYen => Some(Key::INTL_YEN),
380
381 KeyCode::LaunchApp1 => Some(Key::LAUNCH_APP1),
383 KeyCode::LaunchApp2 => Some(Key::LAUNCH_APP2),
384 KeyCode::LaunchMail => Some(Key::LAUNCH_MAIL),
385
386 _ => None,
387 }
388 }
389}
390
391impl WinitKeyExt for PhysicalKey {
392 fn to_key(&self) -> Option<Key> {
393 match self {
394 PhysicalKey::Code(code) => code.to_key(),
395 PhysicalKey::Unidentified(_) => None,
396 }
397 }
398}
399
400pub trait WinitModifiersExt: private::Sealed {
404 #[must_use]
417 fn to_modifiers(&self) -> Vec<Modifier>;
418}
419
420impl WinitModifiersExt for ModifiersState {
421 fn to_modifiers(&self) -> Vec<Modifier> {
422 Modifier::collect_active([
423 (self.control_key(), Modifier::Ctrl),
424 (self.shift_key(), Modifier::Shift),
425 (self.alt_key(), Modifier::Alt),
426 (self.super_key(), Modifier::Super),
427 ])
428 }
429}
430
431#[must_use]
446pub fn winit_key_to_hotkey(physical_key: PhysicalKey, modifiers: ModifiersState) -> Option<Hotkey> {
447 let key = physical_key.to_key()?;
448
449 let mut mods = modifiers.to_modifiers();
450 if let Some(self_modifier) = Modifier::from_key(key) {
451 mods.retain(|m| *m != self_modifier);
452 }
453
454 Some(Hotkey::with_modifiers(key, mods))
455}
456
457pub trait WinitEventExt: private::Sealed {
473 #[must_use]
500 fn to_hotkey(&self, modifiers: ModifiersState) -> Option<Hotkey>;
501}
502
503impl WinitEventExt for KeyEvent {
504 fn to_hotkey(&self, modifiers: ModifiersState) -> Option<Hotkey> {
505 winit_key_to_hotkey(self.physical_key, modifiers)
506 }
507}
508
509#[cfg(test)]
510mod tests {
511 use kbd::hotkey::Hotkey;
512 use kbd::hotkey::Modifier;
513 use kbd::key::Key;
514 use winit::keyboard::KeyCode;
515 use winit::keyboard::ModifiersState;
516 use winit::keyboard::NativeKeyCode;
517 use winit::keyboard::PhysicalKey;
518
519 use super::*;
520
521 #[test]
524 fn keycode_letters() {
525 assert_eq!(KeyCode::KeyA.to_key(), Some(Key::A));
526 assert_eq!(KeyCode::KeyZ.to_key(), Some(Key::Z));
527 }
528
529 #[test]
530 fn keycode_digits() {
531 assert_eq!(KeyCode::Digit0.to_key(), Some(Key::DIGIT0));
532 assert_eq!(KeyCode::Digit9.to_key(), Some(Key::DIGIT9));
533 }
534
535 #[test]
536 fn keycode_function_keys() {
537 assert_eq!(KeyCode::F1.to_key(), Some(Key::F1));
538 assert_eq!(KeyCode::F12.to_key(), Some(Key::F12));
539 assert_eq!(KeyCode::F24.to_key(), Some(Key::F24));
540 assert_eq!(KeyCode::F25.to_key(), Some(Key::F25));
541 }
542
543 #[test]
544 fn keycode_navigation() {
545 assert_eq!(KeyCode::Enter.to_key(), Some(Key::ENTER));
546 assert_eq!(KeyCode::Escape.to_key(), Some(Key::ESCAPE));
547 assert_eq!(KeyCode::Backspace.to_key(), Some(Key::BACKSPACE));
548 assert_eq!(KeyCode::Tab.to_key(), Some(Key::TAB));
549 assert_eq!(KeyCode::Space.to_key(), Some(Key::SPACE));
550 assert_eq!(KeyCode::Delete.to_key(), Some(Key::DELETE));
551 assert_eq!(KeyCode::Insert.to_key(), Some(Key::INSERT));
552 assert_eq!(KeyCode::Home.to_key(), Some(Key::HOME));
553 assert_eq!(KeyCode::End.to_key(), Some(Key::END));
554 assert_eq!(KeyCode::PageUp.to_key(), Some(Key::PAGE_UP));
555 assert_eq!(KeyCode::PageDown.to_key(), Some(Key::PAGE_DOWN));
556 assert_eq!(KeyCode::ArrowUp.to_key(), Some(Key::ARROW_UP));
557 assert_eq!(KeyCode::ArrowDown.to_key(), Some(Key::ARROW_DOWN));
558 assert_eq!(KeyCode::ArrowLeft.to_key(), Some(Key::ARROW_LEFT));
559 assert_eq!(KeyCode::ArrowRight.to_key(), Some(Key::ARROW_RIGHT));
560 }
561
562 #[test]
563 fn keycode_modifiers() {
564 assert_eq!(KeyCode::ControlLeft.to_key(), Some(Key::CONTROL_LEFT));
565 assert_eq!(KeyCode::ControlRight.to_key(), Some(Key::CONTROL_RIGHT));
566 assert_eq!(KeyCode::ShiftLeft.to_key(), Some(Key::SHIFT_LEFT));
567 assert_eq!(KeyCode::ShiftRight.to_key(), Some(Key::SHIFT_RIGHT));
568 assert_eq!(KeyCode::AltLeft.to_key(), Some(Key::ALT_LEFT));
569 assert_eq!(KeyCode::AltRight.to_key(), Some(Key::ALT_RIGHT));
570 assert_eq!(KeyCode::SuperLeft.to_key(), Some(Key::META_LEFT));
572 assert_eq!(KeyCode::SuperRight.to_key(), Some(Key::META_RIGHT));
573 assert_eq!(KeyCode::Meta.to_key(), Some(Key::META_LEFT));
575 }
576
577 #[test]
578 fn keycode_punctuation() {
579 assert_eq!(KeyCode::Minus.to_key(), Some(Key::MINUS));
580 assert_eq!(KeyCode::Equal.to_key(), Some(Key::EQUAL));
581 assert_eq!(KeyCode::BracketLeft.to_key(), Some(Key::BRACKET_LEFT));
582 assert_eq!(KeyCode::BracketRight.to_key(), Some(Key::BRACKET_RIGHT));
583 assert_eq!(KeyCode::Backslash.to_key(), Some(Key::BACKSLASH));
584 assert_eq!(KeyCode::Semicolon.to_key(), Some(Key::SEMICOLON));
585 assert_eq!(KeyCode::Quote.to_key(), Some(Key::QUOTE));
586 assert_eq!(KeyCode::Backquote.to_key(), Some(Key::BACKQUOTE));
587 assert_eq!(KeyCode::Comma.to_key(), Some(Key::COMMA));
588 assert_eq!(KeyCode::Period.to_key(), Some(Key::PERIOD));
589 assert_eq!(KeyCode::Slash.to_key(), Some(Key::SLASH));
590 }
591
592 #[test]
593 fn keycode_numpad() {
594 assert_eq!(KeyCode::Numpad0.to_key(), Some(Key::NUMPAD0));
595 assert_eq!(KeyCode::Numpad9.to_key(), Some(Key::NUMPAD9));
596 assert_eq!(KeyCode::NumpadDecimal.to_key(), Some(Key::NUMPAD_DECIMAL));
597 assert_eq!(KeyCode::NumpadAdd.to_key(), Some(Key::NUMPAD_ADD));
598 assert_eq!(KeyCode::NumpadSubtract.to_key(), Some(Key::NUMPAD_SUBTRACT));
599 assert_eq!(KeyCode::NumpadMultiply.to_key(), Some(Key::NUMPAD_MULTIPLY));
600 assert_eq!(KeyCode::NumpadDivide.to_key(), Some(Key::NUMPAD_DIVIDE));
601 assert_eq!(KeyCode::NumpadEnter.to_key(), Some(Key::NUMPAD_ENTER));
602 }
603
604 #[test]
605 fn keycode_media() {
606 assert_eq!(
607 KeyCode::MediaPlayPause.to_key(),
608 Some(Key::MEDIA_PLAY_PAUSE)
609 );
610 assert_eq!(KeyCode::MediaStop.to_key(), Some(Key::MEDIA_STOP));
611 assert_eq!(
612 KeyCode::MediaTrackNext.to_key(),
613 Some(Key::MEDIA_TRACK_NEXT)
614 );
615 assert_eq!(
616 KeyCode::MediaTrackPrevious.to_key(),
617 Some(Key::MEDIA_TRACK_PREVIOUS)
618 );
619 assert_eq!(KeyCode::AudioVolumeUp.to_key(), Some(Key::AUDIO_VOLUME_UP));
620 assert_eq!(
621 KeyCode::AudioVolumeDown.to_key(),
622 Some(Key::AUDIO_VOLUME_DOWN)
623 );
624 assert_eq!(
625 KeyCode::AudioVolumeMute.to_key(),
626 Some(Key::AUDIO_VOLUME_MUTE)
627 );
628 }
629
630 #[test]
631 fn keycode_system() {
632 assert_eq!(KeyCode::PrintScreen.to_key(), Some(Key::PRINT_SCREEN));
633 assert_eq!(KeyCode::ScrollLock.to_key(), Some(Key::SCROLL_LOCK));
634 assert_eq!(KeyCode::Pause.to_key(), Some(Key::PAUSE));
635 assert_eq!(KeyCode::NumLock.to_key(), Some(Key::NUM_LOCK));
636 assert_eq!(KeyCode::ContextMenu.to_key(), Some(Key::CONTEXT_MENU));
637 assert_eq!(KeyCode::Power.to_key(), Some(Key::POWER));
638 }
639
640 #[test]
641 fn keycode_extended_keys() {
642 assert_eq!(KeyCode::F35.to_key(), Some(Key::F35));
643 assert_eq!(KeyCode::BrowserBack.to_key(), Some(Key::BROWSER_BACK));
644 assert_eq!(KeyCode::Copy.to_key(), Some(Key::COPY));
645 assert_eq!(KeyCode::Sleep.to_key(), Some(Key::SLEEP));
646 assert_eq!(KeyCode::IntlBackslash.to_key(), Some(Key::INTL_BACKSLASH));
647 assert_eq!(KeyCode::NumpadEqual.to_key(), Some(Key::NUMPAD_EQUAL));
648 assert_eq!(KeyCode::Fn.to_key(), Some(Key::FN));
649 assert_eq!(KeyCode::LaunchMail.to_key(), Some(Key::LAUNCH_MAIL));
650 assert_eq!(KeyCode::Convert.to_key(), Some(Key::CONVERT));
651 assert_eq!(KeyCode::Lang1.to_key(), Some(Key::LANG1));
652 }
653
654 #[test]
657 fn physical_key_code_to_key() {
658 let physical = PhysicalKey::Code(KeyCode::KeyA);
659 assert_eq!(physical.to_key(), Some(Key::A));
660 }
661
662 #[test]
663 fn physical_key_unidentified_returns_none() {
664 let physical = PhysicalKey::Unidentified(NativeKeyCode::Unidentified);
665 assert_eq!(physical.to_key(), None);
666 }
667
668 #[test]
671 fn empty_modifiers() {
672 assert_eq!(
673 ModifiersState::empty().to_modifiers(),
674 Vec::<Modifier>::new()
675 );
676 }
677
678 #[test]
679 fn single_modifiers() {
680 assert_eq!(ModifiersState::CONTROL.to_modifiers(), vec![Modifier::Ctrl]);
681 assert_eq!(ModifiersState::SHIFT.to_modifiers(), vec![Modifier::Shift]);
682 assert_eq!(ModifiersState::ALT.to_modifiers(), vec![Modifier::Alt]);
683 assert_eq!(ModifiersState::SUPER.to_modifiers(), vec![Modifier::Super]);
684 }
685
686 #[test]
687 fn combined_modifiers() {
688 let mods = ModifiersState::CONTROL | ModifiersState::SHIFT;
689 assert_eq!(mods.to_modifiers(), vec![Modifier::Ctrl, Modifier::Shift]);
690 }
691
692 #[test]
693 fn all_modifiers() {
694 let mods = ModifiersState::CONTROL
695 | ModifiersState::SHIFT
696 | ModifiersState::ALT
697 | ModifiersState::SUPER;
698 assert_eq!(
699 mods.to_modifiers(),
700 vec![
701 Modifier::Ctrl,
702 Modifier::Shift,
703 Modifier::Alt,
704 Modifier::Super,
705 ]
706 );
707 }
708
709 #[test]
712 fn simple_key_to_hotkey() {
713 let hotkey = winit_key_to_hotkey(PhysicalKey::Code(KeyCode::KeyC), ModifiersState::empty());
714 assert_eq!(hotkey, Some(Hotkey::new(Key::C)));
715 }
716
717 #[test]
718 fn key_with_ctrl_to_hotkey() {
719 let hotkey = winit_key_to_hotkey(PhysicalKey::Code(KeyCode::KeyC), ModifiersState::CONTROL);
720 assert_eq!(hotkey, Some(Hotkey::new(Key::C).modifier(Modifier::Ctrl)));
721 }
722
723 #[test]
724 fn key_with_multiple_modifiers_to_hotkey() {
725 let mods = ModifiersState::CONTROL | ModifiersState::SHIFT;
726 let hotkey = winit_key_to_hotkey(PhysicalKey::Code(KeyCode::KeyA), mods);
727 assert_eq!(
728 hotkey,
729 Some(
730 Hotkey::new(Key::A)
731 .modifier(Modifier::Ctrl)
732 .modifier(Modifier::Shift)
733 )
734 );
735 }
736
737 #[test]
738 fn unidentified_key_to_hotkey_returns_none() {
739 let hotkey = winit_key_to_hotkey(
740 PhysicalKey::Unidentified(NativeKeyCode::Unidentified),
741 ModifiersState::empty(),
742 );
743 assert_eq!(hotkey, None);
744 }
745
746 #[test]
747 fn modifier_key_strips_self() {
748 let hotkey =
751 winit_key_to_hotkey(PhysicalKey::Code(KeyCode::ShiftLeft), ModifiersState::SHIFT);
752 assert_eq!(hotkey, Some(Hotkey::new(Key::SHIFT_LEFT)));
753 }
754
755 #[test]
756 fn modifier_key_keeps_other_modifiers() {
757 let mods = ModifiersState::SHIFT | ModifiersState::CONTROL;
759 let hotkey = winit_key_to_hotkey(PhysicalKey::Code(KeyCode::ControlLeft), mods);
760 assert_eq!(
761 hotkey,
762 Some(Hotkey::new(Key::CONTROL_LEFT).modifier(Modifier::Shift))
763 );
764 }
765
766 #[test]
767 fn ctrl_shift_f5_to_hotkey() {
768 let mods = ModifiersState::CONTROL | ModifiersState::SHIFT;
769 let hotkey = winit_key_to_hotkey(PhysicalKey::Code(KeyCode::F5), mods);
770 assert_eq!(
771 hotkey,
772 Some(
773 Hotkey::new(Key::F5)
774 .modifier(Modifier::Ctrl)
775 .modifier(Modifier::Shift)
776 )
777 );
778 }
779
780 #[test]
781 fn space_to_hotkey() {
782 let hotkey =
783 winit_key_to_hotkey(PhysicalKey::Code(KeyCode::Space), ModifiersState::empty());
784 assert_eq!(hotkey, Some(Hotkey::new(Key::SPACE)));
785 }
786
787 #[test]
788 fn super_key_strips_self() {
789 let hotkey =
791 winit_key_to_hotkey(PhysicalKey::Code(KeyCode::SuperLeft), ModifiersState::SUPER);
792 assert_eq!(hotkey, Some(Hotkey::new(Key::META_LEFT)));
793 }
794}