xdotool is fucking with dvp

前些天突然发现我的有些按键开始不灵了,惊出一身冷汗。

事情是这样的,作为一个重度Emacs用户,我喜欢用Sawfish(一种窗口管理器,可以把它想像成Linux下其他的窗口管理器,比如Gnome、Kde)把其他窗口的按键也映射成Emacs风格的。比如用C-f/C-b来进行光标右移/左移的操作;用C-s/C-r来完成一般程序里用F3/F4完成的搜索下一个/上一个的操作等等。

有一点蛋疼了吗?

更蛋疼的是,sawfish的按键修改对gtk的程序不管用,因为它用的给程序伪造键盘消息的接口被gtk社区的人认为有安全风险,就把它给禁止了。但是!还有另外一套XTEST的接口,是可以用的!xdotool用的就是这个接口。

用sawfish和/或xdotool您可以方便地实现Windows上按键小精灵的功能。Windows下还有一个叫autohotkey的程序,但它的脚本写起来挺费劲的,基本相当于你需要另学一门编程语言。

好了,问题来了,随着Debian的升级,不知什么时候起,我突然发现有一天xdotool不能正常的工作了。我想让它给我发Ctrl-f,但它给我发Ctrl-u出来!

一阵慌乱之后,我发现了规律,这个Bug跟我用的键盘布局有关,我用的不是一般的qwerty布局,而是dvp布局。xdotool给发出来的按键,就是从qwerty布局到dvp布局的映射/反映射(我也搞不清楚是正还是反,反正不对😭)。

折腾了一圈之后,发现只要我在登录到图形界面之后,重新设置过键盘映射,xdotool就能正确工作了。我是怎么发现的呢?呵呵,我有一个脚本,叫 toggle-dvp-us.sh ,可以用来切换dvp/qwerty的键盘布局。现在这个问题既然跟键盘布局有关,我当然会用这个脚本切换一下再看一眼咯,嘿,没想到切换之后,问题就不见了,再切回dvp也没有问题了。

所以,最后解决这个问题的思路很简单,我用一个环境变量记录一下登录之后有没有重新设置过dvp布局,如果没有的话,我第一次运行xdotool的脚本,就会重新设置一下,然后把那个环境变量给置上,这样下次就不需要重新设dvp了:

#!/bin/bash
while query-keyboard-state >/dev/null 2>&1; do
    sleep .1;
done

if test "$DONE_AAAAA" != true; then
    setxkbmap -layout us -variant dvp
    re-xmodmap 2>&1 | cat
    sawfish-client -e '(setenv "DONE_AAAAA" "true")'
fi

xdotool "$@"

这个脚本叫 xdotool-when-keyboard-clear