@@ -66,10 +66,9 @@ public final class Cursor extends Resource {
6666 */
6767 private static final int DEFAULT_ZOOM = 100 ;
6868
69- private HashMap <Integer , Long > zoomLevelToHandle = new HashMap <>();
69+ private HashMap <Integer , CursorHandle > zoomLevelToHandle = new HashMap <>();
7070
7171 private final CursorHandleProvider cursorHandleProvider ;
72- boolean isIcon ;
7372
7473/**
7574 * Constructs a new cursor given a device and a style
@@ -120,7 +119,7 @@ public final class Cursor extends Resource {
120119public Cursor (Device device , int style ) {
121120 super (device );
122121 this .cursorHandleProvider = new StyleCursorHandleProvider (style );
123- this .handle = this .cursorHandleProvider .createHandle (device , DEFAULT_ZOOM );
122+ this .handle = this .cursorHandleProvider .createHandle (device , DEFAULT_ZOOM ). getHandle () ;
124123 init ();
125124 this .device .registerResourceWithZoomSupport (this );
126125}
@@ -161,12 +160,12 @@ public Cursor(Device device, int style) {
161160public Cursor (Device device , ImageData source , ImageData mask , int hotspotX , int hotspotY ) {
162161 super (device );
163162 this .cursorHandleProvider = new ImageDataWithMaskCursorHandleProvider (source , mask , hotspotX , hotspotY );
164- this .handle = this .cursorHandleProvider .createHandle (device , DEFAULT_ZOOM );
163+ this .handle = this .cursorHandleProvider .createHandle (device , DEFAULT_ZOOM ). getHandle () ;
165164 init ();
166165 this .device .registerResourceWithZoomSupport (this );
167166}
168167
169- private static long setupCursorFromImageData (ImageData source , ImageData mask , int hotspotX , int hotspotY ) {
168+ private static CursorHandle setupCursorFromImageData (ImageData source , ImageData mask , int hotspotX , int hotspotY ) {
170169 if (source == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
171170 if (mask == null ) {
172171 if (source .getTransparencyType () != SWT .TRANSPARENCY_MASK ) {
@@ -195,7 +194,7 @@ private static long setupCursorFromImageData(ImageData source, ImageData mask, i
195194 long hInst = OS .GetModuleHandle (null );
196195 long handle = OS .CreateCursor (hInst , hotspotX , hotspotY , source .width , source .height , sourceData , maskData );
197196 if (handle == 0 ) SWT .error (SWT .ERROR_NO_HANDLES );
198- return handle ;
197+ return new CustomCursorHandle ( handle ) ;
199198}
200199
201200/**
@@ -230,13 +229,12 @@ private static long setupCursorFromImageData(ImageData source, ImageData mask, i
230229public Cursor (Device device , ImageData source , int hotspotX , int hotspotY ) {
231230 super (device );
232231 this .cursorHandleProvider = new ImageDataCursorHandleProvider (source , hotspotX , hotspotY );
233- isIcon = true ;
234- this .handle = this .cursorHandleProvider .createHandle (device , DEFAULT_ZOOM );
232+ this .handle = this .cursorHandleProvider .createHandle (device , DEFAULT_ZOOM ).getHandle ();
235233 init ();
236234 this .device .registerResourceWithZoomSupport (this );
237235}
238236
239- private static long setupCursorFromImageData (Device device , ImageData source , int hotspotX , int hotspotY ) {
237+ private static CursorHandle setupCursorFromImageData (Device device , ImageData source , int hotspotX , int hotspotY ) {
240238 if (source == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
241239 /* Check the hotspots */
242240 if (hotspotX >= source .width || hotspotX < 0 ||
@@ -307,7 +305,7 @@ private static long setupCursorFromImageData(Device device, ImageData source, in
307305 OS .DeleteObject (hMask );
308306 if (handle == 0 ) SWT .error (SWT .ERROR_NO_HANDLES );
309307
310- return handle ;
308+ return new IconCursorHandle ( handle ) ;
311309}
312310
313311/**
@@ -343,8 +341,7 @@ public Cursor(Device device, ImageDataProvider imageDataProvider, int hotspotX,
343341 super (device );
344342 if (imageDataProvider == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
345343 this .cursorHandleProvider = new ImageDataProviderCursorHandleProvider (imageDataProvider , hotspotX , hotspotY );
346- isIcon = true ;
347- this .handle = this .cursorHandleProvider .createHandle (device , DEFAULT_ZOOM );
344+ this .handle = this .cursorHandleProvider .createHandle (device , DEFAULT_ZOOM ).getHandle ();
348345 init ();
349346 this .device .registerResourceWithZoomSupport (this );
350347}
@@ -369,18 +366,18 @@ public static Long win32_getHandle (Cursor cursor, int zoom) {
369366 return cursor .handle ;
370367 }
371368 if (cursor .zoomLevelToHandle .get (zoom ) != null ) {
372- return cursor .zoomLevelToHandle .get (zoom );
369+ return cursor .zoomLevelToHandle .get (zoom ). getHandle () ;
373370 }
374371
375- long handle = cursor .cursorHandleProvider .createHandle (cursor .device , zoom );
372+ CursorHandle handle = cursor .cursorHandleProvider .createHandle (cursor .device , zoom );
376373 cursor .setHandleForZoomLevel (handle , zoom );
377374
378- return cursor .zoomLevelToHandle .get (zoom );
375+ return cursor .zoomLevelToHandle .get (zoom ). getHandle () ;
379376}
380377
381- private void setHandleForZoomLevel (long handle , Integer zoom ) {
378+ private void setHandleForZoomLevel (CursorHandle handle , Integer zoom ) {
382379 if (this .handle == 0 ) {
383- this .handle = handle ; // Set handle for default zoom level
380+ this .handle = handle . getHandle () ; // Set handle for default zoom level
384381 }
385382 if (zoom != null && !zoomLevelToHandle .containsKey (zoom )) {
386383 zoomLevelToHandle .put (zoom , handle );
@@ -406,29 +403,13 @@ void destroy () {
406403}
407404
408405private void destroyHandle () {
409- for (Long handle : zoomLevelToHandle .values ()) {
410- destroyHandle ( handle );
406+ for (CursorHandle handle : zoomLevelToHandle .values ()) {
407+ handle . destroy ( );
411408 }
412409 zoomLevelToHandle .clear ();
413410 handle = 0 ;
414411}
415412
416- private void destroyHandle (long handle ) {
417- if (isIcon ) {
418- OS .DestroyIcon (handle );
419- } else {
420- /*
421- * The MSDN states that one should not destroy a shared
422- * cursor, that is, one obtained from LoadCursor.
423- * However, it does not appear to do any harm, so rather
424- * than keep track of how a cursor was created, we just
425- * destroy them all. If this causes problems in the future,
426- * put the flag back in.
427- */
428- OS .DestroyCursor (handle );
429- }
430- }
431-
432413/**
433414 * Compares the argument to the receiver, and returns true
434415 * if they represent the <em>same</em> object using a class
@@ -494,15 +475,59 @@ void destroyHandlesExcept(Set<Integer> zoomLevels) {
494475 zoomLevelToHandle .entrySet ().removeIf (entry -> {
495476 final Integer zoom = entry .getKey ();
496477 if (!zoomLevels .contains (zoom ) && zoom != DPIUtil .getZoomForAutoscaleProperty (DEFAULT_ZOOM )) {
497- destroyHandle ( entry .getValue ());
478+ entry .getValue (). destroy ( );
498479 return true ;
499480 }
500481 return false ;
501482 });
502483}
503484
485+ private static abstract class CursorHandle {
486+ private final long handle ;
487+
488+ public CursorHandle (long handle ) {
489+ this .handle = handle ;
490+ }
491+
492+ long getHandle () {
493+ return handle ;
494+ }
495+
496+ abstract void destroy ();
497+ }
498+
499+ private static class IconCursorHandle extends CursorHandle {
500+ public IconCursorHandle (long handle ) {
501+ super (handle );
502+ }
503+
504+ @ Override
505+ void destroy () {
506+ OS .DestroyIcon (getHandle ());
507+ }
508+ }
509+
510+ private static class CustomCursorHandle extends CursorHandle {
511+ public CustomCursorHandle (long handle ) {
512+ super (handle );
513+ }
514+
515+ @ Override
516+ void destroy () {
517+ /*
518+ * The MSDN states that one should not destroy a shared
519+ * cursor, that is, one obtained from LoadCursor.
520+ * However, it does not appear to do any harm, so rather
521+ * than keep track of how a cursor was created, we just
522+ * destroy them all. If this causes problems in the future,
523+ * put the flag back in.
524+ */
525+ OS .DestroyCursor (getHandle ());
526+ }
527+ }
528+
504529private static interface CursorHandleProvider {
505- long createHandle (Device device , int zoom );
530+ CursorHandle createHandle (Device device , int zoom );
506531}
507532
508533private static class StyleCursorHandleProvider implements CursorHandleProvider {
@@ -513,12 +538,12 @@ public StyleCursorHandleProvider(int style) {
513538 }
514539
515540 @ Override
516- public long createHandle (Device device , int zoom ) {
541+ public CursorHandle createHandle (Device device , int zoom ) {
517542 // zoom ignored, LoadCursor handles scaling internally
518543 return setupCursorFromStyle (this .style );
519544 }
520545
521- private static final long setupCursorFromStyle (int style ) {
546+ private static final CursorHandle setupCursorFromStyle (int style ) {
522547 long lpCursorName = 0 ;
523548 switch (style ) {
524549 case SWT .CURSOR_HAND :
@@ -594,7 +619,7 @@ private static final long setupCursorFromStyle(int style) {
594619 if (handle == 0 ) {
595620 SWT .error (SWT .ERROR_NO_HANDLES );
596621 }
597- return handle ;
622+ return new CustomCursorHandle ( handle ) ;
598623 }
599624}
600625
@@ -625,7 +650,7 @@ public ImageDataProviderCursorHandleProvider(ImageDataProvider provider, int hot
625650 }
626651
627652 @ Override
628- public long createHandle (Device device , int zoom ) {
653+ public CursorHandle createHandle (Device device , int zoom ) {
629654 ImageData source ;
630655 if (zoom == DEFAULT_ZOOM ) {
631656 source = this .provider .getImageData (DEFAULT_ZOOM );
@@ -647,7 +672,7 @@ public ImageDataCursorHandleProvider(ImageData source, int hotspotX, int hotspot
647672 }
648673
649674 @ Override
650- public long createHandle (Device device , int zoom ) {
675+ public CursorHandle createHandle (Device device , int zoom ) {
651676 ImageData scaledSource = DPIUtil .scaleImageData (device , this .source , zoom , DEFAULT_ZOOM );
652677 return setupCursorFromImageData (device , scaledSource , getHotpotXInPixels (zoom ),
653678 getHotpotYInPixels (zoom ));
@@ -663,7 +688,7 @@ public ImageDataWithMaskCursorHandleProvider(ImageData source, ImageData mask, i
663688 }
664689
665690 @ Override
666- public long createHandle (Device device , int zoom ) {
691+ public CursorHandle createHandle (Device device , int zoom ) {
667692 ImageData scaledSource = DPIUtil .scaleImageData (device , this .source , zoom , DEFAULT_ZOOM );
668693 ImageData scaledMask = this .mask != null ? DPIUtil .scaleImageData (device , mask , zoom , DEFAULT_ZOOM )
669694 : null ;
0 commit comments