0 诡异的退格键
最近在用glfw和dear imgui写一个简单的deepseek客户端,又遇到了“喜闻乐见”的输入法问题。最令人恼火的就是退格键不能被正确处理。就像下面这个视频展示的,预编辑的时候,按下退格键不仅会删除预编辑的内容,还会删除已经输入的内容,体验稀烂。
在Linux版本的Minecraft上也会有这样的问题,问题的根源同样是glfw1。
另外,在Wayland下,因为没有实现wayland的输入法协议,glfw直接用不了输入法。
1 临时解决办法
强制使用X11
目前Wayland下面的输入法问题可以说是一团糟,一切都处于过渡状态。解决输入法用不了的最好办法,就是不要用Wayland。在glfwInit()之前,强制glfw选定X11平台。
#ifdef __linux__
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
#endif
给glfw打补丁
GLFW处理XIM协议2的方法不太正确,没有正确过滤掉部分键盘事件(比如输入时的退格键)。下载这个补丁,用patch
命令打到glfw
3.4的源代码上。这个补丁的改动很小,就是让glfw无视被过滤掉的事件。类似的解决方案早有人在MC的bug
report里给出,不知为何glfw至今未改正。
@@ -1242,6 +1245,9 @@ static void processEvent(XEvent *event)
case KeyPress:
{
+ if (filtered) {
+ return;
+ }
const int key = translateKey(keycode);
const int mods = translateState(event->xkey.state);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
2 Linux混乱不堪的输入法
Linux下输入法问题繁多,很大程度是因为缺少稳定、统一的协议。其次,主要开发者中,中国人和日本人少,大部分开发者不用输入法,对这个问题不太重视。最早X11制定了XIM协议,Tedyin的博客3给出了一个很好的例子解释这个协议,建议阅读。XIM协议看起来简洁明了,而且也能用,但据说在特定条件下会导致程序卡死4。社区后来不知出于什么原因,没有进一步改进XIM协议,而是由GTK和Qt分别开发自己的IM Module——从此天下大乱,装个输入法都要手动配几个莫名其妙的环境变量。GLFW既不是GTK,也不是Qt,就更麻烦。
再后来,为了方便输入法开发,又出现了ibus和fcitx。ibus据说在非GNOME环境下表现不佳(但是我没查到具体的问题),且其GNOME下的拼音输入也有不少bug5。在国内社区持续的推广下,现在fcitx是中文输入的主流。
与此同时,Wayland正在逐步取代X11。很遗憾的是,Wayland的出现非但没有缓解输入法问题,反而将其进一步恶化了。Wayland自己另起炉灶,搞了v1-v4一系列协议6,具体兼容情况各不相同。应用开发者的反应没有协议更新的速度快,通常也不会把IME支持放在比较优先的位置,就导致过渡阶段💩一样的体验。
总之,在2025年的今天,Linux的输入法问题成了最混乱、最糟糕、最劝退的问题之一,上Arch中文论坛搜“Wayland+输入法”,能搜出来一整页的帖子。主要开发者长期忽视IME,造成社区不断分裂、造新的轮子,旧的问题刚刚解决,新的问题又产生了。就结果而言,如今哪怕是处理一个很常见的输入法问题,都需要很多无关的底层知识。Linux的输入法完全不应该这么复杂,本来应该和Windows一样简单才对。