This article is originally titled Abandoning treatment for X11, for my xkeymacs project.


I think I’ve done all that’s possible to achieve with X11 API in this project, but there still remain a bunch of issues. This document is about what they are and why they may not be resolved as an X11 application.

Before we start with the issues, we need clarify the situation first.

There are three ways to grab key events in X11: XGrabKeyboard, XGrabKey with GrabModeSync and XGrabKey with GrabModeAsync. In the meantime, there is only one way to send a key event in X11: XTestFakeKeyEvent, while XSendEvents marks events sent as synthesized and a bunch of applications (such as xterm) ignore events with this flag for some security reasons, according to various sources.

If you want to replay the key event you just grabbed, use XAllowEvents with ReplayKeyboard. This requires the key event to come from XGrabKey or a previous XAllowEvents with SyncKeyboard, but not from a XGrabKeyboard.

You cannot use XGrabKeyboard along with XTestFakeKeyEvent because the former sets an active grab and it will receive the key event faked by yourself. If you want to XUngrabKeyboard and wait for XTestFakeKeyEvent to accomplish, sadly there seems to be no way. XFlush flushes your own request to X server, while XSync flushes and make X server process all requests and generate events, but not handling them, according to this thread.

XGrabKey is called a passive grab. It is activated and then behaves like XGrabKeyboard when the registered key and modifier combination is found, and actually ungrabbed after the KeyRelease event of that combination (see this mail). So if you send a key in KeyPress event, you will intercept the key you just sent. To workaround this issue, you can do XUngrabKeyboard before you send the key. This results in garbage KeyRelease events sent to the focused window, however it is normally ignored. Another workaround would be sending the key in KeyRelease event, which works, but is not the desired behavior.

Note that if you replay a key event with XAllowEvents in KeyPress, It will also result in garbage KeyRelease events, because according to the documentation the replayed event will ignore any key grabs set by any client.

So here is the first issue.

  • Grabbed keys sent by XTestFakeKeyEvent cannot be replayed

    When testing the application, I was surprised to find that when I sent keys that are also grabbed by myself and deliberately do the replay in KeyPress, I still receive KeyRelease events for them. That is to say the XAllowEvent replay failed. I guess this is because XTestFakeKeyEvent is part of the XTest extension and is aimed for automating testing, so the internal implementation did not take this situation into consideration. So there may be no workaround for this.

    An example for this issue can be when I grabbed Control+X for C-x mode and I send Control+X inside the handling of Control+W

When sending some key combination, one have to know the status of the modifier keys and adjust them, send the key, and then restore them. This is expected to happen in a very short period of time so the user won’t notice. To accomplish this, XQueryKeymap and multiple XTestFakeKeyEvent is used.

And the second issue.

  • Sending keys containing F1~F8 causes user to be switched to tty

    When sending keys containing F3 or F4, sometimes I got switched to tty by an unexpected Control+Alt+F3/4 combination. This happens for most of the time when I send Control+F4 for (Control+X) k. You can see that there is nothing about Alt, but still I was almost always switched to tty4, however xev reported the expected key sequence for this situation. The underlying logic is unknown, it may have something to do with tty switching hot key implementation.

And some other issues.

  • Auto repeat cannot work if we intercept the KeyPress event

    X server generates continuous paired KeyPress and KeyRelease event for clients if a key is physically held for a long time. However if we intercept the first KeyPress event, and send another key event, then the auto repeat just disappears. There doesn’t seem to be a solution for this issue.

  • Efficiency

    There is a perceptible (annoying but bearable) pause when using the above stated approach to implement keyboard macros. Seems no way to resolve either.

    Note that using GrabModeAsync helps to improve the performance a little bit, but it results in various problems that I haven’t investigated yet.

So the conclusion is that, while X11 provided some API for keyboard event operations, it is vague in documentation and working mechanism, and clearly not designed, nor suitable for translating key sequences into others. This may be the reason why almost no such project like this is known.

For an alternative API, some people in a mailing list suggested Atspi, which I haven’t tried out myself.


UPDATE:

Later I found out that this can be achieved with evdev and uinput.

For a python implementation, see my pykeymacs.

朋友用cinema4d建了audi-rsq的模型,准备导入unity

这是在c4d里渲染的样子

unity和maya都不支持c4d格式、咨询了一下TA,fbx格式更加适合在多平台编辑模型

用fbx格式导入unity发现两个问题

1、smooth参数和texture并没有被导出

2、模型看起来是破的。。。

第一个问题还好了。。把模型导入maya,重新平滑一遍,导入材质,解决、第二个问题比较麻烦,不知道原因。。

在maya里render了一遍,模型看起来是好的,至少是完整的,但是在预览视图里看的时候还是发现了有些面片的颜色比较深,有些面片的颜色比较浅

在unity里重新审视了一遍这辆小车,发现当视线进入小车的时候(也就是从小车内部看小车的时候),原本可以看到的面片不见了,看不到的面片出现了。。

于是就猜想。。unity里面片分正反?查了一下文档,果然如此。。。

但是unity里不能直接编辑面片,于是把模型导入maya,一块一块检查面片,花了半小时,终于把反过来的面片挑出来了,具体的操作在normals–>reverse

再导入unity,看起来一片大好了。。。

终于解决了。。