feat: thread device identity for per-device switch conditions#5
feat: thread device identity for per-device switch conditions#5malpern wants to merge 2 commits into
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Code Review — PR #5: Thread device identity for per-device switch conditionsOverall this is a well-structured PR that threads device identity cleanly through the stack. The two main features (device-indexed switch conditions and per-action High Priority1. Unexplained
|
| Issue | File | Severity |
|---|---|---|
Unexplained staticlib crate type |
Cargo.toml |
High |
| Two parallel HashMaps; stale entries on unplug | oskbd/linux.rs |
High |
saturating_add silently aliases 256+ devices |
oskbd/linux.rs |
Medium |
assert! can panic the daemon |
keyberon/src/action/switch.rs |
Medium |
| 8-arg function suppresses clippy | keyberon/src/action/switch.rs |
Medium |
| macOS changes out-of-scope | macos.rs, oskbd/macos.rs |
Medium |
DeviceInfo dead code |
oskbd/linux.rs |
Low |
current_device timing for deferred actions |
kanata/mod.rs |
Low |
🤖 Generated with Claude Code
|
Parent feature: malpern/KeyPath#63 (per-keyboard rule targeting) |
Code Review: feat: thread device identity for per-device switch conditionsThis PR adds two distinct features plus macOS output-backend refactoring in a single diff (~1000 additions). The implementation is generally solid, but there are a few correctness concerns worth addressing before merge. Critical / Correctness1. Race condition:
|
Code Review — PR #5: Thread device identity for per-device switch conditionsOverall this is a well-structured PR with good test coverage. The two features (per-device 🔴 Correctness / Potential Issues1. Stale
|
| # | Severity | File | Issue |
|---|---|---|---|
| 1 | 🔴 | docs/config.adoc | No user-facing warning about stale device in tap-hold context |
| 2 | 🔴 | src/oskbd/linux.rs | Silent index 255 sharing on overflow |
| 3 | 🟡 | src/oskbd/linux.rs | TryFrom sets device_index=0 then caller overwrites it |
| 4 | 🟡 | Cargo.toml | staticlib crate type affects all builds |
| 5 | 🟡 | src/oskbd/linux.rs | Dead DeviceInfo struct with #[allow(dead_code)] |
| 6 | 🟡 | keyberon/src/action/switch.rs | Too-many-arguments suppression; SwitchContext struct would help |
| 8 | 🟢 | src/oskbd/macos.rs | Redundant .clear() in release_tracked_output_keys |
| 9 | 🟢 | docs/config.adoc | Hot-plug instability not documented |
| 11 | 🟢 | parser tests | No integration test for (switch ((device N) …)) |
The per-action require-prior-idle feature is clean — the count_trailing_options approach is well-designed and the parser tests are comprehensive. The device threading plumbing through Linux KbdIn is also solid. Main asks before merge: address items 2 (overflow behavior) and 4 (staticlib), and add the user-facing warning for item 1.
Code ReviewOverall this is solid, well-structured work. The device-identity pipeline is cleanly threaded from 1. PR scope — two unrelated features bundled togetherThe diff contains three independent changes:
Combining these makes review harder, complicates bisection, and obscures which change broke something if a regression shows up. Consider splitting into separate PRs. 2.
|
PR Review: feat: thread device identity for per-device switch conditionsThis PR adds two distinct features: (1) a 🔴 Issues Worth Addressing Before Merge1. Unexplained
|
Thread device identity from OS input through the event pipeline to keyberon's switch evaluation. Add device_index field to KeyEvent, populated on Linux via mio Token-based device tracking. Add (device N) switch condition matching against the originating device's index. Store current_device on Layout (not in Event row) to preserve the row 0/1 real/virtual key invariant. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
97bc518 to
01fdc29
Compare
Code Review: feat: thread device identity for per-device switch conditionsThis PR adds two independent features: (1) per-device Critical / Bug-Risk Issues1. The PR correctly notes in a code comment that // Note: `current_device` is set here per-event and may be stale when switch actions
// evaluate later (e.g. inside tap-hold's WaitingState resolution from `tick()`).Consider this scenario:
This should be called out in the config docs, not just in a code comment. Users trying to combine 2. Device index overflow silently creates aliased devices // src/oskbd/linux.rs
None => log::warn!(
"device index overflow: device {path} shares index 255 with another device"
),After the overflow, 3. Mutex held during In {
let kanata = kanata.lock(); // <-- lock acquired
if !kanata.kbd_out.wait_until_ready(Some(Duration::from_secs(10))) {
// wait_until_ready spins for up to 10 seconds
}
}
Design / API Issues4. # Cargo.toml
crate-type = ["rlib", "staticlib"]Adding 5. Sim test device syntax supports only single-digit indices // src/tests/sim_tests/mod.rs
dev_press
if dev_press.len() == 2
&& dev_press.starts_with('d')
&& dev_press.as_bytes()[1].is_ascii_digit() =>The 6. // src/oskbd/linux.rs
impl TryFrom<InputEvent> for KeyEvent {
fn try_from(item: InputEvent) -> Result<Self, Self::Err> {
// ...
Ok(Self {
code: ...,
value: ...,
device_index: 0, // always 0; caller must call .with_device()
})
}
}The Code Quality7. Dead code /// Currently unused — scaffolding for device name-based matching (see follow-up issue #6).
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct DeviceInfo { ... }Shipping 8. pub fn device_info(&self) -> Vec<DeviceInfo> {
self.devices.values().map(...).collect()
}
9. In Minor / Style10. The encoding stores 11. The new What's Well Done
🤖 Generated with Claude Code |
Summary
device_index: u8field toKeyEvent, threaded from LinuxKbdInthrough to keyberon switch evaluation(device N)switch condition in the parser that matches events from a specific physical devicecurrent_device: Option<u8>onLayout(not in keyberon Event row) to preserve the row 0/1 real/virtual key invariantdevice_index: 0default (no multi-device support yet)Usage Example
Not in scope (follow-up PRs)
(device "Kinesis")/(defdevice ...)configTest plan
cargo buildsucceeds on all targets🤖 Generated with Claude Code