Workaround for XRandr Problem on Low-end Intel GPUs

Ever since switching my work machine to Ubuntu 9.04 (“Jaunty”), I had an annoying problem.

It turns out that the latest versions of X.org use the XRandr extension for multi-monitor support, instead of the older Xinerama. Now, there are many good reasons for that: Xinerama was hell to configure and it didn’t really support the kind of plug-and-play automatic configuration which users expect nowadays.

XRandr is more convenient and can make lots of changes on-the-fly without a restart, but that convenience comes at the price of flexibility. How it works is by simply setting up a virtual desktop inside the GPU, with dimensions matching those of your physical screen setup. So if you have two 1280x1024 monitors next to each other, then that’s a single 2560x1024 screen as far as X is concerned, except that the window manager does a little extra magic to make the ‘maximize’ button on windows work correctly. Using multiple GPUs in a single machine is not supported, except by running completely independent X servers on them.

If you have a fairly modern NVidia or ATI card, that will work just fine. However, many of the machines at work still use a somewhat older Intel chipset, which does not support framebuffers larger than 2048x2048. With the 2560x1024 setup mentioned above, DRI will be disabled, so you won’t have any kind of hardware acceleration. Window updates will be slow and Compiz won’t work.

A colleague found a creative solution, however. He simply configured X so that his two monitors were above each other, creating a 1280x2048 virtual screen. This works, but of course mouse behaviour is now unintuitive to say the least: in order to drag a window from the left to the right display, you need to drag it downwards!

Well, silly problems call for silly solutions. So over the week-end I wrote a little program which runs in the background and makes the mouse behave appropriately for having the two displays next to each other, while letting X believe that they are stacked vertically. The program simply polls the mouse position ten times per second and when you move it to the edge of the screen, it gets transported to the other monitor. The mouse also gets prevented from crossing the horizontal boundary between the two displays, so that you can hit a button on the taskbar without undue dexterity.

If you have the same situation, you can download the program here. The tarball includes a precompiled 32-bit x86 binary, or you can rebuild it by simply running ‘make’. To test it, just run ‘./movemouse’ from the command line. It should print the text “Display size: 1280x2048” (note that this is the total size of your virtual desktop, not the size of an individual monitor!) and make the mouse behave as described above. Abort with Ctrl-C and if you like it, just set the program to run on startup (System / Preferences / Startup Applications).

(What if you run the program and it creates a horizontal barrier in the center of your screen, wich the mouse refuses to cross? In that case, your setup is not considered by X to be a single 1280x2048 virtual screen, and movemouse cannot help you. On the other hand, in that case you probably also don’t have this specific problem.)

Alternatively, I guess you could try going back to Xinerama and manually configuring it and getting it to work with Gnome. Have fun with that..

I’m a bit disappointed by this design choice, though. I can certainly see the technical reasons for it, and I won’t mourn the disappearance of Xinerama. But one traditional strength of Linux is supposed to be its continuing support for older hardware which Microsoft doesn’t care about anymore. We’re not talking about decades-old hardware here; there are still plenty of perfectly good, fairly new workstations around which use those Intel cards. Seeing Ubuntu fail to support them properly without ugly workarounds like this one, is a bit disappointing, especially since previous Ubuntu releases did work.

Oh well, it’s free and I’m not one of the volunteers who work on X, so who am I to complain. In the meantime, I got to write another fun little hack and now have a perfectly acceptable workaround.