The non-sucking key mapper that works on Wayland, by hooking into /dev/input
.
- Non-sucking: Works for X11, Wayland, and TTY.
- Non-bloating: 18KB for my configuration. No runtime dependency other than libc, which you definitely already installed.
- No GC latency: No one want to pause-the-world while typing. NSKM don't even use the heap.
- No zombies : All children are gifted to
init
immediately, if they ever get spawned.
src/codes.rs
contains some constants found in Linux x64 5.4.2 headers, but I'm not sure how stable they are. If by any
chance those magic numbers changed, the file can be regenerated by:
$ cc sys/codegen.c && ./a.out > src/codes.rs
Don't panic, there is a hard coded LeftCtrl+RightCtrl+K to kill NSKM.
Feature rich key mappers usually come with a complicated configuration or sophisticated scripting language, which I would rather not to touch. Thus, the designated way to use NSKM is use the source. Don't worry, you don't need to learn Rust to just swap Ctrl and Alt. The guide and examples below should cover most common usages and a copy-pasting should solve most problems.
We will use key names like KEY_D
, KEY_PAGEUP
in this guide. They come from /usr/include/linux/input-event-codes.h
.
evtest is a great tool to help find out the code and name of a key.
Let's first get a trivial mapper run: a mapper that do nothing but forward all keys. Download this project with git or
whatever, then rewrite src/hook.rs
with the following snippet:
use super::*;
pub(crate) unsafe fn hook(ev: &input_event, u: &UInput) {
u.emit(ev)
}
compile it with
$ cargo build
If no error occurs, there should be a ./target/debug/nskm
that is ready to use. Run it with
$ sudo ./target/debug/nskm /dev/input/by-path/platform-i8042-serio-0-event-kbd
...wait! What is /dev/input/by-path/platform-i8042-serio-0-event-kbd
? Well, it's the input device you want to capture,
i.e. your keyboard. Try cat /proc/bus/input/devices
or evtest
to findout your. This file is usually owned by root
and no permission for others, that's why we need sudo
here.
If you managed to run it, you will find, well, nothing happened. That's because we just forwarded all key events. To be sure that we actually succeed, modify the file as following:
use super::*;
pub(crate) unsafe fn hook(ev: &input_event, u: &UInput) {
if ev.type_ == EV_KEY && ev.code == KEY_H {
if ev.value == V_KEYDOWN {
u.click(KEY_H);
u.click(KEY_E);
u.click(KEY_L);
u.click(KEY_L);
u.click(KEY_O);
u.click(KEY_SPACE);
u.click(KEY_W);
u.click(KEY_O);
u.click(KEY_R);
u.click(KEY_L);
u.click(KEY_D);
}
} else {
u.emit(ev);
}
}
Compile and run again. If things are still on track, press h will write "hello world" now.