Home
Syndicate
Syndicate content

MPX
Submitted by peter on Tuesday, June 27, 2006 - 22:43

The Multi-Pointer X Server is a modification of the X.Org X server to support multiple mice and keyboards in X, all at the same time and working independently. You can create multiple cursors and keyboard foci and then attach the physical devices to the cursors as needed. MPX is the first multicursor windowing system and allows two-handed interaction with legacy applications, but also the creation of innovative applications and user interfaces.

Read What is MPX? for more details or have a look at the screenshots and videos.



Multi-touch? or multi-point?
Submitted by peter on Thursday, June 12, 2008 - 23:13

Increasingly I get as whether MPX allows multi-touch. The answer is neither yes nor no.

There is a bit of confusion out there as to what constitutes multi-touch. The simple answer "deals with multiple touch points" isn't quite that simple.

What is "touch"? In user interfaces, it usually means being able to manipulate an object by touching a sensitive surface. This can be done indirectly (touchpad on the laptop) or directly (touch screens).

To the X server, whether it's direct or indirect manipulation is irrelevant. What does matter though is the data the touch-device provides. Many devices reduce the touch point to a simple x/y coordinate (e.g. Wacom tablets, most touchscreens in public places, and AFAIK even the iPhone do essentially that [1]). From the X server's point, there is no difference between a mouse and such a touch device. MPX is multi-point, i.e. if your device supports multiple touch points, or you have multiple such devices, you have already won. Use them. Write software for them.

But - and here's the big difference: some devices can detect the area of touch, rather than a single point. And here's where it gets interesting, as this allows gestures. Touch with a flat hand is different to the side of hand, is different to the thumb, is different to a finger. This is true "touch support", and by far not commonplace yet. One of the prominent examples that supports true multi-touch is MS Surface.

MPX doesn't do multi-touch. But it turns out that multi-point is the hard thing and multi-touch is quite easy (once you have multi-point) [2]. The only difference is that you have to get the information to the clients. The X server doesn't have appropriate events to send the data and last year, I dabbled with this for a few weeks [3]. The result were the BlobEvents [4], but that branch hasn't seen many updates since, mainly due to lack of time. It will come back, once I find the time to merge the blob branch into current master, clean it out, and get some public review.

But for now - multi-point. Not multi-touch.

[1] there are exceptions, some provide pressure on the point, wacom tablets provide tilt, etc.
[2] From a technical perspective. Semantically, it's quite hard to get it right.
[3] http://wearables.unisa.edu.au/mpx/?q=node/86
[4] http://wearables.unisa.edu.au/mpx/?q=node/88




So you want to build a multi-device aware application?
Submitted by peter on Thursday, June 5, 2008 - 10:38

The use of Xlib for XInput has changed a bit, but not that much. This mini-tutorial shows you how to get the list of devices and how to register for events. For many applications, this is pretty much all you need.

Let's get started. The two most important changes to previous versions of XInput are:

  • applications have to announce support for XI 2 (MPX).
  • the list of input devices contains multiple core devices.

Announcing support for XI 2 is easy, just issue an XQueryInputVersion() before you use any other XI requests. The reason why this is necessary is simple: the behaviour of XInput has changed, and the server must know which clients suports XI 1.x, and which clients support XI 2. This way, it can change some replies accordingly to make XI 1.x clients not break. In practice, your code should look something like this:

int main (int argc, char* * argv) {
    Display * dpy;

    dpy = XOpenDisplay(NULL);
    XQueryInputVersion(dpy, XI_2_Major, XI_2_Minor);

    /* do stuff */

    XCloseDisplay(dpy);
    return 0;
}

Next, we want to know which devices are actually available. XListInputDevices() does this for us. It returns an array with XDeviceInfo structs, each of which specifies the name, id and the capabilities of the devices. In addition, the XDeviceInfo also contains a "use" field, which is of some importance. The use field can have one of 5 values:

  • IsXPointer for any master pointer (i.e. cursor).
  • IsXKeyboard for any master keyboard (i.e. keyboard focus)
  • IsXExtensionPointer for any physical pointer device.
  • IsXExtensionKeyboard for any physical keyboard device.
  • IsXExtensionDevice for any physical device that is neither pointer nor keyboard (this is fairly uncommon).

As a rule, you never register for events on the physical devices. Really. The cursor and the keyboard focus are the user's input points, so focus on them. Only special applications like the GIMP or configuration apps have to worry about the others. Again some code:

XDeviceInfo* info;
int ndevices;
int i;

info = XListInputDevices(dpy, &ndevices);

for (i = 0; i < ndevices; i++) {
    XDeviceInfo* current = &info[i];
    printf("Found device: %s (%d)\n", current->name, current->id);
    switch(current->use) {
        case IsXExtensionPointer:
        case IsXExtensionKeyboard:
        case IsXExtensionDevice:
                /* foo() */
                break;
        case IsXPointer:
        case IsXKeyboard:
                /* bar() */
                break;
    }
}

XFreeDeviceList(info);

Try calling XListInputDevices before and after a call to XQueryInputVersion().You'll notice that the device list is significantly shorter if the server thinks you do not support XI 2.

Ok. Now we know the devices, let's start using them. Writing most multi-device apps is incredibly easy: Open the device, register for events, wait for events to roll in.

XDevice *pointer1;
XDevice *pointer2;
XEvent ev;

pointer1 = XOpenDevice(id1); /* get the ID from ListInputDevices */
pointer2 = XOpenDevice(id2);

/* register for events, see below */

while(1) {
   XNextEvent(dpy, &ev);
   printf("Event type %d received\n", ev.type);
}

Now, I left out the registering for event for now because this is historically painful. You see, the X Protocol specification requires that extension event codes are dynamically assigned at runtime. That is, while the core protocol's type ButtonPress is always the same, the XI type DeviceButtonPress can change from server to server (and even when you restart the server). So we need to get the type. In addition, because we only want to register for certain device's events, we need to get the EventClass. It's easiest to think of the EventClass as the mask to register for a specific event on a specific device. Xlib provides some macros for us here:

int type_bpress;
XEventClass cls[2];

DeviceButtonPress(pointer1, type_bpress, cls[0]);
DeviceButtonPress(pointer2, type_bpress, cls[1]);

Now, type_bpress is set to the event type for DeviceButtonPress events. We can pass the same variable in both times since the type remains static for the lifetime of the server. The class however is device-specific. (Oh - and by the way, the macros re-use the arguments twice, so don't try to pass in something like (evclass++), it can be pain to debug...)

Now we can complete the above example:

XDevice *pointer1;
XDevice *pointer2;
XEvent ev;
int type_bpress;
XEventClass cls[2];

pointer1 = XOpenDevice(id1); /* get the ID from ListInputDevices */
pointer2 = XOpenDevice(id2);

/* register for events */
DeviceButtonPress(pointer1, type_bpress, cls[0]);
DeviceButtonPress(pointer2, type_bpress, cls[1]);
XSelectExtensionEvent(dpy, myWindow, cls, 2);

while(1) {
   XNextEvent(dpy, &ev);
   printf("Event type %d received\n", ev.type);
   if (ev.type == type_bpress)
   {
        XDeviceButtonEvent* bev = (XDeviceButtonEvent*)&ev;
        printf("Press received by device %d\n", bev->deviceid);
   }
}

Here's another important change in XI 2. Events always contain coordinates in the screen's coordinate system, only valuators are device-specific. So for most apps, you don't have to worry about coordinate conversion, just use x_root, y_root or x/y of the XDeviceButtonEvent structure.

That's it for now. There's a number of other macros such as DeviceMotionNotify, all to be found in XInput.h. All the functions described here have man pages that explain the parameters better than I can.

Click here to see the full source.




jhbuild file
Submitted by peter on Monday, April 7, 2008 - 14:02

I sat down on the weekend to look at jhbuild and found it to be easier to build MPX from scratch. So, for first-timers:

Go to and read http://www.x.org/wiki/JhBuildInstructions
Then

git clone git://people.freedesktop.org/~whot/mpx.git

This small repository contains one jhbuildrc file. Get mpx by running

$> jhbuild -f mpx.jhbuildrc build xserver xf86-input-evdev xf86-video-ati

Add or substititute drivers as needed.

Alternatively, "jhbuild -f mpx.jhbuildrc build xorg" should pull down everything.




Back
Submitted by peter on Thursday, April 3, 2008 - 10:08

I am back from my holidays, currently trying to get through the stack of email. One thing I keep telling people over email repeatedly:

The blob-branch of MPX (think touchscreen) is currently orphaned. I just haven't found the time over the last months to keep it up-to-date with the other branch so I'm not sure if it builds and I'm pretty sure it doesn't work too well.

Bear with me, need to get the standard MPX sorted out first, touchscreen is easy then.




Clarification of last blog post
Submitted by peter on Friday, January 18, 2008 - 12:32

After my last blog post I got some worried emails about the following statement:

"The significant change with all this is that an event can only be sent to a single client."

This statement was ambiguous. Here's the correct version:

"The significant change with all this is that an event can only be sent in one form -- XI or core."

If two clients listen for a key press on the same window, both will receive the event. If however a client has registered for an XI event on the same window, only the XI event will be sent, not the core events.

Mixing core and XI events in the same app is simply not supported. It's an utter nightmare to do so and so far I haven't come up with a decent use-case that would justify all this extra work. This of course is valid for input events only, mixing XI and non-input core events (ConfigureNotify, Expose) is supported.

Thanks to those that sent me the emails, it's good to see someone is listening :)




6 hour wiimote hack
Submitted by peter on Friday, December 14, 2007 - 16:35

I started at 10:23, one lunch break, one donut break and a few hours later it is 4:11 and I have working X driver for the Nintendo wiimote. Version 0.0.0 of course and I have no clue if it works with server-1.4 (it should, but I only tried it on MPX). Dependency on the package libcwiimote-dev.

Grab a tarball or directly from git://people.freedesktop.org/~whot/xf86-input-wiimote.

At the moment, it reports tilt as x/y axis, so you can move the cursor by tilting the thing around. Z tilt is reported as z axis, accelerometers are reported as axes 3-5 (if enabled). IR doesn't work because I couldn't find LEDs that the wiimote would detect. Maybe Mark (who lent me his wiimote) can bring in the sensorbar next week so I can add that.

Here's the obligatory short video:


The code is fairly clean, I really hope somebody picks it up and continues with it. Not sure how much time I will have in the forseeable future. The code should give you a good start though. Feel free to send me patches too.




MPX translations in russian
Submitted by peter on Thursday, December 13, 2007 - 13:30

You probably saw it on the frontpage, the MPX webpage should now be available in russian. (mostly anyway)

Thanks a lot to Andrey Jornyak for doing all the gutwork!

(I also changed the settings in drupal, future posts in russian won't hit the frontpage and the RSS feeds. Please start with the link on the left "MPX на русском")




x2x
Submitted by peter on Wednesday, November 28, 2007 - 16:39

I had a bit of time on the weekend to give something new a try: x2x.

For those that don't know it, x2x is a program that allows you to control the cursor/keyboard on a remote X server (using XTEST). Turns out aside from a few bugs MPX worked exactly like expected: I could export a single cursor to another box while the others are still working locally and likewise I could export the cursor from another box into one specific cursor on the MPX box. While of course using the connected devices to control separate cursors.

This is neat, as it removes the borders between the screen. It doesn't matter which box a device is connected to, you can just interact on any machine that is within reach. Think of a meeting with a shared digital whiteboard. You work on your laptop, then move over to the whiteboard to work together with others, then move back again.

Some bugs are left, grabs don't always work and I'm not sure about keyboards right now. But it's still exciting to see that it works in principle.

VNC works on a similar principle. I connected vncviewer to x11vnc on the MPX box and had vnc control a different cursor than the local one. Pity that vncviewer doesn't render both cursors though.

Aside from that, not much time to work on anything. The thesis is eating up all my time.




LinuxSA talk upcoming Tuesday
Submitted by peter on Thursday, November 15, 2007 - 18:47

If you are in/around Adelaide next Tuesday, I'll be giving a presenation of and about MPX at the LinuxSA monthly meeting.

snippet from Geoffrey's announce email

  When:   7:00pm-9:30pm (doors open 6:45pm) on
          Tuesday, 20th November, 2007
  Where:  Senior Secondary Assessment Board
          of South Australia (SSABSA)
          Boardroom (1st floor)
          60 Greenhill Road
          Wayville SA
  Cost:   FREE
  Who:    Anyone and everyone.
          No pre-registration necessary.

More info about venue etc at www.linuxsa.org




Syndicate content
Browse archives
« November 2009  
Mo Tu We Th Fr Sa Su
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30