leftwm_core/utils/
modmask_lookup.rs

1use bitflags::bitflags;
2use serde::{de::Visitor, Deserialize, Serialize};
3
4bitflags! {
5    /// Represents the state of modifier keys
6    #[derive(Clone, Debug, PartialEq, Eq)]
7    pub struct ModMask: u16 {
8        /// Used as the zero value
9        const Zero = 0;
10        const Any = 1;
11        const Shift = 1 << 1;
12        const Control = 1 << 2;
13        /// Mod1
14        const Alt = 1 << 3;
15        /// Mod2
16        const NumLock = 1 << 4;
17        const Mod3 = 1 << 5;
18        /// Mod4
19        const Super = 1 << 6;
20        const Mod5 = 1 << 7;
21    }
22}
23
24/// Representation of mouse buttons
25#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
26pub enum Button {
27    /// no buttons pressed
28    None,
29    /// Main button (left click for right-handed)
30    /// Button1
31    Main,
32    /// Middle button (pressing the scroll wheel)
33    /// Button2
34    Middle,
35    /// Secondary button (right click for right-handed)
36    /// Button3
37    Secondary,
38    /// Scroll wheel up
39    /// Button4
40    ScrollUp,
41    /// Scroll wheel down
42    /// Button5
43    ScrollDown,
44}
45
46impl From<u8> for Button {
47    fn from(value: u8) -> Self {
48        match value {
49            1 => Self::Main,
50            2 => Self::Middle,
51            3 => Self::Secondary,
52            4 => Self::ScrollUp,
53            5 => Self::ScrollDown,
54            _ => Self::None,
55        }
56    }
57}
58
59impl From<Button> for u8 {
60    fn from(value: Button) -> Self {
61        match value {
62            Button::None => 0,
63            Button::Main => 1,
64            Button::Middle => 2,
65            Button::Secondary => 3,
66            Button::ScrollUp => 4,
67            Button::ScrollDown => 5,
68        }
69    }
70}
71
72#[must_use]
73pub fn into_modmask(keys: &[String]) -> ModMask {
74    let mut mask = ModMask::Zero;
75    for s in keys {
76        mask |= into_mod(s);
77    }
78    // clean the mask
79    mask.remove(ModMask::NumLock);
80    mask.intersection(
81        ModMask::Shift
82            | ModMask::Control
83            | ModMask::Alt
84            | ModMask::Mod3
85            | ModMask::Super
86            | ModMask::Mod5,
87    )
88}
89
90#[must_use]
91pub fn into_mod(key: &str) -> ModMask {
92    match key {
93        "None" => ModMask::Any,
94        "Shift" => ModMask::Shift,
95        "Control" => ModMask::Control,
96        "Mod1" | "Alt" => ModMask::Alt,
97        // NOTE: we are ignoring the state of Numlock
98        // this is left here as a reminder
99        // "Mod2" | "NumLock" => ModMask::NumLock,
100        "Mod3" => ModMask::Mod3,
101        "Mod4" | "Super" => ModMask::Super,
102        "Mod5" => ModMask::Mod5,
103        _ => ModMask::Zero,
104    }
105}
106
107// serde impls (derive is not working with the bitflags macro)
108
109impl Serialize for ModMask {
110    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
111    where
112        S: serde::Serializer,
113    {
114        serializer.serialize_u16(self.bits())
115    }
116}
117
118impl<'de> Deserialize<'de> for ModMask {
119    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
120    where
121        D: serde::Deserializer<'de>,
122    {
123        struct ModmaskVisitor;
124
125        impl Visitor<'_> for ModmaskVisitor {
126            type Value = ModMask;
127
128            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
129                formatter.write_str("a bitfield on 8 bits")
130            }
131
132            fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
133            where
134                E: serde::de::Error,
135            {
136                Ok(ModMask::from_bits_retain(u16::from(v)))
137            }
138
139            fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
140            where
141                E: serde::de::Error,
142            {
143                Ok(ModMask::from_bits_retain(v))
144            }
145        }
146
147        deserializer.deserialize_u16(ModmaskVisitor)
148    }
149}