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
+ * - ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ * - ERROR_NULL_ARGUMENT - if the image is null
+ * - ERROR_INVALID_ARGUMENT - if the hotspot is outside the bounds of the
+ * image
+ *
+ * @exception SWTError
+ * - ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation
+ *
+ *
+ * @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
+ * - ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ * - ERROR_NULL_ARGUMENT - if the image is null
+ * - ERROR_INVALID_ARGUMENT - if the hotspot is outside the bounds of the
+ * image
+ *
+ * @exception SWTError
+ * - ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation
+ *
+ *
+ * @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
+ * - ERROR_NULL_ARGUMENT - if device is null and there is no current device
+ * - ERROR_NULL_ARGUMENT - if the image is null
+ * - ERROR_INVALID_ARGUMENT - if the hotspot is outside the bounds of the
+ * image
+ *
+ * @exception SWTError
+ * - ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation
+ *
+ *
+ * @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.