One bad API in sd-bus

I’m using sd-bus to develop the dbus part for fcitx5, because I’d like to seamlessly support kdbus in the future. (Don’t argue with me about bsd or sth else right now, for now I don’t care about that.)

But one api of sd-bus obviously blows up my mind.

https://github.com/systemd/systemd/blob/09541e49ebd17b41482e447dd8194942f39788c0/src/systemd/sd-bus.h#L428

typedef int (*sd_bus_track_handler_t) (sd_bus_track *track, void *userdata);
int sd_bus_track_new(sd_bus *bus, sd_bus_track **track, sd_bus_track_handler_t handler, void *userdata);

So basically, it’s a wrapper around NameOwnerChanged dbus signal. And let you get notification about when the service disappears (only disappears, yeah).

And it also has capability to track more than one service name by using.

int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m);
int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m);
int sd_bus_track_add_name(sd_bus_track *track, const char *name);
int sd_bus_track_remove_name(sd_bus_track *track, const char *name);

And you are able to query which name is being tracked via:

unsigned sd_bus_track_count(sd_bus_track *track);
const char* sd_bus_track_contains(sd_bus_track *track, const char *names);
const char* sd_bus_track_first(sd_bus_track *track);
const char* sd_bus_track_next(sd_bus_track *track);

So far so good, yeah?

But if you pay attention to the prototype of sd_bus_track_handler_t, you’ll notice that you won’t be able to get the tracked service name when this handler being called.

Which means you simply can’t use it to track more than one service name, because you can’t distinguish which service actually exits.

If I checked all existing usages of sd_bus_track in systemd, they imply that my impression is correct.

So obviously “tracking multiple name” functionality is totally useless.

So here, this is a good example about how this api should looks like: http://doc.qt.io/qt-5/qdbusservicewatcher.html .

For my own use case, I’ll go back to write my own service tracker with other sd-bus api.

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

RFC: a new solution to Input Method + Keyboard Layout

This is not related to KDE itself, but I’d like to hear some opinion from keyboard layout users, especially from those who use more than one keyboard layout.

Right now I’m designing a new feature for fcitx (for people who doesn’t know it, it’s an input method framework under Linux), currently called “input method group”. The goal of this feature is to solve the conflict between keyboard layout and input method (mostly conceptually) . It can also solve some other problem, but the original goal is about keyboard layout.

Before I introduce the feature, I’d like to talk about the problem itself first.

People need to type their own language with their keyboard. For most latin character based languages, keyboard layout is a good solution to them, because the number of different characters in their language is small enough to be handled by the keyboard (26 * (1..2)). But in CJK world (Chinese, Japanese, Korean), number of characters are so large (especially for Chinese, number of characters in Chinese is over thousand) that each character can’t be simply mapped to a key on the keyboard. So people invent input method, which basically maps a sequence of key to a limited number of characters and people can select from it.

But if we re-think about the keyboard layout itself, it can actually be considered as a very simple kind of input methods. The only difference is that the mappings from “keys” to “characters” in keyboard layout is much simpler than those in CJK input method. And that’s why keyboard layouts are handled as input method in modern OS, like windows and mac OSX, and ibus/fcitx nowadays.

It looks so far so good, until you remember that keyboard are not only used to type text. Suppose you want to type French and German, and you add them as your input methods. But hey, French layout is azerty and German is qwertz. Your favorite “Ctrl+Z” for undo is at the different position on the keyboard! If you add Chinese pinyin into consideration, it will be even more messed up. Not to mention if you want to use Dovrak layout with Pinyin and but pinyin is forced you to US layout on Windows.

Though keyboard layout can be considered as an input method, it’s actually a mapping from physical keys to virtual keys (and to characters). And regular CJK input method is a mapping from virtual keys to characters. So they should be able to composed arbitrary to serve user’s own need (e.g. Pinyin + Dovrak).

And we previously had a user provided one of his scenerio:

* Kain(fake name, you know) has two keyboards. One is laptop built-in with US layout, which he will use at  home. Another is a usb keyboard, but it’s in fr layout (key printing).
* He usually use Pinyin and Mozc to type Chinese and Japanese.

He want to automatically switch layout when he’s using different keyboard. While X/wayland doesn’t provide “per physical keyboard” layout (I don’t think “real” per physical keyboard layout is useful though, since you’ll still only use one physical keyboard at a time.), I’d like to support such use case and that’s why I invent the concept of “input method group”.

Basically a input method group contains a list of input methods, and has a layout. This layout will be the actual “system” layout. It affects all the hotkey bindings for your desktop. And for Kain’s use case

His configuration will look like this:
* Default group (us layout):
* Keyboard (default), Pinyin, Mozc
*
* Alternative group (fr layout):
* Input methods are the same as default.

And we can listen to udev event, once the keyboard is plugged in, automatically switch to group fr and he can happily type with fr layout.

For regular CJK user, they can stick to one group. For regular keyboard layout users who want old fashion keyboard layout like setup, they can use different groups with single “keyboard” input method.

And I’d also like to support multiple layout based input method in same group. With help with xkbcommon, this can be actually done. So you can have “Keyboard (US English)” and “Keyboard (Arabic)” in same group, but your system layout will always be US layout even you’re using “Keyboard (Arabic)” to type.

And I think it can also help users who only use some specific language at work and another language at home. And I think is fit quite well with KDE’s activities, e.g. bind different activities with specific input method group. After all, if you want 3 different input methods, but only two of them at a time, it would be easier to switch input method between 2 instead of 3.

What do you think of it? I’d like to make this feature supports the needs of both keyboard layout users and input method users. Do you have any other use case related that you want to share?

Posted in KDE, Linux | Tagged | 11 Comments

Use Jolla Phone to share Wifi via USB

Recently I got a new Surface Pro 4, and starts to use it as my main laptop. I’m glad that it can work with Linux quite well. But it does have some issue that I can’t live with: wifi will stop working after hours randomly.

Though someone points a workaround to me on reddit, but it does not work for me. Fortunately, I was able to just use my usb ethernet at that time. But recently, I moved my seat at home to a place where I couldn’t reach the ethernet cable, so I has been forced to use wifi since then.

Luckily, I found a thread that indicated that I can make my Jolla phone to share the internet via USB. To make it short, one just need to execute

pkcon install usb-moded-connection-sharing-android-config

with developer account and restart the phone.

But later I found that it only works with Cellular network but not with wifi. I digged into the related usb-moded code to confirm that. The implementation explicitly disables wifi and enables cellular network for sharing.

But this is not the end of the story. I found I can still manually enable wifi after select Internet sharing as usb mode. But the network itself doesn’t work, because the implementation only adds the masquerade iptables rule for the cellular network. So I just tried to add my iptables rule manually via:

iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE

And it works!

Then I created an expect(1) script to ssh to phone and execute the iptables command automatically, so now I can happily use Jolla to connect the wifi network for me, just like using a wifi dongle. I still need to configure the dns server manually via networkmanager for my local connection because the dns server pushed by dhcp server is for cellular network, but that’s good enough since I can even use google’s public dns server blindly if I don’t are too much about the dns speed.

This iptables rule also seems to be persistent if you don’t restart the phone, so I’m also considering to add it when the phone boots. For now I’m happy with my current solution.

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

同一台电脑的 Linux/Windows 系统的蓝牙连接同一个设备

http://ubuntuforums.org/showthread.php?t=1479056

方法从这里找到的,不过在这里有少许区别。

情况是这样的,如果你有同一个蓝牙设备,想要同时在 Windows / Linux (或者多个 Linux 系统)使用,你会发现在一个系统下配对之后,在另一个系统连接时会连接失败。因为蓝牙在配对后会生成一个 key,而这个 key 在不同的系统下并没有共享。

那么问题就是怎么修改/读取这个 key 了。

Windows 下,key 保存在注册表中。我没有尝试,但是上面的链接提到即使管理员模式也无权访问?所以改为从 Linux 下读取注册表的方式访问Key 。从 Linux 下面也可以使用方便的工具 chntpw 读取。首先备份一个 Windows\System32\config\SYSTEM 文件,然后使用 chntpw 即可读取。我的 key 在 \ControlSet001\Services\BTHPORT\Parameters\Keys\[Bluetooth adapter MAC address]\[Bluetooth device MAC address] 下。

在执行 chntpw -e [SYSTEM 文件的路径] 之后,可以使用 cd / ls 像访问文件一样访问。在到了最终的目录之后,使用 hex [key 名称] 查看对应的 key 的 16 进制。

在 bluez 5 的环境下,配对后会在 /var/lib/bluetooth/[Bluetooth adapter MAC address]/[Bluetooth device MAC address]/info 这个文件内写入设备的信息,格式就是普通的 ini。找到 [LinkKey] 下面的 Key= 行,填入对应的 16 进制 Key (无空格)即可。

总结一下流程:

  1. 在 Linux 下先配对,生成对应的 info 文件。
  2. 然后在 Windows 下重新配对,产生新的 Key,并存在了注册表中。
  3. 再到 Linux 修改对应文件。
Posted in Linux | Tagged , | 1 Comment

On porting Fcitx KCM module to KF5

Porting Fcitx KCM to KF5 is not that easy. It’s not only about porting kcm itself, but also porting missing part of fcitx-qt5 to Qt5 (mostly widgets). The old pkgconfig file is quite messed up, so I decided to experiment with extra-cmake-modules (ECM) a bit.

I found that fcitx-qt5 could be nicely split into two sub-modules, so I tried to use similiar CMake trick like KF5. So we now have nicely split FcitxQt5DBusAddons and FcitxQt5WidgetsAddons in fcitx-qt5 repo.

ECM and new cmake provide a standardized way to create find_package cmake scripts and I really like it. Another thing that I want to mention is that target_include_directories(xx INTERFACE xx) is  great. If a library adopts this method, the long list inside include_directories is not required anymore, target_link_libraries will resolve all needed include_directories for you and everything will work like magic.

The keyboard layout previewer in kde4 kcm is not ported yet because there’s some X11 related library usage, which need to be ported to xcb because Qt5 is using xcb instead of libX11. But overall it’s usable, and I fixed a quite nasty old bug in KCM too.

I also played a bit with C++ 11 Lambda, and it made my porting job simpler. In old KDialog’s world, there’s a signal passes KDialog::ButtonCode. Though QDialogButtonBox also provides QDialogButtonBox::StandardButton, QDialogButtonBox’s “clicked” signal only passes QAbstractButton pointer. So I used following lambda function to preserve the old behavior.

[this, buttonBox](QAbstractButton* button) {
    this->buttonClicked(buttonBox->standardButton(button);
}

which is quite handy to use.

And here comes a mandatory screenshot, sorry for some Chinese character on it because LANG trick can’t affect all strings (some come from another process via DBus).

kcm-fcitx1

Posted in fcitx development | Tagged | 3 Comments