cognitive_inputs/keyboard_state.rs
1// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
2// the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/
3
4//! This module contains functionality allowing to keep track of state of keyboard.
5
6// -------------------------------------------------------------------------------------------------
7
8use xkbcommon::xkb;
9
10use qualia::{Illusion, KeyboardConfig, InputCode, InputValue};
11
12use keymap::XkbKeymap;
13
14// -------------------------------------------------------------------------------------------------
15
16/// This struct represents state of keyboard modifiers (shift, ctrl, etc...).
17#[derive(Clone, Copy, Debug, Eq, PartialEq)]
18pub struct KeyMods {
19 pub depressed: u32,
20 pub latched: u32,
21 pub locked: u32,
22 pub effective: u32,
23}
24
25// -------------------------------------------------------------------------------------------------
26
27impl KeyMods {
28 /// Constructs default `KeyMods`.
29 pub fn default() -> Self {
30 KeyMods {
31 depressed: 0,
32 latched: 0,
33 locked: 0,
34 effective: 0,
35 }
36 }
37
38 /// Constructs `KeyMods` from given modifiers.
39 pub fn new(depressed: u32, latched: u32, locked: u32, effective: u32) -> Self {
40 KeyMods {
41 depressed: depressed,
42 latched: latched,
43 locked: locked,
44 effective: effective,
45 }
46 }
47}
48
49// -------------------------------------------------------------------------------------------------
50
51/// Represents state of keyboard.
52pub struct KeyboardState {
53 xkb_state: xkb::State,
54 mods: KeyMods,
55}
56
57// -------------------------------------------------------------------------------------------------
58
59impl KeyboardState {
60 /// Constructs new `KeyboardState`.
61 pub fn new(config: &KeyboardConfig) -> Result<Self, Illusion> {
62 let xkb_keymap = if let Some(xkb_keymap) = XkbKeymap::new(config) {
63 xkb_keymap
64 } else {
65 return Err(Illusion::General(format!("Failed to create key map")));
66 };
67
68 Ok(KeyboardState {
69 xkb_state: xkb::State::new(&xkb_keymap.keymap),
70 mods: KeyMods::default(),
71 })
72 }
73
74 /// Updates state with given key. Returns `true` when modifiers changed, false otherwise.
75 pub fn update(&mut self, code: InputCode, value: InputValue) -> bool {
76 let direction = if value == 0 {
77 xkb::KeyDirection::Up
78 } else {
79 xkb::KeyDirection::Down
80 };
81
82 // Offset the key code by 8, as the evdev XKB rules reflect X's
83 // broken key code system, which starts at 8.
84 self.xkb_state.update_key(code as u32 + 8, direction);
85 let mods = KeyMods::new(self.xkb_state.serialize_mods(xkb::STATE_MODS_DEPRESSED),
86 self.xkb_state.serialize_mods(xkb::STATE_MODS_LATCHED),
87 self.xkb_state.serialize_mods(xkb::STATE_MODS_LOCKED),
88 self.xkb_state.serialize_mods(xkb::STATE_MODS_EFFECTIVE));
89
90 if mods != self.mods {
91 self.mods = mods;
92 true
93 } else {
94 false
95 }
96 }
97
98 /// Returns state of modifiers.
99 pub fn get_mods(&self) -> KeyMods {
100 self.mods
101 }
102}
103
104// -------------------------------------------------------------------------------------------------