linux 键盘映射xremap

十二月 25, 2025 #xremap

xremap

cargo install xremap --features gnome   # GNOME Wayland

查看当前 uinput 设备(需要 root)

xremap 使用 /dev/uinput 创建虚拟输入设备。异常退出可能导致设备未释放。

sudo cat /sys/class/misc/uinput/dev

# 查看 uinput 使用者(粗略判断是否被占用)
lsof /dev/uinput
# 或
fuser /dev/uinput

Running xremap without sudo

To do so, your normal user should be able to use evdev and uinput without sudo. In Ubuntu, this can be configured by running the following commands and rebooting your machine.

sudo gpasswd -a YOUR_USER input
echo 'KERNEL=="uinput", GROUP="input", TAG+="uaccess"' | sudo tee /etc/udev/rules.d/input.rules

lsmod | grep uinput
# If it shows up empty:
echo uinput | sudo tee /etc/modules-load.d/uinput.conf

Reboot the machine afterwards or try:

sudo modprobe uinput
sudo udevadm control --reload-rules && sudo udevadm trigger

GNOME Wayland

   <policy context="default">
+    <allow user="root"/>
     <!-- Allow everything to be sent -->
     <allow send_destination="*" eavesdrop="true"/>
     <!-- Allow everything to be received -->

example

This allows a key to be held indefinitely without triggering its held state, which is ideal for keys that also serve as modifiers. For example, you can make the Space key act as Shift when held and combined with another key, but still type a regular Space when tapped.

modmap:
  - name: Space as Shift
    remap:
      Space:
        held: Shift_L
        alone: Space
        free_hold: true # Optional, defaults to false.

问题排查

# 普通用户执行要求
sudo usermod -aG input $USER

# 创建 udev 规则: 新建文件 /etc/udev/rules.d/99-input.rules,内容如下:
KERNEL=="uinput", GROUP="input", MODE="0660"

sudo udevadm control --reload-rules && sudo udevadm trigger

# 查找你的键盘设备 寻找 Name="...Keyboard..." 的条目,记下它的 Handlers(例如 event3)
cat /proc/bus/input/devices

/home/peter/.cargo/bin/xremap /home/peter/project/tools/dotfiles/keymap.yml --device /dev/input/event3

错误举例

xremap 会创建一个名为 xremap 的虚拟键盘。如果程序崩溃了但设备还在,GNOME 会继续尝试从这个“僵尸”设备读取输入

lsinput
# 或者使用更通用的命令
grep -E 'Name|Handlers' /proc/bus/input/devices

使用 libinput 监控实时事件

sudo libinput debug-events

排查设备“锁死”(EVIOCGRAB)

ps aux | grep xremap
sudo killall -9 xremap

通常进程结束后,内核会自动释放设备抓取。

快速恢复手段

sudo modprobe -r uinput && sudo modprobe uinput

终极手段:重置 uinput 子系统

# 卸载并重载 uinput 模块(需 root,会断开所有虚拟输入设备)
sudo rmmod uinput
sudo modprobe uinput
# 此操作会使所有依赖 uinput 的程序(如 xremap、keyd、interception-tools)失效,需重启它们

强制释放所有“卡住”的修饰键(最常用、最有效)

在 GNOME/X11 下,模拟释放所有修饰键即可快速恢复:

# 方法 1:使用 xdotool(推荐)
xdotool keyup Shift_L Shift_R Control_L Control_R Alt_L Alt_R Super_L Super_R

# 方法 2:使用 xte(来自 xautomation 包)
xte 'keyup Shift_L' 'keyup Control_L' 'keyup Alt_L' 'keyup Super_L'

# 方法 3:重启输入法/IM 框架(有时 IBus/Rime 会缓存按键状态)
ibus restart

在 GNOME Wayland 会话中,xdotool 可能失效(因非 X11 后端),此时:

Ctrl+Alt+F3 → 登录 → Ctrl+Alt+F1(或 F2)回到 GNOME
# 这会强制重置输入栈。

# 重启 GNOME Shell(不注销):
# 在 GNOME 中按 Alt+F2,输入:
r
# 或终端执行
busctl --user call org.gnome.Shell /org/gnome/Shell org.gnome.Shell Eval s 'global.reexec_self()'

事件监听

sudo apt install evtest
# 列出所有 X 输入设备
xinput list

# 查找类似 “xremap virtual keyboard” 的设备
xinput list --short | grep -i remap

# 若找到,检查其按键状态(需 evtest)
sudo evtest
# → 选择对应设备编号,观察是否有持续的 KEY_XXX (code xxx) DOWN 事件

# xremap 默认创建一个 uinput virtual device,名字可能为 xremap virtual keyboard 或类似。

xremap 的实现原理

xremap 的工作流程可以分为:拦截 (Grab) -> 转换 (Remap) -> 重发 (Emit)

1. 拦截层 (evdev + EVIOCGRAB)

2. 逻辑转换层 (Logic)

3. 重发层 (uinput)

类似工具

loadkeys(console keymap)

# 编辑 keymap.map
sudo loadkeys keymap.map

kbd / console-setup

用于

sudo dpkg-reconfigure keyboard-configuration

其他类似项目

项目架构Wayland特点
xremapevdev + uinput⚠️YAML,灵活
keydevdev + uinput稳定、简单
kmonadevdev + uinput⚠️Lisp DSL
interception-toolsevdev⚠️管道式
setxkbmapXKB最稳
xmodmapX11已过时
Karabiner (macOS)HID架构标杆