無標題文檔

在 Xorg 中配置苹果的蓝牙键盘

目前同时有台 MacBook Pro 以及 Thinkpad X1,所以想同时使用苹果的蓝牙键盘链接,碰到了键位映射的问题,所以记录下。这次折腾的主要原因是 Thinkpad 的左下角功能键的键位和苹果键盘是不一致,如图:

Apple Keyboard

最主要是对比 Thinkpad 的 Win(Meta) 键和 Alt 和苹果蓝牙键盘的 Apple 和 Alt 是相反的,如果同时使用会有转换的过程,因此需要转换下键位。

硬件方面链接蓝牙的过程就不复述了,Arch Wiki 中有很详细的说明。我使用的是 bluetoothctl 连接硬件,同时使用 BlueMan 作为 GUI 的前端。同时将 BlueMan 加入到 i3wm 的启动脚本中,能够做到自动链接,方便。

键盘链接成功以后,使用 xinput list 查看对应的 device id:

$ xinput list 
⎡ Virtual core pointer                        id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                  id=4    [slave  pointer  (2)]
⎜   ↳ Synaptics TM3072-003                        id=11    [slave  pointer  (2)]
⎜   ↳ Logitech M570                               id=14    [slave  pointer  (2)]
⎜   ↳ TPPS/2 IBM TrackPoint                       id=12    [slave  pointer  (2)]
⎣ Virtual core keyboard                       id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard                 id=5    [slave  keyboard (3)]
    ↳ Power Button                                id=6    [slave  keyboard (3)]
    ↳ Video Bus                                   id=7    [slave  keyboard (3)]
    ↳ Sleep Button                                id=8    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard                id=9    [slave  keyboard (3)]
    ↳ ThinkPad Extra Buttons                      id=10    [slave  keyboard (3)]
    ↳ Integrated Camera: Integrated C             id=13    [slave  keyboard (3)]
    ↳ Apple Inc. Magic Keyboard                   id=15    [slave  keyboard (3)]

其中,能够看到苹果的蓝牙键盘的 device id 是 15,需要暂时记下这个值。然后使用

$ setxkbmap -option altwin:swap_alt_win -device $DEVICE_ID

就可以测试 Win 键和 Alt 键是否对调成功。顺便说一句,对应的还有个命令可以将 Caps Lock 利用起来:

$ setxkbmap -option ctrl:nocaps -device $DEVICE_ID

这样子 Caps Lock 就映射到 Ctrl 键了。具体更多的设置可以在这里 查看(我是 Arch Wiki 的搬运工 😄)。

这样子还有点不方便的地方,就是每次链接蓝牙键盘的时候都要跑下这个命令,于是还是考虑到使用 udev 脚本去自动化。下面是我的 udev 脚本,可以供参考:

ACTION=="bind", SUBSYSTEM=="hid*", DRIVER=="*apple*", RUN+="/usr/bin/sudo -i -u <user> /<path>/key-mapping.sh"

然后还需要考虑到插入 USB 键盘的情况,这再多加一条规则:

ACTION=="bind", SUBSYSTEM=="usb", ENV{ID_VENDOR}=="Apple*", RUN+="/usr/bin/sudo -i -u <user>  /<path>/key-mapping.sh"

其中,key-mapping.sh 是复制下上面命令的脚本。

然后,将这个命令保存到个 rules 文件中,例如我的文件命名是 90-bluetooth-keyboard-mapping.rules 然后放到 /etc/udev/rules.d

最后,重启 udev 规则 sudo udevadm control -R 即可。

- eof -

emojify.php, 让 Typecho 用上 Emoji 表情

Emoji 能让单调的沟通多些色彩,团队这边近期也开始使用 Emoji 作为 git 提交的提示符使用

其中,有很多相关的命令行工具可以使用。但翻遍了一圈,竟然没有 PHP 相关的类库,于是就自己写了一个( 很久没写 PHP 了,感觉生疏了好多 😑 )。

表情符号的数据源自好几个项目,所以从数据量上面来说应该是目前 emojify 类工具的超集了,超过了两千多条。例如,可以完全放心使用 emoji-cheat-sheet 下的定义。

具体的对应数据可以在这里查看(文件很大),顺便还可以看看自己系统对于 Emoji 字符的支持情况。

因为是 PHP 相关,所以在完成这个简单的类库以后顺便做成了 Typecho 插件。这个插件安装很简单,只要在 Typecho 的 Plugin 目录下无脑 git clone :

git clone [email protected]:mingcheng/emojify.php.git  Emojify

然后使用管理员登录,开启插件就可以使用了 😘。Github 的地址在 https://github.com/mingcheng/emojify.php 这里,欢迎测试以及提交 Issues(当然,你也可以留言测试下 Emoji 😄 )。

- eof -

rx-filewatcher.java,基于 NIO WatchService 的 Reactive 封装

嫌我啰嗦的话,直接看代码: https://github.com/mingcheng/rx-filewatcher.java

在写个小东西需要监控文件改变状态的时候,用到了 NIO 东西很方便也好用。但是,在使用 WatchService 的时候碰到了些问题。

首先,使用原生的接口必须开启个线程,然后使用个持续循环去读取 WatchEvent (这也是大部分教程描述这样子做的):

WatchKey key;
while ((key = watchService.take()) != null) {
    for (WatchEvent<?> event : key.pollEvents()) {
        //process
    }
    key.reset();
}

这样子做有几个不好的地方:一是开了个匿名线程,如果后期代码也有类似的情况,线程就不好处理,而且很容易无法监控到这个线程的状态;第二就是破坏了代码原有的业务逻辑,读到这里如果阅读代码的小伙伴不熟悉 WatchService 就很难理解。

其次,WatchService 的注册是一次性的,也就是说无法监控到子目录以下的情况,必须随时监控是否创建了子目录然后再对应 register 子目录 watch(这样子一个简单的功能就会搞得非常的复杂)。

我考虑到使用 Rx 重写这块的代码,然后翻阅 Github 的时候发现已经有人造了这个轮子。代码量不大,但核心功能是我想要的,只是最新更新已经在三年前了。

集成了 Helmbold 这个哥们的库以后,又发现了几个问题:

  1. 这个库是写在三年前的,还在用 Rx1 的库,和我目前的 Rx2 有部分的不兼容;
  2. dispose 部分有问题,dispose 以后线程没有终止还在运行;
  3. 获取到 WatchEvent 的 Context 只有文件名没有路径。

因为代码量本身就不是很多,同时考虑到这块还是需要以后自己维护,因此 fork 了他的代码自己做了些改造

对比以上的原生代码,使用 Rx 封装的代码就会干净和直观很多:

PathObservables
  .subscribeOn(Schedulers.io())
  .watchRecursive(Paths.get("some/directory/"))
  .subscribe(event -> System.out.println(event));

然后,基本上已经满足了我的需求。

顺便说下,WatchService 里面还有个坑,就是使用网络磁盘映射的时候,可能会造成 WatchEvent 会有丢失,在这里有详细的讨论,这是目前 NIO 已知的 Bug。如果你对文件状态监控要求实时性比较高,建议不要使用 WatchService 使用其他的方案。

相关的资源:

  1. https://github.com/mingcheng/rx-filewatcher.java
  2. https://docs.oracle.com/javase/tutorial/essential/io/notification.html

后记,原作者已经 merge 了我的 pull requests

我的照片

嗨!我叫「明城」,八零后、码农、宁波佬,现居杭州。除了这里,同时也欢迎您关注我的 GitHubTwitterInstagram 等。

这个 Blog 原先的名字叫 Gracecode.com 、现在叫 「無標題文檔」 。 要知道作为码农取名是件很难的事情,所以不想在取名这事情上太费心思。

作为八零后,自认为还仅存点点可能不怎么被理解的幽默感,以及对平淡生活的追求和向往。 为了避免不必要的麻烦,声明本站所输出的内容以及观点仅代表个人,不代表自己所服务公司或组织的任何立场。

如果您想联系我,可以发我邮件 `echo bWluZ2NoZW5nQG91dGxvb2suY29tCg== | base64 -d`

分类

搜索

文章