Emacs for Windows的IME输入法字体大小修复
本文介绍我之前给 GNU Emacs for Windows 上输入法字体大小实现跟随缩放而缩放.
相关的 bug报告.
1. 问题描述
GNU Emacs在Windows方面人手不足, 这个问题年久失修, 是长期问题.
表现为IME输入法preedit窗口的字体大小不会跟随着emacs字体的缩放
而缩放, 导致视觉上特别小.
2. 前置知识
首先要了解Windows上的输入法api, 微软提供了两套api, GNU Emacs使用
IME api, 这是Windows老牌api. 还要了解Emacs相关代码和Windows窗口
事件循坏且有基础Windows桌面开发经验.
GNU Emacs政策禁止AI编写代码, 要遵循相关政策知道贡献指南.
开发流程通过邮件列表和linux一模一样.
参考链接
- https://en.wikipedia.org/wiki/Event_loop
- https://en.wikipedia.org/wiki/Input_method
- https://github.com/microsoft/Windows-classic-samples
- https://learn.microsoft.com/en-us/windows/win32/intl/wm-ime-composition
- https://learn.microsoft.com/en-us/windows/win32/intl/ime-composition-string-values
- https://learn.microsoft.com/en-us/windows/win32/api/imm/nf-imm-immgetcompositionstringw
- https://www.gnu.org/software/emacs/manual/html_node/emacs/Contributing.html
3. 修复过程
PATCH的实现
Emacs原先代码只调用了 ImmSetCompositionWindow,
没有设置相关结构体, 准备工作要做的比较多且要注意线程安全.
修复路径
- 调用 ImmSetCompositionFont 传入 LOGFONTW 设置字体大小.
- 通过全局 w32_system_remap_font 使用 GetObjectW 填充 LOGFONTW 结构体.
- 在 lisp 线程里面找到有调用 PostMessage 通知IME相关事件调用栈,
通过 faceremp 机制访问Emacs动态映射的字体并用 w32_system_remap_font 保存.
- 在 lisp 线程里面找到有调用 PostMessage 通知IME相关事件调用栈,
- 通过全局 w32_system_remap_font 使用 GetObjectW 填充 LOGFONTW 结构体.
相关技术细节bug报告会更详细
4. 后日谈
经过我的坚持和努力最终修复了这个问题, PATCH改动不大, 但浓缩了大量知识
中间遇到了线程安全, 不了解Emacs代码架构等问题. 需要感谢GNU Emacs的
核心成员 Eli Zaretskii 指导和review, 还要感谢 Emacs China 的坛友测试.
在LLM流行的当下, 解决这个问题所需要的知识可以轻松获取, 我不知道以后AI Coding
会发展成什么样, 它提升代码编写效率实打实且聪明模型写代码往往正确. 但LLM的代码也
确实存在版权问题, 即AI会在你不知情下使用别人仓库的代码, 有大量相关报道和案列,
这是GNU项目当下所遇到的版权问题.
这是我第一次给GNU项目贡献代码, 我签署了相关fsf版权协议, 这个过程完全电子化,
非常有趣的一次贡献, 让我更加了解GNU项目的思想和历史和熟悉邮件列表交流.
提交合并的那一刻, 正式成为了GNU Emacs的贡献者我很高兴, 用 RMS 的话来说
我也成为了追求自由软件的人且不是搞开源软件的而是自由软件, 这点很重要😉.