1use std::{collections::BTreeMap, fmt};
2
3const MAX_MOD_SLOTS: usize = 32;
5
6pub const LEFT_CTRL: u32 = 29;
8pub const LEFT_SHIFT: u32 = 42;
9pub const RIGHT_SHIFT: u32 = 54;
10pub const RIGHT_CTRL: u32 = 97;
11pub const ALT: u32 = 56;
12pub const ALTGR: u32 = 100;
13pub const LOGO: u32 = 125;
14pub const CAPS_LOCK: u32 = 58;
15pub const NUM_LOCK: u32 = 69;
16pub const SCROLL_LOCK: u32 = 70;
17#[derive(Debug, Clone, Copy, PartialEq)]
21pub enum KeyDirection {
22 Up,
23 Down,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq)]
27pub enum ModType {
28 None,
29 Level2,
30 Level3,
31 Level5,
32 Compose,
33 Caps,
34 Num,
35 Scroll,
36}
37
38#[derive(Debug, Clone)]
39pub enum ModKind {
40 Pressed {
41 pressed: bool,
42 mod_type: ModType,
43 },
44 Lock {
45 pressed: bool,
46 locked: u8,
47 mod_type: ModType,
48 },
49 Latch {
50 pressed: bool,
51 latched: bool,
52 mod_type: ModType,
53 },
54 None,
55}
56
57impl ModKind {
58 pub fn update(&mut self, key_direction: KeyDirection) {
59 match self {
60 ModKind::Pressed {
61 ref mut pressed,
62 mod_type: _,
63 } => match key_direction {
64 KeyDirection::Down => *pressed = true,
65 KeyDirection::Up => *pressed = false,
66 },
67 ModKind::Lock {
68 ref mut pressed,
69 ref mut locked,
70 mod_type: _,
71 } => match key_direction {
72 KeyDirection::Down => {
73 *pressed = true;
74 if *locked == 0 {
75 *locked = 2;
76 }
77 }
78 KeyDirection::Up => {
79 *pressed = false;
80 if *locked != 0 {
81 *locked -= 1;
82 }
83 }
84 },
85 ModKind::Latch {
86 ref mut pressed,
87 ref mut latched,
88 mod_type: _,
89 } => match key_direction {
90 KeyDirection::Down => {
91 *pressed = true;
92 *latched = !*latched;
93 }
94 KeyDirection::Up => {
95 *pressed = false;
96 }
97 },
98 ModKind::None => {}
99 }
100 }
101
102 fn unlatch(&mut self) {
103 if let ModKind::Latch {
104 pressed: _,
105 latched,
106 mod_type: _,
107 } = self
108 {
109 *latched = false
110 }
111 }
112
113 pub fn locked(&self) -> bool {
114 match self {
115 ModKind::Pressed {
116 pressed: _,
117 mod_type: _,
118 } => false,
119 ModKind::Lock {
120 pressed: _,
121 locked,
122 mod_type: _,
123 } => locked > &0,
124 ModKind::Latch {
125 pressed: _,
126 latched: _,
127 mod_type: _,
128 } => false,
129 ModKind::None => false,
130 }
131 }
132
133 pub fn is_active(&self) -> bool {
134 match self {
135 ModKind::Pressed {
136 pressed,
137 mod_type: _,
138 } => *pressed,
139 ModKind::Lock {
140 pressed: _,
141 locked,
142 mod_type: _,
143 } => locked > &0,
144 ModKind::Latch {
145 pressed: _,
146 latched,
147 mod_type: _,
148 } => *latched,
149 ModKind::None => false,
150 }
151 }
152
153 pub(crate) fn get_modkind_from_modtype(&self, mod_type: ModType) -> Option<ModKind> {
154 match self {
155 ModKind::Pressed { mod_type: m_t, .. }
156 | ModKind::Lock { mod_type: m_t, .. }
157 | ModKind::Latch { mod_type: m_t, .. } => {
158 if *m_t == mod_type {
159 Some(self.clone())
160 } else {
161 None
162 }
163 }
164 ModKind::None => None,
165 }
166 }
167}
168
169#[derive(Debug, Clone)]
170pub enum Modifier {
171 Single(ModKind),
172 Leveled(BTreeMap<u8, ModKind>),
173}
174
175#[derive(Debug, Clone)]
176pub struct Modifiers {
177 entries: Vec<(u32, Modifier)>,
179}
180
181impl fmt::Display for Modifiers {
182 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183 for (code, modifier) in &self.entries {
184 write!(f, "code {}: ", code)?;
185 match modifier {
186 Modifier::Single(mod_kind) => {
187 write!(f, "{:?}", mod_kind)?;
188 }
189 Modifier::Leveled(map) => {
190 writeln!(f, "[")?;
191 for (index, mod_kind) in map {
192 writeln!(f, " index {}: {:?}, ", index, mod_kind)?;
193 }
194 write!(f, "]")?;
195 }
196 }
197 writeln!(f)?;
198 }
199 Ok(())
200 }
201}
202
203impl Default for Modifiers {
204 fn default() -> Self {
205 let entries = vec![
206 (
207 LEFT_CTRL,
208 Modifier::Single(ModKind::Pressed {
209 pressed: false,
210 mod_type: ModType::None,
211 }),
212 ),
213 (
214 RIGHT_CTRL,
215 Modifier::Single(ModKind::Pressed {
216 pressed: false,
217 mod_type: ModType::None,
218 }),
219 ),
220 (
221 LEFT_SHIFT,
222 Modifier::Single(ModKind::Pressed {
223 pressed: false,
224 mod_type: ModType::Level2,
225 }),
226 ),
227 (
228 RIGHT_SHIFT,
229 Modifier::Single(ModKind::Pressed {
230 pressed: false,
231 mod_type: ModType::Level2,
232 }),
233 ),
234 (
235 ALT,
236 Modifier::Single(ModKind::Pressed {
237 pressed: false,
238 mod_type: ModType::None,
239 }),
240 ),
241 (
242 ALTGR,
243 Modifier::Single(ModKind::Pressed {
244 pressed: false,
245 mod_type: ModType::None,
246 }),
247 ),
248 (
249 LOGO,
250 Modifier::Single(ModKind::Pressed {
251 pressed: false,
252 mod_type: ModType::None,
253 }),
254 ),
255 (
256 CAPS_LOCK,
257 Modifier::Single(ModKind::Lock {
258 pressed: false,
259 locked: 0,
260 mod_type: ModType::Caps,
261 }),
262 ),
263 (
264 NUM_LOCK,
265 Modifier::Single(ModKind::Lock {
266 pressed: false,
267 locked: 0,
268 mod_type: ModType::Num,
269 }),
270 ),
271 (
272 SCROLL_LOCK,
273 Modifier::Single(ModKind::Lock {
274 pressed: false,
275 locked: 0,
276 mod_type: ModType::Scroll,
277 }),
278 ),
279 ];
280 Self { entries }
281 }
282}
283
284impl Modifiers {
285 pub fn new() -> Self {
286 Self {
287 entries: Vec::with_capacity(MAX_MOD_SLOTS),
288 }
289 }
290
291 #[inline]
293 pub fn get(&self, evdev_code: u32) -> Option<&Modifier> {
294 self.entries
295 .iter()
296 .find(|(c, _)| *c == evdev_code)
297 .map(|(_, m)| m)
298 }
299
300 #[inline]
302 pub fn get_mut(&mut self, evdev_code: u32) -> Option<&mut Modifier> {
303 self.entries
304 .iter_mut()
305 .find(|(c, _)| *c == evdev_code)
306 .map(|(_, m)| m)
307 }
308
309 #[inline]
311 pub fn iter(&self) -> impl Iterator<Item = (&u32, &Modifier)> {
312 self.entries.iter().map(|(c, m)| (c, m))
313 }
314
315 pub fn set_modifier(&mut self, evdev_code: u32, modifier: Modifier) {
317 if let Some((_, existing)) = self.entries.iter_mut().find(|(c, _)| *c == evdev_code) {
318 *existing = modifier;
319 } else {
320 self.entries.push((evdev_code, modifier));
321 }
322 }
323
324 pub fn active_mod_type(&self, mod_type: ModType) -> bool {
325 self.entries.iter().any(|(_, modifier)| match modifier {
326 Modifier::Single(mod_kind) => {
327 if let Some(mk) = mod_kind.get_modkind_from_modtype(mod_type) {
328 mk.is_active()
329 } else {
330 false
331 }
332 }
333 Modifier::Leveled(map) => map.values().any(|mod_kind| {
334 if let Some(mk) = mod_kind.get_modkind_from_modtype(mod_type) {
335 mk.is_active()
336 } else {
337 false
338 }
339 }),
340 })
341 }
342
343 #[inline]
346 pub fn active_none_and_levels(&self) -> (bool, bool, bool, bool) {
347 let mut none_active = false;
348 let mut l2 = false;
349 let mut l3 = false;
350 let mut l5 = false;
351
352 for (_, modifier) in &self.entries {
353 match modifier {
354 Modifier::Single(mk) => {
355 Self::check_mod_kind(mk, &mut none_active, &mut l2, &mut l3, &mut l5);
356 }
357 Modifier::Leveled(map) => {
358 for mk in map.values() {
359 Self::check_mod_kind(mk, &mut none_active, &mut l2, &mut l3, &mut l5);
360 }
361 }
362 }
363 }
364 (none_active, l2, l3, l5)
365 }
366
367 #[inline(always)]
368 fn check_mod_kind(
369 mk: &ModKind,
370 none_active: &mut bool,
371 l2: &mut bool,
372 l3: &mut bool,
373 l5: &mut bool,
374 ) {
375 match mk {
376 ModKind::Pressed { pressed, mod_type } if *pressed => match mod_type {
377 ModType::None => *none_active = true,
378 ModType::Level2 => *l2 = true,
379 ModType::Level3 => *l3 = true,
380 ModType::Level5 => *l5 = true,
381 _ => {}
382 },
383 ModKind::Lock {
384 locked, mod_type, ..
385 } if *locked > 0 => match mod_type {
386 ModType::None => *none_active = true,
387 ModType::Level2 => *l2 = true,
388 ModType::Level3 => *l3 = true,
389 ModType::Level5 => *l5 = true,
390 _ => {}
391 },
392 ModKind::Latch {
393 latched, mod_type, ..
394 } if *latched => match mod_type {
395 ModType::None => *none_active = true,
396 ModType::Level2 => *l2 = true,
397 ModType::Level3 => *l3 = true,
398 ModType::Level5 => *l5 = true,
399 _ => {}
400 },
401 _ => {}
402 }
403 }
404
405 pub fn unlatch(&mut self) {
406 self.entries
407 .iter_mut()
408 .for_each(|(_, modifier)| match modifier {
409 Modifier::Single(mod_kind) => {
410 mod_kind.unlatch();
411 }
412 Modifier::Leveled(map) => {
413 map.values_mut().for_each(|mod_kind| {
414 mod_kind.unlatch();
415 });
416 }
417 });
418 }
419
420 pub fn locked(&self, evdev_code: u32) -> bool {
421 self.get(evdev_code).is_some_and(|modifier| match modifier {
422 Modifier::Single(mod_kind) => mod_kind.locked(),
423 Modifier::Leveled(map) => map.values().any(|mod_kind| mod_kind.locked()),
424 })
425 }
426
427 pub fn locked_with_type(&self, evdev_code: u32, mod_type: ModType) -> bool {
428 self.get(evdev_code).is_some_and(|modifier| match modifier {
429 Modifier::Single(mod_kind) => {
430 mod_kind.locked() && mod_kind.get_modkind_from_modtype(mod_type).is_some()
431 }
432 Modifier::Leveled(map) => map.values().any(|mod_kind| {
433 mod_kind.locked() && mod_kind.get_modkind_from_modtype(mod_type).is_some()
434 }),
435 })
436 }
437
438 #[inline]
439 pub fn set_state(&mut self, evdev_code: u32, key_direction: KeyDirection) -> bool {
440 let pos = match self.entries.iter().position(|(c, _)| *c == evdev_code) {
441 Some(p) => p,
442 None => return false,
443 };
444 let is_leveled = matches!(&self.entries[pos].1, Modifier::Leveled(_));
445 if is_leveled {
446 let (_, l2, l3, l5) = self.active_none_and_levels();
447 let level = level_index(l5, l3, l2) as u8;
448 if let Modifier::Leveled(map) = &mut self.entries[pos].1 {
449 if let Some(mod_kind) = map.get_mut(&level) {
450 mod_kind.update(key_direction);
451 } else if let Some(mod_kind) = map.get_mut(&0) {
452 mod_kind.update(key_direction);
453 } else {
454 return false;
455 }
456 }
457 } else if let Modifier::Single(mod_kind) = &mut self.entries[pos].1 {
458 mod_kind.update(key_direction);
459 }
460 true
461 }
462}
463
464#[inline(always)]
465pub fn level_index(level5: bool, level3: bool, level2: bool) -> usize {
466 ((level5 as usize) << 2) | ((level3 as usize) << 1) | (level2 as usize)
467}