src/macosx/classes/sun/lwawt/macosx/CCustomCursor.java

Print this page

        

@@ -24,21 +24,21 @@
  */
 
 package sun.lwawt.macosx;
 
 import java.awt.*;
+import java.awt.image.BufferedImage;
 
 public class CCustomCursor extends Cursor {
     static Dimension sMaxCursorSize;
     static Dimension getMaxCursorSize() {
         if (sMaxCursorSize != null) return sMaxCursorSize;
         final Rectangle bounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().getBounds();
         return sMaxCursorSize = new Dimension(bounds.width / 2, bounds.height / 2);
     }
 
     Image fImage;
-    private boolean isImageOk = false;
     Point fHotspot;
 
     public CCustomCursor(final Image cursor, final Point hotSpot, final String name) throws IndexOutOfBoundsException, HeadlessException {
         super(name);
         fImage = cursor;

@@ -59,26 +59,24 @@
         int height = fImage.getHeight(c);
 
         // Fix for bug 4212593 The Toolkit.createCustomCursor does not
         // check absence of the image of cursor
         // If the image is invalid, the cursor will be hidden (made completely
-        // transparent). In this case, getBestCursorSize() will adjust negative w and h,
-        // but we need to set the hotspot inside the image here.
+        // transparent).
         if (tracker.isErrorAny() || width < 0 || height < 0) {
             fHotspot.x = fHotspot.y = 0;
-            isImageOk = false;
+            width = height = 1;
+            fImage = createTransparentImage(width, height);
         } else {
-            isImageOk = true;
-        }
-
         // Scale image to nearest supported size
         final Dimension nativeSize = toolkit.getBestCursorSize(width, height);
         if (nativeSize.width != width || nativeSize.height != height) {
             fImage = fImage.getScaledInstance(nativeSize.width, nativeSize.height, Image.SCALE_DEFAULT);
             width = nativeSize.width;
             height = nativeSize.height;
         }
+        }
 
         // NOTE: this was removed for 3169146, but in 1.5 the JCK tests for an exception and fails if one isn't thrown.
         // See what JBuilder does.
         // Verify that the hotspot is within cursor bounds.
         if (fHotspot.x >= width || fHotspot.y >= height || fHotspot.x < 0 || fHotspot.y < 0) {

@@ -96,10 +94,25 @@
         } else if (fHotspot.y < 0) {
             fHotspot.y = 0;
         }
     }
 
+    private static BufferedImage createTransparentImage(int w, int h) {
+        GraphicsEnvironment ge =
+                GraphicsEnvironment.getLocalGraphicsEnvironment();
+        GraphicsDevice gs = ge.getDefaultScreenDevice();
+        GraphicsConfiguration gc = gs.getDefaultConfiguration();
+
+        BufferedImage img = gc.createCompatibleImage(w, h, Transparency.BITMASK);
+        Graphics2D g = (Graphics2D)img.getGraphics();
+        g.setBackground(new Color(0, 0, 0, 0));
+        g.clearRect(0, 0, w, h);
+        g.dispose();
+
+        return img;
+    }
+
     public static Dimension getBestCursorSize(final int preferredWidth, final int preferredHeight) {
         // With Panther, cursors have no limit on their size. So give the client their
         // preferred size, but no larger than half the dimensions of the main screen
         // This will allow large cursors, but not cursors so large that they cover the
         // screen. Since solaris nor windows allow cursors this big, this shouldn't be

@@ -109,36 +122,31 @@
         final Dimension d = new Dimension(Math.max(1, Math.abs(preferredWidth)), Math.max(1, Math.abs(preferredHeight)));
         return new Dimension(Math.min(d.width, maxCursorSize.width), Math.min(d.height, maxCursorSize.height));
     }
 
     // Called from native when the cursor is set
-    // Returns long array of [NSImage ptr, x hotspot, y hotspot]
     CImage fCImage;
     long getImageData() {
         if (fCImage != null) {
             return fCImage.ptr;
         }
 
-        if (isImageOk) {
             try {
                 fCImage = CImage.getCreator().createFromImage(fImage);
-
                 if (fCImage == null) {
-                    isImageOk = false;
+                // Something unexpected happened: CCustomCursor constructor
+                // takes care of invalid cursor images, yet createFromImage()
+                // failed to do its job. Return null to keep the cursor unchanged.
                     return 0L;
                 } else {
                     return fCImage.ptr;
                 }
             } catch (IllegalArgumentException iae) {
-                // Silently return null - we want to hide cursor by providing an empty
-                // ByteArray or just null
+            // see comment above
                 return 0L;
             }
         }
 
-        return 0L;
-    }
-
     Point getHotSpot() {
         return fHotspot;
     }
 }