Skip to content

Commit f271319

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. # Conflicts: # bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Cursor.java
1 parent 35119f0 commit f271319

File tree

1 file changed

+23
-32
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

1 file changed

+23
-32
lines changed

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

Lines changed: 23 additions & 32 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];
@@ -368,8 +360,7 @@ private void setHandleForZoomLevel(CursorHandle handle, Integer zoom) {
368360
* @return the cursor scaling factor (e.g., 1 for default size, 2 for double
369361
* size, etc.)
370362
*/
371-
372-
private static int getPointerSizeScaleFactor() {
363+
private static float getPointerSizeScaleFactor() {
373364
if (OsVersion.IS_WIN10_1809) {
374365
int[] cursorBaseSize = OS.readRegistryDwords(OS.HKEY_CURRENT_USER, "Control Panel\\Cursors", "CursorBaseSize");
375366
if (cursorBaseSize != null && cursorBaseSize.length > 0 && cursorBaseSize[0] > 0) {
@@ -649,7 +640,7 @@ public CursorHandle createHandle(Device device, int zoom) {
649640
source = tempImage.getImageData(zoom);
650641
tempImage.dispose();
651642
}
652-
return setupCursorFromImageData(device, source, getHotpotXInPixels(zoom), getHotpotYInPixels(zoom));
643+
return setupCursorFromImageData(device, source, null, getHotpotXInPixels(zoom), getHotpotYInPixels(zoom));
653644
}
654645
}
655646

@@ -665,9 +656,9 @@ public ImageDataCursorHandleProvider(ImageData source, int hotspotX, int hotspot
665656

666657
@Override
667658
public CursorHandle createHandle(Device device, int zoom) {
668-
int accessibilityFactor = getPointerSizeScaleFactor();
669-
ImageData scaledSource = DPIUtil.scaleImageData(device, this.source, zoom * accessibilityFactor, DEFAULT_ZOOM);
670-
return setupCursorFromImageData(device, scaledSource, getHotpotXInPixels(zoom),
659+
float accessibilityFactor = getPointerSizeScaleFactor();
660+
ImageData scaledSource = DPIUtil.scaleImageData(device, this.source, (int)(zoom * accessibilityFactor), DEFAULT_ZOOM);
661+
return setupCursorFromImageData(device, scaledSource, null, getHotpotXInPixels(zoom),
671662
getHotpotYInPixels(zoom));
672663
}
673664
}
@@ -697,10 +688,10 @@ private void validateMask(ImageData source, ImageData mask) {
697688

698689
@Override
699690
public CursorHandle createHandle(Device device, int zoom) {
700-
ImageData scaledSource = DPIUtil.scaleImageData(device, this.source, zoom, DEFAULT_ZOOM);
701-
ImageData scaledMask = this.mask != null ? DPIUtil.scaleImageData(device, mask, zoom, DEFAULT_ZOOM)
702-
: null;
703-
return setupCursorFromImageData(scaledSource, scaledMask, getHotpotXInPixels(zoom), getHotpotYInPixels(zoom));
691+
float zoomFactor = getPointerSizeScaleFactor() * ((float) zoom) / 100f;
692+
ImageData scaledSource = this.source.scaledTo((int) (this.source.width * zoomFactor), (int) (this.source.height * zoomFactor));
693+
ImageData scaledMask = this.mask!= null? this.mask.scaledTo((int) (this.mask.width * zoomFactor), (int) (this.mask.height * zoomFactor)) : null;
694+
return setupCursorFromImageData(device, scaledSource, scaledMask, getHotpotXInPixels(zoom), getHotpotYInPixels(zoom));
704695
}
705696
}
706697

0 commit comments

Comments
 (0)