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