RKTK API Docs RKTK Home Repo

rktk_keymanager/state/
mod.rs

1//! Keyboard state management.
2
3#![allow(clippy::let_unit_value)]
4#![allow(clippy::single_match)]
5
6use crate::{
7    interface::state::{
8        KeymapInfo,
9        config::StateConfig,
10        input_event::InputEvent,
11        output_event::{EventType, OutputEvent},
12    },
13    keymap::Keymap,
14};
15
16pub mod hid_report;
17mod key_resolver;
18mod shared;
19mod updater;
20
21// TODO: Delete these generics hell in some day...
22
23/// Represents the state of the keyboard.
24pub struct State<
25    const LAYER: usize,
26    const ROW: usize,
27    const COL: usize,
28    const ENCODER_COUNT: usize,
29    const NORMAL_MAX_PRESSED_KEYS: usize,
30    const ONESHOT_STATE_SIZE: usize,
31    const TAP_DANCE_MAX_DEFINITIONS: usize,
32    const TAP_DANCE_MAX_REPEATS: usize,
33    const COMBO_KEY_MAX_DEFINITIONS: usize,
34    const COMBO_KEY_MAX_SOURCES: usize,
35> {
36    key_resolver: key_resolver::KeyResolver<
37        NORMAL_MAX_PRESSED_KEYS,
38        ONESHOT_STATE_SIZE,
39        TAP_DANCE_MAX_DEFINITIONS,
40        TAP_DANCE_MAX_REPEATS,
41        COMBO_KEY_MAX_DEFINITIONS,
42        COMBO_KEY_MAX_SOURCES,
43    >,
44    shared: shared::SharedState<
45        LAYER,
46        ROW,
47        COL,
48        ENCODER_COUNT,
49        TAP_DANCE_MAX_DEFINITIONS,
50        TAP_DANCE_MAX_REPEATS,
51        COMBO_KEY_MAX_DEFINITIONS,
52        COMBO_KEY_MAX_SOURCES,
53    >,
54    config: StateConfig,
55    updater_state: updater::UpdaterState,
56}
57
58impl<
59    const LAYER: usize,
60    const ROW: usize,
61    const COL: usize,
62    const ENCODER_COUNT: usize,
63    const NORMAL_MAX_PRESSED_KEYS: usize,
64    const ONESHOT_STATE_SIZE: usize,
65    const TAP_DANCE_MAX_DEFINITIONS: usize,
66    const TAP_DANCE_MAX_REPEATS: usize,
67    const COMBO_KEY_MAX_DEFINITIONS: usize,
68    const COMBO_KEY_MAX_SOURCES: usize,
69>
70    State<
71        LAYER,
72        ROW,
73        COL,
74        ENCODER_COUNT,
75        NORMAL_MAX_PRESSED_KEYS,
76        ONESHOT_STATE_SIZE,
77        TAP_DANCE_MAX_DEFINITIONS,
78        TAP_DANCE_MAX_REPEATS,
79        COMBO_KEY_MAX_DEFINITIONS,
80        COMBO_KEY_MAX_SOURCES,
81    >
82{
83    /// Creates a new state with the given keymap and configuration.
84    pub fn new(
85        keymap: Keymap<
86            LAYER,
87            ROW,
88            COL,
89            ENCODER_COUNT,
90            TAP_DANCE_MAX_DEFINITIONS,
91            TAP_DANCE_MAX_REPEATS,
92            COMBO_KEY_MAX_DEFINITIONS,
93            COMBO_KEY_MAX_SOURCES,
94        >,
95        config: StateConfig,
96    ) -> Self {
97        const {
98            assert!(LAYER >= 1, "Layer count must be at least 1");
99        }
100
101        Self {
102            config: config.clone(),
103            key_resolver: key_resolver::KeyResolver::new(
104                config.key_resolver,
105                keymap.tap_dance.clone(),
106                keymap.combo.clone(),
107            ),
108            shared: shared::SharedState::new(keymap),
109            updater_state: updater::UpdaterState::new(config.mouse),
110        }
111    }
112
113    pub fn get_keymap(
114        &self,
115    ) -> &Keymap<
116        LAYER,
117        ROW,
118        COL,
119        ENCODER_COUNT,
120        TAP_DANCE_MAX_DEFINITIONS,
121        TAP_DANCE_MAX_REPEATS,
122        COMBO_KEY_MAX_DEFINITIONS,
123        COMBO_KEY_MAX_SOURCES,
124    > {
125        &self.shared.keymap
126    }
127
128    pub fn get_config(&self) -> &StateConfig {
129        &self.config
130    }
131
132    pub fn get_layer_active(&self) -> &shared::LayerActive<LAYER> {
133        &self.shared.layer_active
134    }
135
136    pub fn get_keymap_info() -> KeymapInfo {
137        KeymapInfo {
138            layer_count: LAYER as u8,
139            max_tap_dance_key_count: TAP_DANCE_MAX_DEFINITIONS as u8,
140            max_tap_dance_repeat_count: TAP_DANCE_MAX_REPEATS as u8,
141            oneshot_state_size: ONESHOT_STATE_SIZE as u8,
142        }
143    }
144
145    pub fn update(
146        &mut self,
147        event: InputEvent,
148        since_last_update: core::time::Duration,
149        mut cb: impl FnMut(OutputEvent),
150    ) {
151        self.shared.now = self.shared.now + since_last_update.into();
152        let mut updater = self.updater_state.start_update();
153
154        let key_change = match event {
155            InputEvent::Key(key_change) => Some(key_change),
156            InputEvent::Mouse(movement) => {
157                updater.update_by_mouse_move(movement, &mut cb);
158                None
159            }
160            InputEvent::Encoder((id, dir)) => {
161                if let Some(kc) = self
162                    .shared
163                    .keymap
164                    .get_encoder_key(self.shared.layer_active, id as usize, dir)
165                    .copied()
166                {
167                    updater.update_by_keycode(&kc, EventType::Pressed, &mut self.shared, &mut cb);
168                    updater.update_by_keycode(&kc, EventType::Released, &mut self.shared, &mut cb);
169                }
170                None
171            }
172            _ => None,
173        };
174
175        self.key_resolver
176            .resolve_key(&mut self.shared, key_change.as_ref(), |shared, et, kc| {
177                updater.update_by_keycode(&kc, et, shared, &mut cb);
178            });
179
180        updater.end(self.shared.highest_layer(), &mut self.shared, cb);
181    }
182}
183
184#[cfg(test)]
185mod tests;