Skip to content

Commit 7b36487

Browse files
Use OS.CreateIconIndirect for colored cursors with source and mask
Previously, the Cursor constructor that accepted both source and mask used OS.CreateCursor, which only supports monochrome cursors. As a result, any color information in the source was ignored and the cursor always appeared black. This change updates the constructor to use OS.CreateIconIndirect, allowing full-color cursors while still respecting the mask for transparency. DPI scaling of the source and mask now works correctly with colored cursors.
1 parent b5cfe6b commit 7b36487

File tree

1 file changed

+25
-33
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

1 file changed

+25
-33
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Cursor.java

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -154,25 +154,6 @@ public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int
154154
this.device.registerResourceWithZoomSupport(this);
155155
}
156156

157-
private static CursorHandle setupCursorFromImageData(ImageData source, ImageData mask, int hotspotX, int hotspotY) {
158-
if (mask == null) {
159-
mask = source.getTransparencyMask();
160-
}
161-
/* Convert depth to 1 */
162-
mask = ImageData.convertMask(mask);
163-
source = ImageData.convertMask(source);
164-
165-
/* Make sure source and mask scanline pad is 2 */
166-
byte[] sourceData = ImageData.convertPad(source.data, source.width, source.height, source.depth, source.scanlinePad, 2);
167-
byte[] maskData = ImageData.convertPad(mask.data, mask.width, mask.height, mask.depth, mask.scanlinePad, 2);
168-
169-
/* Create the cursor */
170-
long hInst = OS.GetModuleHandle(null);
171-
long handle = OS.CreateCursor(hInst, hotspotX, hotspotY, source.width, source.height, sourceData, maskData);
172-
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
173-
return new CustomCursorHandle(handle);
174-
}
175-
176157
/**
177158
* Constructs a new cursor given a device, image data describing
178159
* the desired cursor appearance, and the x and y coordinates of
@@ -209,7 +190,7 @@ public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) {
209190
this.device.registerResourceWithZoomSupport(this);
210191
}
211192

212-
private static CursorHandle setupCursorFromImageData(Device device, ImageData source, int hotspotX, int hotspotY) {
193+
private static CursorHandle setupCursorFromImageData(Device device, ImageData source, ImageData maskData, int hotspotX, int hotspotY) {
213194
if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
214195
long hBitmap = 0;
215196
long hMask = 0;
@@ -255,10 +236,21 @@ private static CursorHandle setupCursorFromImageData(Device device, ImageData so
255236
}
256237
}
257238
OS.MoveMemory(dibBM.bmBits, srcData, srcData.length);
258-
hMask = OS.CreateBitmap(source.width, source.height, 1, 1, new byte[(((source.width + 7) / 8) + 3) / 4 * 4 * source.height]);
239+
if (maskData != null) {
240+
long[] maskResult = Image.initIcon(device, maskData, maskData);
241+
hMask = maskResult[1];
242+
} else {
243+
hMask = OS.CreateBitmap(source.width, source.height, 1, 1,
244+
new byte[(((source.width + 7) / 8) + 3) / 4 * 4 * source.height]);
245+
}
259246
if (hMask == 0) SWT.error(SWT.ERROR_NO_HANDLES);
260247
} else {
261-
ImageData mask = source.getTransparencyMask();
248+
ImageData mask;
249+
if(maskData != null) {
250+
mask = maskData;
251+
} else {
252+
mask = source.getTransparencyMask();
253+
}
262254
long [] result = Image.initIcon(device, source, mask);
263255
hBitmap = result[0];
264256
hMask = result[1];
@@ -369,14 +361,14 @@ private void setHandleForZoomLevel(CursorHandle handle, Integer zoom) {
369361
* size, etc.)
370362
*/
371363

372-
private static int getPointerSizeScaleFactor() {
364+
private static float getPointerSizeScaleFactor() {
373365
final int defaultCursorSize = 32;
374-
int scaleFactor = 1; // Default: standard size
366+
float scaleFactor = 1.0f; // Default: standard size
375367

376368
if (OsVersion.IS_WIN10_1809) {
377369
int[] cursorBaseSize = OS.readRegistryDwords(OS.HKEY_CURRENT_USER, "Control Panel\\Cursors", "CursorBaseSize");
378370
if (cursorBaseSize != null && cursorBaseSize.length > 0 && cursorBaseSize[0] > 0) {
379-
scaleFactor = cursorBaseSize[0] / defaultCursorSize;
371+
scaleFactor = ((float) cursorBaseSize[0]) / defaultCursorSize;
380372
}
381373
}
382374

@@ -653,7 +645,7 @@ public CursorHandle createHandle(Device device, int zoom) {
653645
source = tempImage.getImageData(zoom);
654646
tempImage.dispose();
655647
}
656-
return setupCursorFromImageData(device, source, getHotpotXInPixels(zoom), getHotpotYInPixels(zoom));
648+
return setupCursorFromImageData(device, source, null, getHotpotXInPixels(zoom), getHotpotYInPixels(zoom));
657649
}
658650
}
659651

@@ -669,9 +661,9 @@ public ImageDataCursorHandleProvider(ImageData source, int hotspotX, int hotspot
669661

670662
@Override
671663
public CursorHandle createHandle(Device device, int zoom) {
672-
int accessibilityFactor = getPointerSizeScaleFactor();
673-
ImageData scaledSource = DPIUtil.scaleImageData(device, this.source, zoom * accessibilityFactor, DEFAULT_ZOOM);
674-
return setupCursorFromImageData(device, scaledSource, getHotpotXInPixels(zoom),
664+
float accessibilityFactor = getPointerSizeScaleFactor();
665+
ImageData scaledSource = DPIUtil.scaleImageData(device, this.source, (int)(zoom * accessibilityFactor), DEFAULT_ZOOM);
666+
return setupCursorFromImageData(device, scaledSource, null, getHotpotXInPixels(zoom),
675667
getHotpotYInPixels(zoom));
676668
}
677669
}
@@ -701,10 +693,10 @@ private void validateMask(ImageData source, ImageData mask) {
701693

702694
@Override
703695
public CursorHandle createHandle(Device device, int zoom) {
704-
ImageData scaledSource = DPIUtil.scaleImageData(device, this.source, zoom, DEFAULT_ZOOM);
705-
ImageData scaledMask = this.mask != null ? DPIUtil.scaleImageData(device, mask, zoom, DEFAULT_ZOOM)
706-
: null;
707-
return setupCursorFromImageData(scaledSource, scaledMask, getHotpotXInPixels(zoom), getHotpotYInPixels(zoom));
696+
float zoomFactor = getPointerSizeScaleFactor() * ((float) zoom) / 100f;
697+
ImageData scaledSource = this.source.scaledTo((int) (this.source.width * zoomFactor), (int) (this.source.height * zoomFactor));
698+
ImageData scaledMask = this.mask!= null? this.mask.scaledTo((int) (this.mask.width * zoomFactor), (int) (this.mask.height * zoomFactor)) : null;
699+
return setupCursorFromImageData(device, scaledSource, scaledMask, getHotpotXInPixels(zoom), getHotpotYInPixels(zoom));
708700
}
709701
}
710702

0 commit comments

Comments
 (0)