将CapsLock键在单击和长按时分别映射为Esc和Ctrl

Caps Lock键可能是我最讨厌的一个键,毫无用处却存在感极强,我们来好好折腾一下
环境:Win10和Manjaro双系统

前言

Caps Lock的作用是锁定输入为大写字母,这个键或许对于英语国家的人来说比较常用,但对使用中文的我们来说,这个键一年也用不了几次,完全可以使用Shift代替。并且Caps Lock键所处的位置极佳,甚至比Shift和Ctrl的位置都要好,这不仅是浪费,还会导致误触,经常输入密码按到了Caps Lock键,还以为密码记错了

在Windows上,我希望把Caps Lock键修改为Ctrl键,Ctrl键经常作为组合键使用,并且只能使用小拇指,我最常使用的快捷键就是Ctrl+S保存,因为我有强迫症,码代码的时候经常会把我小拇指按抽筋,而Caps Lock的位置就舒服太多了

在Linux中,我希望把Caps Lock键修改为Esc键。相信使用过vim的人都知道,Esc键可能是最常使用的一个键了,用于退回到普通模式。但Esc的位置同样不好,盲打时经常按错

当我都搞定的时候,我突发奇想,为什么鱼和熊掌不能兼得,单击时修改为Esc,长按时修改为Ctrl

果然,网上很多人和我有同样的想法,但是都没有可行的解决方案,不过,功夫不负有心人,最终还是找到了办法,且让我慢慢道来

解决方案

Windows

一般的按键修改都是通过修改注册表来实现,理论上是不能实现单击和长按分别映射成不同的按键

不过在我翻遍全网后,发现一位大佬提出了可行的解决方案,通过拦截键盘输入,可以实现了Caps单击为Esc,长按为Ctrl,同时Esc修改为Caps,同时诞生了Interception项目

The Interception API aims to build a portable programming interface that allows one to intercept and control a range of input devices.

Interception API旨在构建一种可移植的编程接口,该接口允许用户拦截和控制各种输入设备

这个项目开源,可以自己修改或者编译程序,也可以实现一些有意思的功能,作者已经实现实现了Caps映射为Esc和Ctrl,所以我们可以直接使用

经过摸索,终于明白了使用方法

  1. 先下载文件,解压

  2. 使用快捷键Win + X,再按a即可打开管理员权限的CMD或者Powershell窗口,进入该文件夹,执行下列代码

    1
    .\install-interception.exe /install

  3. 点击caps2esc.exe就会拦截键盘输入,将Caps Lock同时映射为Esc和Ctrl

  4. 但是每次都要点一次,这可不方便,所以我们可以把caps2esc.exe快捷方式放入C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp,每次启动都会自动执行

  5. 如果要卸载,重复第二步,执行代码

    1
    .\install-interception.exe /uninstall

Linux

这就是上面提出Windows解决方案的大佬移植到Linux上的 caps2esc

  1. 大佬直接提供了AUR包,arch/Manjaro直接使用下列代码安装

    1
    2
    yay -S interception-tools
    yay -S interception-caps2esc

    使用其他Linux发行版的自行编译,相信既然都在用Linux了,make肯定会用吧,解决办法

  2. 安装好了以后,在/etc/udevmon.yaml添加下列代码

    1
    2
    3
    4
    - JOB: "intercept -g $DEVNODE | caps2esc | uinput -d $DEVNODE"
    DEVICE:
    EVENTS:
    EV_KEY: [KEY_CAPSLOCK, KEY_ESC]
  3. /etc/systemd/system/udevmon.service中添加下列代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [Unit]
    Description=udevmon
    Wants=systemd-udev-settle.service
    After=systemd-udev-settle.service

    [Service]
    ExecStart=/usr/bin/nice -n -20 /usr/bin/udevmon -c /etc/udevmon.yaml

    [Install]
    WantedBy=multi-user.target
  4. 最后使用sudo systemctl enable --now udevmon来启动

这下就可以愉快的码代码了

其他

我们来研究研究Linux下通过xmodmap来修改键位,从底层了解一下输入的原理,虽然这种办法是不能实现单击和长按时分别映射成不同的键,但也很值得学习

比如我们要交换Caps Lock键和Esc键

  • 十分简单,将下列代码添加到~/.profile,然后重启

    1
    xmodmap -e 'remove lock = Num_Lock' -e 'keycode 66 = Escape' -e 'keycode 9 = Num_Lock'

    ~/.profile文件的作用就是系统启动时会自动执行里面的命令,

  • 也可以直接修改xmodmap的配置文件~/.Xmodmap,添加下列代码

    1
    2
    3
    remove lock = Num_Lock
    keycode 66 = Escape
    eycode 9 = Num_Lock

    修改完使用xmodmap ~/.Xmodmap,立即生效

其实上面两个方法本质是一样的,可以互相转换,使用 -e隔开每一行即可

xmodmap 是一个在 X 图形环境下用于修改键盘和鼠标按钮映射的工具。比如你可以使用它来实现鼠标的左右键互换,把 caps lock 键改成 ctrl 键, a 键改成 b 键等

关于xmodmap的使用,可以通过命令行临时执行,重启失效,比如第一个办法,所以需要放在~/.profile在每次系统启动时执行
也可以直接修改xmodmap的配置文件,永久有效

我们先了解一下系统是如何处理键盘的输入

  1. 按下键盘时,会产生一个信号,也就是一个keycode值,相当于物理按键转化为一个数字
  2. 系统得到keycode值后,执行相应的动作,也就是这个数字又转化为了虚拟按键

也就是说,每一个键位的keycode值是不可能改变的,但是我们修改系统处理信号做出的动作,物理按键 -> 虚拟按键,就修改这个虚拟按键

我们可以使用 xev 这个工具来获取不同按钮产生的 keycode,使用方法

常用的keycode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
9 Escape
23 Tab
66 Caps
50 Shift_L
37 Control_L
64 Alt_L
108 Alt_R
105 Control_R
62 Shift_R
119 Delete
38 a
56 b
54 c
40 d
53 x
29 y
52 z

另外还可以获取16进值的keycode值

修改普通按键的行为

普通按键区别于Ctrl、Shift这些修饰按键,按下直接起作用,比如字母和数字
比如我们可以把a修改为b

1
2
keycode 38 = b
keycode 38 = b B

keycode 的作用是将一个按键与一串处理方法绑定,注意是一串而不是一个,空格隔开

好像最多可以写8个,第一个为单击时的处理方法,第二个为配合Shift时的处理方法,其他的我也不知道了,好像没Ctrl吧

还有keysym方法,可以直接写成

1
2
keysym a = b
keysym a = b B

它会自动转化成keycode

修改修饰键的行为

也就是Ctrl,Shift之类的,需要配合其他键一起使用
在终端中使用xmodmap -pm
我们可以知道

1
2
3
4
5
6
7
8
shift               Shift_L (0x32),  Shift_R (0x3e)
lock Num_Lock (0x4d)
control Control_L (0x25), Control_R (0x69)
mod1 Alt_L (0x40), Alt_R (0x6c), Meta_L (0xcd)
mod2
mod3
mod4 Super_L (0x85), Super_R (0x86), Super_L (0xce), Hyper_L (0xcf)
mod5 ISO_Level3_Shift (0x5c), Mode_switch (0xcb)

这是系统定义的8种修饰方式,然后shift分配给了Shift_L和Shift_R两个键,所以Shift_L和Shift_R都绑定shift的修饰方式了,也就是字母大写什么的

我们可以添加add shift = Control_L使Control_L同时绑定ctrl和shift的效果,这样,Shift_L, Shift_R, Control_L都绑定了shift修饰效果

也可以添加remove shift = Control_L,以清除Control_L绑定的shift修饰效果

而添加clear shift,可以清除shift所有的关联

要修改修饰键的行为

  1. 清除其修饰效果,也就是删除它绑定的修饰方式
  2. 修改信号对应的动作,也就是信号在系统中对应的虚拟按键
  3. 绑定修饰效果

比如我需要把Control_L和Shift_L交换

1
2
3
4
5
6
remove control = Control_L
remove shift = Shift_L
keysym Control_L = Shift_L
keysym Shift_L = Control_L
add control = Control_L
add shift = Shift_L

keysym可能看着有点奇怪,反正记住keycode始终没变,只是名字变了
写成这样就好多了,尽量使用keycode,keysym有可能出现意想不到的错误,比如休眠就失效

1
2
keycode 17 = Shift_L
keycode 50 = Control_L

如果只是把Shift_L修改为Control_L

1
2
remove shift = Shift_L
keysym Shift_L = Control_L

差不多就这样了吧

参考链接

文章作者: ourongxing
文章链接: https://orxing.top/post/d3c3145e.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 OURONGXING

评论