Client Side Input panel for Fcitx 5

(English version is at the end of this post.)

输入框的定位相关的问题其实很复杂,过去 Fcitx 总是自己绘制相关的窗口。X11 这个办法还好使,但是其他情况可能就没这么好使了。让客户端绘制窗口的想法其实比 Fcitx 5 要早得多,最早是为了 fbterm 而增加的支持。

显然 fbterm 没法利用任何来自显示管理器的界面,所以它需要自己绘制它自己的界面。那会儿我添加了一个很简单的实现来支持这个功能。

为了正确显示界面需要支持以下功能:

  • 窗口显示在光标的位置
  • 窗口不能移出屏幕

在 wayland 里,和 X 最大的区别就是不知道窗口的位置,所以不得不使用特别的方法来支持。

  • 用 wayland 的输入法协议的话,它确实是支持将某个窗口标记为输入法窗口并让混成器帮你进行定位,但是需要程序自己先使用 wayland 的输入法协议,混成器也要支持这个协议。目前这两部分的支持并不好。
  • 或者让窗口传送一个相对坐标,然后让混成器帮忙移动窗口。gnome wayland + kimpanel 的扩展就是这样进行定位的,因为 kimpanel 扩展正好是运行在混成器里面所以知道所有的窗口信息。但是让各种混成器都支持这个也不太现实。
  • 然后就是本次说到的方式,让程序自己绘制界面。当然,缺点就是实现通过 im module 的话,就只能支持 Gtk / Qt 的程序,但相对来说可以覆盖大部分的程序了。我个人对于这个方法比较反感,因为感觉可能出问题的地方很多,对于程序来说添加一个额外窗口和过去的 im module 相比有了更强的侵入性。不过在其他很多系统上,例如 windows 和 uim 可能都使用了这个方式。

不过相比只是因为担心就不采取行动的话,还不如先试一试,毕竟解决实际存在的问题的意义更加重大。想要测试的话需要使用 fcitx5 / fcitx5-qt / fcitx5-gtk 的 git代码。

目前还有一些实现的限制:

Gtk 3 不支持已经实现的窗口重新移动位置,Gtk 4 对于不支持较新的 xdg popup positioner 的混成器的是采用隐藏再显示窗口的方式,而这个方式会导致窗口闪烁(Qt 用同样的 hack 就不会,我猜测是 Gtk 有和刷新率对齐之类的操作?)。所以我干脆就没在 Gtk 3 用这个 hack,毕竟闪烁起来看着更糟一点…

Qt 的话出于没有暴露 xdg positioner api 的限制,在窗口定位方面并不能保证不移出屏幕,因此我采取了另一个方式:保证输入框总是在窗口范围内。这个对于小窗口并不是特别友好,例如 krunner,不过我也没有更好的办法了。

本文就是用 firefox + wayland 输入的,整体来说还行……Gtk 3 定位延迟虽然有点难受不过反正我也没更好办法啦。

In the past years, fcitx always renders its pop up on by itself. This is Ok for X11, but not so good for other cases. The idea of letting client to render its UI actually existed long before fcitx 5 comes out. It was first introduced in fcitx 4 for fbterm.

Obviously, fbterm can not render UI using any display server, so it need to render the UI by itself. At that time I added an adhoc implementation for it to display a UI with a minimum implmentation.

In order to properly display an input window, there are certain features need to be supported:

  • Input window should be positioned right beside the cursor poistion.
  • Input window should not be placed out of screen.

In the wayland world, things is also very different from X. Without the knowledge of window positioning, we need to have some different way to support this.

There are current multiple approaches being used with in Fcitx:

  • With zwp_input_method, the wayland protocol, it has support to declare a surface to be input panel window, and compositor will position it properly. Unfortunately, this requires client to use wayland and text-input protocol, which is not yet well supported by the clients.
  • Or, with im module, send over a relative coordinates and ask composition to position the window with this “relative” coordinates instead of traditional absolute ones. This is used by gnome wayland + kimpanel extension. Luckily, gnome-shell extension runs within compositor, which means it has all information about the windows, e.g. which window currently has focus, window position. It can also to freely move the window created by extension. But this won’t scale anyway, because it’s unlikely to make all the compositors to support the same thing.
  • Then we can still ask client to render the window, just like fcitx-fbterm. This is an intrusive way for the application, so I never tried this approach before. Just FYI, this approach is being used by many other systems, for example, Windows, So it is not an rare solution. I also heard that uim is using such approach. But it also has its downside: duplication of code for rendering, inconsistency between toolkits, only support Gtk/Qt, more likely to have problem for certain weird application.

There is no silver bullet to this problem, but I always want to help our users to type text more freely, regardless of which desktop they want to use.

So free free to give it a try, you’ll need git from fcitx5 / fcitx5-gtk / fcitx5-qt. So far I tested many applications, including libreoffce, firefox that I suspect may have problem, but so far it looks good.

There still some limitation in this implementation:

  1. Gtk 3 doesn’t support xdg popup reposition, while this is not yet supported by a lot of compositor, Gtk 4 workaround this automatically by show and hide the window. But if I use such workaround manually in Gtk 3, it will cause the window flicker (Similar code in Qt won’t, which is really weird. My guess is this is related to frame alignment or sth.).
  2. Qt doesn’t expose all the possible interface for xdg popup, which means the position can’t use the slide / flip parameter like Gtk to ensure it is within the screen. So I took another approach here: ensure the popup window always within the range of original window. This doesn’t work well for tiny window like krunner, but I have no other good solution for it. Qt 6’s wayland is able to get the native interface for xdg popup, so it might be possible to do some manual coding there.
Posted in fcitx development | Tagged , , , | 3 Comments

构建一个给 WPS 用的 fcitx im module

WPS 处于许可证的考虑,里面自带的 fcitx 的 im module 是由 WPS 的开发自己写的。但是这就有一个问题了,他们对于跟随 fcitx 上游的变化可以说是几乎没有。在 Fcitx 4 已经加入了对于 flatpak / fcitx 5 的支持之后他们并没有做出对应的改变,导致了现在的很多问题。

在过去的这篇也曾经写到了,如何构建一个给闭源 Qt 程序用的模块。

我不知道过去有没有人干过这样的事情,但我们现在就来做这么一趟。

首先观察 WPS 使用的 Qt 版本

$ ls /usr/lib/office6/libQtCore.so -l                       
lrwxrwxrwx 1 root root 18  1月 15 14:23 /usr/lib/office6/libQtCore.so -> libQtCore.so.4.7.4

显而易见,是 Qt 4.7.4,出于 Qt API 的修改可能有兼容性的考虑,我们先去下载一下 4.7.4 的源代码。现在可能面临两个问题:

1、Qt 4.7.4 的代码在当前系统上可能编译不了了

2、WPS 的 Qt 可能修改过大。

当然 2 的概率相对是较小的,即使内部的修改也不太可能影响到 API。但 1 确实是有这样的现实的问题。而且在这次也确实遇见了,但是我们其实不需要大部分的工具,我们需要的只是 moc,qmake 这两个工具,即使其他都编译失败也没有关系,因为 WPS 里面已经有了对应的编译好的库。

下载源代码之后,编辑 configure 文件,设置 CFG_INOTIFY=no ,执行

 ./configure -opensource -confirm-license -no-openssl
make

当然确实是出现了一些奇怪的错误,不管他。我们其实需要的只是生成的 qtconfig.h 文件和 qmake 和 moc。

然后准备一些 fcitx 的源文件,用 fcitx 或者 fcitx5-qt 都可以,早前我已经基本让 fcitx 4 的 im module 脱离需要链接 fcitx 本身的库,只需要链接 Qt 即可。但是我还是引用了一些 fcitx 的头文件。用 fcitx 4 的代码就需要手动复制一些 enum 的定义过来。因此 fcitx5-qt 可能更好一点。

我特意修改了一下 fcitx5-qt 的代码让它可以不修改就能编译通过。写了一个专门的 cmake 配置,我也就是随意一写,所以放到了个人帐号上。 https://github.com/wengxt/fcitx5-wps 。利用 git submodule 直接引用了 fcitx5-qt 的代码,所以 clone 之后别忘了 git submodule update –init

具体编译参数就需要设置 -DQT_QMAKE_EXECUTABLE=<qt源代码路径>/bin/qmake 还有 -DWPS_LIBRARY_DIR=<WPS 的 qt 库路径>

然后生成了库之后把他复制到 WPS 对应目录 /usr/lib/office6/qt/plugins/inputmethods/qtim-fcitx.so 测试运行。当然,最好删掉原来的那个 libqim-fcitx.so 文件,避免环境变量设置成 fcitx 时会读到这个。

嗯?为什么不行?这时候就要利用 Qt 的一个调试用环境变量来测试了

QT_DEBUG_PLUGINS=1 /usr/lib/office6/wps

可以发现有如下输出:

QFactoryLoader::QFactoryLoader() looking at "/usr/lib/office6/qt/plugins/inputmethods/qtim-fcitx.so"  
In /usr/lib/office6/qt/plugins/inputmethods/qtim-fcitx.so:
 Plugin uses incompatible Qt library
 expected build key "x86_64 linux clang full-config", got "x86_64 linux g++-10.2.0 full-config"
"The plugin '/usr/lib/office6/qt/plugins/inputmethods/qtim-fcitx.so' uses incompatible Qt library. Expected build key "x86_64 linux clang full-config", got "x86_6
4 linux g++-10.2.0 full-config""  
        not a plugin

哦,QT_BUILD_KEY 对不上号呗。好办,直接强行修改生成的对应 qconfig 文件的内容。

在 Qt 源代码里面找到 src/corelib/global/qconfig.h ,把 QT_BUILD_KEY 修改成 WPS 对应的。这部分是直接构建在 plugin 里面的,所以重新编译。测试输入,成功。

Posted in fcitx development | 1 Comment

仿原神 UI 的 KDE 系统配色

原神痴竟是我自己

下载地址:https://uploads.csslayer.info/uploads/Genshin.colors

Posted in Linux | Tagged , , | Leave a comment

如何现在就用上 Fcitx 5 (Flatpak)

折腾了很久的自动构建,现在终于可以拿出来给大家用一下了。当然,据说 flathub 有特色网络问题……这部分我就不负责解决了。

首先添加源:

# 添加 flathub 到用户级
flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
# 添加 fcitx5-unstable 到用户级配置
flatpak remote-add --user --if-not-exists fcitx5-unstable https://flatpak.fcitx-im.org/unstable-repo/fcitx5-unstable.flatpakrepo

安装 Fcitx 5 和输入法:

flatpak install org.fcitx.Fcitx5
flatpak install org.fcitx.Fcitx5.Addon.ChineseAddons
# 例如需要 Rime: flatpak install org.fcitx.Fcitx5.Addon.Rime
# 可以用 flatpak remote-ls fcitx5-unstable 查看有哪些包

然后,在本地非 flatpak 程序上使用的话,还需要安装 fcitx 4/5 的 im module。这个 repo 除了提供另一种更新方式之外,也主要是为了方便还没提供 fcitx 5 的发行版测试。fcitx 4 只要是最近的版本,都可以直接和 fcitx 5 配合使用。环境变量方面当然还是和过去一样,比较传统的就是设置在 ~/.xprofile 里面(和过去一样,如果你已经对 fcitx 4 进行设置了就不用修改什么。)

export QT_IM_MODULE=fcitx
export GTK_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx

自动启动就把 flatpak 的 fcitx 5 的 desktop file 加入到自动启动即可。但相对的也需要阻止 fcitx 4 的自动启动。如果没有拆包而导致 fcitx 被安装,如果系统提供了 /etc/xdg/autostart/fcitx-autostart.desktop 就需要在 ~/.config/autostart/fcitx-autostart.desktop 新建如下内容的文件

[Desktop Entry]
Hidden=true

如果是采用 im-config 等类似的方式,则直接禁用并自行配置环境变量即可。

目前仅仅是测试版本,可能会遇见各种问题(例如图标缺失等),如果在用 flatpak 版本的时候有任何问题请汇报到 https://github.com/fcitx/flatpak-fcitx5/ 。

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

关于之前发在 Archlinux CN 群里 Fcitx 5 问卷里面问题的几个回答

1、sni图标似乎不响应系统(kde)配色了?

图标上来说用的是 input-keyboard-symbolic ,不幸他们没这个图标的 plasma 版本。其他图标都挺正常的啊?可以给 breeze 提交一个希望增加 input-keyboard 这个图标的请求。

2、非kde下面托盤和托盤右鍵菜單太醜了,還沒之前的4好看。

右键菜单和输入框一个主题吧。自带主题来说应该还行,没有修改的打算。如果你用的别的主题那就和 Fcitx 无关了。

3、更好康的皮肤,更佳的英文混输体验

皮肤本身就不说了,我自己应该不会再做什么别的皮肤。不过目前给皮肤增加了好几个新的功能,应该能帮助大家做出更好的皮肤。一个是 Overlay 图片,一个不会受到缩放的图片,可以固定显示在背景上。另一个是增加了 KWin 的模糊背景的支持,目前暂时可以设定一个矩形区域并模糊。

混合输入这个应该继续学习一下有什么办法……短期内肯定是没有大的改进。

4、Doesn’t work well on Sway, but that’s mainly a Wayland input protocol issue, no rush.

这个确实是比较难的事情…不过我对 wlroots 那个协议很不满意,下一步反正是打算自己实现一个新的协议。

5、fcitx5 拼音的繁体翻译建议改一下 OpenCC 的配置档或者提供选项供偏好设定,个人不是很喜欢直接用 s2t 的翻译

安排上了,已经修改了。

6、Kimpanel的菜单要是能模糊就好了

……右键菜单是就是普通的菜单,输入框本身也可以模糊,如果你的系统输入窗口没有模糊建议检查窗口配置。

7、完善对 steam 的支持

steam 完善对输入法的支持才对

8、希望能增强对wsl/wsl2环境的兼容性

用 opensuse leap 测试了一下,没有问题。建议网上搜索一下别人的设置步骤。

9、词库太少 云输入太慢

open-gram 确实数据版本是有年头了…不知道能不能联系他们有机会在训练一次。其他有可以直接下载 sogou 词库的功能,另外也可以试试 zhwiki 这个词库。

10、支持用户自己加入个别未收录的字

现在就可以的。拼音词库的话可以随便添加字(只要拼音本身合法),如果有特殊读音的需求请提交 issue 给 libime。

11、可以配置指定程序初始化指定的输入法(比如可以手动设置tg默认使用中文,终端默认英文)

如果急切需要的话,其实写个插件就可以实现。

12、对wm有更好的支持

这个……不够具体。不太懂说的意思。

Posted in fcitx development | Tagged , | Leave a comment