diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Cursor.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Cursor.java index 31edc8c942e..17b7c8e4c0c 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Cursor.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Cursor.java @@ -382,6 +382,10 @@ void createNSCursor(int hotspotX, int hotspotY, byte[] buffer, int width, int he */ public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) { super(device); + setupCursorFromImageData(source, hotspotX, hotspotY); +} + +private void setupCursorFromImageData(ImageData source, int hotspotX, int hotspotY) { if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (hotspotX >= source.width || hotspotX < 0 || hotspotY >= source.height || hotspotY < 0) { @@ -448,6 +452,41 @@ public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) { } } +/** + * Constructs a new cursor given a device, image describing + * the desired cursor appearance, and the x and y coordinates of + * the hotspot (that is, the point within the area + * covered by the cursor which is considered to be where the + * on-screen pointer is "pointing"). + *

+ * You must dispose the cursor when it is no longer required. + *

+ * + * @param device the device on which to allocate the cursor + * @param imageDataProvider the ImageDataProvider for the cursor + * @param hotspotX the x coordinate of the cursor's hotspot + * @param hotspotY the y coordinate of the cursor's hotspot + * + * @exception IllegalArgumentException + * @exception SWTError + * + * @see #dispose() + * + * @since 3.131 + */ +public Cursor(Device device, ImageDataProvider imageDataProvider, int hotspotX, int hotspotY) { + super(device); + if (imageDataProvider == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + setupCursorFromImageData(imageDataProvider.getImageData(100), hotspotX, hotspotY); +} + @Override void destroy() { handle.release(); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Cursor.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Cursor.java index 422386d30e4..0fc7cde8a72 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Cursor.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Cursor.java @@ -272,6 +272,11 @@ public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int */ public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) { super(device); + setupCursorFromImageData(source, hotspotX, hotspotY); + +} + +private void setupCursorFromImageData(ImageData source, int hotspotX, int hotspotY) { if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (hotspotX >= source.width || hotspotX < 0 || hotspotY >= source.height || hotspotY < 0) { @@ -355,6 +360,41 @@ public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) { init(); } +/** + * Constructs a new cursor given a device, image describing + * the desired cursor appearance, and the x and y coordinates of + * the hotspot (that is, the point within the area + * covered by the cursor which is considered to be where the + * on-screen pointer is "pointing"). + *

+ * You must dispose the cursor when it is no longer required. + *

+ * + * @param device the device on which to allocate the cursor + * @param imageDataProvider the ImageDataProvider for the cursor + * @param hotspotX the x coordinate of the cursor's hotspot + * @param hotspotY the y coordinate of the cursor's hotspot + * + * @exception IllegalArgumentException + * @exception SWTError + * + * @see #dispose() + * + * @since 3.131 + */ +public Cursor(Device device, ImageDataProvider imageDataProvider, int hotspotX, int hotspotY) { + super(device); + if (imageDataProvider == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + setupCursorFromImageData(imageDataProvider.getImageData(100), hotspotX, hotspotY); +} + long createCursor(byte[] sourceData, byte[] maskData, int width, int height, int hotspotX, int hotspotY, boolean reverse) { for (int i = 0; i < sourceData.length; i++) { byte s = sourceData[i]; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Cursor.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Cursor.java index f1002ba50be..84468972a40 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Cursor.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Cursor.java @@ -69,6 +69,7 @@ public final class Cursor extends Resource { private HashMap zoomLevelToHandle = new HashMap<>(); boolean isIcon; + private final ImageDataProvider imageDataProvider; private final ImageData source; private final ImageData mask; private final int hotspotX; @@ -79,6 +80,7 @@ public final class Cursor extends Resource { Cursor(Device device) { super(device); this.source = null; + this.imageDataProvider = null; this.mask = null; this.hotspotX = -1; this.hotspotY = -1; @@ -204,6 +206,7 @@ public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int this.mask = mask; this.hotspotX = hotspotX; this.hotspotY = hotspotY; + this.imageDataProvider = null; if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (mask == null) { if (source.getTransparencyType() != SWT.TRANSPARENCY_MASK) { @@ -271,6 +274,11 @@ public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) { this.mask = null; this.hotspotX = hotspotX; this.hotspotY = hotspotY; + this.imageDataProvider = null; + setupCursorFromImageData(source); +} + +private void setupCursorFromImageData(ImageData source) { if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); /* Check the hotspots */ if (hotspotX >= source.width || hotspotX < 0 || @@ -345,6 +353,46 @@ public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) { this.device.registerResourceWithZoomSupport(this); } +/** + * Constructs a new cursor given a device, image describing + * the desired cursor appearance, and the x and y coordinates of + * the hotspot (that is, the point within the area + * covered by the cursor which is considered to be where the + * on-screen pointer is "pointing"). + *

+ * You must dispose the cursor when it is no longer required. + *

+ * + * @param device the device on which to allocate the cursor + * @param imageDataProvider the ImageDataProvider for the cursor + * @param hotspotX the x coordinate of the cursor's hotspot + * @param hotspotY the y coordinate of the cursor's hotspot + * + * @exception IllegalArgumentException + * @exception SWTError + * + * @see #dispose() + * + * @since 3.131 + */ +public Cursor(Device device, ImageDataProvider imageDataProvider, int hotspotX, int hotspotY) { + super(device); + if (imageDataProvider == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + this.imageDataProvider = imageDataProvider; + this.source = imageDataProvider.getImageData(100); + this.mask = null; + this.hotspotX = hotspotX; + this.hotspotY = hotspotY; + setupCursorFromImageData(this.source); +} + /** * IMPORTANT: This method is not part of the public * API for Image. It is marked public only so that it @@ -371,7 +419,13 @@ public static Long win32_getHandle (Cursor cursor, int zoom) { if (cursor.source == null) { cursor.setHandleForZoomLevel(cursor.handle, zoom); } else { - ImageData source = DPIUtil.scaleImageData(cursor.device, cursor.source, zoom, DEFAULT_ZOOM); + ImageData source; + if (cursor.imageDataProvider != null) { + source = DPIUtil.validateAndGetImageDataAtZoom(cursor.imageDataProvider, zoom).element(); + } + else { + source = DPIUtil.scaleImageData(cursor.device, cursor.source, zoom, DEFAULT_ZOOM); + } if (cursor.isIcon) { Cursor newCursor = new Cursor(cursor.device, source, cursor.hotspotX, cursor.hotspotY); cursor.setHandleForZoomLevel(newCursor.handle, zoom); diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_Cursor.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_Cursor.java index 4d225025354..46577f6fe07 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_Cursor.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_Cursor.java @@ -24,7 +24,9 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.ImageDataProvider; import org.eclipse.swt.graphics.ImageLoader; import org.eclipse.swt.widgets.Display; import org.junit.Before; @@ -153,6 +155,23 @@ public void test_ConstructorLorg_eclipse_swt_graphics_DeviceLorg_eclipse_swt_gra } } +@Test +public void test_ConstructorWithImageDataProvider() { + // Test new Cursor(Device device, ImageData source, ImageData mask, int + // hotspotX, int hotspotY) + Image sourceImage = new Image(display, 10, 10); + Cursor cursor = new Cursor(display, sourceImage::getImageData, 0, 0); + cursor.dispose(); + sourceImage.dispose(); + + try { + cursor = new Cursor(display, (ImageDataProvider) null, 0, 0); + cursor.dispose(); + fail("No exception thrown when ImageDataProvider is null"); + } catch (IllegalArgumentException e) { + } +} + @Test public void test_equalsLjava_lang_Object() { /* Note: Two cursors are only considered equal if their handles are equal.