Thursday, October 16, 2014

Building the Forking X server

Building the Forking X server

I work on Debian (Sid), so the Git repositories contain debian/ and  packages are built by git-buildpackage as documented in another post.

You can also install by using my debian repository:
deb sid main

I did not implement a new Extension - I extended the protocol of XKB.
So, first build the x11proto-kb-dev package
Now it's possible to build both libX11 and the server:
Since the ABI between the server and "input device" driver, it's necessary to recompile them. I use only evdev & synaptics. But, evdev is used for the keyboard, and I need precise timestamps, so there are changes, hence build from this repo:
At this point the Xserver could be restarted. After building the X11 from:

    one can start asking the X server about the active plugins. There is a tool for that:
At this point it is possible to:
$ xinput list
....Virtual core keyboard                       id=3    [master keyboard (2)]
$  xplugin -l -d 3  
3 plugins in the pipeline
1: never-freeze-queue
2: xkb-auto-repeat
0: core

The function of each plugin:  

never-freeze-queue collects events while waiting for following plugins to proceed (& accept the events).  xkb-auto-repeat generates the auto-repeat events, core is the interface with dix/events.c.

Now we can finaly build the interesting feature: the "fork" plugin to be inserted before the auto-repeat plugin. It is implemented in C++ which explains some effort in the X server and x11proto-kb sources to make them C++ compatible.
so after building (& installing) you can insert that plugin:
xplugin -d 3 fork       # 3 is still the id of keyboard.
or also remove it:
$ xplugin -d 3 -fork

Now to activate some of the forks we need to communicate with that plugin, 
and build up a language to express the configuration.
For the configuration language, I chose to use Scheme, in the Gauche implementation. So, one needs to install Gauche-dev, and build this binding module:
building that one is more involved (see my blog about building Gauche modules).

That packages contains my configuration to be used this way:
$ fork-config-mmc.scm 3

When trying to configure, keep in mind, that allocation of the "fork" keycodes
is possible only if the XKB Geometry allows it. I.e. keycodes not found on the Geometry will be used.

See in how key "f" is used as Hyper modifier, or how Meta key acts as Escape key.

Monday, August 18, 2014

Forking -- multitouch on keyboard

Multitouch on keyboard is about ... interpreting simultaneous key presses
in a way that is different from sequential.

That is pressing 2 keys A+B should be something different from A, followed by B.
Years ago, I was told focus on the problem of converting one of the
letters into a modifier, and keep B as is. This has been enough of challenge to implement (properly), and I can share the software now.

The implementation includes patches to several components of the X-Windows system, and configuration tools.

Here's a diagram of involved parts:

The most complex part is extension of the Xorg server, to somehow postpone processing key events while maintaining the semantics of Un/Grab requests.

Since we use the timing of key events, we want to get best precision timestamps on them. Xorg server has to get the monotonic timestamp from the kernel/evdev.
That implies a bit of patches to input driver(xorg-evdev), and the DDX code to accepts events and put them into the event queue.

From there we want to plug this new functionality in the heap of machinery which implements auto-repeat, other XKB functionality, and then the Grab/Ungrab ops.

I have tried to separate, serialize the implementation of these functionalities, using this simple architecture: a linked list of  blocks with this API:
 (image missing)

These blocks pass Events  to the next one (in one direction), and in the other direction the information about Grab/Ungrab state is passed.

Indeed, if no event comes in, time can still be "pushed" through all these plugins,
so a plugin can also tell how early it is significant to push time to it.