Emacs Application Framework 支持大写字符事件了!
Emacs
EAF
2019-09-21 1182字

Emacs Application Framework 是我为 Emacs 设计的新一代应用框架, 可以利用 PyQt5 去扩展 Emacs, 你可以用 PyQt5 去实现任何你想实现的图形应用,并完美和 Emacs 进行无缝融合。

但是 EAF 从发布到现在有一个非常不爽的 bug 就是无法输入大写字符, 几个月时间都百思不得其解。

事件监听原理

EAF 的键盘事件监听原理是:

  1. eaf.el 中监听 Emacs 端每次键盘事件敲击的钩子, 然后放到 eaf-monitor-key-event 函数中进行键盘事件过滤解析
  2. eaf-monitor-key-event 中探测到是单字符按键的时候, 通过 RPC 协议, 发送 send_key 消息给 EAF 的 Python 进程
  3. EAF Python 进程接到来自 Elisp 进程的 send_key 事件消息后, 在 Python 进程中的 fake_key_event 函数中构造 Qt 键盘事件 QKeyEvent , 最后通过 QApplication.sendEvent 函数发送事件给 Python 进程的 Qt5 控件

通过上面的三个步骤, EAF 实现了 Emacs 端控制 PyQt5 应用事件的完整逻辑。

问题线索

每次在 Emacs EAF Buffer 中敲击大写字符, Emacs 会报错 buffer read-only 的错误

重新思考

  1. 既然输入大写字符时候, EAF 的 Python 端应用没有任何反馈, 证明没有接受到 Elisp 端发送的键盘事件。
  2. 如果 Elisp 端没有发送键盘事件, 一定是 eaf-monitor-key-event 这个函数没有执行

那每次输入大写字符时 EAF 报 read-only 的错误为什么会导致 eaf-monitor-key-event 函数没有被正常执行呢?

这几个月都在想这个问题, 可是每次想到这个问题, 都是一头雾水, 百思不得其解。

今天在想这个问题的时候, 我一直在反复敲击大写字符, 比如我要敲击 H, 左手先按 Shift , 右手按 H, 左手按 Shift 的时候已经报 read-only 的错误了, 突然灵光一闪…

大胆猜测

因为 EAF 的 buffer 最开始设计的时候, 只是用于传递窗口位置和大小给 EAF 的 Python 端, 并不会在 EAF Emacs buffer 中敲入任何字符, 所以, 我把所有 EAF Buffer 都默认设置成 read-only 模式。

会不会因为左手按 Shift 的时候, 已经触发了 read-only 的错误, 然后导致 eaf-monitor-key-event 函数无法调用, 最终无法发送大写字符的事件给 EAF Python 端?

搞定

按照上面的猜测, 首先移除了 EAF Buffer 的 read-only 模式, 然后在 EAF Python 端的 fake_key_event 函数中根据传递事件字符串是否是大写键来给 QKeyEvent 事件添加 ShiftModifier 的修饰符。

重启 EAF 测试, 哇, 搞定了。

皇天不负有心人, 这个纠缠了我几个月的 Bug 终于被我给解决了, 哈哈哈哈。