Chrome/Chromium 今日 Wayland 输入法支持现状

最新的信息请参见 https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland#Chromium_.2F_Electron

似乎有不少人总是有疑问,Chrome的Wayland输入法支持到底是什么情况,能不能输入,支不支持,那么就姑且来总结一番。本文仅代表写作时的状态,不代表后续的情况。(以下用 Chrome 指代 Chrome/Chromium)。

首先简单介绍一下 Chrome 对 Wayland 支持的情况。对于 Chrome 这种跨平台的项目来说,肯定有自己的抽象层,从而能够高效地利用对应平台的 GPU,图形栈。现阶段来说,这一层抽象的项目的名称是 Ozone,更多详细的介绍可以参考 https://chromium.googlesource.com/chromium/src.git/+/HEAD/docs/ozone_overview.md。这里的描述是这样的:Ozone 是在使用了底层输入和图形的 Aura 窗口系统下的平台抽象层。一旦完成,这个抽象将支持各种系统,包括嵌入式 SoC,或者新的 Linux X11 替代:Wayland/Mir 来启动 Aura。

现在如果要在 Wayland 上用原生 Wayland 而不是 XWayland 来显示,那么将要使用 Ozone 作为它的图形栈。那么 Ozone 有什么样的输入法支持呢?在很长的一段时间内,它的输入法支持只有 text_input_v1,并且需要使用 –enable-wayland-ime 来启用。对于不了解 Wayland 输入法架构的人来说,这里对 Wayland 输入法的现状做一个解释。

Wayland 上的输入法分为两个部分,程序和 Wayland Compositor 之间的协议,和 Wayland Compositor 和输入法服务之间的协议。无论对哪个协议,都需要通信的双方同时支持相同的协议才能正常运作。Compositor 和程序间的协议名称是 text-input,目前的版本有 v1 – v4。Compositor 方面 v1 几乎没有支持,只有 weston 作为一个 demo 有简单的实现。v2 的功能是 v1 的扩展,但没有获得广泛的支持,也没有合并到上游的 wayland-protocols 里面。v3 则是 v1 的精简版。因为它已经合并到了 wayland-protocols 里,因此有较为广泛的 Compositor 和程序支持。text-input-v3 Compositor 的支持包括 mutter,kwin,wlroots,基本上可以说涵盖了所有 linux 主流 Compositor。text-input-v2 的 Compositor 支持则只有 KWin。而在 Toolkit 方面,Gtk 和其他一些基于 Rust 或者完全手写的 Wayland 程序支持的是 text-input-v3。 不知出于什么理由,Qt 只支持 v2 和 v4,相信主要有两个原因,v3 的功能不足,以及单纯的诞生时间的问题。

Toolkit / Compositorwestonmutter(GNOME Shell)kwinwlroots(sway等)
Gtkv3v3v3
Qtv2
Chromev1
其他如 winit 等v3v3v3
text-input 的支持情况

和输入法之间的协议则主要有 zwp_input_method_v1 和 v2,v2 并未合并到上游,只被 wlroots 部分支持,以至于至今稳定版的 sway 也不能支持显示输入框。v1 则有 weston 和 kwin 支持。KWin 支持 zwp_input_method_v1 主要是为了 Plasma mobile 和 Maliit,在 PLasma 5.24 我修复了绝大部分 kwin 的 zwp_input_method_v1 在桌面上的使用问题,现在可以和 Fcitx 5 使用。具体配置方式可以参考之前的一篇博客。而特立独行的 GNOME 则采用了 IBus 的 DBus 协议作为程序和 Compositor 的协议,间接导致我不得不在 Fcitx 5 里实现 IBus 的 DBus 协议。Fcitx 5 做到了完全支持所有现存的 Compositor 和输入法之间的协议支持。所以不要说什么 Fcitx 不支持,根本不是 Fcitx 这一边的问题。

zwp-input-method 版本westonmutter(GNOME Shell)kwinwlroots(sway等)
v1
v2
zwp-input-method 支持情况

让话题回到 Chrome 的情况上来。Chrome 早在 2018年就实现了 text-input-v1 的支持,后续虽然有 text-input-v3 的支持请求,但并没有任何后续动作。前面我们说道,支持 text-input-v1 的 Compositor 有且仅有 weston,几乎等于是没有桌面支持。Ozone 作为抽象,没有使用 Gtk 作为图形栈,因此也就没有自动获得使用 im module 的能力。而在 2021 年,他们添加了 gtk im module 的支持,但是仅限启用 gtk 4 的情况。尽管他们添加了这样的支持,由于他们完全没有用 Gtk 作为图形栈实现图形显示,因此他们的实现仅有部分能正常工作。主要体现在一些按键处理,以及输入法窗口弹出位置上。这里为了解释发生问题的原因,再稍微介绍一下相关的 gtk im module 的工作流程。gtk im module 需要程序调用对应的 API gtk_im_context_set_client_widget 来告知程序当前是哪个 Widget。而对于完全没有使用 Gtk 作为图形栈的 Ozone 来说,他们没有这样一个 GtkWidget 可以传递给 gtk im module。因此,他们目前的实现就是创建一个从不显示的 dummy gtk window,作为传递给这个 API 的参数。这里略微对比一下架构不同的 Firefox,Firefox 是采用 Gtk 作为他们的窗口的 API 的,因此 Firefox 的窗口是一个货真价实的 GtkWindow,而 Ozone 的 Window 则是他们自己直接使用 wayland API 创建的,和 Gtk 完全没有关系。而他们创建的 Dummy window 是完全无法用于让输入法弹出窗口定位在正确位置上的。甚至于由于这个窗口完全不被显示,Fcitx 5 im module 的 client side input panel 技术受限于 Wayland 的限制(xdg_popup 的父窗口必须被显示才能显示)甚至无法显示。而即使考虑是否能使用 gtk 自己的 text-input-v3 的 im module,也因为这个 dummy gtk window 对应的 wl_surface 不被显示,因此不会获取焦点(和 text-input 绑定的 surface 必须获得焦点才能使用 text-input 进行输入法相关操作),也无法正常工作。也就是说,采用 gtk im module 在 Wayland 下 Chrome 正常使用输入法的道路是「几乎」被堵死的。存在两个问题 1、输入事件处理栈并非 Gtk,一些输入法 API (Forward Key,但是是小问题)并不能正常使用 2、图形栈并非 Gtk,弹出窗口的显示既无法使用 Gtk 自身的 text-input-v3 实现,也无法使用 fcitx 5 im module 的 client side input panel。

对于 Fcitx 5 的现状来说,在使用 Chrome + Ozone Wayland + fcitx 5 im module 的情况会 Fallback 到 Fcitx 5 的 X11 输入窗口。也许你有疑问,为什么要 Fallback 到 X11 的输入窗口,不能用 Wayland 窗口显示吗?因为 Wayland 完全无法指定要把窗口显示在哪里,而 Gtk im module 尽管不能获得 Gtk Widget,但好歹能获得一个相对浏览器窗口的坐标。尽管把窗口完全显示在正常位置需要获得窗口自身位置,但如果在「单屏幕」,「窗口最大化」的前提下,这个不完全的相对坐标能够利用 XWayland「恰好」把窗口显示在一个差不多的位置上,总比随机显示在不知道哪里要强得多。

弹出窗口位置能够相对正常显示的唯一的情况,则是 Chrome + GNOME + Fcitx im module + Kimpanel 的组合。这里稍微再讲解一下 Kimpanel 的显示窗口位置逻辑帮助理解为什么这个组合可以工作。Fcitx im module 获取的坐标位置,根据 im module 获取的当前显示服务器类型,会针对 Wayland 额外设置一个标记「Relative/相对」,表示这个坐标是相对当前窗口的坐标。而 GNOME 上刚好运行在 Mutter 同一个进程的 GNOME 插件,则可以获得当前激活窗口的坐标。因此 Kimpanel 如果看到「相对坐标」,就会请求当前窗口坐标然后加上相对坐标来显示输入法弹出窗口。而反过来,对于 KDE Kimpanel 的情况,KWin 和 Plasma 在不同进程的情形,则拿着一个相对坐标束手无策,只能「假装」它是绝对坐标移动一下。而对 KDE Plasma 一个刚刚好的巧合是,Plasma 自身是占用全部屏幕的全屏窗口,因此如果拿到绝对坐标它是可以任意的移动窗口位置的。

综上所述,当前 Chrome 如果要在 Wayland 下使用输入法,各种桌面的组合和实际效果如下:

1、weston + chrome –enable-wayland-ime ,完美支持

2、GNOME + fcitx im module + chrome –gtk-version=4 + kimpanel,支持,但坐标似乎有些小偏移量问题(疑似和边框大小有关)

3、非GNOME,或者不使用 Kimpanel 的 GNOME + fcitx im module + chrome –gtk-version=4 可以输入,但窗口位置不对。

4、chrome Xwayland,完美支持(或者说和 X11 支持程度一致)

而根据 Chrome 当前架构设计,想要完美支持大部分 Linux 桌面的道路只有一条,就是原生支持 text-input-v3 。事实上,考虑已经有 text-input-v1 的实现情况下,代码应该不是很难写。所以如果想要让 Chrome 听见你的呼声,顶这个 bug 就对了 https://bugs.chromium.org/p/chromium/issues/detail?id=1039161

顺便,这个问题也对 electron on wayland 适用。

最后说一些不算解决方案的解决方案,如果你只是想用 chromium 的网页渲染引擎,你可以考虑一些基于 QtWebEngine 的浏览器,例如 https://www.falkon.org/ QtWebEngine 的输入法实现是对接给 Qt 的,可以完全正常在 Wayland 下使用,但缺点也明显,就是不支持 Web Extensions,但 falkon 内置了一些常用功能如油猴 adblock,所以没有复杂要求也可以考虑使用。或者也可以换成 Firefox,它的 Wayland 下输入法支持很好。

P.S. 最后的最后 Fcitx 5 能对这件事做什么?什么也做不了。这不是 Fcitx 5 的 Bug。我是想不到目前有任何改动属于 Fcitx 项目代码的方式能够完美支持 Chrome。

如果非要让「我」力所能及支持点什么的话,1、可能就是给 KWin/Plasma 写一个Wayland 私有协议,允许把窗口移动到相对当前活动窗口的坐标位置上去给 Kimpanel 用。2、或者加回 KWin 删掉了的「没人用」的text-input-v1 支持。说实话,这两种如果写了都是技术债,第一个可能还有点用(通用意义上),但我也并非什么 KWin 的专家。就像我之前说的,我一个臭写输入法的,怎么就去开发 Compositor 去了。

Posted in fcitx development | Tagged , , , , | 15 Comments

New compose mode in Fcitx 5

1.5MB gif for demostration.

Basically it allows you to use backspace to modify the compose sequence, or type character directly with dead keys (e.g. you may simply press dead key once and continue to type).

If you want the old traditional X11 behavior back, you may simply uncheck the “Use new behavior” option in keyboard input method.

Posted in fcitx development | Tagged , , | Leave a comment

Setup Fcitx 5 on Linux (Video)

Recently I started to make some video with detailed step on how to setup Fcitx 5 on different distribution.

Helps are also welcome if you want to make an instruction for the distribution that you use.

Fedora/KDE: https://www.youtube.com/watch?v=FwqTtGEN4vQ (Vocal by me in English)

Archlinux: https://www.youtube.com/watch?v=8XDmLr6wb4M (No voice, English/Chinese subtitled)

Posted in 日志 | 1 Comment

一个小玩具:fcitx5-tmux

就是觉得这个应该还挺好玩的。一开始其实还想着靠着写这个练习一下 Rust,结果就发现这个文档丰富程度实在是感人,特别是你用一些很少人用的库的时候,觉得还是算了。C++糊一下也就200多行。

原理很简单,就是通过手工执行 bind-key 把 tmux (几乎)所有的按键都绑定成一个 dbus 调用命令,然后交给一个代理的 dbus 服务和 fcitx 进行交互。把处理的结果再利用 send-key 发送回来。

现实来说还是有很多不太理想的地方,例如Control 的组合键就无法区分大小写,还有一些其他的小问题,所以总之是当作一个玩具来写。

代码地址:https://github.com/wengxt/fcitx5-tmux

梦回CCDOS

Posted in fcitx development | Tagged , , | Leave a comment

Use Plasma 5.24 to type in Alacritty (Or any other text-input-v3 client) with Fcitx 5 on Wayland

Relationship between the input method server and applications under Fcitx5+KWin/Wayland

With the latest release of Plasma 5.24, the native wayland input method support in KWin is improved to support non-virtual keyboard input method like Fcitx 5. (There are lots of issues if you try to use zwp_input_method_v1 in 5.23).

This leads to a outcome that non-Gtk/Qt application using text-input-v3 can be used flawlessly under KWin Wayland. Though, there is some small step that you’ll need to follow.

First of all, I suggest you have most up-to-date Plasma 5.24 and Fcitx 5.0.14. I believe the distribution that picks up Plasma 5.24 should also have up-to-date Fcitx 5.

Next, you’ll need to make KWin Wayland to launch Fcitx 5. This is required because only the privileged client is allowed to talk to KWin on input method protocol. KWin will send a socket file descriptor to the input method and input method service need to use this socket to connect to KWin.

Thanks to a simple KCM, which is accessible from systemettings -> Virtual keyboard (Naming of the KCM is not so good, because it was designed for mobile phone to launch maliit initially.)

From there, just select Fcitx 5. This requires you to have up-to-date Fcitx 5 to make it show up in this KCM, because it requires a special new field in the Fcitx 5 desktop file.

Although kwin will launch input method in a pretty early stage, but there might still be some race condition if there is another mechanism (Like XDG autostart) to launch Fcitx 5. You can try to re-login to see if if works, if not, you may want to disable Fcitx 5’s own XDG autostart or what ever mechanism you’re using to launch Fcitx 5.

Theoretically you don’t need to re-login, KWin can reload it immediately after you apply the setting in systemsettings. I would just re-login to make sure everything it properly launched, then you should be good to go.

Hello world from Chinese Pinyin!

Should I keep setting GTK_IM_MODULE / QT_IM_MODULE / XMODIFIERS?

  1. QT_IM_MODULE
    Qt has text-input-v2 support which can be used if QT_IM_MODULE is empty, but it has some small issue regarding the preedit. Also, with current version of wayland input method protocol, there can be only one global input context for wayland. So right now it can be a problem if you want to use the “per-application” input state supported by Fcitx 5. But using Qt’s text-input protocol has one benefit, is that visually there won’t be blinking for input window.
  2. GTK_IM_MODULE
    Gtk has text-input-v3 support, but it’s preedit is poorly styled with bold font for highlight. Also, its surrounding text support is poorly implemented. So for now, using GTK_IM_MODULE=fcitx might still be good option if you want to have all Fcitx features.
  3. XMODIFIERS
    It’s required to support XWayland.
Posted in Linux | Tagged , , , , , , | 3 Comments