Skip to content

Commit cfb3f6f

Browse files
committed
feat: Have backend map mod-tap keycodes to/from strings
1 parent b319ed3 commit cfb3f6f

File tree

6 files changed

+49
-5
lines changed

6 files changed

+49
-5
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ license = "GPL-3.0-or-later"
66
edition = "2018"
77

88
[dependencies]
9+
cascade = "1"
910
futures = "0.3.13"
1011
futures-timer = "3.0.2"
1112
glib = { git = "https://github.com/pop-os/gtk-rs" }
1213
hidapi = { version = "1.2", default-features = false, features = ["linux-static-hidraw"] }
1314
once_cell = "1.4"
1415
ordered-float = { version = "2.0", features = ["serde"] }
1516
palette = "0.5"
17+
regex = "1"
1618
serde = { version = "1.0", features = ["derive"] }
1719
serde_json = "1.0"
1820
log = "0.4.0"

backend/src/key.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ impl Key {
147147
let board = self.board();
148148
let scancode = self.scancodes.get(layer)?.get();
149149
let scancode_name = match board.layout().scancode_to_name(scancode) {
150-
Some(some) => some.to_string(),
150+
Some(some) => some,
151151
None => String::new(),
152152
};
153153
Some((scancode, scancode_name))

backend/src/layout/meta.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ pub struct Meta {
2020
pub has_brightness: bool,
2121
/// Has LED with color (i.e. not monochrome)
2222
pub has_color: bool,
23+
/// Supports mod-tap bindings (assumes QMK mod-tap encoding)
24+
#[serde(default)]
25+
pub has_mod_tap: bool,
2326
/// Number or layers; e.g. 2 where layer 2 is used when `Fn` is held
2427
#[serde(default = "num_layers_default")]
2528
pub num_layers: u8,

backend/src/layout/mod.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,32 @@
1+
use cascade::cascade;
2+
use regex::Regex;
13
use std::{collections::HashMap, fs, path::Path};
24

35
mod meta;
6+
use once_cell::sync::Lazy;
47
mod physical_layout;
58
pub use self::meta::Meta;
69
pub(crate) use physical_layout::{PhysicalLayout, PhysicalLayoutKey};
710

811
use crate::KeyMap;
912

13+
const QK_MOD_TAP: u16 = 0x6000;
14+
const QK_MOD_TAP_MAX: u16 = 0x7FFF;
15+
16+
pub static MOD_TAP_MODS: Lazy<HashMap<&str, u16>> = Lazy::new(|| {
17+
cascade! {
18+
HashMap::new();
19+
..insert("LEFT_CTRL", 0x01);
20+
..insert("LEFT_SHIFT", 0x02);
21+
..insert("LEFT_ALT", 0x04);
22+
..insert("LEFT_SUPER", 0x08);
23+
..insert("RIGHT_CTRL", 0x11);
24+
..insert("RIGHT_SHIFT", 0x12);
25+
..insert("RIGHT_ALT", 0x14);
26+
..insert("RIGHT_SUPER", 0x18);
27+
}
28+
});
29+
1030
pub struct Layout {
1131
/// Metadata for keyboard
1232
pub meta: Meta,
@@ -123,13 +143,29 @@ impl Layout {
123143
}
124144

125145
/// Get the scancode number corresponding to a name
126-
pub fn scancode_to_name(&self, scancode: u16) -> Option<&str> {
127-
self.scancode_names.get(&scancode).map(String::as_str)
146+
pub fn scancode_to_name(&self, scancode: u16) -> Option<String> {
147+
if scancode >= QK_MOD_TAP && scancode <= QK_MOD_TAP_MAX {
148+
let mod_ = (scancode >> 8) & 0x1f;
149+
let kc = scancode & 0xff;
150+
let mod_name = MOD_TAP_MODS.iter().find(|(_, v)| **v == mod_)?.0;
151+
let kc_name = self.scancode_names.get(&kc)?;
152+
Some(format!("MT({}, {})", mod_name, kc_name))
153+
} else {
154+
self.scancode_names.get(&scancode).cloned()
155+
}
128156
}
129157

130158
/// Get the name corresponding to a scancode number
131159
pub fn scancode_from_name(&self, name: &str) -> Option<u16> {
132-
self.keymap.get(name).copied()
160+
// Check if mod-tap
161+
let mt_re = Regex::new("MT\\(([^()]+), ([^()]+)\\)").unwrap();
162+
if let Some(captures) = mt_re.captures(name) {
163+
let mod_ = *MOD_TAP_MODS.get(&captures.get(1).unwrap().as_str())?;
164+
let kc = *self.keymap.get(captures.get(2).unwrap().as_str())?;
165+
Some(QK_MOD_TAP | ((mod_ & 0x1f) << 8) | (kc & 0xff))
166+
} else {
167+
self.keymap.get(name).copied()
168+
}
133169
}
134170
}
135171

layouts/system76/launch_1/meta.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"num_layers": 4,
66
"has_brightness": true,
77
"has_color": true,
8+
"has_mod_tap": true,
89
"pressed_color": "#202020",
910
"keyboard": "system76/launch_1"
10-
}
11+
}

0 commit comments

Comments
 (0)