Skip to main content

smart_keymap_core/key/
layered.rs

1use core::fmt::Debug;
2use core::marker::Copy;
3use core::ops::{BitAnd, BitOr, Index, Not};
4
5use serde::Deserialize;
6
7use crate::input;
8use crate::key;
9use crate::key::KeyboardModifiers;
10use crate::slice::Slice;
11
12/// The type used for layer index.
13///
14/// Layer modifiers and layer events use **1-based** indices (`1` = first non-base
15/// layer). Index `0` is reserved (base / always active). Call sites must only
16/// pass indices in range for the keymap's layer count; out-of-range values are
17/// a construction bug and are checked with [`debug_assert`] in debug builds.
18pub type LayerIndex = u32;
19
20/// Fixed-capacity bitset of layers for modifier / conditional-layer state.
21///
22/// Bit `i` corresponds to layer index `i`.
23///  Capacity is [Self::BITS] layers (indices `0..=[MAX_BITSET_LAYER]`).
24///
25/// This is a thin `no_std` newtype over [`u32`]
26///  so keymap `const` data can build bitsets
27///  without a heap or an external bitset crate.
28/// Widening capacity later is a storage-type change (`u64`, `u128`, or multi-limb)
29///  behind the same API.
30#[repr(transparent)]
31#[derive(Debug, Clone, Copy, Eq, PartialEq, Deserialize)]
32#[serde(transparent)]
33pub struct LayerBitset(u32);
34
35impl LayerBitset {
36    /// Number of representable layer bits.
37    pub const BITS: usize = 32;
38
39    /// Empty bitset (no layers selected).
40    pub const EMPTY: Self = Self(0);
41
42    /// Bitset with every representable layer bit set.
43    pub const ALL: Self = Self(u32::MAX);
44
45    /// Construct from raw bits (bit `i` = layer `i`).
46    pub const fn from_bits(bits: u32) -> Self {
47        Self(bits)
48    }
49
50    /// Raw bit pattern.
51    pub const fn bits(self) -> u32 {
52        self.0
53    }
54
55    /// Returns true if bit `index` is set.
56    pub const fn contains(self, index: usize) -> bool {
57        index < Self::BITS && (self.0 & (1u32 << index)) != 0
58    }
59
60    /// Returns a copy with bit `index` set, if `index` is in range.
61    pub const fn insert(self, index: usize) -> Self {
62        if index < Self::BITS {
63            Self(self.0 | (1u32 << index))
64        } else {
65            self
66        }
67    }
68
69    /// Returns a copy with bit `index` cleared, if `index` is in range.
70    pub const fn remove(self, index: usize) -> Self {
71        if index < Self::BITS {
72            Self(self.0 & !(1u32 << index))
73        } else {
74            self
75        }
76    }
77
78    /// Returns true if every bit set in `other` is also set in `self`.
79    pub const fn is_superset_of(self, other: Self) -> bool {
80        (self.0 & other.0) == other.0
81    }
82}
83
84impl Default for LayerBitset {
85    fn default() -> Self {
86        Self::EMPTY
87    }
88}
89
90impl From<u32> for LayerBitset {
91    fn from(bits: u32) -> Self {
92        Self::from_bits(bits)
93    }
94}
95
96impl From<LayerBitset> for u32 {
97    fn from(bitset: LayerBitset) -> Self {
98        bitset.bits()
99    }
100}
101
102impl BitAnd for LayerBitset {
103    type Output = Self;
104
105    fn bitand(self, rhs: Self) -> Self::Output {
106        Self(self.0 & rhs.0)
107    }
108}
109
110impl BitOr for LayerBitset {
111    type Output = Self;
112
113    fn bitor(self, rhs: Self) -> Self::Output {
114        Self(self.0 | rhs.0)
115    }
116}
117
118impl Not for LayerBitset {
119    type Output = Self;
120
121    fn not(self) -> Self::Output {
122        Self(!self.0)
123    }
124}
125
126/// The maximum layer bit index representable in a [LayerBitset].
127///
128/// For a 32-bit [LayerBitset], this is 31 (bits 0..=31, i.e. 32 layers).
129pub const MAX_BITSET_LAYER: usize = LayerBitset::BITS - 1;
130
131/// The bitset with all representable modifier layers in the mask.
132///
133/// Includes bit [MAX_BITSET_LAYER].
134pub const BITSET_MASK_ALL: LayerBitset = LayerBitset::ALL;
135
136/// Struct for modifying layers with a bitset.
137#[repr(C)]
138#[derive(Debug, Deserialize, Clone, Copy, Eq, PartialEq)]
139pub struct ModifierBitset {
140    /// The set of layers modified.
141    pub layers: LayerBitset,
142    /// The mask for which layers are affected by the modification.
143    #[serde(default = "default_modifier_bitset_mask")]
144    pub mask: LayerBitset,
145}
146
147fn default_modifier_bitset_mask() -> LayerBitset {
148    BITSET_MASK_ALL
149}
150
151/// Reference for a keyboard key.
152#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
153pub enum Ref {
154    /// Ref to a layer modifier key.
155    Modifier(u8),
156    /// Ref to a layered key.
157    Layered(u8),
158}
159
160/// Target of a layer-lock action.
161#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq)]
162pub enum LayerLockTarget {
163    /// Highest currently active layer.
164    HighestActive,
165    /// A specific layer.
166    Layer(LayerIndex),
167}
168
169/// Modifier layer key affects what layers are active.
170#[derive(Debug, Deserialize, Clone, Copy, PartialEq)]
171pub enum ModifierKey {
172    /// Activates the given layer when held.
173    Hold(LayerIndex, KeyboardModifiers),
174    /// Toggles whether the given layer is active when pressed.
175    Toggle(LayerIndex),
176    /// Sticky layer modifier, similar to sticky modifier key.
177    ///
178    /// Acts the same as `Hold` variant if interrupted.
179    /// If tapped, then the layer is activated for the next key tap.
180    Sticky(LayerIndex),
181    /// Sets the set of active layers to the given layers when the key is pressed.
182    SetActiveLayers(ModifierBitset),
183    /// Sets the default layer.
184    Default(LayerIndex),
185    /// Layer lock key.
186    ///
187    /// Inverts lock on the [LayerLockTarget]: if unlocked, lock and activate; if locked,
188    /// unlock and deactivate.
189    ///
190    /// While a layer is locked, releasing a [`ModifierKey::Hold`] that activated it leaves the
191    /// layer active. Pressing that [`ModifierKey::Hold`] again unlocks and turns the layer off.
192    Lock(LayerLockTarget),
193}
194
195impl ModifierKey {
196    /// Create a new [ModifierKey] that activates the given layer when held.
197    pub const fn hold(layer: LayerIndex) -> Self {
198        ModifierKey::Hold(layer, key::KeyboardModifiers::NONE)
199    }
200
201    /// Adds keyboard modifiers to a Hold modifier key.
202    pub const fn with_keyboard_modifiers(self, mods: key::KeyboardModifiers) -> Self {
203        match self {
204            ModifierKey::Hold(layer, _) => ModifierKey::Hold(layer, mods),
205            other => other,
206        }
207    }
208
209    /// Create a new [ModifierKey] that activates the layer when held,
210    ///  or makes it sticky when tapped.
211    pub const fn sticky(layer: LayerIndex) -> Self {
212        ModifierKey::Sticky(layer)
213    }
214
215    /// Create a new [ModifierKey] that toggles the given layer.
216    pub const fn toggle(layer: LayerIndex) -> Self {
217        ModifierKey::Toggle(layer)
218    }
219
220    /// Create a new [ModifierKey] that sets the active layers to the given slice of layers when pressed.
221    ///
222    /// Each LayerIndex in the slice must be at most [MAX_BITSET_LAYER].
223    pub const fn set_active_layers(layers: &[LayerIndex]) -> Self {
224        let mut bitset = LayerBitset::EMPTY;
225
226        let mut idx = 0;
227        while idx < layers.len() {
228            let layer = layers[idx] as usize;
229            if layer <= MAX_BITSET_LAYER {
230                bitset = bitset.insert(layer);
231            } else {
232                panic!("LayerIndex must be at most MAX_BITSET_LAYER");
233            }
234            idx += 1;
235        }
236
237        let mask = BITSET_MASK_ALL;
238        ModifierKey::SetActiveLayers(ModifierBitset {
239            layers: bitset,
240            mask,
241        })
242    }
243
244    /// Create a new [ModifierKey] that sets the active layers bitset.
245    pub const fn set_active_layers_from_bitset(bitset: LayerBitset) -> Self {
246        let mask = BITSET_MASK_ALL;
247        ModifierKey::SetActiveLayers(ModifierBitset {
248            layers: bitset,
249            mask,
250        })
251    }
252
253    /// Create a new [ModifierKey] that sets the active layers bitset.
254    pub const fn set_active_layers_from_bitset_with_mask(
255        layers: LayerBitset,
256        mask: LayerBitset,
257    ) -> Self {
258        ModifierKey::SetActiveLayers(ModifierBitset { layers, mask })
259    }
260
261    /// Create a new [ModifierKey] that sets the default layer.
262    pub const fn default(layer: LayerIndex) -> Self {
263        ModifierKey::Default(layer)
264    }
265
266    /// Create a [ModifierKey::Lock] that targets the highest currently active layer.
267    pub const fn lock() -> Self {
268        ModifierKey::Lock(LayerLockTarget::HighestActive)
269    }
270
271    /// Create a [ModifierKey::Lock] that targets a specific layer.
272    pub const fn lock_layer(layer: LayerIndex) -> Self {
273        ModifierKey::Lock(LayerLockTarget::Layer(layer))
274    }
275
276    /// Create a new [input::PressedKey] and [key::ScheduledEvent] for the given keymap index.
277    ///
278    /// Pressing a [ModifierKey::Hold] emits a [LayerEvent::Activated] event.
279    pub fn new_pressed_key(&self) -> (ModifierKeyState, Option<LayerEvent>) {
280        match self {
281            ModifierKey::Hold(layer, _) => {
282                (ModifierKeyState::new(), Some(LayerEvent::Activated(*layer)))
283            }
284            ModifierKey::Toggle(layer) => {
285                (ModifierKeyState::new(), Some(LayerEvent::Toggled(*layer)))
286            }
287            ModifierKey::Sticky(layer) => (
288                ModifierKeyState::sticky(),
289                Some(LayerEvent::StickyActivated(*layer)),
290            ),
291            ModifierKey::SetActiveLayers(modifier_bitset) => (
292                ModifierKeyState::new(),
293                Some(LayerEvent::Set(*modifier_bitset)),
294            ),
295            ModifierKey::Default(layer) => (
296                ModifierKeyState::new(),
297                Some(LayerEvent::SetDefault(*layer)),
298            ),
299            ModifierKey::Lock(target) => (
300                ModifierKeyState::new(),
301                Some(LayerEvent::LockInvert(*target)),
302            ),
303        }
304    }
305}
306
307impl From<LayerEvent> for () {
308    fn from(_: LayerEvent) -> Self {}
309}
310
311/// Style of activating a layer.
312#[derive(Debug, Clone, Copy, PartialEq)]
313pub enum ActivationStyle {
314    /// Regular layer activation.
315    Regular,
316    /// Sticky layer activation.
317    ///
318    /// Sticky layer activation is similar to sticky key modifiers.
319    /// The sticky layer activation is implemented using the sticky layer modifier key.
320    Sticky,
321}
322
323/// State of an individual layer: active or inactive.
324#[derive(Debug, Clone, Copy, PartialEq)]
325pub enum Activity {
326    /// The layer is active.
327    Active(ActivationStyle),
328    /// The layer is inactive.
329    Inactive,
330}
331
332impl Activity {
333    /// Returns true if the layer is active.
334    pub fn is_active(&self) -> bool {
335        matches!(self, Activity::Active(_))
336    }
337}
338
339/// Tracks state of active layers.
340pub trait LayerState: Copy + Debug {
341    /// Activate the given layer.
342    fn activate(&mut self, layer: LayerIndex, style: ActivationStyle);
343    /// Deactivate the given layer.
344    fn deactivate(&mut self, layer: LayerIndex);
345    /// Get the active layers, from highest active layer to lowest.
346    fn active_layers(&self) -> impl Iterator<Item = LayerIndex>;
347}
348
349impl<const L: usize> LayerState for [Activity; L] {
350    fn activate(&mut self, layer_index: LayerIndex, style: ActivationStyle) {
351        let layer_index: usize = layer_index as usize;
352        // 1-based layer indices; keymap construction / NCL validation must ensure range.
353        debug_assert!(
354            (1..=L).contains(&layer_index),
355            "layer must be in 1..={} (got {})",
356            L,
357            layer_index
358        );
359        self[layer_index - 1] = Activity::Active(style);
360    }
361
362    fn deactivate(&mut self, layer_index: LayerIndex) {
363        let layer_index: usize = layer_index as usize;
364        debug_assert!(
365            (1..=L).contains(&layer_index),
366            "layer must be in 1..={} (got {})",
367            L,
368            layer_index
369        );
370        self[layer_index - 1] = Activity::Inactive;
371    }
372
373    fn active_layers(&self) -> impl Iterator<Item = LayerIndex> {
374        self.iter().enumerate().rev().filter_map(|(i, activity)| {
375            if activity.is_active() {
376                Some(i as LayerIndex + 1)
377            } else {
378                None
379            }
380        })
381    }
382}
383
384struct ActiveLayersDebugHelper<'a, const LAYER_COUNT: usize> {
385    active_layers: &'a [Activity; LAYER_COUNT],
386}
387
388impl<const LAYER_COUNT: usize> core::fmt::Debug for ActiveLayersDebugHelper<'_, LAYER_COUNT> {
389    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
390        // Reverse-find the last Active layer to avoid printing large arrays.
391        let last_active_pos = self
392            .active_layers
393            .iter()
394            .rposition(|&pc| pc.is_active())
395            .map_or(0, |pos| pos + 1);
396        if last_active_pos < LAYER_COUNT {
397            f.debug_list()
398                .entries(&self.active_layers[..last_active_pos])
399                .finish_non_exhaustive()
400        } else {
401            f.debug_list().entries(&self.active_layers[..]).finish()
402        }
403    }
404}
405
406/// Conditional layer rule: activate [Self::then_layer] while every layer in
407/// [Self::if_layers] is active.
408///
409/// Layer indices are 1-based (same as [ModifierKey]).
410///  Bit `i` of [Self::if_layers] corresponds to layer `i` (same layout as [ModifierBitset]).
411#[repr(C)]
412#[derive(Debug, Deserialize, Clone, Copy, Eq, PartialEq)]
413pub struct ConditionalLayer {
414    /// Layer activated while the condition holds.
415    pub then_layer: LayerIndex,
416    /// Bitset of layers that must all be active.
417    pub if_layers: LayerBitset,
418}
419
420impl ConditionalLayer {
421    /// Constructs a rule from a then-layer and an if-layers bitset.
422    pub const fn new(then_layer: LayerIndex, if_layers: LayerBitset) -> Self {
423        Self {
424            then_layer,
425            if_layers,
426        }
427    }
428
429    /// Constructs a rule from a then-layer and if-layer indices.
430    pub const fn from_if_layers(then_layer: LayerIndex, if_layers: &[LayerIndex]) -> Self {
431        let mut bitset = LayerBitset::EMPTY;
432        let mut i = 0;
433        while i < if_layers.len() {
434            let layer = if_layers[i] as usize;
435            if layer <= MAX_BITSET_LAYER {
436                bitset = bitset.insert(layer);
437            }
438            i += 1;
439        }
440        Self {
441            then_layer,
442            if_layers: bitset,
443        }
444    }
445}
446
447/// Configuration for layered keys / sticky layers / conditional layers.
448#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
449pub struct Config<const CONDITIONAL_LAYER_COUNT: usize = 0> {
450    /// Timeout (ms) after which an unused sticky layer deactivates.
451    ///
452    /// When [None], sticky layers stay active until another key is used.
453    ///
454    /// The timeout starts when a sticky layer modifier is *released*
455    ///  without interruption (sticky committed).
456    /// If another key is pressed while sticky is active,
457    ///  the timeout is cancelled / ignored.
458    #[serde(default)]
459    pub sticky_timeout: Option<u16>,
460
461    /// Rules that activate a then-layer when all of their if-layers are active.
462    #[serde(default)]
463    pub conditional_layers: Slice<ConditionalLayer, CONDITIONAL_LAYER_COUNT>,
464}
465
466/// Default layered config (no sticky timeout, no conditional layers).
467pub const DEFAULT_CONFIG: Config = Config {
468    sticky_timeout: None,
469    conditional_layers: Slice::from_slice(&[]),
470};
471
472impl<const CONDITIONAL_LAYER_COUNT: usize> Config<CONDITIONAL_LAYER_COUNT> {
473    /// Constructs a new default [Config].
474    pub const fn new() -> Self {
475        Self {
476            sticky_timeout: None,
477            conditional_layers: Slice::from_slice(&[]),
478        }
479    }
480}
481
482impl<const CONDITIONAL_LAYER_COUNT: usize> Default for Config<CONDITIONAL_LAYER_COUNT> {
483    fn default() -> Self {
484        Self::new()
485    }
486}
487
488/// [crate::key::Context] for [LayeredKey] that tracks active layers.
489#[derive(Clone, Copy)]
490pub struct Context<const LAYER_COUNT: usize, const CONDITIONAL_LAYER_COUNT: usize = 0> {
491    config: Config<CONDITIONAL_LAYER_COUNT>,
492    default_layer: Option<LayerIndex>,
493    active_layers: [Activity; LAYER_COUNT],
494    /// Bitset of locked layers (bit `i` = layer `i` is locked).
495    ///
496    /// Locked layers stay active when a [ModifierKey::Hold] for that layer is released.
497    locked_layers: LayerBitset,
498    // Keymap index which was pressed while a layer was sticky.
499    pressed_keymap_index: Option<u16>,
500    // Invalidates pending sticky-timeout events when advanced.
501    sticky_timeout_id: u8,
502}
503
504impl<const LAYER_COUNT: usize, const CONDITIONAL_LAYER_COUNT: usize> Debug
505    for Context<LAYER_COUNT, CONDITIONAL_LAYER_COUNT>
506{
507    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
508        f.debug_struct("Context")
509            .field("config", &self.config)
510            .field("default_layer", &self.default_layer)
511            .field(
512                "active_layers",
513                &ActiveLayersDebugHelper {
514                    active_layers: &self.active_layers,
515                },
516            )
517            .field("locked_layers", &self.locked_layers)
518            .field("pressed_keymap_index", &self.pressed_keymap_index)
519            .field("sticky_timeout_id", &self.sticky_timeout_id)
520            .finish()
521    }
522}
523
524impl<const LAYER_COUNT: usize, const CONDITIONAL_LAYER_COUNT: usize>
525    Context<LAYER_COUNT, CONDITIONAL_LAYER_COUNT>
526{
527    /// Create a new [Context].
528    pub const fn new() -> Self {
529        Self::from_config(Config::new())
530    }
531
532    /// Constructs a context from the given config.
533    pub const fn from_config(config: Config<CONDITIONAL_LAYER_COUNT>) -> Self {
534        Context {
535            config,
536            default_layer: None,
537            active_layers: [Activity::Inactive; LAYER_COUNT],
538            locked_layers: LayerBitset::EMPTY,
539            pressed_keymap_index: None,
540            sticky_timeout_id: 0,
541        }
542    }
543
544    /// Re-construct from context's [Config], clearing active layers and sticky state.
545    pub fn reset(&mut self) {
546        *self = Self::from_config(self.config);
547    }
548
549    fn invalidate_sticky_timeouts(&mut self) {
550        self.sticky_timeout_id = self.sticky_timeout_id.wrapping_add(1);
551    }
552
553    fn deactivate_sticky_layer(&mut self, layer: LayerIndex) {
554        self.active_layers.deactivate(layer);
555        self.clear_layer_lock(layer);
556        self.pressed_keymap_index = None;
557        self.invalidate_sticky_timeouts();
558        self.apply_conditional_layers();
559    }
560
561    /// Returns true if `layer` is currently locked.
562    pub fn is_layer_locked(&self, layer: LayerIndex) -> bool {
563        self.locked_layers.contains(layer as usize)
564    }
565
566    fn set_layer_lock(&mut self, layer: LayerIndex) {
567        self.locked_layers = self.locked_layers.insert(layer as usize);
568    }
569
570    fn clear_layer_lock(&mut self, layer: LayerIndex) {
571        self.locked_layers = self.locked_layers.remove(layer as usize);
572    }
573
574    /// Highest active layer index, if any (1-based layers only).
575    fn highest_active_layer(&self) -> Option<LayerIndex> {
576        self.active_layers.active_layers().next()
577    }
578
579    /// Invert lock on `layer`.
580    ///
581    /// If unlocked: lock and turn the layer on.
582    /// If locked: unlock and turn the layer off.
583    ///
584    /// `layer` must be a valid 1-based index (`1..=LAYER_COUNT`); debug builds assert this
585    /// via [LayerState::activate] / [LayerState::deactivate].
586    fn lock_invert(&mut self, layer: LayerIndex) {
587        if self.is_layer_locked(layer) {
588            self.clear_layer_lock(layer);
589            self.active_layers.deactivate(layer);
590            if self.sticky_layer() == Some(layer) {
591                self.pressed_keymap_index = None;
592                self.invalidate_sticky_timeouts();
593            }
594        } else {
595            self.set_layer_lock(layer);
596            self.active_layers.activate(layer, ActivationStyle::Regular);
597            // Lock supersedes sticky wait on this layer.
598            if self.sticky_layer() == Some(layer) {
599                self.pressed_keymap_index = None;
600                self.invalidate_sticky_timeouts();
601            } else {
602                self.invalidate_sticky_timeouts();
603            }
604        }
605        self.apply_conditional_layers();
606    }
607
608    /// Bitset of currently active layers (bit `i` = layer `i`).
609    fn active_layers_bitset(&self) -> LayerBitset {
610        let max_layer = 1 + LAYER_COUNT.min(MAX_BITSET_LAYER);
611        (1..max_layer).fold(LayerBitset::EMPTY, |bits, li| {
612            if self.active_layers[li - 1].is_active() {
613                bits.insert(li)
614            } else {
615                bits
616            }
617        })
618    }
619
620    /// One pass over conditional rules; returns whether any then-layer changed.
621    fn apply_conditional_layers_once(&mut self) -> bool {
622        // Copy rules so we can mutate active_layers while iterating.
623        let rules = self.config.conditional_layers;
624        let active = self.active_layers_bitset();
625        rules.as_slice().iter().fold(false, |changed, rule| {
626            let should = active.is_superset_of(rule.if_layers);
627            let is_active = active.contains(rule.then_layer as usize);
628            if should == is_active {
629                changed
630            } else if should {
631                self.active_layers
632                    .activate(rule.then_layer, ActivationStyle::Regular);
633                true
634            } else if self.is_layer_locked(rule.then_layer) {
635                // Locked layers stay active even when conditional if-layers drop.
636                changed
637            } else {
638                self.active_layers.deactivate(rule.then_layer);
639                true
640            }
641        })
642    }
643
644    /// Evaluate conditional layer rules until stable, or up to one pass per rule.
645    ///
646    /// Nested rules (a then-layer used as an if-layer of another rule)
647    ///  settle without depending on rule definition order.
648    /// The pass limit bounds the work for a pure dependency chain
649    ///  and prevents non-termination
650    ///  if rules disagree about the same then-layer.
651    fn apply_conditional_layers(&mut self) {
652        for _ in 0..CONDITIONAL_LAYER_COUNT {
653            if !self.apply_conditional_layers_once() {
654                break;
655            }
656        }
657    }
658}
659
660impl<const LAYER_COUNT: usize, const CONDITIONAL_LAYER_COUNT: usize> Default
661    for Context<LAYER_COUNT, CONDITIONAL_LAYER_COUNT>
662{
663    fn default() -> Self {
664        Self::new()
665    }
666}
667
668impl<const LAYER_COUNT: usize, const CONDITIONAL_LAYER_COUNT: usize>
669    Context<LAYER_COUNT, CONDITIONAL_LAYER_COUNT>
670{
671    /// Get the active layers.
672    pub fn layer_state(&self) -> &[Activity; LAYER_COUNT] {
673        &self.active_layers
674    }
675
676    fn sticky_layer(&self) -> Option<LayerIndex> {
677        self.active_layers
678            .iter()
679            .position(|&a| a == Activity::Active(ActivationStyle::Sticky))
680            .map(|i| i as LayerIndex + 1)
681    }
682
683    /// Updates the context with the [LayerEvent].
684    ///
685    /// Returns scheduled events (e.g. sticky timeout).
686    fn handle_layer_event(&mut self, event: LayerEvent) -> key::KeyEvents<LayerEvent> {
687        match event {
688            LayerEvent::Activated(layer) => {
689                if self.is_layer_locked(layer) {
690                    // Hold pressed while layer is locked: unlock and turn off.
691                    self.clear_layer_lock(layer);
692                    self.active_layers.deactivate(layer);
693                } else {
694                    self.active_layers.activate(layer, ActivationStyle::Regular);
695                }
696                // Sticky cancelled / converted to hold — drop any sticky timeout.
697                self.invalidate_sticky_timeouts();
698                self.apply_conditional_layers();
699                key::KeyEvents::no_events()
700            }
701            LayerEvent::Deactivated(layer) => {
702                if self.is_layer_locked(layer) {
703                    // Locked layers stay on when the Hold that activated them is released.
704                    key::KeyEvents::no_events()
705                } else {
706                    self.active_layers.deactivate(layer);
707                    self.invalidate_sticky_timeouts();
708                    self.apply_conditional_layers();
709                    key::KeyEvents::no_events()
710                }
711            }
712            LayerEvent::StickyActivated(layer) => {
713                self.active_layers.activate(layer, ActivationStyle::Sticky);
714                self.pressed_keymap_index = None;
715                // Previous sticky wait is superseded while this sticky key is held.
716                self.invalidate_sticky_timeouts();
717                self.apply_conditional_layers();
718                key::KeyEvents::no_events()
719            }
720            LayerEvent::StickyReleased => {
721                // Sticky key released without interruption: layer stays sticky.
722                // Arm optional timeout for "no next key pressed".
723                if self.sticky_layer().is_none() {
724                    key::KeyEvents::no_events()
725                } else {
726                    self.invalidate_sticky_timeouts();
727                    let timeout_id = self.sticky_timeout_id;
728                    match self.config.sticky_timeout {
729                        Some(timeout) => {
730                            key::KeyEvents::scheduled_event(key::ScheduledEvent::after(
731                                timeout,
732                                key::Event::key_event(0, LayerEvent::StickyTimeout(timeout_id)),
733                            ))
734                        }
735                        None => key::KeyEvents::no_events(),
736                    }
737                }
738            }
739            LayerEvent::StickyTimeout(timeout_id) => {
740                if timeout_id == self.sticky_timeout_id && self.pressed_keymap_index.is_none() {
741                    if let Some(layer) = self.sticky_layer() {
742                        // deactivate_sticky_layer applies conditionals.
743                        self.deactivate_sticky_layer(layer);
744                    }
745                }
746                key::KeyEvents::no_events()
747            }
748            LayerEvent::Toggled(layer) => {
749                if self.active_layers[layer as usize - 1].is_active() {
750                    self.active_layers.deactivate(layer);
751                    self.clear_layer_lock(layer);
752                } else {
753                    self.active_layers.activate(layer, ActivationStyle::Regular);
754                }
755                self.apply_conditional_layers();
756                key::KeyEvents::no_events()
757            }
758            LayerEvent::Set(ModifierBitset { layers, mask }) => {
759                let max_layer = 1 + LAYER_COUNT.min(MAX_BITSET_LAYER);
760
761                // layer 0 is always active.
762                for li in 1..max_layer {
763                    if mask.contains(li) {
764                        if layers.contains(li) {
765                            self.active_layers
766                                .activate(li as LayerIndex, ActivationStyle::Regular);
767                        } else {
768                            self.active_layers.deactivate(li as LayerIndex);
769                            self.clear_layer_lock(li as LayerIndex);
770                        }
771                    }
772                }
773                self.apply_conditional_layers();
774                key::KeyEvents::no_events()
775            }
776            LayerEvent::SetDefault(0) => {
777                self.default_layer = None;
778                key::KeyEvents::no_events()
779            }
780            LayerEvent::SetDefault(layer) => {
781                self.default_layer = Some(layer);
782                key::KeyEvents::no_events()
783            }
784            LayerEvent::LockInvert(target) => {
785                let layer = match target {
786                    LayerLockTarget::HighestActive => self.highest_active_layer(),
787                    LayerLockTarget::Layer(layer) => Some(layer),
788                };
789                if let Some(layer) = layer {
790                    self.lock_invert(layer);
791                }
792                key::KeyEvents::no_events()
793            }
794        }
795    }
796
797    /// Updates the context with the [key::Event].
798    fn handle_event(&mut self, event: key::Event<LayerEvent>) -> key::KeyEvents<LayerEvent> {
799        match event {
800            key::Event::Input(input::Event::Press { keymap_index, .. }) => {
801                if let Some(sticky_layer_index) = self.sticky_layer() {
802                    if self.pressed_keymap_index.is_some() {
803                        // The sticky layer modifier has already been used;
804                        // the sticky layer should be deactivated for subsequent presses.
805                        self.deactivate_sticky_layer(sticky_layer_index);
806                    } else {
807                        // Next key is using the sticky layer; cancel timeout.
808                        self.invalidate_sticky_timeouts();
809                        self.pressed_keymap_index = Some(keymap_index);
810                    }
811                }
812                key::KeyEvents::no_events()
813            }
814            key::Event::Input(input::Event::Release { keymap_index, .. }) => {
815                if let Some(sticky_layer_index) = self.sticky_layer() {
816                    if self.pressed_keymap_index == Some(keymap_index) {
817                        self.deactivate_sticky_layer(sticky_layer_index);
818                    }
819                }
820                key::KeyEvents::no_events()
821            }
822            key::Event::Key { key_event, .. } => self.handle_layer_event(key_event),
823            _ => key::KeyEvents::no_events(),
824        }
825    }
826}
827
828impl<const LAYER_COUNT: usize, const CONDITIONAL_LAYER_COUNT: usize> key::Context
829    for Context<LAYER_COUNT, CONDITIONAL_LAYER_COUNT>
830{
831    type Event = LayerEvent;
832
833    fn handle_event(&mut self, event: key::Event<Self::Event>) -> key::KeyEvents<Self::Event> {
834        self.handle_event(event)
835    }
836
837    fn reset(&mut self) {
838        Context::reset(self);
839    }
840}
841
842/// Errors when constructing Layers.
843#[derive(Debug, Clone, Copy, PartialEq)]
844pub enum LayersError {
845    /// Trying to construct more layers than the Layers can store.
846    Overflow,
847}
848
849impl core::fmt::Display for LayersError {
850    // This trait requires `fmt` with this exact signature.
851    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
852        write!(f, "LayersError::Overflow")
853    }
854}
855
856/// Trait for layers of [LayeredKey].
857pub trait Layers<R>: Copy + Debug {
858    /// Get the highest active key, if any, for the given [LayerState].
859    fn highest_active_key<LS: LayerState>(
860        &self,
861        layer_state: &LS,
862        default_layer: Option<LayerIndex>,
863    ) -> Option<(LayerIndex, R)>;
864    /// Constructs layers; return Err if the iterable has more keys than Layers can store.
865    fn from_iterable<I: IntoIterator<Item = Option<R>>>(keys: I) -> Result<Self, LayersError>;
866}
867
868impl<R: Copy + Debug, const L: usize> Layers<R> for [Option<R>; L] {
869    fn highest_active_key<LS: LayerState>(
870        &self,
871        layer_state: &LS,
872        default_layer: Option<LayerIndex>,
873    ) -> Option<(LayerIndex, R)> {
874        for layer_index in layer_state.active_layers() {
875            if self[layer_index as usize - 1].is_some() {
876                return self[layer_index as usize - 1].map(|k| (layer_index, k));
877            }
878        }
879
880        match default_layer {
881            Some(layer_index) if self[layer_index as usize - 1].is_some() => {
882                self[layer_index as usize - 1].map(|k| (layer_index, k))
883            }
884            _ => None,
885        }
886    }
887
888    fn from_iterable<I: IntoIterator<Item = Option<R>>>(keys: I) -> Result<Self, LayersError> {
889        let mut layered: [Option<R>; L] = [None; L];
890        for (i, maybe_key) in keys.into_iter().enumerate() {
891            if i < L {
892                layered[i] = maybe_key;
893            } else {
894                return Err(LayersError::Overflow);
895            }
896        }
897        Ok(layered)
898    }
899}
900
901/// Constructs an array of keys for the given array.
902pub const fn layered_keys<K: Copy, const L: usize, const LAYER_COUNT: usize>(
903    keys: [Option<K>; L],
904) -> [Option<K>; LAYER_COUNT] {
905    let mut layered: [Option<K>; LAYER_COUNT] = [None; LAYER_COUNT];
906
907    if L > LAYER_COUNT {
908        panic!("Too many layers for layered_keys");
909    }
910
911    let mut i = 0;
912
913    while i < L {
914        layered[i] = keys[i];
915        i += 1;
916    }
917
918    layered
919}
920
921/// A key whose behavior depends on which layer is active.
922#[derive(Debug, Deserialize, Clone, Copy, PartialEq)]
923pub struct LayeredKey<R: Copy + Debug + PartialEq, const LAYER_COUNT: usize> {
924    /// The base key, used when no layers are active.
925    pub base: R,
926    /// The layered keys, used when the corresponding layer is active.
927    ///
928    /// `None` is full transparency for that layer (`K.TTTT` / `null` in JSON).
929    #[serde(deserialize_with = "deserialize_layered")]
930    #[serde(bound(deserialize = "R: Deserialize<'de>"))]
931    pub layered: [Option<R>; LAYER_COUNT],
932    /// Layers that exit when their cell is a hole (`None`) and is skipped.
933    ///
934    /// Bit `i` is layer index `i` (same layout as [LayerBitset] / `SetActiveLayers`).
935    /// Used for FAK-style transparent layer exit (`K.tlex`): skip the hole, schedule
936    ///  [LayerEvent::Deactivated] for a non-persistent activation, and continue the walk.
937    /// Ordinary transparency leaves this empty.
938    #[serde(default)]
939    pub exit_on_skip: LayerBitset,
940}
941
942/// Deserialize a [Layers].
943fn deserialize_layered<'de, R, L: Layers<R>, D>(deserializer: D) -> Result<L, D::Error>
944where
945    R: Deserialize<'de>,
946    D: serde::Deserializer<'de>,
947{
948    let keys_vec: heapless::Vec<Option<R>, 64> = Deserialize::deserialize(deserializer)?;
949
950    L::from_iterable(keys_vec).map_err(serde::de::Error::custom)
951}
952
953impl<R: Copy + Debug + PartialEq, const LAYER_COUNT: usize> LayeredKey<R, LAYER_COUNT> {
954    /// Constructs a new [LayeredKey] with no exit-on-skip holes.
955    pub const fn new<const L: usize>(base: R, layered: [Option<R>; L]) -> Self {
956        let layered = layered_keys(layered);
957        Self {
958            base,
959            layered,
960            exit_on_skip: LayerBitset::EMPTY,
961        }
962    }
963
964    /// Sets layers that deactivate when a transparent cell is skipped on that layer.
965    pub const fn with_exit_on_skip(self, exit_on_skip: LayerBitset) -> Self {
966        Self {
967            exit_on_skip,
968            ..self
969        }
970    }
971}
972
973/// Whether exit-on-skip should schedule [LayerEvent::Deactivated] for `layer`.
974///
975/// Only non-persistent activations (regular hold/toggle and sticky).
976/// A layer that is only the default (not Regular/Sticky-active) is not cleared.
977///
978/// `layer` is a 1-based [LayerIndex] (same as [LayerState::activate]): array
979///  slots and `exit_on_skip` cells use `layer - 1` / bit `layer`.
980fn is_exit_deactivatable<const LAYER_COUNT: usize, const CONDITIONAL_LAYER_COUNT: usize>(
981    context: &Context<LAYER_COUNT, CONDITIONAL_LAYER_COUNT>,
982    layer: LayerIndex,
983) -> bool {
984    let layer_index = layer as usize;
985    (1..=LAYER_COUNT).contains(&layer_index)
986        && matches!(
987            context.active_layers[layer_index - 1],
988            Activity::Active(ActivationStyle::Regular | ActivationStyle::Sticky)
989        )
990}
991
992impl<R: Copy + Debug + PartialEq, const LAYER_COUNT: usize> LayeredKey<R, LAYER_COUNT> {
993    /// Presses the key: highest defined active binding, with exit-on-skip side effects.
994    fn new_pressed_key<const CONDITIONAL_LAYER_COUNT: usize>(
995        &self,
996        context: &Context<LAYER_COUNT, CONDITIONAL_LAYER_COUNT>,
997        keymap_index: u16,
998    ) -> (key::NewPressedKey<R>, key::KeyEvents<LayerEvent>) {
999        // Active layers high → low, in range for this key's layered array.
1000        // `layer_index` stays 1-based; array access is always `layer_index - 1`.
1001        let active_in_range = || {
1002            context
1003                .layer_state()
1004                .active_layers()
1005                .filter(|&layer_index| {
1006                    let layer_index = layer_index as usize;
1007                    (1..=LAYER_COUNT).contains(&layer_index)
1008                })
1009        };
1010
1011        // First defined cell among active layers (and its 1-based layer index).
1012        let picked = active_in_range().find_map(|layer_index| {
1013            self.layered[layer_index as usize - 1].map(|r| (layer_index, r))
1014        });
1015
1016        // Exit holes strictly above the pick (or all active holes if none defined).
1017        // `exit_on_skip` bits are 1-based layer indices (same as [LayerBitset]).
1018        let events = active_in_range()
1019            .take_while(|&layer_index| {
1020                picked
1021                    .map(|(picked_layer, _)| layer_index != picked_layer)
1022                    .unwrap_or(true)
1023            })
1024            .filter(|&layer_index| {
1025                self.layered[layer_index as usize - 1].is_none()
1026                    && self.exit_on_skip.contains(layer_index as usize)
1027                    && is_exit_deactivatable(context, layer_index)
1028            })
1029            .fold(key::KeyEvents::no_events(), |mut events, layer_index| {
1030                events.add_event(key::Event::key_event(
1031                    keymap_index,
1032                    LayerEvent::Deactivated(layer_index),
1033                ));
1034                events
1035            });
1036
1037        let passthrough_ref = picked
1038            .map(|(_, r)| r)
1039            .or_else(|| {
1040                context.default_layer.and_then(|layer_index| {
1041                    let layer_index = layer_index as usize;
1042                    (1..=LAYER_COUNT)
1043                        .contains(&layer_index)
1044                        .then(|| self.layered[layer_index - 1])
1045                        .flatten()
1046                })
1047            })
1048            .unwrap_or(self.base);
1049
1050        (key::NewPressedKey::key(passthrough_ref), events)
1051    }
1052}
1053
1054/// Events from [ModifierKey] which affect [Context].
1055#[derive(Debug, Clone, Copy, Eq, PartialEq)]
1056pub enum LayerEvent {
1057    /// Activates the given layer (1-based; see [LayerIndex]).
1058    Activated(LayerIndex),
1059    /// Deactivates the given layer (1-based; see [LayerIndex]).
1060    Deactivated(LayerIndex),
1061    /// Toggles the given layer (1-based; see [LayerIndex]).
1062    Toggled(LayerIndex),
1063    /// Activates the given layer as sticky (on sticky-mod press).
1064    StickyActivated(LayerIndex),
1065    /// Sticky layer modifier released without interruption (sticky committed).
1066    StickyReleased,
1067    /// Sticky layer timed out while unused.
1068    ///
1069    /// The payload is a generation id used to ignore stale timeouts.
1070    StickyTimeout(u8),
1071    /// Sets the active layers to the given set of layers.
1072    Set(ModifierBitset),
1073    /// Changes the default layer.
1074    SetDefault(LayerIndex),
1075    /// Invert lock on the given [LayerLockTarget].
1076    ///
1077    /// See [ModifierKey::Lock].
1078    LockInvert(LayerLockTarget),
1079}
1080
1081/// Struct for layer system pending key state. (No pending state).
1082#[derive(Debug, Clone, Copy, PartialEq)]
1083pub struct PendingKeyState;
1084
1085/// Whether the pressed Sticky modifier key is "sticky" or "regular".
1086#[derive(Debug, Clone, Copy, Eq, PartialEq)]
1087pub enum Behavior {
1088    /// Key state is "sticky". (Will activate sticky modifier when released).
1089    Sticky,
1090    /// Key state is "regular". (No sticky modifiers activated when released).
1091    Regular,
1092}
1093
1094/// [crate::key::KeyState] of [ModifierKey].
1095#[derive(Debug, Clone, Copy, PartialEq)]
1096pub struct ModifierKeyState {
1097    behavior: Behavior,
1098}
1099
1100impl Default for ModifierKeyState {
1101    fn default() -> Self {
1102        Self::new()
1103    }
1104}
1105
1106impl ModifierKeyState {
1107    /// Constructs a regular ModifierKeyState
1108    pub fn new() -> Self {
1109        Self {
1110            behavior: Behavior::Regular,
1111        }
1112    }
1113
1114    /// Constructs a sticky ModifierKeyState
1115    pub fn sticky() -> Self {
1116        Self {
1117            behavior: Behavior::Sticky,
1118        }
1119    }
1120
1121    /// Handle the given event for the given key.
1122    pub fn handle_event(
1123        &mut self,
1124        keymap_index: u16,
1125        event: key::Event<LayerEvent>,
1126        key: &ModifierKey,
1127    ) -> Option<LayerEvent> {
1128        match key {
1129            ModifierKey::Hold(layer, _) => match event {
1130                key::Event::Input(input::Event::Release { keymap_index: ki }) => {
1131                    if keymap_index == ki {
1132                        Some(LayerEvent::Deactivated(*layer))
1133                    } else {
1134                        None
1135                    }
1136                }
1137                _ => None,
1138            },
1139            ModifierKey::Toggle(_) => None,
1140            ModifierKey::Sticky(layer) => match event {
1141                key::Event::Input(input::Event::Press { keymap_index: _ }) => {
1142                    if self.behavior == Behavior::Sticky {
1143                        // Another key pressed while sticky modifier is held; make self regular
1144                        self.behavior = Behavior::Regular;
1145                        // Change the layer state to *regular*
1146                        Some(LayerEvent::Activated(*layer))
1147                    } else {
1148                        None
1149                    }
1150                }
1151                key::Event::Input(input::Event::Release { keymap_index: ki })
1152                    if keymap_index == ki =>
1153                {
1154                    match self.behavior {
1155                        Behavior::Regular => Some(LayerEvent::Deactivated(*layer)),
1156                        // Sticky key tapped (released without interruption):
1157                        // layer stays sticky; arm optional timeout via context.
1158                        Behavior::Sticky => Some(LayerEvent::StickyReleased),
1159                    }
1160                }
1161                _ => None,
1162            },
1163            ModifierKey::SetActiveLayers(_modifier_bitset) => None,
1164            ModifierKey::Default(layer) => match event {
1165                key::Event::Input(input::Event::Release { keymap_index: ki }) => {
1166                    if keymap_index == ki {
1167                        Some(LayerEvent::SetDefault(*layer))
1168                    } else {
1169                        None
1170                    }
1171                }
1172                _ => None,
1173            },
1174            ModifierKey::Lock(_) => None,
1175        }
1176    }
1177}
1178
1179/// The [key::System] implementation for layer system keys.
1180///
1181/// `CONDITIONAL_LAYER_COUNT` is carried so
1182///  the system's context matches the layered [Config] / [Context] used by the keymap
1183///  (rules live on context, not system).
1184#[derive(Debug, Clone, Copy, PartialEq)]
1185pub struct System<
1186    R: Copy + Debug + PartialEq,
1187    ModifierKeys: Index<usize, Output = ModifierKey>,
1188    LayeredKeys: Index<usize, Output = LayeredKey<R, LAYER_COUNT>>,
1189    const LAYER_COUNT: usize,
1190    const CONDITIONAL_LAYER_COUNT: usize = 0,
1191> {
1192    modifier_keys: ModifierKeys,
1193    layered_keys: LayeredKeys,
1194}
1195
1196impl<
1197        R: Copy + Debug + PartialEq,
1198        ModifierKeys: Index<usize, Output = ModifierKey>,
1199        LayeredKeys: Index<usize, Output = LayeredKey<R, LAYER_COUNT>>,
1200        const LAYER_COUNT: usize,
1201        const CONDITIONAL_LAYER_COUNT: usize,
1202    > System<R, ModifierKeys, LayeredKeys, LAYER_COUNT, CONDITIONAL_LAYER_COUNT>
1203{
1204    /// Constructs a new [System] with the given key data.
1205    pub const fn new(modifier_keys: ModifierKeys, layered_keys: LayeredKeys) -> Self {
1206        Self {
1207            modifier_keys,
1208            layered_keys,
1209        }
1210    }
1211}
1212
1213impl<
1214        R: Copy + Debug + PartialEq,
1215        ModifierKeys: Debug + Index<usize, Output = ModifierKey>,
1216        LayeredKeys: Debug + Index<usize, Output = LayeredKey<R, LAYER_COUNT>>,
1217        const LAYER_COUNT: usize,
1218        const CONDITIONAL_LAYER_COUNT: usize,
1219    > key::System<R>
1220    for System<R, ModifierKeys, LayeredKeys, LAYER_COUNT, CONDITIONAL_LAYER_COUNT>
1221{
1222    type Ref = Ref;
1223    type Context = Context<LAYER_COUNT, CONDITIONAL_LAYER_COUNT>;
1224    type Event = LayerEvent;
1225    type PendingKeyState = PendingKeyState;
1226    type KeyState = ModifierKeyState;
1227
1228    fn new_pressed_key(
1229        &self,
1230        keymap_index: u16,
1231        context: &Self::Context,
1232        key_ref: Ref,
1233    ) -> (
1234        key::PressedKeyResult<R, Self::PendingKeyState, Self::KeyState>,
1235        key::KeyEvents<Self::Event>,
1236    ) {
1237        match key_ref {
1238            Ref::Modifier(mod_key_index) => {
1239                let key = self.modifier_keys[mod_key_index as usize];
1240                let (m_ks, maybe_lmod_ev) = key.new_pressed_key();
1241                let pks = key::PressedKeyResult::Resolved(m_ks);
1242                let pke = match maybe_lmod_ev {
1243                    Some(lmod_ev) => {
1244                        key::KeyEvents::event(key::Event::key_event(keymap_index, lmod_ev))
1245                    }
1246                    None => key::KeyEvents::no_events(),
1247                };
1248                (pks, pke)
1249            }
1250            Ref::Layered(i) => {
1251                let key = &self.layered_keys[i as usize];
1252                let (npk, pke) = key.new_pressed_key(context, keymap_index);
1253                (key::PressedKeyResult::NewPressedKey(npk), pke)
1254            }
1255        }
1256    }
1257
1258    fn update_pending_state(
1259        &self,
1260        _pending_state: &mut Self::PendingKeyState,
1261        _keymap_index: u16,
1262        _context: &Self::Context,
1263        _key_ref: Ref,
1264        _event: key::Event<Self::Event>,
1265    ) -> (Option<key::NewPressedKey<R>>, key::KeyEvents<Self::Event>) {
1266        panic!()
1267    }
1268
1269    fn update_state(
1270        &self,
1271        key_state: &mut Self::KeyState,
1272        key_ref: &Self::Ref,
1273        _context: &Self::Context,
1274        keymap_index: u16,
1275        event: key::Event<Self::Event>,
1276    ) -> key::KeyEvents<Self::Event> {
1277        match key_ref {
1278            Ref::Modifier(mod_key_index) => {
1279                let mod_key = &self.modifier_keys[*mod_key_index as usize];
1280                let maybe_ev = key_state.handle_event(keymap_index, event, mod_key);
1281                maybe_ev.map_or(key::KeyEvents::no_events(), |ev| {
1282                    key::KeyEvents::event(key::Event::key_event(keymap_index, ev))
1283                })
1284            }
1285            _ => key::KeyEvents::no_events(),
1286        }
1287    }
1288
1289    fn key_output(
1290        &self,
1291        key_ref: &Self::Ref,
1292        _key_state: &Self::KeyState,
1293    ) -> Option<key::KeyOutput> {
1294        if let Ref::Modifier(mod_key_index) = key_ref {
1295            let key = self.modifier_keys[*mod_key_index as usize];
1296            match key {
1297                ModifierKey::Hold(_, mods) if mods != key::KeyboardModifiers::NONE => {
1298                    Some(key::KeyOutput::from_key_modifiers(mods))
1299                }
1300                _ => None,
1301            }
1302        } else {
1303            None
1304        }
1305    }
1306}
1307
1308#[cfg(test)]
1309#[allow(clippy::unwrap_used, clippy::expect_used)]
1310mod tests {
1311    use super::*;
1312
1313    use crate::key::keyboard;
1314
1315    use crate::key::System as _;
1316
1317    const LAYER_COUNT: usize = 8;
1318
1319    type Context = super::Context<LAYER_COUNT>;
1320
1321    #[test]
1322    fn test_sizeof_ref() {
1323        assert_eq!(2, core::mem::size_of::<Ref>());
1324    }
1325
1326    #[test]
1327    fn test_sizeof_modifier_bitset() {
1328        // Two LayerBitset (u32) fields.
1329        assert_eq!(8, core::mem::size_of::<ModifierBitset>());
1330    }
1331
1332    #[test]
1333    fn test_sizeof_event() {
1334        // Firmware RAM budget on 32-bit targets: LayerEvent::Set is a ModifierBitset.
1335        assert_eq!(12, core::mem::size_of::<LayerEvent>());
1336    }
1337
1338    #[test]
1339    fn test_layer_bitset_capacity() {
1340        assert_eq!(32, LayerBitset::BITS);
1341        assert_eq!(31, MAX_BITSET_LAYER);
1342        assert!(LayerBitset::EMPTY.insert(31).contains(31));
1343        assert!(!LayerBitset::EMPTY.insert(32).contains(32));
1344        assert!(!LayerBitset::ALL.remove(31).contains(31));
1345        assert!(LayerBitset::ALL.is_superset_of(LayerBitset::from_bits(0b1010)));
1346    }
1347
1348    #[test]
1349    fn deserialize_set_active_layers_record_json() {
1350        let key: ModifierKey =
1351            serde_json::from_str(r#"{"SetActiveLayers": {"layers": 5, "mask": 3}}"#).unwrap();
1352        assert_eq!(
1353            ModifierKey::SetActiveLayers(ModifierBitset {
1354                layers: LayerBitset::from_bits(5),
1355                mask: LayerBitset::from_bits(3),
1356            }),
1357            key,
1358        );
1359
1360        let key: ModifierKey =
1361            serde_json::from_str(r#"{"SetActiveLayers": {"layers": 5}}"#).unwrap();
1362        assert_eq!(
1363            ModifierKey::SetActiveLayers(ModifierBitset {
1364                layers: LayerBitset::from_bits(5),
1365                mask: BITSET_MASK_ALL,
1366            }),
1367            key,
1368        );
1369    }
1370
1371    #[test]
1372    fn test_pressing_hold_modifier_key_emits_event_activate_layer() {
1373        let layer = 1;
1374        let key = ModifierKey::hold(layer);
1375
1376        let (_pressed_key, layer_event) = key.new_pressed_key();
1377
1378        assert_eq!(Some(LayerEvent::Activated(layer)), layer_event);
1379    }
1380
1381    #[test]
1382    fn test_releasing_hold_modifier_key_emits_event_deactivate_layer() {
1383        // Assemble: press a Hold layer modifier key
1384        let layer = 1;
1385        let key = ModifierKey::hold(layer);
1386        let keymap_index = 9; // arbitrary
1387        let (mut pressed_key_state, _) = key.new_pressed_key();
1388
1389        // Act: the modifier key handles "release key" input event
1390        let actual_events = pressed_key_state
1391            .handle_event(
1392                keymap_index,
1393                key::Event::Input(input::Event::Release { keymap_index }),
1394                &key,
1395            )
1396            .into_iter()
1397            .next();
1398
1399        // Assert: the pressed key should have emitted a layer deactivation event
1400        let first_ev = actual_events.into_iter().next();
1401        if let Some(actual_layer_event) = first_ev {
1402            let expected_layer_event = LayerEvent::Deactivated(layer);
1403            assert_eq!(expected_layer_event, actual_layer_event);
1404        } else {
1405            panic!("Expected Some LayerDeactivated event");
1406        }
1407    }
1408
1409    #[test]
1410    fn test_releasing_different_hold_modifier_key_does_not_emit_event() {
1411        // Assemble: press a Hold layer modifier key
1412        let layer = 1;
1413        let key = ModifierKey::hold(layer);
1414        let keymap_index = 9; // arbitrary
1415        let (mut pressed_key_state, _) = key.new_pressed_key();
1416
1417        // Act: the modifier key handles "release key" input event for a different key
1418        let different_keymap_index = keymap_index + 1;
1419        let different_key_released_ev = key::Event::Input(input::Event::Release {
1420            keymap_index: different_keymap_index,
1421        });
1422        let actual_events = pressed_key_state
1423            .handle_event(keymap_index, different_key_released_ev, &key)
1424            .into_iter()
1425            .next();
1426
1427        // Assert: the pressed key should not emit an event
1428        if actual_events.is_some() {
1429            panic!("Expected no event emitted");
1430        }
1431    }
1432
1433    #[test]
1434    fn test_context_handling_event_adjusts_active_layers() {
1435        let mut context = Context::default();
1436
1437        context.handle_layer_event(LayerEvent::Activated(2));
1438
1439        let actual_active_layers = &context.active_layers[0..3];
1440        assert_eq!(
1441            &[
1442                Activity::Inactive,
1443                Activity::Active(ActivationStyle::Regular),
1444                Activity::Inactive
1445            ],
1446            actual_active_layers
1447        );
1448    }
1449
1450    /// Classic tri-layer: layer 3 active iff layers 1 and 2 are both active.
1451    fn tri_layer_context() -> super::Context<LAYER_COUNT, 1> {
1452        super::Context::from_config(Config {
1453            sticky_timeout: None,
1454            conditional_layers: Slice::from_slice(&[ConditionalLayer::from_if_layers(3, &[1, 2])]),
1455        })
1456    }
1457
1458    #[test]
1459    fn test_conditional_layer_partial_if_layers_does_not_activate_then() {
1460        // Assemble
1461        let mut context = tri_layer_context();
1462
1463        // Act
1464        context.handle_layer_event(LayerEvent::Activated(1));
1465
1466        // Assert
1467        assert_eq!(Activity::Inactive, context.active_layers[2]);
1468    }
1469
1470    #[test]
1471    fn test_conditional_layer_activates_when_all_if_layers_active() {
1472        // Assemble
1473        let mut context = tri_layer_context();
1474        context.handle_layer_event(LayerEvent::Activated(1));
1475
1476        // Act
1477        context.handle_layer_event(LayerEvent::Activated(2));
1478
1479        // Assert
1480        assert_eq!(
1481            Activity::Active(ActivationStyle::Regular),
1482            context.active_layers[2]
1483        );
1484    }
1485
1486    #[test]
1487    fn test_conditional_layer_deactivates_when_if_layer_releases() {
1488        // Assemble
1489        let mut context = tri_layer_context();
1490        context.handle_layer_event(LayerEvent::Activated(1));
1491        context.handle_layer_event(LayerEvent::Activated(2));
1492
1493        // Act
1494        context.handle_layer_event(LayerEvent::Deactivated(1));
1495
1496        // Assert
1497        assert_eq!(Activity::Inactive, context.active_layers[2]);
1498    }
1499
1500    #[test]
1501    fn test_locked_conditional_layer_stays_active_when_if_layers_release() {
1502        // Assemble: lower+raise → adjust; lock adjust while both if-layers held
1503        let mut context = tri_layer_context();
1504        context.handle_layer_event(LayerEvent::Activated(1));
1505        context.handle_layer_event(LayerEvent::Activated(2));
1506        assert!(context.active_layers[2].is_active());
1507        context.handle_layer_event(LayerEvent::LockInvert(LayerLockTarget::Layer(3)));
1508        assert!(context.is_layer_locked(3));
1509
1510        // Act: release if-layers (would normally turn adjust off)
1511        context.handle_layer_event(LayerEvent::Deactivated(1));
1512        context.handle_layer_event(LayerEvent::Deactivated(2));
1513
1514        // Assert: lock keeps adjust on
1515        assert!(context.is_layer_locked(3));
1516        assert!(context.active_layers[2].is_active());
1517    }
1518
1519    #[test]
1520    fn test_conditional_layer_nested_fixed_point() {
1521        // Assemble: C ← A ∧ B; E ← C ∧ D  (layers 1,2 → 3; 3,4 → 5)
1522        let mut context = super::Context::<LAYER_COUNT, 2>::from_config(Config {
1523            sticky_timeout: None,
1524            conditional_layers: Slice::from_slice(&[
1525                ConditionalLayer::from_if_layers(3, &[1, 2]),
1526                ConditionalLayer::from_if_layers(5, &[3, 4]),
1527            ]),
1528        });
1529        context.handle_layer_event(LayerEvent::Activated(1));
1530        context.handle_layer_event(LayerEvent::Activated(2));
1531
1532        // Act: activate D; fixed-point should turn on C (already) and E
1533        context.handle_layer_event(LayerEvent::Activated(4));
1534
1535        // Assert
1536        assert_eq!(
1537            [
1538                Activity::Active(ActivationStyle::Regular), // 3
1539                Activity::Active(ActivationStyle::Regular), // 4
1540                Activity::Active(ActivationStyle::Regular), // 5
1541            ],
1542            context.active_layers[2..5]
1543        );
1544    }
1545
1546    #[test]
1547    fn test_conditional_layer_sticky_if_layer_counts_as_active() {
1548        // Assemble
1549        let mut context = tri_layer_context();
1550        context.handle_layer_event(LayerEvent::StickyActivated(1));
1551
1552        // Act
1553        context.handle_layer_event(LayerEvent::Activated(2));
1554
1555        // Assert
1556        assert_eq!(
1557            Activity::Active(ActivationStyle::Regular),
1558            context.active_layers[2]
1559        );
1560    }
1561
1562    #[test]
1563    fn test_conditional_layer_set_active_layers_reevaluates() {
1564        // Assemble
1565        let mut context = tri_layer_context();
1566        context.handle_layer_event(LayerEvent::Activated(1));
1567        context.handle_layer_event(LayerEvent::Activated(2));
1568
1569        // Act: clear layer 1 via Set (mask only layer 1)
1570        context.handle_layer_event(LayerEvent::Set(ModifierBitset {
1571            layers: LayerBitset::EMPTY,
1572            mask: LayerBitset::EMPTY.insert(1),
1573        }));
1574
1575        // Assert
1576        assert_eq!(Activity::Inactive, context.active_layers[2]);
1577    }
1578
1579    #[test]
1580    fn test_pressing_layered_key_acts_as_base_key_when_no_layers_active() {
1581        // Assemble
1582        let context = Context::default();
1583        let expected_ref = keyboard::Ref::KeyCode(0x04);
1584        let layered_key = LayeredKey::new(
1585            expected_ref,
1586            [
1587                Some(keyboard::Ref::KeyCode(0x05)),
1588                Some(keyboard::Ref::KeyCode(0x06)),
1589                Some(keyboard::Ref::KeyCode(0x07)),
1590            ],
1591        );
1592        let system = System::new([], [layered_key]);
1593
1594        // Act: without activating a layer, press the layered key
1595        let keymap_index = 9; // arbitrary
1596        let key_ref = Ref::Layered(0);
1597        let (pkr, _pke) = system.new_pressed_key(keymap_index, &context, key_ref);
1598
1599        // Assert
1600        let expected_pkr =
1601            key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(expected_ref));
1602        assert_eq!(expected_pkr, pkr,);
1603    }
1604
1605    // Terminology:
1606    //   "defined layer" = LayeredKey.layered[] is Some for that layer;
1607    //   "active layer" = Context.active_layers[] = true for that layer.
1608
1609    #[test]
1610    fn test_pressing_layered_key_falls_through_undefined_active_layers() {
1611        // Assemble: layered key (with no layered definitions)
1612        let mut context = Context::default();
1613        let expected_ref = keyboard::Ref::KeyCode(0x04);
1614        let layered_key = LayeredKey::new(expected_ref, [None, None, None]);
1615        let system = System::new([], [layered_key]);
1616
1617        // Act: activate all layers, press layered key
1618        context.handle_layer_event(LayerEvent::Activated(1));
1619        context.handle_layer_event(LayerEvent::Activated(2));
1620        context.handle_layer_event(LayerEvent::Activated(3));
1621        let keymap_index = 9; // arbitrary
1622        let key_ref = Ref::Layered(0);
1623        let (pkr, _pke) = system.new_pressed_key(keymap_index, &context, key_ref);
1624
1625        // Assert
1626        let expected_pkr =
1627            key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(expected_ref));
1628        assert_eq!(expected_pkr, pkr,);
1629    }
1630
1631    #[test]
1632    fn test_pressing_layered_key_acts_as_highest_defined_active_layer() {
1633        // Assemble: layered key (with no layered definitions)
1634        let mut context = Context::default();
1635        let expected_ref = keyboard::Ref::KeyCode(0x09);
1636        let layered_key = LayeredKey::new(
1637            keyboard::Ref::KeyCode(0x04),
1638            [
1639                Some(keyboard::Ref::KeyCode(0x05)),
1640                Some(keyboard::Ref::KeyCode(0x06)),
1641                Some(expected_ref),
1642            ],
1643        );
1644        let system = System::new([], [layered_key]);
1645
1646        // Act: activate all layers, press layered key
1647        context.handle_layer_event(LayerEvent::Activated(1));
1648        context.handle_layer_event(LayerEvent::Activated(2));
1649        context.handle_layer_event(LayerEvent::Activated(3));
1650        let keymap_index = 9; // arbitrary
1651        let key_ref = Ref::Layered(0);
1652        let (pkr, _pke) = system.new_pressed_key(keymap_index, &context, key_ref);
1653
1654        // Assert
1655        let expected_pkr =
1656            key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(expected_ref));
1657        assert_eq!(expected_pkr, pkr,);
1658    }
1659
1660    #[test]
1661    fn test_pressing_layered_key_with_some_transparency_acts_as_highest_defined_active_layer() {
1662        // Assemble: layered key (with no layered definitions)
1663        let mut context = Context::default();
1664        let expected_ref = keyboard::Ref::KeyCode(0x09);
1665        let layered_key = LayeredKey::new(
1666            keyboard::Ref::KeyCode(0x04),
1667            [Some(expected_ref), Some(keyboard::Ref::KeyCode(0x06)), None],
1668        );
1669        let system = System::new([], [layered_key]);
1670
1671        // Act: activate all layers, press layered key
1672        context.handle_layer_event(LayerEvent::Activated(1));
1673        context.handle_layer_event(LayerEvent::Activated(3));
1674        let keymap_index = 9; // arbitrary
1675        let key_ref = Ref::Layered(0);
1676        let (pkr, _pke) = system.new_pressed_key(keymap_index, &context, key_ref);
1677
1678        // Assert
1679        let expected_pkr =
1680            key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(expected_ref));
1681        assert_eq!(expected_pkr, pkr,);
1682    }
1683
1684    #[test]
1685    fn test_layer_state_array_active_layers() {
1686        let mut layer_state: [Activity; 5] = [Activity::Inactive; 5];
1687        layer_state.activate(1, ActivationStyle::Regular);
1688        layer_state.activate(2, ActivationStyle::Regular);
1689        layer_state.activate(4, ActivationStyle::Regular);
1690        let actual_active_layers: Vec<LayerIndex> = layer_state.active_layers().collect();
1691        let expected_active_layers: Vec<LayerIndex> = vec![4, 2, 1];
1692
1693        assert_eq!(expected_active_layers, actual_active_layers);
1694    }
1695
1696    #[test]
1697    fn test_pressing_toggle_modifier_key_emits_event_layer_toggled() {
1698        // Assemble
1699        let layer = 1;
1700        let key = ModifierKey::Toggle(layer);
1701
1702        // Act
1703        let (_pressed_key, layer_event) = key.new_pressed_key();
1704
1705        // Assert
1706        assert_eq!(Some(LayerEvent::Toggled(layer)), layer_event);
1707    }
1708
1709    #[test]
1710    fn test_pressing_lock_key_emits_lock_invert_highest() {
1711        // Assemble
1712        let key = ModifierKey::lock();
1713
1714        // Act
1715        let (_pressed_key, layer_event) = key.new_pressed_key();
1716
1717        // Assert
1718        assert_eq!(
1719            Some(LayerEvent::LockInvert(LayerLockTarget::HighestActive)),
1720            layer_event
1721        );
1722    }
1723
1724    #[test]
1725    fn test_pressing_lock_layer_key_emits_lock_invert_layer() {
1726        // Assemble
1727        let key = ModifierKey::lock_layer(2);
1728
1729        // Act
1730        let (_pressed_key, layer_event) = key.new_pressed_key();
1731
1732        // Assert
1733        assert_eq!(
1734            Some(LayerEvent::LockInvert(LayerLockTarget::Layer(2))),
1735            layer_event
1736        );
1737    }
1738
1739    #[test]
1740    fn test_exit_on_skip_emits_deactivated_and_resolves_to_base() {
1741        // Assemble: layer 1 cell is a tlex hole over base A
1742        let mut context = Context::default();
1743        let base = keyboard::Ref::KeyCode(0x04);
1744        let layered_key = LayeredKey::new(base, [None]).with_exit_on_skip(LayerBitset::from_bits(
1745            // bit 1 = layer 1
1746            1 << 1,
1747        ));
1748        let system = System::new([], [layered_key]);
1749
1750        // Act: activate layer 1, press the layered key
1751        context.handle_layer_event(LayerEvent::Activated(1));
1752        let keymap_index = 3;
1753        let (pkr, pke) = system.new_pressed_key(keymap_index, &context, Ref::Layered(0));
1754
1755        // Assert: this press is base; Deactivated(1) is scheduled
1756        assert_eq!(
1757            key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(base)),
1758            pkr,
1759        );
1760        let events: Vec<_> = pke.into_iter().collect();
1761        assert_eq!(1, events.len());
1762        assert_eq!(
1763            key::ScheduledEvent::immediate(key::Event::key_event(
1764                keymap_index,
1765                LayerEvent::Deactivated(1)
1766            )),
1767            events[0],
1768        );
1769    }
1770
1771    #[test]
1772    fn test_exit_on_skip_does_not_exit_default_only_layer() {
1773        // Assemble: layer 1 is only the default, not Regular/Sticky
1774        let mut context = Context::default();
1775        let base = keyboard::Ref::KeyCode(0x04);
1776        let layered_key =
1777            LayeredKey::new(base, [None]).with_exit_on_skip(LayerBitset::from_bits(1 << 1));
1778        let system = System::new([], [layered_key]);
1779
1780        // Act: set default layer 1 (not Regular activation)
1781        context.handle_layer_event(LayerEvent::SetDefault(1));
1782        let (pkr, pke) = system.new_pressed_key(0, &context, Ref::Layered(0));
1783
1784        // Assert: resolves via default path without Deactivated
1785        assert_eq!(
1786            key::PressedKeyResult::NewPressedKey(key::NewPressedKey::Key(base)),
1787            pkr,
1788        );
1789        assert_eq!(0, pke.into_iter().count());
1790    }
1791
1792    #[test]
1793    fn test_tttt_without_exit_bit_does_not_emit_deactivated() {
1794        // Assemble: ordinary transparency (no exit_on_skip)
1795        let mut context = Context::default();
1796        let base = keyboard::Ref::KeyCode(0x04);
1797        let layered_key = LayeredKey::new(base, [None]);
1798        let system = System::new([], [layered_key]);
1799
1800        // Act
1801        context.handle_layer_event(LayerEvent::Activated(1));
1802        let (_pkr, pke) = system.new_pressed_key(0, &context, Ref::Layered(0));
1803
1804        // Assert
1805        assert_eq!(0, pke.into_iter().count());
1806    }
1807
1808    #[test]
1809    fn test_lock_highest_keeps_layer_after_hold_release() {
1810        // Assemble: hold activates layer 1, then lock highest
1811        let mut context = Context::default();
1812        context.handle_layer_event(LayerEvent::Activated(1));
1813        context.handle_layer_event(LayerEvent::LockInvert(LayerLockTarget::HighestActive));
1814        assert!(context.is_layer_locked(1));
1815        assert!(context.active_layers[0].is_active());
1816
1817        // Act: hold release (would normally deactivate)
1818        context.handle_layer_event(LayerEvent::Deactivated(1));
1819
1820        // Assert: still active and locked
1821        assert!(context.is_layer_locked(1));
1822        assert!(context.active_layers[0].is_active());
1823    }
1824
1825    #[test]
1826    fn test_lock_again_unlocks_and_deactivates() {
1827        // Assemble: lock highest after hold, then release hold
1828        let mut context = Context::default();
1829        context.handle_layer_event(LayerEvent::Activated(1));
1830        context.handle_layer_event(LayerEvent::LockInvert(LayerLockTarget::HighestActive));
1831        context.handle_layer_event(LayerEvent::Deactivated(1));
1832        assert!(context.is_layer_locked(1));
1833        assert!(context.active_layers[0].is_active());
1834
1835        // Act: lock again (unlock)
1836        context.handle_layer_event(LayerEvent::LockInvert(LayerLockTarget::HighestActive));
1837
1838        // Assert
1839        assert!(!context.is_layer_locked(1));
1840        assert!(!context.active_layers[0].is_active());
1841    }
1842
1843    #[test]
1844    fn test_hold_press_while_locked_unlocks() {
1845        // Assemble: lock layer, then release hold so only lock keeps it active
1846        let mut context = Context::default();
1847        context.handle_layer_event(LayerEvent::Activated(1));
1848        context.handle_layer_event(LayerEvent::LockInvert(LayerLockTarget::HighestActive));
1849        context.handle_layer_event(LayerEvent::Deactivated(1));
1850        assert!(context.is_layer_locked(1));
1851        assert!(context.active_layers[0].is_active());
1852
1853        // Act: press hold again while locked
1854        context.handle_layer_event(LayerEvent::Activated(1));
1855
1856        // Assert
1857        assert!(!context.is_layer_locked(1));
1858        assert!(!context.active_layers[0].is_active());
1859    }
1860
1861    #[test]
1862    fn test_lock_specific_layer_activates_when_inactive() {
1863        // Assemble
1864        let mut context = Context::default();
1865
1866        // Act
1867        context.handle_layer_event(LayerEvent::LockInvert(LayerLockTarget::Layer(2)));
1868
1869        // Assert
1870        assert!(context.is_layer_locked(2));
1871        assert!(context.active_layers[1].is_active());
1872    }
1873
1874    #[test]
1875    fn test_lock_no_active_layer_is_noop() {
1876        // Assemble
1877        let mut context = Context::default();
1878
1879        // Act
1880        context.handle_layer_event(LayerEvent::LockInvert(LayerLockTarget::HighestActive));
1881
1882        // Assert
1883        assert_eq!(LayerBitset::EMPTY, context.locked_layers);
1884        assert!(!context.active_layers.iter().any(|a| a.is_active()));
1885    }
1886
1887    #[test]
1888    fn deserialize_lock_json() {
1889        // Assemble / Act
1890        let highest: ModifierKey = serde_json::from_str(r#"{"Lock":"HighestActive"}"#).unwrap();
1891        let layer: ModifierKey = serde_json::from_str(r#"{"Lock":{"Layer":3}}"#).unwrap();
1892
1893        // Assert
1894        assert_eq!(ModifierKey::Lock(LayerLockTarget::HighestActive), highest);
1895        assert_eq!(ModifierKey::Lock(LayerLockTarget::Layer(3)), layer);
1896    }
1897}