4949 */
5050public final class Cursor extends Resource {
5151
52- /**
53- * the handle to the OS cursor resource
54- * (Warning: This field is platform dependent)
55- * <p>
56- * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
57- * public API. It is marked public only so that it can be shared
58- * within the packages provided by SWT. It is not available on all
59- * platforms and should never be accessed from application code.
60- * </p>
61- *
62- */
63- private long handle ;
6452 /**
6553 * Attribute to cache current native zoom level
6654 */
@@ -70,6 +58,8 @@ public final class Cursor extends Resource {
7058
7159 private final CursorHandleProvider cursorHandleProvider ;
7260
61+ private boolean isDestroyed ;
62+
7363/**
7464 * Constructs a new cursor given a device and a style
7565 * constant describing the desired cursor appearance.
@@ -119,7 +109,6 @@ public final class Cursor extends Resource {
119109public Cursor (Device device , int style ) {
120110 super (device );
121111 this .cursorHandleProvider = new StyleCursorHandleProvider (style );
122- this .handle = this .cursorHandleProvider .createHandle (this .device , DEFAULT_ZOOM ).getHandle ();
123112 init ();
124113 this .device .registerResourceWithZoomSupport (this );
125114}
@@ -160,28 +149,17 @@ public Cursor(Device device, int style) {
160149public Cursor (Device device , ImageData source , ImageData mask , int hotspotX , int hotspotY ) {
161150 super (device );
162151 this .cursorHandleProvider = new ImageDataWithMaskCursorHandleProvider (source , mask , hotspotX , hotspotY );
163- this .handle = this .cursorHandleProvider .createHandle (this .device , DEFAULT_ZOOM ).getHandle ();
164152 init ();
165153 this .device .registerResourceWithZoomSupport (this );
166154}
167155
168156private static CursorHandle setupCursorFromImageData (ImageData source , ImageData mask , int hotspotX , int hotspotY ) {
169- if (source == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
170157 if (mask == null ) {
171158 if (source .getTransparencyType () != SWT .TRANSPARENCY_MASK ) {
172159 SWT .error (SWT .ERROR_NULL_ARGUMENT );
173160 }
174161 mask = source .getTransparencyMask ();
175162 }
176- /* Check the bounds. Mask must be the same size as source */
177- if (mask .width != source .width || mask .height != source .height ) {
178- SWT .error (SWT .ERROR_INVALID_ARGUMENT );
179- }
180- /* Check the hotspots */
181- if (hotspotX >= source .width || hotspotX < 0 ||
182- hotspotY >= source .height || hotspotY < 0 ) {
183- SWT .error (SWT .ERROR_INVALID_ARGUMENT );
184- }
185163 /* Convert depth to 1 */
186164 mask = ImageData .convertMask (mask );
187165 source = ImageData .convertMask (source );
@@ -229,18 +207,12 @@ private static CursorHandle setupCursorFromImageData(ImageData source, ImageData
229207public Cursor (Device device , ImageData source , int hotspotX , int hotspotY ) {
230208 super (device );
231209 this .cursorHandleProvider = new ImageDataCursorHandleProvider (source , hotspotX , hotspotY );
232- this .handle = this .cursorHandleProvider .createHandle (this .device , DEFAULT_ZOOM ).getHandle ();
233210 init ();
234211 this .device .registerResourceWithZoomSupport (this );
235212}
236213
237214private static CursorHandle setupCursorFromImageData (Device device , ImageData source , int hotspotX , int hotspotY ) {
238215 if (source == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
239- /* Check the hotspots */
240- if (hotspotX >= source .width || hotspotX < 0 ||
241- hotspotY >= source .height || hotspotY < 0 ) {
242- SWT .error (SWT .ERROR_INVALID_ARGUMENT );
243- }
244216 long hBitmap = 0 ;
245217 long hMask = 0 ;
246218 if (source .maskData == null && source .transparentPixel == -1 && (source .alpha != -1 || source .alphaData != null )) {
@@ -341,7 +313,6 @@ public Cursor(Device device, ImageDataProvider imageDataProvider, int hotspotX,
341313 super (device );
342314 if (imageDataProvider == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
343315 this .cursorHandleProvider = new ImageDataProviderCursorHandleProvider (imageDataProvider , hotspotX , hotspotY );
344- this .handle = this .cursorHandleProvider .createHandle (this .device , DEFAULT_ZOOM ).getHandle ();
345316 init ();
346317 this .device .registerResourceWithZoomSupport (this );
347318}
@@ -363,7 +334,7 @@ public Cursor(Device device, ImageDataProvider imageDataProvider, int hotspotX,
363334 */
364335public static Long win32_getHandle (Cursor cursor , int zoom ) {
365336 if (cursor .isDisposed ()) {
366- return cursor . handle ;
337+ return 0L ;
367338 }
368339 if (cursor .zoomLevelToHandle .get (zoom ) != null ) {
369340 return cursor .zoomLevelToHandle .get (zoom ).getHandle ();
@@ -376,38 +347,19 @@ public static Long win32_getHandle (Cursor cursor, int zoom) {
376347}
377348
378349private void setHandleForZoomLevel (CursorHandle handle , Integer zoom ) {
379- if (this .handle == 0 ) {
380- this .handle = handle .getHandle (); // Set handle for default zoom level
381- }
382350 if (zoom != null && !zoomLevelToHandle .containsKey (zoom )) {
383351 zoomLevelToHandle .put (zoom , handle );
384352 }
385353}
386354
387355@ Override
388356void destroy () {
389- /*
390- * It is an error in Windows to destroy the current
391- * cursor. Check that the cursor that is about to
392- * be destroyed is the current cursor. If so, set
393- * the current cursor to be IDC_ARROW. Note that
394- * Windows shares predefined cursors so the call to
395- * LoadCursor() does not leak.
396- */
397- // TEMPORARY CODE
398- // if (OS.GetCursor() == handle) {
399- // OS.SetCursor(OS.LoadCursor(0, OS.IDC_ARROW));
400- // }
401357 device .deregisterResourceWithZoomSupport (this );
402- destroyHandle ();
403- }
404-
405- private void destroyHandle () {
406358 for (CursorHandle handle : zoomLevelToHandle .values ()) {
407359 handle .destroy ();
408360 }
409361 zoomLevelToHandle .clear ();
410- handle = 0 ;
362+ this . isDestroyed = true ;
411363}
412364
413365/**
@@ -425,7 +377,7 @@ public boolean equals (Object object) {
425377 if (object == this ) return true ;
426378 if (!(object instanceof Cursor )) return false ;
427379 Cursor cursor = (Cursor ) object ;
428- return device == cursor .device && handle == cursor . handle ;
380+ return device == cursor .device && win32_getHandle ( this , DEFAULT_ZOOM ) == win32_getHandle ( cursor , DEFAULT_ZOOM ) ;
429381}
430382
431383/**
@@ -440,7 +392,7 @@ public boolean equals (Object object) {
440392 */
441393@ Override
442394public int hashCode () {
443- return ( int ) handle ;
395+ return win32_getHandle ( this , DEFAULT_ZOOM ). intValue () ;
444396}
445397
446398/**
@@ -455,7 +407,7 @@ public int hashCode () {
455407 */
456408@ Override
457409public boolean isDisposed () {
458- return handle == 0 ;
410+ return isDestroyed ;
459411}
460412
461413/**
@@ -467,7 +419,7 @@ public boolean isDisposed() {
467419@ Override
468420public String toString () {
469421 if (isDisposed ()) return "Cursor {*DISPOSED*}" ;
470- return "Cursor {" + handle + "}" ;
422+ return "Cursor {" + zoomLevelToHandle + "}" ;
471423}
472424
473425@ Override
@@ -531,19 +483,23 @@ private static interface CursorHandleProvider {
531483}
532484
533485private static class StyleCursorHandleProvider implements CursorHandleProvider {
534- private final int style ;
486+ private final long lpCursorName ;
535487
536488 public StyleCursorHandleProvider (int style ) {
537- this .style = style ;
489+ this .lpCursorName = getOSCursorIdFromStyle ( style ) ;
538490 }
539491
540492 @ Override
541493 public CursorHandle createHandle (Device device , int zoom ) {
542494 // zoom ignored, LoadCursor handles scaling internally
543- return setupCursorFromStyle (this .style );
495+ long handle = OS .LoadCursor (0 , lpCursorName );
496+ if (handle == 0 ) {
497+ SWT .error (SWT .ERROR_NO_HANDLES );
498+ }
499+ return new CustomCursorHandle (handle );
544500 }
545501
546- private static final CursorHandle setupCursorFromStyle (int style ) {
502+ private static final long getOSCursorIdFromStyle (int style ) {
547503 long lpCursorName = 0 ;
548504 switch (style ) {
549505 case SWT .CURSOR_HAND :
@@ -615,11 +571,7 @@ private static final CursorHandle setupCursorFromStyle(int style) {
615571 default :
616572 SWT .error (SWT .ERROR_INVALID_ARGUMENT );
617573 }
618- long handle = OS .LoadCursor (0 , lpCursorName );
619- if (handle == 0 ) {
620- SWT .error (SWT .ERROR_NO_HANDLES );
621- }
622- return new CustomCursorHandle (handle );
574+ return lpCursorName ;
623575 }
624576}
625577
@@ -639,13 +591,24 @@ protected final int getHotpotXInPixels(int zoom) {
639591 protected final int getHotpotYInPixels (int zoom ) {
640592 return Win32DPIUtils .pointToPixel (hotspotY , zoom );
641593 }
594+
595+ protected static final void validateHotspotInsideImage (ImageData source , int hotspotX , int hotspotY ) {
596+ if (source == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
597+ /* Check the hotspots */
598+ if (hotspotX >= source .width || hotspotX < 0 ||
599+ hotspotY >= source .height || hotspotY < 0 ) {
600+ SWT .error (SWT .ERROR_INVALID_ARGUMENT );
601+ }
602+ }
642603}
643604
644605private static class ImageDataProviderCursorHandleProvider extends HotspotAwareCursorHandleProvider {
645606 private final ImageDataProvider provider ;
646607
647608 public ImageDataProviderCursorHandleProvider (ImageDataProvider provider , int hotspotX , int hotspotY ) {
648609 super (hotspotX , hotspotY );
610+ ImageData source = provider .getImageData (DEFAULT_ZOOM );
611+ validateHotspotInsideImage (source , hotspotX , hotspotY );
649612 this .provider = provider ;
650613 }
651614
@@ -668,6 +631,7 @@ private static class ImageDataCursorHandleProvider extends HotspotAwareCursorHan
668631
669632 public ImageDataCursorHandleProvider (ImageData source , int hotspotX , int hotspotY ) {
670633 super (hotspotX , hotspotY );
634+ validateHotspotInsideImage (source , hotspotX , hotspotY );
671635 this .source = source ;
672636 }
673637
@@ -685,6 +649,21 @@ private static class ImageDataWithMaskCursorHandleProvider extends ImageDataCurs
685649 public ImageDataWithMaskCursorHandleProvider (ImageData source , ImageData mask , int hotspotX , int hotspotY ) {
686650 super (source , hotspotX , hotspotY );
687651 this .mask = mask ;
652+ validateMask (source , mask );
653+ }
654+
655+ private void validateMask (ImageData source , ImageData mask ) {
656+ ImageData testMask = mask == null ? null : (ImageData ) mask .clone ();
657+ if (testMask == null ) {
658+ if (source .getTransparencyType () != SWT .TRANSPARENCY_MASK ) {
659+ SWT .error (SWT .ERROR_NULL_ARGUMENT );
660+ }
661+ testMask = source .getTransparencyMask ();
662+ }
663+ /* Check the bounds. Mask must be the same size as source */
664+ if (testMask .width != source .width || testMask .height != source .height ) {
665+ SWT .error (SWT .ERROR_INVALID_ARGUMENT );
666+ }
688667 }
689668
690669 @ Override
0 commit comments