<AWT Dev> Toolkit.createCustomCursor throws exceptions

Mario Torre neugens at redhat.com
Wed Apr 20 10:06:43 UTC 2016


Hi all,

I happens that I stumbled upon an interesting issue with
XToolkit.createCustomCursor().

On a very specific combination of hardware and X11 driver we get an
exception propagating from XToolkit.createCustomCursor(), the
exception is:

java.awt.AWTException: Exception: class
java.lang.IllegalArgumentException Width (0) and height (0) must be
non-zero occurred while creating cursor CopyDrop.32x32

But the real thing is a bit more interesting (as to why exactly is 0,0):

Exception in thread "main" java.lang.IllegalArgumentException: Width
(0) and height (0) must be non-zero
at java.awt.image.ReplicateScaleFilter.<init>(ReplicateScaleFilter.java:102)
at java.awt.Image.getScaledInstance(Image.java:174)
at sun.awt.CustomCursor.<init>(CustomCursor.java:69)
at sun.awt.X11CustomCursor.<init>(X11CustomCursor.java:43)
at sun.awt.X11.XCustomCursor.<init>(XCustomCursor.java:42)
at sun.awt.X11.XToolkit.createCustomCursor(XToolkit.java:1140)
at FindCursor.main(FindCursor.java:19)

The issue happen every time we try to create a custom cursor which
includes as little as this:

public static void main(String[] args) {
    System.out.println(DragSource.isDragImageSupported());
}

As I said, I was able to detect that the actual issue is really an X11
driver problem, Toolkit.getBestCursorSize (which invokes
XQueryBestCursor on X11) returns 0,0 as the closest size, causing the
resize of the custom cursor image to be invalid. Although this driver
should be fixed, it's not technically wrong really, the driver is just
saying that it doesn't support custom cursors, so I wonder if the
exception (IllegalArgumentException) is correct. First of all, in the
case of DragSource.isDragImageSupported it's interesting since the
user doesn't create any custom cursor, it's simply asking if a drag
image is supported, I would expect "false" rather than a runtime
exception. The reason is that DragSource loads a bunch of custom
cursors at class loading:

private static Cursor load(String name) {
    if (GraphicsEnvironment.isHeadless()) {
        return null;
    }

    try {
        return (Cursor)Toolkit.getDefaultToolkit().getDesktopProperty(name);
    } catch (Exception e) {
        e.printStackTrace();

        throw new RuntimeException("failed to load system cursor: " +
name + " : " + e.getMessage());
    }
}

We could change this to simply skip the loading process, so at least
to not crash without apparent reason. I have a couple of alternative
fixes, but I'm not sure what's the best to do, if to patch the Toolkit
to simply return the default Cursor if the driver says it doesn't
support custom cursors, or if to change the load to either return the
default one or skip loading at all.

BTW, Toolkit.createCustomCursor  doesn't say to throw anything upon
failure, I would expect user code to check getBestCursorSize before
calling createCustomCursor, but this seems to never be done in the
internal code, and I don't know if we can fix this since it would be a
behaviour difference, perhaps some people rely on this exception.

Any ideas or suggestions?

I would like to approach a possible solution for JDK 8 as well as 9,
so an 8 compatible fix would be ideal.

Cheers,
Mario


More information about the awt-dev mailing list