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 */
@@ -74,6 +62,8 @@ public final class Cursor extends Resource {
7462 private final ImageData mask ;
7563 private final int hotspotX ;
7664 private final int hotspotY ;
65+ private boolean isDestroyed ;
66+ private Integer style ;
7767/**
7868 * Prevents uninitialized instances from being created outside the package.
7969 */
@@ -135,7 +125,9 @@ public final class Cursor extends Resource {
135125 */
136126public Cursor (Device device , int style ) {
137127 this (device );
138- this .handle = setupCursorFromStyle (style );
128+ this .style = style ;
129+ long handle = setupCursorFromStyle (style );
130+ zoomLevelToHandle .put (DEFAULT_ZOOM , handle );
139131 init ();
140132}
141133
@@ -212,7 +204,8 @@ public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int
212204 this .hotspotX = hotspotX ;
213205 this .hotspotY = hotspotY ;
214206 this .imageDataProvider = null ;
215- this .handle = setupCursorFromImageData (source , mask , hotspotX , hotspotY );
207+ long handle = setupCursorFromImageData (source , mask , hotspotX , hotspotY );
208+ zoomLevelToHandle .put (DEFAULT_ZOOM , handle );
216209 init ();
217210 this .device .registerResourceWithZoomSupport (this );
218211}
@@ -285,8 +278,53 @@ public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) {
285278 this .hotspotX = hotspotX ;
286279 this .hotspotY = hotspotY ;
287280 this .imageDataProvider = null ;
288- this . handle = setupCursorFromImageData (device , source , hotspotX , hotspotY );
281+ long handle = setupCursorFromImageData (device , source , hotspotX , hotspotY );
289282 isIcon = true ;
283+ zoomLevelToHandle .put (DEFAULT_ZOOM , handle );
284+ init ();
285+ this .device .registerResourceWithZoomSupport (this );
286+ }
287+
288+ /**
289+ * Constructs a new cursor given a device, image describing
290+ * the desired cursor appearance, and the x and y coordinates of
291+ * the <em>hotspot</em> (that is, the point within the area
292+ * covered by the cursor which is considered to be where the
293+ * on-screen pointer is "pointing").
294+ * <p>
295+ * You must dispose the cursor when it is no longer required.
296+ * </p>
297+ *
298+ * @param device the device on which to allocate the cursor
299+ * @param imageDataProvider the ImageDataProvider for the cursor
300+ * @param hotspotX the x coordinate of the cursor's hotspot
301+ * @param hotspotY the y coordinate of the cursor's hotspot
302+ *
303+ * @exception IllegalArgumentException <ul>
304+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
305+ * <li>ERROR_NULL_ARGUMENT - if the image is null</li>
306+ * <li>ERROR_INVALID_ARGUMENT - if the hotspot is outside the bounds of the
307+ * image</li>
308+ * </ul>
309+ * @exception SWTError <ul>
310+ * <li>ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation</li>
311+ * </ul>
312+ *
313+ * @see #dispose()
314+ *
315+ * @since 3.131
316+ */
317+ public Cursor (Device device , ImageDataProvider imageDataProvider , int hotspotX , int hotspotY ) {
318+ super (device );
319+ if (imageDataProvider == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
320+ this .imageDataProvider = imageDataProvider ;
321+ this .source = imageDataProvider .getImageData (100 );
322+ this .mask = null ;
323+ this .hotspotX = hotspotX ;
324+ this .hotspotY = hotspotY ;
325+ long handle = setupCursorFromImageData (device , this .source , hotspotX , hotspotY );
326+ isIcon = true ;
327+ zoomLevelToHandle .put (DEFAULT_ZOOM , handle );
290328 init ();
291329 this .device .registerResourceWithZoomSupport (this );
292330}
@@ -365,49 +403,6 @@ private static long setupCursorFromImageData(Device device, ImageData source, in
365403 return handle ;
366404}
367405
368- /**
369- * Constructs a new cursor given a device, image describing
370- * the desired cursor appearance, and the x and y coordinates of
371- * the <em>hotspot</em> (that is, the point within the area
372- * covered by the cursor which is considered to be where the
373- * on-screen pointer is "pointing").
374- * <p>
375- * You must dispose the cursor when it is no longer required.
376- * </p>
377- *
378- * @param device the device on which to allocate the cursor
379- * @param imageDataProvider the ImageDataProvider for the cursor
380- * @param hotspotX the x coordinate of the cursor's hotspot
381- * @param hotspotY the y coordinate of the cursor's hotspot
382- *
383- * @exception IllegalArgumentException <ul>
384- * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
385- * <li>ERROR_NULL_ARGUMENT - if the image is null</li>
386- * <li>ERROR_INVALID_ARGUMENT - if the hotspot is outside the bounds of the
387- * image</li>
388- * </ul>
389- * @exception SWTError <ul>
390- * <li>ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation</li>
391- * </ul>
392- *
393- * @see #dispose()
394- *
395- * @since 3.131
396- */
397- public Cursor (Device device , ImageDataProvider imageDataProvider , int hotspotX , int hotspotY ) {
398- super (device );
399- if (imageDataProvider == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
400- this .imageDataProvider = imageDataProvider ;
401- this .source = imageDataProvider .getImageData (100 );
402- this .mask = null ;
403- this .hotspotX = hotspotX ;
404- this .hotspotY = hotspotY ;
405- this .handle = setupCursorFromImageData (device , this .source , hotspotX , hotspotY );
406- isIcon = true ;
407- init ();
408- this .device .registerResourceWithZoomSupport (this );
409- }
410-
411406/**
412407 * <b>IMPORTANT:</b> This method is not part of the public
413408 * API for Image. It is marked public only so that it
@@ -424,41 +419,40 @@ public Cursor(Device device, ImageDataProvider imageDataProvider, int hotspotX,
424419 * @noreference This method is not intended to be referenced by clients.
425420 */
426421public static Long win32_getHandle (Cursor cursor , int zoom ) {
427- if (cursor .isDisposed () ) {
428- return cursor . handle ;
422+ if (cursor .zoomLevelToHandle . size () == 0 ) {
423+ return 0L ;
429424 }
430425 if (cursor .zoomLevelToHandle .get (zoom ) != null ) {
431426 return cursor .zoomLevelToHandle .get (zoom );
432427 }
433428
434- if (cursor .source == null ) {
435- cursor .setHandleForZoomLevel (cursor .handle , zoom );
429+ if (cursor .style != null ) {
430+ // we don't need to pass zoom in this case. LoadCursor will always return scaled cursor even though handle value will be same for all zoom levels.
431+ long handle = setupCursorFromStyle (cursor .style );
432+ cursor .setHandleForZoomLevel (handle , zoom );
436433 } else {
437434 ImageData source ;
438435 if (cursor .imageDataProvider != null ) {
439436 Image tempImage = new Image (cursor .getDevice (), cursor .imageDataProvider );
440437 source = tempImage .getImageData (zoom );
441438 tempImage .dispose ();
439+ } else {
440+ source = DPIUtil .scaleImageData (cursor .getDevice (), cursor .source , zoom , DEFAULT_ZOOM );
442441 }
443- else {
444- source = DPIUtil .scaleImageData (cursor .device , cursor .source , zoom , DEFAULT_ZOOM );
445- }
442+
446443 if (cursor .isIcon ) {
447- Cursor newCursor = new Cursor (cursor .device , source , Win32DPIUtils .pointToPixel (cursor .hotspotX , zoom ), Win32DPIUtils .pointToPixel (cursor .hotspotY , zoom ));
448- cursor .setHandleForZoomLevel (newCursor . handle , zoom );
444+ long handle = setupCursorFromImageData (cursor .getDevice () , source , Win32DPIUtils .pointToPixel (cursor .hotspotX , zoom ), Win32DPIUtils .pointToPixel (cursor .hotspotY , zoom ));
445+ cursor .setHandleForZoomLevel (handle , zoom );
449446 } else {
450- ImageData mask = DPIUtil .scaleImageData (cursor .device , cursor .mask , zoom , DEFAULT_ZOOM );
451- Cursor newCursor = new Cursor ( cursor . device , source , mask , Win32DPIUtils .pointToPixel (cursor .hotspotX , zoom ), Win32DPIUtils .pointToPixel (cursor .hotspotY , zoom ));
452- cursor .setHandleForZoomLevel (newCursor . handle , zoom );
447+ ImageData mask = DPIUtil .scaleImageData (cursor .getDevice () , cursor .mask , zoom , DEFAULT_ZOOM );
448+ long handle = setupCursorFromImageData ( source , mask , Win32DPIUtils .pointToPixel (cursor .hotspotX , zoom ), Win32DPIUtils .pointToPixel (cursor .hotspotY , zoom ));
449+ cursor .setHandleForZoomLevel (handle , zoom );
453450 }
454451 }
455452 return cursor .zoomLevelToHandle .get (zoom );
456453}
457454
458455private void setHandleForZoomLevel (long handle , Integer zoom ) {
459- if (this .handle == 0 ) {
460- this .handle = handle ; // Set handle for default zoom level
461- }
462456 if (zoom != null && !zoomLevelToHandle .containsKey (zoom )) {
463457 zoomLevelToHandle .put (zoom , handle );
464458 }
@@ -480,14 +474,14 @@ void destroy () {
480474// }
481475 device .deregisterResourceWithZoomSupport (this );
482476 destroyHandle ();
477+ this .isDestroyed = true ;
483478}
484479
485480private void destroyHandle () {
486481 for (Long handle : zoomLevelToHandle .values ()) {
487482 destroyHandle (handle );
488483 }
489484 zoomLevelToHandle .clear ();
490- handle = 0 ;
491485}
492486
493487private void destroyHandle (long handle ) {
@@ -521,7 +515,7 @@ public boolean equals (Object object) {
521515 if (object == this ) return true ;
522516 if (!(object instanceof Cursor )) return false ;
523517 Cursor cursor = (Cursor ) object ;
524- return device == cursor .device && handle == cursor . handle ;
518+ return device == cursor .device && win32_getHandle ( this , DEFAULT_ZOOM ) == win32_getHandle ( cursor , DEFAULT_ZOOM ) ;
525519}
526520
527521/**
@@ -536,7 +530,7 @@ public boolean equals (Object object) {
536530 */
537531@ Override
538532public int hashCode () {
539- return ( int ) handle ;
533+ return this . zoomLevelToHandle . get ( DEFAULT_ZOOM ) != null ? this . zoomLevelToHandle . get ( DEFAULT_ZOOM ). intValue () : 0 ;
540534}
541535
542536/**
@@ -551,7 +545,7 @@ public int hashCode () {
551545 */
552546@ Override
553547public boolean isDisposed () {
554- return handle == 0 ;
548+ return isDestroyed ;
555549}
556550
557551/**
@@ -563,7 +557,7 @@ public boolean isDisposed() {
563557@ Override
564558public String toString () {
565559 if (isDisposed ()) return "Cursor {*DISPOSED*}" ;
566- return "Cursor {" + handle + "}" ;
560+ return "Cursor {" + zoomLevelToHandle + "}" ;
567561}
568562
569563@ Override
0 commit comments