RANDR support for Xvnc

March 8, 2004

Based on feedback from Tom Vera , I've fixed a bug that caused the X server to incorrectly report the screen resolution. Here are the updated versions:

October 7, 2004

I've patched Xvnc 3.3.7 (the Debian 3.3.7-6 package) to support the X Resize and Rotation extension (RANDR).

The modified X server understands the standard RANDR extension protocol, and supports all four rotation possibilities, but not reflection (those this would not be difficult to add). The xrandr utility (distributed with XFree 4.4.0, not sure about other versions) can be used to query and set the current screen rotation.

I use it on my Toshiba Portege 3505 (a convertible laptop/tablet model) with a standard X server running xvncviewer in fullscreen mode to allow rotations into different screen orientations.

There is a virtual keyboard program (xvkbd) available separately.

Availability

The modified Xvnc source code can be downloaded here.

A Linux executable (compiled against libc 2.3.2) is available here.

I started this project by writing a Perl script (available here) that sits between a client and a server and rotates the server's output by 180 degrees. It's slow, but since it reads and decodes both the client and server VNC protocol, it could be used for other Perl-based VNC applications.

How it works

The changes are not difficult to understand. Basically, I ripped the generic RANDR code from XFree 4.4.0 and backported it (easily - few changes were required) into the Xvnc server (based on XFree 3.3.2). All the VNC-specific changes are confined to the hw/vnc directory. When the VNC X server initializes, it creates a framebuffer in memory that all the X operations write into. The pixels are pulled out of this memory buffer and transmitted to the clients using the VNC protocol. This is the way it has always worked.

The modified server creates a square in-memory framebuffer and initializes the X code with square dimensions. For example, if you request a 1024x768 display, a 1024x1024 framebuffer is created. The X operations don't require any modifications to write into this larger framebuffer. Only the parts actually visable are transmitted to the clients. Only a few elements in the X screen structure are altered to indicate the actual width/height of the screen, which are only used in a few places by the X server. To rotate, we leave the in-memory framebuffer unaltered (so the X part of the code never does anything special), and changes the VNC transmission code to pull the pixels out of the framebuffer in the correct order for the current rotation.

Example

The server is started as normal:

And I can connect to it as normal:

I've added options to my fvwm2 configuration to allow menu-driven orientation changes:

...and in my MenuFvwmRoot section I add...

The Restart command is included on all the orientation changes in case we've switched between landscape and portrait modes; then fvwm needs to reinitialize to get the new screen geometry. If, like me, you use fvwm's virtual desktop feature, you can take advantage of the 4:3 aspect ratio of most display hardware to create a square virtual desktop whose dimensions remain constant during orientation changes:

In my case, this creates a 3072x3072 virtual desktop (3072 = 1024x3 = 768x4) partitioned into either a 3x4 1024x768 geometry or a 4x3 768x1024 geometry. Since the virtual desktop size is constant, windows can never disappear from the desktop after an orientation change. For this to work, you need to preprocess this statement with M4, see the FvwmM4 manual page for details.