Gaps between Wayland and Fcitx (or all Input methods).

Though some people have no problem (or, only few problems) about using fcitx (to be more specifically version 4) with wayland, but the truth is there are still lots of problems left to be addressed.

The truth is, wayland is not yet ready for input method.

  1. Generic input method protocol is not widely adopted.
    In the old good X11 world, there is a protocol call XIM. No matter how bad it is, it widely used and adopted by nearly all applications. But as for wayland’s protocol “text-input”, the current situation is:
    – Gtk3 doesn’t support it.
    – Qt5 support a not-upstreamed version 2.
    – EFL / weston support the official version in wayland-protocols.
    – SDL2 doesn’t support it.
    – Weston’s reference client side implementation has critical bug.
    What does this mean? This means even you’re using wayland + (GNOME/KDE) for now, you’re still using the old im module via DBus.
  2. The generic input method protocol is bad.
    It is weird that in wayland world, key repetition is a task of client. But the problem is, it even becomes a work for input method. Fcitx 5 for now is the only implementation handles key-repetition correctly. But I don’t even care about this because I don’t even have a real application to test this feature. (You need a patched version for weston-editor to play with it).Also, the wayland input context will be destroyed once it get unfocused, which makes it unable for input method server to track different window and keep different input state for different window (e.g. different window + different im will need this feature) .
  3. The window positioning issue.
    In Wayland world, there’s no way for a non-compositor window to place the window by abstract coordinates (x, y). Also there is no way for a non-compositor window to know about its own location. But for input method, you need to display a window at the position of cursor. The “input-method” protocol in wayland allows you to assign a surface as “input panel”, and the compositor will move it for you.
    This means: when you’re using im module via dbus or typing in a Xwayland window with XIM, it can’t make use of this feature. But you may say, under plasma wayland, or gnome-shell I didn’t see any problem.This is because:
    – GNOME shell is the compositor, it can do hacky things to move the input method window around and make use of compositor feature. Currently gnome-shell’s ibus extension and https://github.com/wengxt/kimpanel-for-gnome-shell/ (you can use it with fcitx) use this method.
    – For Plasma, the plasma shell window occupies the whole screen, which makes kimpanel able to locate its window freely with absolute coordinates.Except these two specific environment (no, weston will not work), input method server will not be able to move the input method window freely.
  4. Keyboard layout management
    This is somewhat less important for now, because of the issue listed above. Input method server (fcitx or ibus) are trying to managing keyboard layout, but there’s no common interface to do this.

Due to the issues above, I do not recommend to use wayland if you need input method. You can try it today, but you may find it working or not working. Also, these issues also largely extinguished my passion about working on wayland. Since for now there are still a lot of works going on with fcitx 5 and libime, my focus are mostly on them instead of making fcitx working on wayland.

But no need to give up too soon, as for the solution, It seems that KWin wants to run input method inside compositor process and this may solve a large portion of problem listed above, because: 1. kwin is compositor, it knows everything about a window, 2. kwin on wayland will control keyboard layout, 3. no “input-method” protocol is needed. Fcitx 5 also contains work to make fcitx run as a library more easily.

Right now my work replacing fcitx 4’s pinyin and table with libime is  near completion. Let’s see how it goes from here.

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

最近的一个 Linux Intel 驱动问题和 Workaround

老实说一般我都不愿意写这种文章。因为这种文章基本上都是很有时效性的。但毕竟这个问题已经困扰了我好几个月,所以还是打算记录一下方便同样遇到问题的人。

具体表现是,开机正常,使用正常,但是如果放久了就会黑屏再也起不来。这时还能 ssh 进去,但是从 ssh 重启很大可能会等待很久。上游的 bug report 我也不好分辨到底是哪个,就随便列出几个我觉得相关的。

https://bugs.freedesktop.org/show_bug.cgi?id=102224
https://bugs.freedesktop.org/show_bug.cgi?id=102853

那么最后我的解决方案是什么呢……总之也是在某个 report 里面看到有人提到的方法。

在 /etc/modprobe.d/90-i915.conf 里面写上

options i915 enable_guc_loading=1 enable_guc_submission=1 disable_power_well=0

总之我加上这个参数之后好久都没有出过问题了。

顺带一提我正在使用的内核版本是 4.13.0 但是这个问题至少困扰我了好久好久大概从 4.9 之后升级了 BIOS 开始……

Posted in Linux | Tagged , , , | Leave a comment

一个关于 Pimpl 的小技巧

使用 Pimpl 很多时候是必须的,ABI 兼容的时候基本都要靠它。在 C++ 11 当中,通过 default member initializer 可以实现很多有趣的效果,加上宏的话很多时候可以利用来实现 Metadata 的效果,例如:

#define PROPERTY(NAME) \
    Property NAME{this, #NAME};

class Registry {
    friend class Property;
    public:
        int& getValueByName(const std::string &name) {
            return *values_[name];
        }
    
    protected:
        void registerValue(const std::string name, int* value) {
            values_[name] = value;
        }
        std::unordered_map<std::string, int*> values_;
};


class Property {
public:
    Property(Registry* r, const std::string& name) {
        r->registerValue(name, &value_);
    }
    
    operator int() { return value_; }
    Property& operator=(int v) { value_ = v; return *this; }
    
private:
    int value_;
};

class MyRegistry : public Registry {
public:
    PROPERTY(a);
    PROPERTY(b);
};

int main()
{
    MyRegistry r;
    r.getValueByName("a") = 1;
    r.b = 2;
    return r.a + r.getValueByName("b");
}

但是实际上这还是需要定义新的 member,如果将来有了新的 member 就没法保证 Binary compatibility 了,假设我们要把 MyRegistry 转变成 Pimpl 怎么办呢?简单实现一下的话就会变成这样:

class MyRegistryPrivate {
    Property a{???, "a"};
};

那么 ??? 处传什么才好呢?

你可能会想到把 MyRegistry 的 pointer 传给 Pimpl 不就行了吗?但是不要忘了,我们还依旧希望通过 default member initializer 的形式来定义。传过来的参数之后即使直接去 initialize,也是在 default member initializer 之后才进行了。也就是说这样是不行的:

class MyRegistryPrivate {
    public:
        MyRegistryPrivate(MyRegistry *q) : q_ptr(q) {}

        MyRegistry *q_ptr;
        Property a{q_ptr, "a"};
};

也就是说要保证在更早的时候初始化 q_ptr,可以用一层继承来保证这点。

template
class QPtrInit {
public:
    QPtrInit(T *q) : q_ptr(q) { }
    
protected:
    T* q_ptr;
};

class MyRegistryPrivate;

#define PROPERTY_PRIVATE(NAME) \
    Property NAME{q_ptr, #NAME};

class MyRegistryPrivate : QPtrInit {
    public:
        MyRegistryPrivate(MyRegistry* q) : QPtrInit(q) {}
        
        PROPERTY_PRIVATE(a);
        PROPERTY_PRIVATE(b);
};

完整例子参见:http://cpp.sh/4bhvh

Posted in Linux | Tagged , , | Leave a comment

Shell script for Google TTS on Plasma desktop

My wife has extreme dry eye condition, so she want to avoid looking at the screen as much as possible. She asked me for a solution for Text-to-Speech on linux desktop.

Basically her requirement is to press a key and read out what she selects. I check jovie, but that’s somehow discontinued and the only speech-dispatcher backend available on my distro is espeak, whose voice quality is poor comparing to any modern solution on the desktop.

So I decided to check if there’s any available solution on internet and see if there’s a solution that using Google translate’s TTS service.

So far I found a script from http://elinux.org/RPi_Text_to_Speech_(Speech_Synthesis)#Google_Text_to_Speech

Which I adjusted a little for my usecase:

#!/bin/bash

TEXT=$(xsel)

say() { local IFS=+;/usr/bin/mplayer -really-quiet -noconsolecontrols "http://translate.google.com/translate_tts?ie=UTF-8&client=tw-ob&q=$*&tl=en"; }
say $TEXT

I added xsel for reading string from primary selection, which is exactly what she’s asking for. And then I use plasma’s convenient custom global shortcut to bind a key to this script. Then you can enjoy the google tts with a single key press.

Posted in KDE | Tagged | 2 Comments

A new pinyin input method that might be slightly better than sunpinyin

What do I mean when I say “slightly better”?

First of all, thanks to sunpinyin’s open-gram, I can use its data for free. So, on the pinyin side, libime IS using the exact same data from sunpinyin. So what’s the difference?

  1. By default, it learns user input faster (you can do that by tuning sunpinyin option, though).
  2. As a library, it supports multiple dictionary.
  3. It gives you more “candidate phrase” by default.
    I guess I need to explain this a little. So in sunpinyin, many common multiple character words are not represented as a single phrase, but as an ngram. By default, it seems that sunpinyin does not provide enough phrase in such form, while libime will try to provides more ngram phrases as candidates.
  4. It has less bug when you try to modify pinyin in the middle of your input.
  5. Its data file is smaller in size. Thanks to the highly compressed format provided by kenlm.
    $ ls /usr/share/sunpinyin/lm_sc.t3g -lh
    -rw-r–r– 1 root root 38M 3月  23 19:51 /usr/share/sunpinyin/lm_sc.t3g
    $ ls ~/Develop/build/fcitx5/share/libime/sc.lm -lh
    -rw-r–r– 1 saber saber 17M 5月  19 17:59 /home/saber/Develop/build/fcitx5/share/libime/sc.lm
  6. It does not have problem about upgrade dictionary because history stores word directly instead of word id, which may be a problem across different version of data.

I’m using this new pinyin powered by lining daily right now. It just simply “feels” slightly better.

For those who interested: https://github.com/fcitx/libime

Also, FAQ:

– Will I have this with fcitx4 in the future?

No, this is designed to replace the default pinyin and table in fcitx 4 and will only be used for fcitx 5. If you want you can still work on your own solution for fcitx 4.

– How can I use it now?

Build fcitx5 and fcitx5-chinese-addons, you’ll need fcitx5-gtk and fcitx5-qt too, however, I never tried to clean up the optional dependency for it because it’s not the main task right now. So you probably need to have/build everything in dependency. Especially, xcb-imdkit needs to be built. Also please aware that UI of fcitx 5 is still in an extremely poor state. Also you’ll needi to write a config file manually and place it under ~/.config/fcitx5/profile .

[Profile]
# CurrentGroup
CurrentGroup=Default

[Profile/GroupOrder]
0=Default

[Profile/Groups/0]
# Default Input Method
DefaultIM=pinyin
# Layout
Default Layout=us
# Group Name
Name=Default

[Profile/Groups/0/Items/1]
# Layout
Layout=
# Name
Name=pinyin

[Profile/Groups/0/Items/0]
# Layout
Layout=
# Name
Name=keyboard-us

 

Posted in fcitx development | Tagged , | 1 Comment