简单来说就是这样一件事,std::unique_ptr 在析构途中调用了 .get() 会发生什么这样一个问题。
当然,你是不应该写出这样的代码的……但是有时候这样的行为可能并不是非常明显。所以就会导致问题…
一个 FreeBSD 上的人汇报了在 Linux 上没有的 crash。估计是 libc++ 和 libstdc++ 的行为差别。一个在析构途中就返回 null 了,一个还是返回原始的指针。
总之,小心避免写出这样的代码吧。
简单来说就是这样一件事,std::unique_ptr 在析构途中调用了 .get() 会发生什么这样一个问题。
当然,你是不应该写出这样的代码的……但是有时候这样的行为可能并不是非常明显。所以就会导致问题…
一个 FreeBSD 上的人汇报了在 Linux 上没有的 crash。估计是 libc++ 和 libstdc++ 的行为差别。一个在析构途中就返回 null 了,一个还是返回原始的指针。
总之,小心避免写出这样的代码吧。
I have been always care about the compatibility. Fcitx 5 will be able to type with either fcitx 4’s im module, or fcitx 5’s im module.
Fcitx 5’s im module will announce itself to accept both “fcitx5” and “fcitx”. Even if you did it wrong or forget to upgrade, application will still be able to pick up one of the fcitx im module. Even if it is the wrong one, the latest fcitx 4 im module is compatible with fcitx 5 server. There is no more excuse if you configure it wrong.
Even today, I just commit the code to even support ibus im module. So, when you start fcitx 5, it will automatically replace any existing ibus and initiate a shim dbus layer to provide ibus input context interface. So even your system is wrongly configured or forced by your desktop to use ibus im module, you should still be able to use fcitx anyway, as long as you didn’t forget to start it
.
Due to the fact, that Qt 5 does not support XIM, the only way to type with fcitx under Qt is to use platforminputcontext plugin. The problem is that for some proprietary software like mathematica, it is impossible to use the system Qt plugin because the Qt version does not match (also the library path may not be correct).
If the proprietary software uses shared library version of Qt, it is still possible to get a special version of platforminputcontext plugin compiled. Though, they may have private modification on the Qt library, but it is highly likely the plugin interface is not changed so we can compile it with official Qt 5 source code but link to the private shared Qt library in the proprietary software. So here’s how I did it for mathematica.
First, you need to figure out which version of Qt that the software is using, this can be done easily by using some very hacky tool like strings / objdump since Qt encode it’s compilation info in Qt5Core library in string literals.
$ strings /opt/Mathematica/SystemFiles/Libraries/Linux-x86-64/libQt5CoreWRI.so.5 | grep "Qt 5" Qt 5.6.2 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 4.8.2 20140120 (Red Hat 4.8.2-15)) This is the QtCore library version Qt 5.6.2 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 4.8.2 20140120 (Red Hat 4.8.2-15)) If that is not possible, in Qt 5 you must at least reimplement
Now we know it’s Qt 5.6.2. Then we can go to Qt’s offical site to download a official version of Qt 5.6.2. http://download.qt.io/official_releases/qt/5.6/5.6.2/ You can just use the QtCreator bundled with in it so it’ll be much easier to get compilation argument right.
Then, use QtCreator and choose import project from Git, https://github.com/fcitx/fcitx-qt5/ , and select the Qt that comes with your installation, instead of your system Qt 5. I managed to make fcitx-qt5 plugin standalone recently, so it will be really easy to get it compiled.
But remember, we need to link it against the mathematica’s Qt, instead of the Qt binary that we just installed. The problem is, Qt relies on qmake to find the library path, and it is hard to make it find the mathematica’s Qt. In order to solve this problem, we can directly hack the final link command line generated by cmake.
First, cd to the right path. fcitx-qt5’s plugin does not rely on fcitx-qt5’s library any more, so it is possible to only compile and copy the plugin library. If you already compiled it with QtCreator, you need to run make clean first. So here’s what it looks like:
# Locate the build-fcitx-qt5-Desktop_Qt_5_6_2_GCC_64bit-Default directory. cd platforminputcontext/ make clean make VERBOSE=1
Pay attention to the last command, it may looks like this:
/usr/bin/c++ -fPIC -std=c++11 -Wall -Wl,--no-undefined -shared -o libfcitxplatforminputcontextplugin.so CMakeFiles/fcitxplatforminputcontextplugin.dir/fcitxinputcontextproxy.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/fcitxqtdbustypes.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/fcitxwatcher.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/qfcitxplatforminputcontext.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/main.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/qtkey.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/inputcontextproxy.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/inputcontext1proxy.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/inputmethodproxy.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/inputmethod1proxy.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/fcitxplatforminputcontextplugin_autogen/moc_compilation.cpp.o -Wl,-rpath,/home/saber/Develop/build/Qt560/5.6/gcc_64/lib: /home/saber/Develop/build/Qt560/5.6/gcc_64/lib/libQt5Gui.so.5.6.2 /home/saber/Develop/build/Qt560/5.6/gcc_64/lib/libQt5DBus.so.5.6.2 /usr/lib/libxkbcommon.so /home/saber/Develop/build/Qt560/5.6/gcc_64/lib/libQt5Core.so.5.6.2
You’ll need to replace the Qt library with the one comes with mathematica.
/usr/bin/c++ -fPIC -std=c++11 -Wall -Wl,--no-undefined -shared -o libfcitxplatforminputcontextplugin.so CMakeFiles/fcitxplatforminputcontextplugin.dir/fcitxinputcontextproxy.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/fcitxqtdbustypes.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/fcitxwatcher.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/qfcitxplatforminputcontext.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/main.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/qtkey.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/inputcontextproxy.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/inputcontext1proxy.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/inputmethodproxy.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/inputmethod1proxy.cpp.o CMakeFiles/fcitxplatforminputcontextplugin.dir/fcitxplatforminputcontextplugin_autogen/moc_compilation.cpp.o /opt/Mathematica/SystemFiles/Libraries/Linux-x86-64/libQt5CoreWRI.so.5 /opt/Mathematica/SystemFiles/Libraries/Linux-x86-64/libQt5DBusWRI.so.5 /opt/Mathematica/SystemFiles/Libraries/Linux-x86-64/libQt5GuiWRI.so.5 /usr/lib/libxkbcommon.so
Also remember to remove the rpath option from it. If the command finishes successfully, now you’ll get an usable fcitx plugin for mathematica. Then just copy it to the right directory:
sudo cp libfcitxplatforminputcontextplugin.so /opt/Mathematica/SystemFiles/Libraries/Linux-x86-64/Qt-Plugins/platforminputcontexts/
Then you can enjoy typing with fcitx in mathematica.
The directory path above need to be adjusted based on your own system.
With a few recent changes on Fcitx 5, Fcitx can now be used to type on Wayland. (Even the window is rendered with EGL! .. ok this is not important)
And as of today, I’d say it is the first and only input method that can display UI correctly on a XWayland setup theoretically, although it’s still pretty useless (See my old post about wayland’s input method).
I used to have a branch on fcitx 4 to support this protocol, but, due to the architecture we can’t render UI on different display easily, so I gave it up and moved this work to Fcitx 5.
As described before, Xwayland client still uses XIM, while Wayland input method protocol need to use Wayland to display GUI. Now, Fcitx can render both X and Wayland input window in order to solve such problem. And to my own knowledge it is also the first one and the only one that can do this correctly.
Here’s a small video to demonstrate this feature. Though, it comes with some limitation, because only in classicui we render window ourselves. Also I have no idea about weston’s overlay input method window placement. I’d say the positioning issue is a bug in weston because fcitx can’t do any placement on wayland.
But, don’t get too excited, as described before, this is the only client app that uses this protocol and as you can see from video the application’s implementation has some problem with backspace (backspace should be send to input method first). Also when your application loses focus, the input context is destroyed which makes it impossible to keep track of the input state in the same application. (Also that silly wobbly animation is done by weston..)
Unfortunately, this is the best we can get for now.
I’d like to clarify one thing about this series of articles first. All features described in this series are already implemented, because I do not fell comfortable about writing about vaporware. The purpose of this series is to share some interesting experience during the development that might be useful to other people, so it may describe user invisible changes and uninteresting technical details.
Focus is an important concept to input method. In old Fcitx 4 world, fcitx 4 assume that you may only have one focused input context. And this is gonna changed in Fcitx 5.
There used to be an interesting feature request about using Fcitx on different X11 screen (In old days when xrand or xinerama does not exists). But the problem is you can not do that because it is not possible to open multiple connection or use different screen. The window of GUI must be created separated for different display.
And now things may change in Fcitx 5. Because we will end up with two display server at the same time, so why not support multiple X server too 😛 ?
In Fcitx 5, every input context will have a property about its display. And every display has a new concept called focus group. In Fcitx 5, there will be at most one input context in the same focus group.
Also, one important thing about multiple display support is that, the GUI also need to handle multiple display. As I already stated in previous post, the wayland im protocol will NOT work with X11 client. X11 client must keep using XIM/IM module. Thus X11 window is even necessary for display Input method window under Wayland for Xwayland client. The display server information in input context will also help UI to decide how to display UI for the application in different Display.
Also, Fcitx 5 will use more input context specific state because the many API is now forced to pass a relevant input context. So, although unfocus will still trigger reset (IMHO that’s a reasonable thing to do), the under-hood states are separated instead of shared.
One interesting technical detail about DBus based client is that, we need to put DBus client in to the right focus group. In order to do that, the im module will now send a X client message to a special Fcitx X window to indicate the actual focus group of display server that it wants to join. The message contains a UUID generated by Fcitx. And client will send this UUID back to the fcitx window. If fcitx recognize this UUID, it will put the input context in the corresponding focus group. In this way, we avoid matching DISPLAY env var because it not always reliable. For example, DISPLAY=:0 and DISPLAY=:0.0 may not have visible difference to the client, but if we match it based on $DISPLAY, it is hard to say if these two display are the same display. But by sending the client message to current connected X window, we will always send message to the right X server.
See you next time 🙂 .
P. S.
Also, if you find my work helpful to you, feel free to buy me a beer. The donation link can be found at https://www.csslayer.info/wordpress/donation/ .