Linux 修改键位映射

2022-08-28 17:44:05 +08:00
 phoulx
折腾了几天, 分享一下 Linux 下修改键位映射的思路和工具。

需达到的效果:
CapsLock 单按为 Esc ,组合按为 Ctrl
左 Shift 单按切输入法,右 Shift 单按打出左括号
文本编辑时适配 Emacs 基础快捷键
按键布局尽量与 macOS 一致

macOS 键位的好处是 Command 与 Ctrl 分开,使得一些 Emacs 快捷键与系统命令快捷键能够共存(如 Ctrl+A 跳至行首,Command+A 全选等)。

调研:
Linux 下的改键软件大致分为两类:
一类为使用 X11/Xorg 的键盘映射接口,如 xmodmap 、xkeysnail 等;
另一类为调用 kernel 层的输入接口,如 keyd 、KMonad 等。
因为我用的桌面是 Gnome Wayland ,所以 X11 下的就无法考虑了。後面两个目前都在积极开发中:keyd 用 C 写的,配置文件类似 TOML ,Linux 专属; KMonad 是 Haskell ,配置文件是类似 Lisp 但惊人的直观,且跨平台。考虑到效率,我选择了 keyd ( https://github.com/rvaiya/keyd )。

安装过程不表,说一下遇到的体会和小坑。
keyd 以 layer 为核心概念,每个 layer 就是一段配置,layer 可以继承和切换。这样很容易实现我需要的效果(如:左 Alt 继承 Ctrl 功能,但特定键下可触发自定义)。
不过要注意的是,目前 git 仓库中的示例配置有部分是错的(应该是近期迭代了 2.0 版但示例未及时更新),修改要点:
1. 2.0 版舍弃了`leftmeta = alt`的语法,现在必须写成`leftmeta = layer(alt)`
2. 切换 layer 时如果有参数,要用 swap2 而不是 swap ,具体用法在 man page 有写

现在仍有部分 Emacs 键位无法实现,如 Ctrl+k (删至行末),因这一功能没有单键对应。如果定义为 Shift+End+Delete 组合键,不仅删除时有延迟,而且会影响 Terminal 中 Ctrl+k 的行为。
注意到 Gnome Tweak 中有一个启用 Emacs 键位的选项,研究了一下如何实现的,发现是使用了 gtk 的 Api 自定义了一些配置(位于:/usr/share/themes/Emacs/gtk-3.0/gtk-keys.css ),这样我们可以仿照此配置,新建一个 YourKey 文件夹,将 gtk-keys.css 中需要的搬过来,再通过`gsettings set org.gnome.desktop.interface gtk-key-theme YourKey`设为自己想到的效果。
不过这衹对 gtk 应用生效,好在我装的非 gtk 应用不多,目前已基本够用。
4185 次点击
所在节点    Linux
20 条回复
everyx
2022-08-28 20:19:08 +08:00
正在用 https://github.com/sezanzeb/input-remapper ,就是不能映射 fn 组合键,请问不知道 keyd 可以吗?
haoliang
2022-08-28 20:28:09 +08:00
我依稀记得有人是在 udev 层面做的改映射,不需要借助额外程序。
哦,找到个参考: https://wiki.archlinux.org/title/map_scancodes_to_keycodes
beetlerx
2022-08-28 20:28:48 +08:00
我用的是这个文章里的修改 scancode 方法
https://harttle.land/2019/08/08/linux-keymap-on-macbook.html
auvt
2022-08-28 21:03:06 +08:00
感谢 lz 分享,在 mac 上实现了全局 vim 方向按键,想跟 mac 快捷键一起搬到 linux 上,结果可耻地失败了无数次,就为了码个字,后来放弃了……
phoulx
2022-08-28 21:07:42 +08:00
@everyx 应该也不行,试了下 Filco 的 fn ,检测不到
everyx
2022-08-28 21:23:24 +08:00
@phoulx 谢谢回复,看来这种应该是要那类支持修改固件的键盘才行了
jinweijie
2022-08-29 08:11:52 +08:00
用 AutoKey 可以吗?
leighton
2022-08-29 09:30:50 +08:00
phoulx
2022-08-29 10:07:02 +08:00
@jinweijie AutoKey 也是 X11 专属,而且 GUI 觉得没必要
TravisMtg
2022-08-29 13:38:50 +08:00
非常好推荐!这段时间一直在纠结 spacefn 咋弄,keyd 能完美整出 spacefn 的方案
xxiaowangwang
2022-08-29 15:45:18 +08:00
setxkbmap -option "caps:swapescape" 用 XWayland 的话,这个不可以吗?
phoulx
2022-08-30 00:22:52 +08:00
@xxiaowangwang 没试过诶,感觉 setxkbmap 预设项太多了,对于复杂需求用起来会混乱…
phoulx
2022-08-30 01:30:43 +08:00
贴一个我目前的 keyd 配置(适用 v2.4.2 ): https://paste.rs/nFR
kaiger
2022-09-01 09:47:39 +08:00
很好用,多谢:)
kaiger
2022-09-01 10:56:52 +08:00
OP ,有个问题
为特定的 app 改键好像不成功,例如配置文件:

~/.config/keyd/app.conf
```
[google-chrome]
# Remaps the escape key to capslock
esc = capslock
```
是我的语法有问题吗?
975779964
2022-09-08 21:50:59 +08:00
请问这个支持 远程 xrdp 或者 nomachine 按键映射么?
xiaket
2022-12-18 17:59:29 +08:00
xremap 挺好用的, 配置文件思路很清晰也很好读. 不推荐 xkeysnail, 依赖多, 出问题不好排查. ref: https://blog.xiaket.org/2022/xremap.html
jqtmviyu
338 天前
感谢, 之前 用 xmodmap, 非常麻烦

你的配置链接失效了.
我到 issues 区抄了下, 暂时还没搞清楚怎么实现 mac 上的向前 /后删除一个单词, 向后退格.
幸好大部分情况都是在 shell 和 vim 中编辑, 它们有泛用的快捷键

```
[ids]

*

[main]
capslock = overload(capslock_layer, esc)

[capslock_layer]
esc = capslock

h = left
j = down
k = up
l = right

u = pageup
p = pagedown
i = home
o = end

m = backspace
```
yczjing
298 天前
@jqtmviyu
```
[capslock_layer:C-S-A-M]
```
这样可以把 caps 默认配置为 hyper
txl263
116 天前
@auvt mac 上用 karabiner elements

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/875994

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX