当然,这个并不是总是特别好用的。因为这里牵扯到第二个问题,就是程序的焦点问题。在你切换到终端的时候,你用来测试输入的程序就失去了焦点,会导致程序直接进入重置状态,很有可能无法达到原本想要调试的状态。这里就可以采取第二种方法,启动一个新的 X server,从而避免焦点抢占的问题。常用的一般就是 Xephyr。
然后就是本次说到的方式,让程序自己绘制界面。当然,缺点就是实现通过 im module 的话,就只能支持 Gtk / Qt 的程序,但相对来说可以覆盖大部分的程序了。我个人对于这个方法比较反感,因为感觉可能出问题的地方很多,对于程序来说添加一个额外窗口和过去的 im module 相比有了更强的侵入性。不过在其他很多系统上,例如 windows 和 uim 可能都使用了这个方式。
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:
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.).
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.