Possible regression in Java 6 DisplayMode functionality on Ubuntu Gutsy

I upgraded my desktop machine to Gutsy today to have a play with it before upgrading my laptop. I’m really glad I did so in this order, as it appears there may be a regression in the version of Java 6 shipping on Gutsy.

I tested out the product I’m working on, which uses Full Screen Exclusive Mode with a DisplayMode of 800x600. So far the app has been working ok on Feisty but when I tested it today on Gutsy it couldn’t change display mode. I discovered that Java was only able to see the current screen mode of 1280x1024 and no others. This is a major pain for me; to continue developing I’m either going to have skip upgrading Ubuntu, or switch to another platform, and I’d really like to be able to continue using Ubuntu going forward.

I’ve opened a bug on Launchpad here: #154613: Java cannot change display modes / screen resolution in Gutsy, and I’ve been digging in trying to work out what’s going wrong.

I managed to locate the JNI function call in Java’s native C source code where it gets the list of modes. It’s called

Java_sun_awt_X11GraphicsDevice_enumDisplayModes(...)

and is in the file j2se/src/solaris/native/sun/awt/awt_GraphicsEnv.c. As expected the Ubuntu packages are built from the Sun Linux binaries - no source code. I couldn’t find the Java 6 source on Sun’s site, the link appears to be wrong. Instead I found the file in the Icedtea/OpenJDK source tree. Icedtea on Gutsy has the same problem so I’m fairly happy this is the the same or roughly the same code as in Java 6.

The function makes use of the Xrandr Xorg extension to query the available display modes. I coded up a small test to see if Xrandr was behaving correctly:

/* standard lib imports */
#include <stdio.h>
#include <stdlib.h>

/* Xorg imports */
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>

/* This doesn't really do anything but allows the same output as the DisplayModeLister */
#define BIT_DEPTH_MULTI -1

/*
 * xrandr-lsmodes -- binary to prove that the XRandr calls Java makes to list available display
 * modes are working ok.
 *
 * Screen mode listing code located in Java 7 / Icedtea
 * http://icedtea.classpath.org/hg/openjdk/file/ce9dde984c21/j2se/src/solaris/native/sun/awt/awt_GraphicsEnv.c
 * function: Java_sun_awt_X11GraphicsDevice_enumDisplayModes(...)
 */

int main(/* int argc, char *argv[] */)
{
    Display *display;
    int screen_num;
    XRRScreenConfiguration *config;
    XRRScreenSize *sizes;
    int nsizes, i;

    char *display_name = getenv("DISPLAY"); /* address of X display */

    display = XOpenDisplay(display_name);
    if (NULL == display) {
        fprintf(stderr, "Cannot connection to X server %s\n", display_name);
        exit(-1);
    }
    screen_num = DefaultScreen(display);

    config = XRRGetScreenInfo(display, RootWindow(display, screen_num));
    if (NULL == config) {
        fprintf(stderr, "Could not retrieve screen configuration\n");
        exit(-1);
    }

    sizes = XRRConfigSizes(config, &nsizes);
    if (NULL == sizes) {
        fprintf(stderr, "Could not retrieve list of sizes\n");
        exit(-1);
    }

    for (i = 0; i < nsizes; ++i) {
        int nrates, j;
        XRRScreenSize size = sizes[i];
        short *rates = XRRConfigRates(config, i, &nrates);

        for (j = 0; j < nrates; ++j) {
            printf("%3d: %4d x%4d @ %dHz %dbit\n",
                    i+1, size.width, size.height,
                    rates[j], BIT_DEPTH_MULTI);
        }
    }

    XRRFreeScreenConfigInfo(config);
    XCloseDisplay(display);

    return 0;
}

It is, on both Gutsy and Feisty. So it looks like it could be something in Java 6 u3.

Will keep digging, as I really need this to work.