jay_config/keyboard/mod.rs
1//! Tools affecting the keyboard behavior.
2
3use {
4 crate::keyboard::{mods::Modifiers, syms::KeySym},
5 serde::{Deserialize, Serialize},
6 std::ops::{BitOr, BitOrAssign},
7};
8
9pub mod mods;
10pub mod syms;
11
12/// A keysym with zero or more modifiers
13#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Hash, Debug)]
14pub struct ModifiedKeySym {
15 pub mods: Modifiers,
16 pub sym: KeySym,
17}
18
19impl From<KeySym> for ModifiedKeySym {
20 fn from(sym: KeySym) -> Self {
21 Self {
22 mods: Modifiers(0),
23 sym,
24 }
25 }
26}
27
28impl BitOr<Modifiers> for ModifiedKeySym {
29 type Output = ModifiedKeySym;
30
31 fn bitor(self, rhs: Modifiers) -> Self::Output {
32 ModifiedKeySym {
33 mods: self.mods | rhs,
34 sym: self.sym,
35 }
36 }
37}
38
39impl BitOrAssign<Modifiers> for ModifiedKeySym {
40 fn bitor_assign(&mut self, rhs: Modifiers) {
41 self.mods |= rhs;
42 }
43}
44
45/// A keymap.
46#[derive(Serialize, Deserialize, Copy, Clone, Debug, Eq, PartialEq, Hash)]
47pub struct Keymap(pub u64);
48
49impl Keymap {
50 /// The invalid keymap.
51 pub const INVALID: Self = Self(0);
52
53 /// Returns whether this keymap is valid.
54 pub fn is_valid(self) -> bool {
55 self != Self::INVALID
56 }
57
58 /// Returns whether this keymap is invalid.
59 pub fn is_invalid(self) -> bool {
60 self == Self::INVALID
61 }
62
63 /// Destroys this reference to the keymap.
64 ///
65 /// Seats that are currently using this keymap are unaffected.
66 pub fn destroy(self) {
67 if self.is_valid() {
68 get!().destroy_keymap(self);
69 }
70 }
71}
72
73/// Parses a keymap.
74///
75/// The returned keymap can later be used to set the keymap of a seat. If the keymap cannot
76/// be parsed, returns an invalid keymap. Trying to set a seat's keymap to an invalid keymap
77/// has no effect.
78///
79/// A simple keymap looks as follows:
80///
81/// ```text
82/// xkb_keymap {
83/// xkb_keycodes { include "evdev+aliases(qwerty)" };
84/// xkb_types { include "complete" };
85/// xkb_compat { include "complete" };
86/// xkb_symbols { include "pc+inet(evdev)+us(basic)" };
87/// };
88/// ```
89///
90/// To use a programmer Dvorak, replace the corresponding line by
91///
92/// ```text
93/// xkb_symbols { include "pc+inet(evdev)+us(dvp)" };
94/// ```
95///
96/// To use a German keymap, replace the corresponding line by
97///
98/// ```text
99/// xkb_symbols { include "pc+inet(evdev)+de(basic)" };
100/// ```
101///
102/// You can also use a completely custom keymap that doesn't use any includes. See the
103/// [default][default] Jay keymap for an example.
104///
105/// General information about the keymap format can be found in the [arch wiki][wiki].
106///
107/// [default]: https://github.com/mahkoh/jay/tree/master/src/keymap.xkb
108/// [wiki]: https://wiki.archlinux.org/title/X_keyboard_extension
109pub fn parse_keymap(keymap: &str) -> Keymap {
110 get!(Keymap::INVALID).parse_keymap(keymap)
111}