kbvm/xkb/keymap.rs
1//! XKB keymaps.
2//!
3//! This module contains types representing the components of an XKB keymap.
4//!
5//! The entry point to this module is the [`Keymap`].
6
7mod format;
8mod from_lookup;
9mod from_resolved;
10pub mod iterators;
11#[cfg(test)]
12mod tests;
13mod to_builder;
14
15pub use crate::xkb::keymap::format::Formatter;
16use {
17 crate::{
18 builder::Redirect,
19 group::{GroupDelta, GroupIndex},
20 xkb::{
21 controls::ControlMask,
22 group::{GroupIdx, GroupMask},
23 group_component::GroupComponent,
24 indicator::IndicatorIdx,
25 keymap::{
26 actions::{
27 ControlsLockAction, ControlsSetAction, GroupLatchAction, GroupLockAction,
28 GroupSetAction, ModsLatchAction, ModsLockAction, ModsSetAction,
29 RedirectKeyAction,
30 },
31 iterators::{Groups, Indicators, Keys, Levels, Mappings, VirtualModifiers},
32 },
33 level::Level,
34 mod_component::ModComponentMask,
35 radio_group::RadioGroup,
36 resolved::GroupsRedirect,
37 },
38 Components, ControlsMask, Keysym, ModifierIndex, ModifierMask,
39 },
40 hashbrown::DefaultHashBuilder,
41 indexmap::IndexMap,
42 smallvec::SmallVec,
43 std::sync::Arc,
44};
45#[expect(unused_imports)]
46use {
47 crate::{lookup::LookupTable, xkb::Context},
48 std::fmt::Display,
49};
50
51/// A fully-resolved XKB keymap.
52///
53/// This object is usually created from a [`Context`] but can also be created via
54/// [`LookupTable::to_xkb_keymap`].
55///
56/// # Creating a keymap from XKB source
57///
58/// ```xkb
59/// xkb_keymap {
60/// xkb_keycodes {
61/// <a> = 38;
62/// <leftshift> = 50;
63/// };
64/// xkb_symbols {
65/// key <a> {
66/// [ a, A ],
67/// };
68/// key <leftshift> {
69/// [ Shift_L ],
70/// [ SetMods(mods = Shift) ],
71/// };
72/// };
73/// };
74/// ```
75///
76/// ```no_run
77/// # use kbvm::xkb::Context;
78/// # use kbvm::xkb::diagnostic::WriteToLog;
79/// # const MAP: &str = "...";
80/// let context = Context::default();
81/// let keymap = context.keymap_from_bytes(WriteToLog, None, MAP.as_bytes()).unwrap();
82/// ```
83///
84/// # Creating a keymap from RMLVO names
85///
86/// ```
87/// # use kbvm::xkb::Context;
88/// # use kbvm::xkb::diagnostic::WriteToLog;
89/// # use kbvm::xkb::rmlvo::Group;
90/// let context = Context::default();
91/// let keymap = context.keymap_from_names(
92/// WriteToLog,
93/// None,
94/// None,
95/// Some(&[Group {
96/// layout: "de",
97/// variant: "neo",
98/// }]),
99/// None,
100/// );
101/// ```
102#[derive(Debug, PartialEq)]
103pub struct Keymap {
104 pub(crate) name: Option<Arc<String>>,
105 pub(crate) max_keycode: u32,
106 pub(crate) indicators: Vec<Indicator>,
107 pub(crate) keycodes: Vec<Keycode>,
108 pub(crate) types: Vec<Arc<KeyType>>,
109 pub(crate) virtual_modifiers: Vec<VirtualModifier>,
110 pub(crate) mod_maps: Vec<(ModifierIndex, ModMapValue)>,
111 pub(crate) group_names: Vec<(GroupIdx, Arc<String>)>,
112 pub(crate) keys: IndexMap<crate::Keycode, Key, DefaultHashBuilder>,
113}
114
115#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
116pub(crate) struct ModMapValue {
117 pub(crate) key_name: Arc<String>,
118 pub(crate) key_sym: Option<Keysym>,
119}
120
121/// An indicator.
122///
123/// # Example
124///
125/// ```xkb
126/// xkb_compat {
127/// indicator "Caps Lock" {
128/// modifiers = Lock;
129/// whichModState = Effective;
130/// };
131/// };
132/// ```
133#[derive(Debug, PartialEq)]
134pub struct Indicator {
135 pub(crate) virt: bool,
136 pub(crate) index: IndicatorIdx,
137 pub(crate) name: Arc<String>,
138 pub(crate) modifier_mask: ModifierMask,
139 pub(crate) group_mask: GroupMask,
140 pub(crate) controls: ControlMask,
141 pub(crate) mod_components: ModComponentMask,
142 pub(crate) group_component: GroupComponent,
143}
144
145/// An indicator matcher that determines if an indicator should be active.
146pub struct IndicatorMatcher {
147 mods_pressed: u32,
148 mods_latched: u32,
149 mods_locked: u32,
150 mods: u32,
151 group_pressed: bool,
152 group_not_pressed: bool,
153 group_latched: bool,
154 group_not_latched: bool,
155 group_locked: u32,
156 group: u32,
157 controls: u32,
158}
159
160#[derive(Debug, PartialEq)]
161pub(crate) struct Keycode {
162 pub(crate) name: Arc<String>,
163 pub(crate) keycode: crate::Keycode,
164}
165
166/// A virtual modifier.
167///
168/// # Example
169///
170/// ```xkb
171/// xkb_compat {
172/// virtual_modifiers V1 = 0x100;
173/// };
174/// ```
175#[derive(Debug, PartialEq)]
176pub struct VirtualModifier {
177 pub(crate) name: Arc<String>,
178 pub(crate) values: ModifierMask,
179}
180
181/// A key type.
182///
183/// # Example
184///
185/// ```xkb
186/// xkb_types {
187/// type "X" {
188/// modifiers = Shift+Mod1;
189/// map[Shift] = Level2;
190/// map[Mod1] = Level2;
191/// };
192/// };
193/// ```
194#[derive(Debug, PartialEq)]
195pub struct KeyType {
196 pub(crate) name: Arc<String>,
197 pub(crate) modifiers: ModifierMask,
198 pub(crate) mappings: Vec<KeyTypeMapping>,
199 pub(crate) level_names: Vec<(Level, Arc<String>)>,
200}
201
202/// A key-type mapping.
203///
204/// # Example
205///
206/// ```xkb
207/// xkb_types {
208/// type "X" {
209/// modifiers = Shift+Mod1;
210/// map[Shift] = Level2;
211/// map[Mod1] = Level2;
212/// };
213/// };
214/// ```
215///
216/// This object might refer to either `map[Shift]` or `map[Mod1]`.
217#[derive(Debug, PartialEq)]
218pub struct KeyTypeMapping {
219 pub(crate) modifiers: ModifierMask,
220 pub(crate) preserved: ModifierMask,
221 pub(crate) level: Level,
222}
223
224/// An XKB action.
225///
226/// # Example
227///
228/// ```xkb
229/// xkb_symbols {
230/// key <leftshift> {
231/// [ SetMods(mods = Shift) ],
232/// };
233/// };
234/// ```
235#[derive(Clone, Debug, PartialEq)]
236#[non_exhaustive]
237pub enum Action {
238 /// A `SetMods` action.
239 ModsSet(ModsSetAction),
240 /// A `LatchMods` action.
241 ModsLatch(ModsLatchAction),
242 /// A `LockMods` action.
243 ModsLock(ModsLockAction),
244 /// A `SetGroup` action.
245 GroupSet(GroupSetAction),
246 /// A `LatchGroup` action.
247 GroupLatch(GroupLatchAction),
248 /// A `LockGroup` action.
249 GroupLock(GroupLockAction),
250 /// A `RedirectKey` action.
251 RedirectKey(RedirectKeyAction),
252 /// A `SetControls` action.
253 ControlsSet(ControlsSetAction),
254 /// A `LockControls` action.
255 ControlsLock(ControlsLockAction),
256}
257
258/// The XKB actions supported by KBVM.
259pub mod actions {
260 use {
261 crate::{
262 xkb::{controls::ControlMask, group},
263 ModifierMask,
264 },
265 std::sync::Arc,
266 };
267
268 /// A `SetMods` action.
269 ///
270 /// # Example
271 ///
272 /// ```xkb
273 /// xkb_symbols {
274 /// key <leftshift> {
275 /// [ SetMods(mods = Shift) ],
276 /// };
277 /// };
278 /// ```
279 #[derive(Clone, Debug, PartialEq)]
280 pub struct ModsSetAction {
281 pub(crate) clear_locks: bool,
282 pub(crate) modifiers: ModifierMask,
283 }
284
285 /// A `LatchMods` action.
286 ///
287 /// # Example
288 ///
289 /// ```xkb
290 /// xkb_symbols {
291 /// key <leftshift> {
292 /// [ LatchMods(mods = Shift) ],
293 /// };
294 /// };
295 /// ```
296 #[derive(Clone, Debug, PartialEq)]
297 pub struct ModsLatchAction {
298 pub(crate) clear_locks: bool,
299 pub(crate) latch_to_lock: bool,
300 pub(crate) modifiers: ModifierMask,
301 }
302
303 /// A `LockMods` action.
304 ///
305 /// # Example
306 ///
307 /// ```xkb
308 /// xkb_symbols {
309 /// key <leftshift> {
310 /// [ LockMods(mods = Shift) ],
311 /// };
312 /// };
313 /// ```
314 #[derive(Clone, Debug, PartialEq)]
315 pub struct ModsLockAction {
316 pub(crate) modifiers: ModifierMask,
317 pub(crate) lock: bool,
318 pub(crate) unlock: bool,
319 }
320
321 /// A `SetGroup` action.
322 ///
323 /// # Example
324 ///
325 /// ```xkb
326 /// xkb_symbols {
327 /// key <compose> {
328 /// [ SetGroup(group = +1) ],
329 /// };
330 /// };
331 /// ```
332 #[derive(Clone, Debug, PartialEq)]
333 pub struct GroupSetAction {
334 pub(crate) group: group::GroupChange,
335 pub(crate) clear_locks: bool,
336 }
337
338 /// A `LatchGroup` action.
339 ///
340 /// # Example
341 ///
342 /// ```xkb
343 /// xkb_symbols {
344 /// key <compose> {
345 /// [ LatchGroup(group = +1) ],
346 /// };
347 /// };
348 /// ```
349 #[derive(Clone, Debug, PartialEq)]
350 pub struct GroupLatchAction {
351 pub(crate) group: group::GroupChange,
352 pub(crate) clear_locks: bool,
353 pub(crate) latch_to_lock: bool,
354 }
355
356 /// A `LockGroup` action.
357 ///
358 /// # Example
359 ///
360 /// ```xkb
361 /// xkb_symbols {
362 /// key <compose> {
363 /// [ LockGroup(group = +1) ],
364 /// };
365 /// };
366 /// ```
367 #[derive(Clone, Debug, PartialEq)]
368 pub struct GroupLockAction {
369 pub(crate) group: group::GroupChange,
370 }
371
372 /// A `RedirectKey` action.
373 ///
374 /// # Example
375 ///
376 /// ```xkb
377 /// xkb_symbols {
378 /// key <a> {
379 /// [ RedirectKey(key = b) ],
380 /// };
381 /// };
382 /// ```
383 ///
384 /// # Implementation
385 ///
386 /// KBVM implements this action as follows:
387 ///
388 /// The new key code is emitted in `KeyDown` and `KeyUp` events instead of the
389 /// original key code.
390 ///
391 /// If the [`Self::modifier_mask`] of the action is not empty, then it additionally
392 /// modifies the components before and after the `KeyDown` and `KeyUp` events as
393 /// follows:
394 ///
395 /// - Before the event:
396 ///
397 /// 1. Save the pressed, latched, and locked modifiers.
398 /// 2. Set the latched and locked modifiers to 0.
399 /// 3. Set the pressed modifiers to the effective modifiers.
400 /// 4. Clear the modifiers from [`Self::mods_to_clear`] from the pressed modifiers.
401 /// 5. Set the modifiers from [`Self::mods_to_set`] in the pressed modifiers.
402 ///
403 /// - After the event:
404 ///
405 /// 1. Restore the pressed, latched, and locked modifiers.
406 #[derive(Clone, Debug, PartialEq)]
407 pub struct RedirectKeyAction {
408 pub(crate) key_name: Arc<String>,
409 pub(crate) keycode: crate::Keycode,
410 pub(crate) mods_to_set: ModifierMask,
411 pub(crate) mods_to_clear: ModifierMask,
412 }
413
414 /// A `SetControls` action.
415 ///
416 /// # Example
417 ///
418 /// ```xkb
419 /// xkb_symbols {
420 /// key <leftshift> {
421 /// [ SetControls(controls = Overlay1) ],
422 /// };
423 /// };
424 /// ```
425 #[derive(Clone, Debug, PartialEq)]
426 pub struct ControlsSetAction {
427 pub(crate) controls: ControlMask,
428 }
429
430 /// A `LockControls` action.
431 ///
432 /// # Example
433 ///
434 /// ```xkb
435 /// xkb_symbols {
436 /// key <leftshift> {
437 /// [ LockControls(controls = Overlay1) ],
438 /// };
439 /// };
440 /// ```
441 #[derive(Clone, Debug, PartialEq)]
442 pub struct ControlsLockAction {
443 pub(crate) controls: ControlMask,
444 pub(crate) lock: bool,
445 pub(crate) unlock: bool,
446 }
447}
448
449/// A group change performed by an [`Action`].
450pub enum GroupChange {
451 /// An absolute change of a group.
452 ///
453 /// # Example
454 ///
455 /// ```xkb
456 /// xkb_symbols {
457 /// key <compose> {
458 /// [ SetGroup(group = Group2) ],
459 /// };
460 /// };
461 /// ```
462 Absolute(GroupIndex),
463 /// A relative change of a group.
464 ///
465 /// # Example
466 ///
467 /// ```xkb
468 /// xkb_symbols {
469 /// key <compose> {
470 /// [ SetGroup(group = +1) ],
471 /// };
472 /// };
473 /// ```
474 Relative(GroupDelta),
475}
476
477/// A key.
478///
479/// # Example
480///
481/// ```xkb
482/// xkb_symbols {
483/// key <a> { [ a, A ] };
484/// };
485/// ```
486#[derive(Clone, Debug, PartialEq)]
487pub struct Key {
488 pub(crate) key_name: Arc<String>,
489 pub(crate) keycode: crate::Keycode,
490 pub(crate) groups: Vec<Option<KeyGroup>>,
491 pub(crate) repeat: bool,
492 pub(crate) behavior: Option<KeyBehavior>,
493 pub(crate) redirect: GroupsRedirect,
494}
495
496/// A key behavior.
497///
498/// # Example
499///
500/// ```xkb
501/// xkb_symbols {
502/// key <a> {
503/// locks = true,
504/// [ a, A ],
505/// };
506/// };
507/// ```
508///
509/// The key behavior is `KeyBehavior::Lock`.
510#[derive(Clone, Debug, PartialEq)]
511#[non_exhaustive]
512pub enum KeyBehavior {
513 /// The key locks.
514 Lock,
515 /// The key is affected by an overlay control.
516 Overlay(OverlayBehavior),
517 /// The key is affected by a radio-group control.
518 RadioGroup(RadioGroupBehavior),
519}
520
521/// The overlay that affects a key behavior.
522///
523/// # Example
524///
525/// ```xkb
526/// xkb_symbols {
527/// key <a> {
528/// overlay2 = <b>,
529/// };
530/// };
531/// ```
532///
533/// The overlay is `Overlay2`.
534#[derive(Copy, Clone, Debug, PartialEq)]
535#[non_exhaustive]
536pub enum KeyOverlay {
537 /// The first overlay.
538 Overlay1,
539 /// The second overlay.
540 Overlay2,
541}
542
543/// An overlay behavior.
544///
545/// # Example
546///
547/// ```xkb
548/// xkb_symbols {
549/// key <a> {
550/// overlay1 = <b>,
551/// [ a, A ],
552/// };
553/// };
554/// ```
555#[derive(Clone, Debug, PartialEq)]
556pub struct OverlayBehavior {
557 pub(crate) overlay: KeyOverlay,
558 pub(crate) key_name: Arc<String>,
559 pub(crate) keycode: crate::Keycode,
560}
561
562/// A radio-group behavior.
563///
564/// # Example
565///
566/// ```xkb
567/// xkb_symbols {
568/// key <a> {
569/// radiogroup = 1,
570/// [ a, A ],
571/// };
572/// };
573/// ```
574#[derive(Clone, Debug, PartialEq)]
575pub struct RadioGroupBehavior {
576 pub(crate) allow_none: bool,
577 pub(crate) radio_group: RadioGroup,
578}
579
580/// A key group.
581///
582/// # Example
583///
584/// ```xkb
585/// xkb_symbols {
586/// key <a> {
587/// [ a, A ],
588/// [ b, B ],
589/// };
590/// };
591/// ```
592///
593/// This object might refer to either `[ a, A ]` or `[ b, B ]`.
594#[derive(Clone, Debug, PartialEq)]
595pub struct KeyGroup {
596 pub(crate) key_type: Arc<KeyType>,
597 pub(crate) levels: Vec<KeyLevel>,
598}
599
600/// A key level.
601///
602/// # Example
603///
604/// ```xkb
605/// xkb_symbols {
606/// key <a> {
607/// symbols[Group1] = [ a, A ],
608/// actions[Group1] = [ NoAction(), SetMods(mods = Mod1) ],
609/// symbols[Group2] = [ b, B ],
610/// };
611/// };
612/// ```
613///
614/// This object might refer to any of
615///
616/// - `a`,
617/// - `A` / `SetMods(mods = Mod1)`,
618/// - `b`, or
619/// - `B`.
620#[derive(Clone, Debug, Default, PartialEq)]
621pub struct KeyLevel {
622 pub(crate) symbols: SmallVec<[Keysym; 1]>,
623 pub(crate) actions: SmallVec<[Action; 1]>,
624}
625
626impl Keymap {
627 /// Returns an iterator over the virtual modifiers of this map.
628 ///
629 /// Note that the real modifiers are not included in this iterator. The real modifiers
630 /// use the following hard-coded assignments:
631 ///
632 /// | name | index | mask |
633 /// | ------------ | ----- | ------ |
634 /// | Shift | `0` | `0x01` |
635 /// | Lock | `1` | `0x02` |
636 /// | Control | `2` | `0x04` |
637 /// | Mod1/Alt | `3` | `0x08` |
638 /// | Mod2/NumLock | `4` | `0x10` |
639 /// | Mod3 | `5` | `0x20` |
640 /// | Mod4/Logo | `6` | `0x40` |
641 /// | Mod5 | `7` | `0x80` |
642 ///
643 /// # Example
644 ///
645 /// ```xkb
646 /// xkb_compat {
647 /// virtual_modifiers A;
648 /// virtual_modifiers B;
649 /// virtual_modifiers C;
650 /// };
651 /// ```
652 ///
653 /// The iterator returns 3 elements, one for A, one for B, and one for C.
654 pub fn virtual_modifiers(&self) -> VirtualModifiers<'_> {
655 VirtualModifiers {
656 modifiers: self.virtual_modifiers.iter(),
657 }
658 }
659
660 /// Returns an iterator over the keys of this map.
661 ///
662 /// # Example
663 ///
664 /// ```xkb
665 /// xkb_symbols {
666 /// key <a> { [ a, A ] };
667 /// key <leftshift> { [ SetMods(mods = Shift) ] };
668 /// };
669 /// ```
670 ///
671 /// The iterator returns 2 elements, one for `<a>` and one for `<leftshift>`.
672 pub fn keys(&self) -> Keys<'_> {
673 Keys {
674 keys: self.keys.values(),
675 }
676 }
677
678 /// Returns an iterator over the indicators of this map.
679 ///
680 /// # Example
681 ///
682 /// ```xkb
683 /// xkb_compat {
684 /// indicator "Caps Lock" {
685 /// modifiers = Lock;
686 /// };
687 /// indicator "Num Lock" {
688 /// modifiers = Mod2;
689 /// };
690 /// };
691 /// ```
692 ///
693 /// The iterator returns 2 elements, one for `Caps Lock` and one for `Num Lock`.
694 pub fn indicators(&self) -> Indicators<'_> {
695 Indicators {
696 indicators: self.indicators.iter(),
697 }
698 }
699
700 /// Returns a type that can be used to format the map in XKB text format.
701 ///
702 /// # Warning
703 ///
704 /// When using this function to create a keymap for Xwayland, compositors should
705 /// enable both [`Formatter::lookup_only`] and [`Formatter::rename_long_keys`].
706 ///
707 /// `lookup_only` prevents key actions and key behaviors from being included in the
708 /// map. This works around a bug in Xwayland where Xwayland will execute the actions
709 /// and behaviors instead of only passing the key events to X clients.
710 ///
711 /// `rename_long_keys` is only necessary if the original keymap contains key names
712 /// that are longer than 4 bytes. Xwayland cannot handle such key names.
713 ///
714 /// # Example
715 ///
716 /// ```
717 /// # use kbvm::xkb::Keymap;
718 /// fn pretty_print_keymap(keymap: &Keymap) -> String {
719 /// format!("{}\n", keymap.format())
720 /// }
721 /// ```
722 pub fn format(&self) -> Formatter<'_> {
723 Formatter {
724 keymap: self,
725 single_line: false,
726 lookup_only: false,
727 multiple_actions_per_level: false,
728 rename_long_keys: false,
729 }
730 }
731}
732
733impl Indicator {
734 pub(crate) fn dummy() -> Self {
735 Self {
736 virt: false,
737 index: IndicatorIdx::ONE,
738 name: Arc::new("DUMMY".to_string()),
739 modifier_mask: Default::default(),
740 group_mask: Default::default(),
741 controls: Default::default(),
742 mod_components: Default::default(),
743 group_component: Default::default(),
744 }
745 }
746}
747
748impl VirtualModifier {
749 pub(crate) fn dummy() -> Self {
750 Self {
751 name: Arc::new("Dummy".to_string()),
752 values: Default::default(),
753 }
754 }
755
756 /// Returns the name of the modifier.
757 ///
758 /// # Example
759 ///
760 /// ```xkb
761 /// xkb_compat {
762 /// virtual_modifiers V1 = 0x100;
763 /// };
764 /// ```
765 ///
766 /// The function returns `"V1"`.
767 pub fn name(&self) -> &str {
768 &self.name
769 }
770
771 /// Returns the modifier mask that the modifier maps to.
772 ///
773 /// # Example 1
774 ///
775 /// ```xkb
776 /// xkb_compat {
777 /// virtual_modifiers V1 = 0x100;
778 /// };
779 /// ```
780 ///
781 /// The function returns `0x100`.
782 ///
783 /// # Example 2
784 ///
785 /// ```xkb
786 /// xkb_compat {
787 /// virtual_modifiers Alt;
788 ///
789 /// interpret Alt_L {
790 /// virtualmodifier = Alt;
791 /// };
792 /// };
793 ///
794 /// xkb_symbols {
795 /// key <leftalt> { [ Alt_L ] };
796 /// modmap Mod1 { <leftalt> };
797 /// };
798 /// ```
799 ///
800 /// The function returns [`ModifierMask::MOD1`].
801 pub fn mask(&self) -> ModifierMask {
802 self.values
803 }
804}
805
806impl Key {
807 /// Returns the name of the key.
808 ///
809 /// # Example
810 ///
811 /// ```xkb
812 /// xkb_symbols {
813 /// key <abcd> { [ a, A ] };
814 /// };
815 /// ```
816 ///
817 /// The function returns `abcd`.
818 pub fn name(&self) -> &str {
819 &self.key_name
820 }
821
822 /// Returns the keycode of the key.
823 ///
824 /// # Example
825 ///
826 /// ```xkb
827 /// xkb_keycodes {
828 /// <a> = 38;
829 /// };
830 /// xkb_symbols {
831 /// key <a> { [ a, A ] };
832 /// };
833 /// ```
834 ///
835 /// The function returns `38`.
836 pub fn keycode(&self) -> crate::Keycode {
837 self.keycode
838 }
839
840 /// Returns whether the key repeats.
841 ///
842 /// # Example
843 ///
844 /// ```xkb
845 /// xkb_symbols {
846 /// key <a> {
847 /// repeats = false,
848 /// [ a, A ],
849 /// };
850 /// };
851 /// ```
852 ///
853 /// The function returns `false`.
854 pub fn repeats(&self) -> bool {
855 self.repeat
856 }
857
858 /// Returns the group-redirect setting of this key.
859 ///
860 /// # Example
861 ///
862 /// ```xkb
863 /// xkb_symbols {
864 /// key <a> {
865 /// groupsClamp,
866 /// [ a, A ],
867 /// };
868 /// };
869 /// ```
870 ///
871 /// The function returns [`Redirect::Clamp`].
872 pub fn redirect(&self) -> Redirect {
873 self.redirect.to_redirect()
874 }
875
876 /// Returns the behavior of the key.
877 ///
878 /// # Example
879 ///
880 /// ```xkb
881 /// xkb_symbols {
882 /// key <a> {
883 /// locks = true,
884 /// [ a, A ],
885 /// };
886 /// };
887 /// ```
888 ///
889 /// The function returns `KeyBehavior::Lock`.
890 pub fn behavior(&self) -> Option<&KeyBehavior> {
891 self.behavior.as_ref()
892 }
893
894 /// Returns an iterator over the groups of this key.
895 ///
896 /// # Example 1
897 ///
898 /// ```xkb
899 /// xkb_symbols {
900 /// key <a> {
901 /// [ a, A ],
902 /// [ b, B ],
903 /// };
904 /// };
905 /// ```
906 ///
907 /// The iterator returns two elements, one for `[ a, A ]` and one for `[ b, B ]`.
908 ///
909 /// # Example 2
910 ///
911 /// ```xkb
912 /// xkb_symbols {
913 /// key <a> {
914 /// symbols[Group1] = [ a, A ],
915 /// symbols[Group3] = [ b, B ],
916 /// };
917 /// };
918 /// ```
919 ///
920 /// The iterator returns three elements:
921 ///
922 /// - `Some([ a, A ])`
923 /// - `None`
924 /// - `Some([ b, B ])`
925 pub fn groups(&self) -> Groups<'_> {
926 Groups {
927 groups: self.groups.iter(),
928 }
929 }
930}
931
932impl KeyGroup {
933 /// Returns the type of this group.
934 ///
935 /// # Example
936 ///
937 /// ```xkb
938 /// xkb_types {
939 /// type "X" {
940 /// modifiers = Shift;
941 /// map[Shift] = Level2;
942 /// };
943 /// };
944 /// xkb_symbols {
945 /// key <a> {
946 /// type[Group1] = "X";
947 /// symbols[Group1] = [ a, A ],
948 /// };
949 /// };
950 /// ```
951 ///
952 /// The function returns the `X` type.
953 pub fn ty(&self) -> &KeyType {
954 &self.key_type
955 }
956
957 /// Returns an iterator over the levels of this group.
958 ///
959 /// # Example
960 ///
961 /// ```xkb
962 /// xkb_symbols {
963 /// key <a> {
964 /// [ a, A ],
965 /// };
966 /// };
967 /// ```
968 ///
969 /// The iterator returns two elements, one for `a` and one for `A`.
970 pub fn levels(&self) -> Levels<'_> {
971 Levels {
972 levels: self.levels.iter(),
973 }
974 }
975}
976
977impl KeyType {
978 /// Returns the modifier mask of this key type.
979 ///
980 /// Modifiers outside of this mask are completely ignored by this key type. That is,
981 /// they are masked out before considering which level to map to and are never
982 /// consumed.
983 ///
984 /// # Example
985 ///
986 /// ```xkb
987 /// xkb_types {
988 /// type "X" {
989 /// modifiers = Shift+Mod1;
990 /// map[Shift] = Level2;
991 /// map[Mod1] = Level2;
992 /// };
993 /// };
994 /// ```
995 ///
996 /// The function returns [`ModifierMask::SHIFT | ModifierMask::MOD1`](ModifierMask).
997 pub fn mask(&self) -> ModifierMask {
998 self.modifiers
999 }
1000
1001 /// Returns an iterator over the mappings of this key type.
1002 ///
1003 /// Mappings that are not explicitly defined are not returned. Such mappings map to
1004 /// level 1 and consume all input modifiers.
1005 ///
1006 /// # Example
1007 ///
1008 /// ```xkb
1009 /// xkb_types {
1010 /// type "X" {
1011 /// modifiers = Shift+Mod1;
1012 /// map[Shift] = Level2;
1013 /// map[Mod1] = Level2;
1014 /// };
1015 /// };
1016 /// ```
1017 ///
1018 /// The iterator returns one mapping for `map[Shift]` and one mapping for
1019 /// `map[Mod1]`.
1020 ///
1021 /// Note that no mappings are returned for `map[None]` and `map[Shift+Mod1]`.
1022 pub fn mappings(&self) -> Mappings<'_> {
1023 Mappings {
1024 mappings: self.mappings.iter(),
1025 }
1026 }
1027}
1028
1029impl KeyTypeMapping {
1030 /// Returns the modifier mask of this mapping.
1031 ///
1032 /// After masking with the [type mask](KeyType::mask), the effective modifiers must
1033 /// match this mask exactly for the mapping to be applicable.
1034 ///
1035 /// # Example
1036 ///
1037 /// ```xkb
1038 /// xkb_types {
1039 /// type "X" {
1040 /// modifiers = Shift+Mod1;
1041 /// map[Shift] = Level2;
1042 /// map[Mod1] = Level2;
1043 /// };
1044 /// };
1045 /// ```
1046 ///
1047 /// If this mapping is `map[Shift]`, then this function returns
1048 /// [`ModifierMask::SHIFT`].
1049 pub fn mask(&self) -> ModifierMask {
1050 self.modifiers
1051 }
1052
1053 /// Returns the preserved modifiers of this mapping.
1054 ///
1055 /// If this mapping is applicable, then the preserved modifiers are not consumed by
1056 /// the mapping and might be used for keyboard shortcuts or keysym transformations.
1057 ///
1058 /// # Example
1059 ///
1060 /// ```xkb
1061 /// xkb_types {
1062 /// type "X" {
1063 /// modifiers = Control+Shift;
1064 /// map[Control+Shift] = Level2;
1065 /// preserve[Control+Shift] = Control;
1066 /// };
1067 /// };
1068 /// ```
1069 ///
1070 /// If this mapping is `map[Control+Shift]`, then function returns
1071 /// [`ModifierMask::CONTROL`].
1072 pub fn preserved(&self) -> ModifierMask {
1073 self.modifiers & self.preserved
1074 }
1075
1076 /// Returns the consumed modifiers of this mapping.
1077 ///
1078 /// If this mapping is applicable, then the consumed modifiers should no longer be
1079 /// considered for keyboard shortcuts and keysym transformations.
1080 ///
1081 /// # Example
1082 ///
1083 /// ```xkb
1084 /// xkb_types {
1085 /// type "X" {
1086 /// modifiers = Control+Shift;
1087 /// map[Control+Shift] = Level2;
1088 /// preserve[Control+Shift] = Control;
1089 /// };
1090 /// };
1091 /// ```
1092 ///
1093 /// If this mapping is `map[Control+Shift]`, then function returns
1094 /// [`ModifierMask::SHIFT`].
1095 pub fn consumed(&self) -> ModifierMask {
1096 self.modifiers & !self.preserved
1097 }
1098
1099 /// Returns the 0-based level that this mapping maps to.
1100 ///
1101 /// # Example
1102 ///
1103 /// ```xkb
1104 /// xkb_types {
1105 /// type "X" {
1106 /// modifiers = Shift;
1107 /// map[Shift] = Level2;
1108 /// };
1109 /// };
1110 /// ```
1111 ///
1112 /// If this mapping is `map[Shift]`, then function returns `1`.
1113 pub fn level(&self) -> usize {
1114 self.level.to_offset()
1115 }
1116}
1117
1118impl KeyLevel {
1119 /// Returns the symbols of this level.
1120 ///
1121 /// Note that returning more than 1 keysym is an extension that does not work for X
1122 /// applications.
1123 ///
1124 /// # Example
1125 ///
1126 /// ```xkb
1127 /// xkb_symbols {
1128 /// key <a> {
1129 /// [
1130 /// a,
1131 /// { A, B },
1132 /// ],
1133 /// };
1134 /// };
1135 /// ```
1136 ///
1137 /// If this object refers to the first level, then this function returns `&[syms::a]`.
1138 ///
1139 /// If this object refers to the second level, then this function returns
1140 /// `&[syms::A, syms::B]`.
1141 pub fn symbols(&self) -> &[Keysym] {
1142 &self.symbols
1143 }
1144
1145 /// Returns the actions of this level.
1146 ///
1147 /// # Example
1148 ///
1149 /// ```xkb
1150 /// xkb_symbols {
1151 /// key <a> {
1152 /// [
1153 /// SetMods(mods = Mod1),
1154 /// {
1155 /// SetMods(mods = Mod2),
1156 /// LockGroup(group = 2),
1157 /// },
1158 /// ],
1159 /// };
1160 /// };
1161 /// ```
1162 ///
1163 /// If this object refers to the first level, then this function returns
1164 /// `&[SetMods(mods = Mod1)]`.
1165 ///
1166 /// If this object refers to the second level, then this function returns
1167 /// `&[SetMods(mods = Mod2), LockGroup(group = 2)]`.
1168 pub fn actions(&self) -> &[Action] {
1169 &self.actions
1170 }
1171}
1172
1173impl ModsSetAction {
1174 /// Returns whether this action has the `clearLocks` flag set.
1175 ///
1176 /// # Example
1177 ///
1178 /// ```xkb
1179 /// xkb_symbols {
1180 /// key <leftshift> {
1181 /// [ SetMods(mods = Shift, clearLocks) ],
1182 /// };
1183 /// };
1184 /// ```
1185 ///
1186 /// The function returns `true`.
1187 pub fn clear_locks(&self) -> bool {
1188 self.clear_locks
1189 }
1190
1191 /// Returns the modifier mask of this action.
1192 ///
1193 /// # Example
1194 ///
1195 /// ```xkb
1196 /// xkb_symbols {
1197 /// key <leftshift> {
1198 /// [ SetMods(mods = Shift) ],
1199 /// };
1200 /// };
1201 /// ```
1202 ///
1203 /// The function returns `Shift`.
1204 pub fn mask(&self) -> ModifierMask {
1205 self.modifiers
1206 }
1207}
1208
1209impl ModsLatchAction {
1210 /// Returns whether this action has the `clearLocks` flag set.
1211 ///
1212 /// # Example
1213 ///
1214 /// ```xkb
1215 /// xkb_symbols {
1216 /// key <leftshift> {
1217 /// [ LatchMods(mods = Shift, clearLocks) ],
1218 /// };
1219 /// };
1220 /// ```
1221 ///
1222 /// The function returns `true`.
1223 pub fn clear_locks(&self) -> bool {
1224 self.clear_locks
1225 }
1226
1227 /// Returns whether this action has the `latchToLock` flag set.
1228 ///
1229 /// # Example
1230 ///
1231 /// ```xkb
1232 /// xkb_symbols {
1233 /// key <leftshift> {
1234 /// [ LatchMods(mods = Shift, latchToLock) ],
1235 /// };
1236 /// };
1237 /// ```
1238 ///
1239 /// The function returns `true`.
1240 pub fn latch_to_lock(&self) -> bool {
1241 self.latch_to_lock
1242 }
1243
1244 /// Returns the modifier mask of this action.
1245 ///
1246 /// # Example
1247 ///
1248 /// ```xkb
1249 /// xkb_symbols {
1250 /// key <leftshift> {
1251 /// [ LatchMods(mods = Shift) ],
1252 /// };
1253 /// };
1254 /// ```
1255 ///
1256 /// The function returns `Shift`.
1257 pub fn mask(&self) -> ModifierMask {
1258 self.modifiers
1259 }
1260}
1261
1262impl ModsLockAction {
1263 /// Returns whether this action will lock the modifiers.
1264 ///
1265 /// # Example
1266 ///
1267 /// ```xkb
1268 /// xkb_symbols {
1269 /// key <leftshift> {
1270 /// [ LockMods(mods = Shift, affect = unlock) ],
1271 /// };
1272 /// };
1273 /// ```
1274 ///
1275 /// The function returns `false`.
1276 pub fn lock(&self) -> bool {
1277 self.lock
1278 }
1279
1280 /// Returns whether this action will unlock previously-locked modifiers.
1281 ///
1282 /// # Example
1283 ///
1284 /// ```xkb
1285 /// xkb_symbols {
1286 /// key <leftshift> {
1287 /// [ LockMods(mods = Shift, affect = lock) ],
1288 /// };
1289 /// };
1290 /// ```
1291 ///
1292 /// The function returns `false`.
1293 pub fn unlock(&self) -> bool {
1294 self.unlock
1295 }
1296
1297 /// Returns the modifier mask of this action.
1298 ///
1299 /// # Example
1300 ///
1301 /// ```xkb
1302 /// xkb_symbols {
1303 /// key <leftshift> {
1304 /// [ LockMods(mods = Shift) ],
1305 /// };
1306 /// };
1307 /// ```
1308 ///
1309 /// The function returns `Shift`.
1310 pub fn mask(&self) -> ModifierMask {
1311 self.modifiers
1312 }
1313}
1314
1315impl GroupSetAction {
1316 /// Returns whether this action has the `clearLocks` flag set.
1317 ///
1318 /// # Example
1319 ///
1320 /// ```xkb
1321 /// xkb_symbols {
1322 /// key <compose> {
1323 /// [ SetGroup(group = +1, clearLocks) ],
1324 /// };
1325 /// };
1326 /// ```
1327 ///
1328 /// The function returns `true`.
1329 pub fn clear_locks(&self) -> bool {
1330 self.clear_locks
1331 }
1332
1333 /// Returns the group change of this action.
1334 ///
1335 /// # Example
1336 ///
1337 /// ```xkb
1338 /// xkb_symbols {
1339 /// key <compose> {
1340 /// [ SetGroup(group = -1) ],
1341 /// };
1342 /// };
1343 /// ```
1344 ///
1345 /// The function returns `GroupChange::Relative(-1)`.
1346 pub fn group(&self) -> GroupChange {
1347 self.group.to_group_change()
1348 }
1349}
1350
1351impl GroupLatchAction {
1352 /// Returns whether this action has the `clearLocks` flag set.
1353 ///
1354 /// # Example
1355 ///
1356 /// ```xkb
1357 /// xkb_symbols {
1358 /// key <compose> {
1359 /// [ LatchGroup(group = +1, clearLocks) ],
1360 /// };
1361 /// };
1362 /// ```
1363 ///
1364 /// The function returns `true`.
1365 pub fn clear_locks(&self) -> bool {
1366 self.clear_locks
1367 }
1368
1369 /// Returns whether this action has the `latchToLock` flag set.
1370 ///
1371 /// # Example
1372 ///
1373 /// ```xkb
1374 /// xkb_symbols {
1375 /// key <compose> {
1376 /// [ LatchGroup(group = +1, latchToLock) ],
1377 /// };
1378 /// };
1379 /// ```
1380 ///
1381 /// The function returns `true`.
1382 pub fn latch_to_lock(&self) -> bool {
1383 self.latch_to_lock
1384 }
1385
1386 /// Returns the group change of this action.
1387 ///
1388 /// # Example
1389 ///
1390 /// ```xkb
1391 /// xkb_symbols {
1392 /// key <compose> {
1393 /// [ LatchGroup(group = -1) ],
1394 /// };
1395 /// };
1396 /// ```
1397 ///
1398 /// The function returns `GroupChange::Relative(-1)`.
1399 pub fn group(&self) -> GroupChange {
1400 self.group.to_group_change()
1401 }
1402}
1403
1404impl GroupLockAction {
1405 /// Returns the group change of this action.
1406 ///
1407 /// # Example
1408 ///
1409 /// ```xkb
1410 /// xkb_symbols {
1411 /// key <compose> {
1412 /// [ LockGroup(group = -1) ],
1413 /// };
1414 /// };
1415 /// ```
1416 ///
1417 /// The function returns `GroupChange::Relative(-1)`.
1418 pub fn group(&self) -> GroupChange {
1419 self.group.to_group_change()
1420 }
1421}
1422
1423impl RedirectKeyAction {
1424 /// Returns the name of the key that this action redirects to.
1425 ///
1426 /// # Example
1427 ///
1428 /// ```xkb
1429 /// xkb_symbols {
1430 /// key <a> {
1431 /// [ RedirectKey(key = <b>) ],
1432 /// };
1433 /// };
1434 /// ```
1435 ///
1436 /// The function returns `"b"`.
1437 pub fn key_name(&self) -> &str {
1438 &self.key_name
1439 }
1440
1441 /// Returns the keycode of the key that this action redirects to.
1442 ///
1443 /// # Example
1444 ///
1445 /// ```xkb
1446 /// xkb_symbols {
1447 /// key <a> {
1448 /// [ RedirectKey(key = <b>) ],
1449 /// };
1450 /// };
1451 /// ```
1452 ///
1453 /// The function returns the keycode of `<b>`.
1454 pub fn keycode(&self) -> crate::Keycode {
1455 self.keycode
1456 }
1457
1458 /// Returns the mods that will be set by this action.
1459 ///
1460 /// # Example
1461 ///
1462 /// ```xkb
1463 /// xkb_symbols {
1464 /// key <a> {
1465 /// [ RedirectKey(key = <b>, mods = Shift+Mod1) ],
1466 /// };
1467 /// };
1468 /// ```
1469 ///
1470 /// The function returns `ModifierMask::SHIFT | ModifierMask::MOD1`.
1471 pub fn mods_to_set(&self) -> ModifierMask {
1472 self.mods_to_set
1473 }
1474
1475 /// Returns the mods that will be cleared by this action.
1476 ///
1477 /// # Example
1478 ///
1479 /// ```xkb
1480 /// xkb_symbols {
1481 /// key <a> {
1482 /// [ RedirectKey(key = <b>, clearMods = Shift+Mod1) ],
1483 /// };
1484 /// };
1485 /// ```
1486 ///
1487 /// The function returns `ModifierMask::SHIFT | ModifierMask::MOD1`.
1488 pub fn mods_to_clear(&self) -> ModifierMask {
1489 self.mods_to_clear
1490 }
1491
1492 /// Returns the mods that are affected by this action.
1493 ///
1494 /// This is a shorthand for `self.mods_to_set() | self.mods_to_clear()`.
1495 pub fn modifier_mask(&self) -> ModifierMask {
1496 self.mods_to_set | self.mods_to_clear
1497 }
1498}
1499
1500impl ControlsSetAction {
1501 /// Returns the controls mask of this action.
1502 ///
1503 /// # Example
1504 ///
1505 /// ```xkb
1506 /// xkb_symbols {
1507 /// key <leftshift> {
1508 /// [ SetControls(mods = Overlay1) ],
1509 /// };
1510 /// };
1511 /// ```
1512 ///
1513 /// The function returns the mask for `Overlay1`.
1514 pub fn mask(&self) -> ControlsMask {
1515 ControlsMask(self.controls.0 as u32)
1516 }
1517}
1518
1519impl ControlsLockAction {
1520 /// Returns whether this action will lock the controls.
1521 ///
1522 /// # Example
1523 ///
1524 /// ```xkb
1525 /// xkb_symbols {
1526 /// key <leftshift> {
1527 /// [ LockControls(controls = Overlay1, affect = unlock) ],
1528 /// };
1529 /// };
1530 /// ```
1531 ///
1532 /// The function returns `false`.
1533 pub fn lock(&self) -> bool {
1534 self.lock
1535 }
1536
1537 /// Returns whether this action will unlock previously-locked controls.
1538 ///
1539 /// # Example
1540 ///
1541 /// ```xkb
1542 /// xkb_symbols {
1543 /// key <leftshift> {
1544 /// [ LockControls(controls = Overlay1, affect = lock) ],
1545 /// };
1546 /// };
1547 /// ```
1548 ///
1549 /// The function returns `false`.
1550 pub fn unlock(&self) -> bool {
1551 self.unlock
1552 }
1553
1554 /// Returns the controls mask of this action.
1555 ///
1556 /// # Example
1557 ///
1558 /// ```xkb
1559 /// xkb_symbols {
1560 /// key <leftshift> {
1561 /// [ LockControls(mods = Overlay1) ],
1562 /// };
1563 /// };
1564 /// ```
1565 ///
1566 /// The function returns the mask for `Overlay1`.
1567 pub fn mask(&self) -> ControlsMask {
1568 ControlsMask(self.controls.0 as u32)
1569 }
1570}
1571
1572impl OverlayBehavior {
1573 /// Returns the overlay that controls this behavior.
1574 ///
1575 /// # Example
1576 ///
1577 /// ```xkb
1578 /// xkb_symbols {
1579 /// key <a> {
1580 /// overlay2 = <b>,
1581 /// };
1582 /// };
1583 /// ```
1584 ///
1585 /// The function returns `KeyOverlay::Overlay2`.
1586 pub fn overlay(&self) -> KeyOverlay {
1587 self.overlay
1588 }
1589
1590 /// Returns the name of the key that this behavior redirects to if the overlay is
1591 /// active.
1592 ///
1593 /// # Example
1594 ///
1595 /// ```xkb
1596 /// xkb_symbols {
1597 /// key <a> {
1598 /// overlay1 = <b>,
1599 /// };
1600 /// };
1601 /// ```
1602 ///
1603 /// The function returns `"b"`.
1604 pub fn key_name(&self) -> &str {
1605 &self.key_name
1606 }
1607
1608 /// Returns the keycode of the key that this action redirects to if the overlay is
1609 /// active.
1610 ///
1611 /// # Example
1612 ///
1613 /// ```xkb
1614 /// xkb_symbols {
1615 /// key <a> {
1616 /// overlay1 = <b>,
1617 /// };
1618 /// };
1619 /// ```
1620 ///
1621 /// The function returns the keycode of `<b>`.
1622 pub fn keycode(&self) -> crate::Keycode {
1623 self.keycode
1624 }
1625}
1626
1627impl RadioGroupBehavior {
1628 /// Returns whether pressing this key can release the pressed key.
1629 ///
1630 /// # Example
1631 ///
1632 /// ```xkb
1633 /// xkb_symbols {
1634 /// key <a> {
1635 /// allownone,
1636 /// radiogroup = 1,
1637 /// };
1638 /// };
1639 /// ```
1640 ///
1641 /// The function returns `true`.
1642 pub fn allow_none(&self) -> bool {
1643 self.allow_none
1644 }
1645
1646 /// Returns the group that this key belongs to. This is a value between 1 and 32.
1647 ///
1648 /// # Example
1649 ///
1650 /// ```xkb
1651 /// xkb_symbols {
1652 /// key <a> {
1653 /// radiogroup = 1,
1654 /// };
1655 /// };
1656 /// ```
1657 ///
1658 /// The function returns `1`.
1659 pub fn group(&self) -> u32 {
1660 self.radio_group.raw()
1661 }
1662}
1663
1664impl Indicator {
1665 /// The name of the `Num Lock` indicator.
1666 pub const NUM_LOCK: &str = "Num Lock";
1667 /// The name of the `Caps Lock` indicator.
1668 pub const CAPS_LOCK: &str = "Caps Lock";
1669 /// The name of the `Scroll Lock` indicator.
1670 pub const SCROLL_LOCK: &str = "Scroll Lock";
1671 /// The name of the `Compose` indicator.
1672 pub const COMPOSE: &str = "Compose";
1673 /// The name of the `Kana` indicator.
1674 pub const KANA: &str = "Kana";
1675
1676 /// Returns the name of the indicator.
1677 ///
1678 /// # Example
1679 ///
1680 /// ```xkb
1681 /// xkb_compat {
1682 /// indicator "Caps Lock" {
1683 /// modifiers = Lock;
1684 /// whichModState = Effective;
1685 /// };
1686 /// };
1687 /// ```
1688 ///
1689 /// The function returns `"Caps Lock"`.
1690 pub fn name(&self) -> &str {
1691 &self.name
1692 }
1693
1694 /// Returns the matcher for the indicator.
1695 ///
1696 /// # Example
1697 ///
1698 /// ```xkb
1699 /// xkb_compat {
1700 /// indicator "Caps Lock" {
1701 /// modifiers = Lock;
1702 /// whichModState = Effective;
1703 /// };
1704 /// };
1705 /// ```
1706 ///
1707 /// The matcher will match if the effective group contains the Lock modifier.
1708 pub fn matcher(&self) -> IndicatorMatcher {
1709 macro_rules! mods {
1710 ($comp:ident) => {
1711 self.mod_components
1712 .contains(ModComponentMask::$comp)
1713 .then_some(self.modifier_mask.0)
1714 .unwrap_or_default()
1715 };
1716 }
1717 macro_rules! group_flag {
1718 ($comp:ident, $tt:tt) => {
1719 self.group_component == GroupComponent::$comp
1720 && self.group_mask.0 $tt 0
1721 };
1722 }
1723 macro_rules! group_mask {
1724 ($comp:ident) => {
1725 (self.group_component == GroupComponent::$comp)
1726 .then_some(self.group_mask.0)
1727 .unwrap_or_default()
1728 };
1729 }
1730 IndicatorMatcher {
1731 mods_pressed: mods!(BASE),
1732 mods_latched: mods!(LATCHED),
1733 mods_locked: mods!(LOCKED),
1734 mods: mods!(EFFECTIVE),
1735 group_pressed: group_flag!(Base, !=),
1736 group_not_pressed: group_flag!(Base, ==),
1737 group_latched: group_flag!(Latched, !=),
1738 group_not_latched: group_flag!(Latched, ==),
1739 group_locked: group_mask!(Locked),
1740 group: group_mask!(Effective),
1741 controls: self.controls.0 as u32,
1742 }
1743 }
1744}
1745
1746impl IndicatorMatcher {
1747 /// Returns whether this indicator should be illuminated.
1748 pub fn matches(&self, components: &Components) -> bool {
1749 let mut res = 0;
1750 res |= self.mods_pressed & components.mods_pressed.0;
1751 res |= self.mods_latched & components.mods_latched.0;
1752 res |= self.mods_locked & components.mods_locked.0;
1753 res |= self.mods & components.mods.0;
1754 res |= (self.group_pressed & (components.group_pressed.0 != 0)) as u32;
1755 res |= (self.group_not_pressed & (components.group_pressed.0 == 0)) as u32;
1756 res |= (self.group_latched & (components.group_latched.0 != 0)) as u32;
1757 res |= (self.group_not_latched & (components.group_latched.0 == 0)) as u32;
1758 if components.group_locked.0 < u32::BITS {
1759 res |= self.group_locked & (1 << components.group_locked.0);
1760 }
1761 if components.group.0 < u32::BITS {
1762 res |= self.group & (1 << components.group.0);
1763 }
1764 res |= self.controls & components.controls.0;
1765 res != 0
1766 }
1767}