1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#[cfg(test)]
mod tests;
#[allow(unused_imports)]
use crate::state_machine::StateMachine;
use crate::{
ModifierMask,
controls::ControlsMask,
group::{GroupDelta, GroupIndex},
state_machine::Event,
};
/// The active modifiers/group of a keyboard.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
#[non_exhaustive]
pub struct Components {
/// The pressed modifiers.
pub mods_pressed: ModifierMask,
/// The latched modifiers.
pub mods_latched: ModifierMask,
/// The locked modifiers.
pub mods_locked: ModifierMask,
/// The effective modifiers.
///
/// This is defined as the bitwise OR of the pressed, latched, and locked modifiers.
pub mods: ModifierMask,
/// The pressed group.
pub group_pressed: GroupDelta,
/// The latched group.
pub group_latched: GroupDelta,
/// The locked group.
///
/// Under wayland, this field corresponds to the `group` argument in
/// `wl_keyboard.modifiers` events.
pub group_locked: GroupIndex,
/// The effective group.
///
/// This is defined as the sum of the pressed, latched, and locked group.
pub group: GroupIndex,
/// The controls.
pub controls: ControlsMask,
}
impl Components {
/// Applies an [`Event`] from a [`StateMachine`] to these components.
///
/// This function is intended for compositors. Clients receiving components via
/// `wl_keyboard` events should instead use [`Self::update_effective`]. See the
/// example therein.
pub fn apply_event(&mut self, event: Event) -> bool {
macro_rules! change {
($field:ident, $val:expr) => {{
let changed = self.$field != $val;
self.$field = $val;
changed
}};
}
match event {
Event::ModsPressed(v) => change!(mods_pressed, v),
Event::ModsLatched(v) => change!(mods_latched, v),
Event::ModsLocked(v) => change!(mods_locked, v),
Event::ModsEffective(v) => change!(mods, v),
Event::GroupPressed(v) => change!(group_pressed, v),
Event::GroupLatched(v) => change!(group_latched, v),
Event::GroupLocked(v) => change!(group_locked, v),
Event::GroupEffective(v) => change!(group, v),
Event::Controls(v) => change!(controls, v),
_ => false,
}
}
/// Updates the effective modifiers and group in terms of the pressed/latched/locked
/// modifiers/group.
///
/// This function is intended for clients receiving the pressed/latched/locked
/// modifiers and the locked group via `wl_keyboard` events.
///
/// If you're using the [`Self::apply_event`] function to process events generated by
/// a [`StateMachine`], then you don't have to use this function because the event
/// stream will contain events updating the effective modifiers/group directly.
///
/// # Example
///
/// ```
/// # use kbvm::{Components, GroupIndex, ModifierMask};
/// #
/// fn handle_wl_keyboard_modifiers(
/// components: &mut Components,
/// mods_pressed: ModifierMask,
/// mods_latched: ModifierMask,
/// mods_locked: ModifierMask,
/// group: GroupIndex,
/// ) {
/// components.mods_pressed = mods_pressed;
/// components.mods_latched = mods_latched;
/// components.mods_locked = mods_locked;
/// components.group_locked = group;
/// components.update_effective();
/// }
/// ```
pub fn update_effective(&mut self) {
self.group = self.group_locked + self.group_pressed + self.group_latched;
self.mods = self.mods_pressed | self.mods_latched | self.mods_locked;
}
pub(crate) fn any_latched(&self) -> bool {
self.group_latched.0 != 0 || self.mods_latched.0 != 0
}
}