Skip to content

Commit 8c5bc7f

Browse files
ShahzaibIbrahimfedejeanne
authored andcommitted
Non system cursors adaption to DPI scale changes
Creating a map to provide different handle w.r.t the current zoom of the display. The method win32_getHandle provides the appropriate handle for the scaled image as per requested by the client.
1 parent b7d8173 commit 8c5bc7f

File tree

5 files changed

+108
-10
lines changed

5 files changed

+108
-10
lines changed

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

Lines changed: 103 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
package org.eclipse.swt.graphics;
1515

1616

17+
import java.util.*;
18+
1719
import org.eclipse.swt.*;
20+
import org.eclipse.swt.internal.*;
1821
import org.eclipse.swt.internal.win32.*;
1922

2023
/**
@@ -56,17 +59,30 @@ public final class Cursor extends Resource {
5659
* platforms and should never be accessed from application code.
5760
* </p>
5861
*
59-
* @noreference This field is not intended to be referenced by clients.
6062
*/
61-
public long handle;
63+
private long handle;
64+
/**
65+
* Attribute to cache current native zoom level
66+
*/
67+
private static final int DEFAULT_ZOOM = 100;
6268

63-
boolean isIcon;
69+
private HashMap<Integer, Long> zoomLevelToHandle = new HashMap<>();
6470

71+
boolean isIcon;
72+
private final ImageData source;
73+
private final ImageData mask;
74+
private final int hotspotX;
75+
private final int hotspotY;
6576
/**
6677
* Prevents uninitialized instances from being created outside the package.
6778
*/
6879
Cursor(Device device) {
6980
super(device);
81+
this.source = null;
82+
this.mask = null;
83+
this.hotspotX = -1;
84+
this.hotspotY = -1;
85+
this.device.registerResourceWithZoomSupport(this);
7086
}
7187

7288
/**
@@ -116,7 +132,7 @@ public final class Cursor extends Resource {
116132
* @see #dispose()
117133
*/
118134
public Cursor(Device device, int style) {
119-
super(device);
135+
this(device);
120136
long lpCursorName = 0;
121137
switch (style) {
122138
case SWT.CURSOR_HAND: lpCursorName = OS.IDC_HAND; break;
@@ -184,6 +200,10 @@ public Cursor(Device device, int style) {
184200
*/
185201
public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY) {
186202
super(device);
203+
this.source = source;
204+
this.mask = mask;
205+
this.hotspotX = hotspotX;
206+
this.hotspotY = hotspotY;
187207
if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
188208
if (mask == null) {
189209
if (source.getTransparencyType() != SWT.TRANSPARENCY_MASK) {
@@ -213,6 +233,7 @@ public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int
213233
handle = OS.CreateCursor(hInst, hotspotX, hotspotY, source.width, source.height, sourceData, maskData);
214234
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
215235
init();
236+
this.device.registerResourceWithZoomSupport(this);
216237
}
217238

218239
/**
@@ -246,6 +267,10 @@ public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int
246267
*/
247268
public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) {
248269
super(device);
270+
this.source = source;
271+
this.mask = null;
272+
this.hotspotX = hotspotX;
273+
this.hotspotY = hotspotY;
249274
if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
250275
/* Check the hotspots */
251276
if (hotspotX >= source.width || hotspotX < 0 ||
@@ -317,6 +342,56 @@ public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) {
317342
if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
318343
isIcon = true;
319344
init();
345+
this.device.registerResourceWithZoomSupport(this);
346+
}
347+
348+
/**
349+
* <b>IMPORTANT:</b> This method is not part of the public
350+
* API for Image. It is marked public only so that it
351+
* can be shared within the packages provided by SWT. It is not
352+
* available on all platforms, and should never be called from
353+
* application code.
354+
*
355+
* Get the handle for a cursor given a zoom level.
356+
*
357+
* @param cursor the cursor
358+
* @param zoom zoom level (in %) of the monitor the cursor is currently in.
359+
*
360+
* @return The handle of the cursor.
361+
*
362+
* @noreference This method is not intended to be referenced by clients.
363+
*/
364+
public static Long win32_getHandle (Cursor cursor, int zoom) {
365+
if (cursor.isDisposed()) {
366+
return cursor.handle;
367+
}
368+
if (cursor.zoomLevelToHandle.get(zoom) != null) {
369+
return cursor.zoomLevelToHandle.get(zoom);
370+
}
371+
372+
if (cursor.source == null) {
373+
cursor.setHandleForZoomLevel(cursor.handle, zoom);
374+
} else {
375+
ImageData source = DPIUtil.scaleImageData(cursor.device, cursor.source, zoom, DEFAULT_ZOOM);
376+
if (cursor.isIcon) {
377+
Cursor newCursor = new Cursor(cursor.device, source, cursor.hotspotX, cursor.hotspotY);
378+
cursor.setHandleForZoomLevel(newCursor.handle, zoom);
379+
} else {
380+
ImageData mask = DPIUtil.scaleImageData(cursor.device, cursor.mask, zoom, DEFAULT_ZOOM);
381+
Cursor newCursor = new Cursor(cursor.device, source, mask, cursor.hotspotX, cursor.hotspotY);
382+
cursor.setHandleForZoomLevel(newCursor.handle, zoom);
383+
}
384+
}
385+
return cursor.zoomLevelToHandle.get(zoom);
386+
}
387+
388+
private void setHandleForZoomLevel(long handle, Integer zoom) {
389+
if (this.handle == 0) {
390+
this.handle = handle; // Set handle for default zoom level
391+
}
392+
if (zoom != null && !zoomLevelToHandle.containsKey(zoom)) {
393+
zoomLevelToHandle.put(zoom, handle);
394+
}
320395
}
321396

322397
@Override
@@ -333,7 +408,19 @@ void destroy () {
333408
// if (OS.GetCursor() == handle) {
334409
// OS.SetCursor(OS.LoadCursor(0, OS.IDC_ARROW));
335410
// }
411+
device.deregisterResourceWithZoomSupport(this);
412+
destroyHandle();
413+
}
336414

415+
private void destroyHandle () {
416+
for (Long handle : zoomLevelToHandle.values()) {
417+
destroyHandle(handle);
418+
}
419+
zoomLevelToHandle.clear();
420+
handle = 0;
421+
}
422+
423+
private void destroyHandle(long handle) {
337424
if (isIcon) {
338425
OS.DestroyIcon(handle);
339426
} else {
@@ -347,7 +434,6 @@ void destroy () {
347434
*/
348435
OS.DestroyCursor(handle);
349436
}
350-
handle = 0;
351437
}
352438

353439
/**
@@ -410,6 +496,18 @@ public String toString () {
410496
return "Cursor {" + handle + "}";
411497
}
412498

499+
@Override
500+
void destroyHandlesExcept(Set<Integer> zoomLevels) {
501+
zoomLevelToHandle.entrySet().removeIf(entry -> {
502+
final Integer zoom = entry.getKey();
503+
if (!zoomLevels.contains(zoom) && zoom != DPIUtil.getZoomForAutoscaleProperty(DEFAULT_ZOOM)) {
504+
destroyHandle(entry.getValue());
505+
return true;
506+
}
507+
return false;
508+
});
509+
}
510+
413511
/**
414512
* Invokes platform specific functionality to allocate a new cursor.
415513
* <p>

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5417,7 +5417,7 @@ LRESULT WM_SETCURSOR (long wParam, long lParam) {
54175417
if (control == null) return null;
54185418
Cursor cursor = control.findCursor ();
54195419
if (cursor != null) {
5420-
OS.SetCursor (cursor.handle);
5420+
OS.SetCursor (Cursor.win32_getHandle(cursor, getZoom()));
54215421
return LRESULT.ONE;
54225422
}
54235423
}

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Shell.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2624,7 +2624,7 @@ LRESULT WM_SETCURSOR (long wParam, long lParam) {
26242624
RECT rect = new RECT ();
26252625
OS.GetClientRect (handle, rect);
26262626
if (OS.PtInRect (rect, pt)) {
2627-
OS.SetCursor (cursor.handle);
2627+
OS.SetCursor (Cursor.win32_getHandle(cursor, getZoom()));
26282628
switch (msg) {
26292629
case OS.WM_LBUTTONDOWN:
26302630
case OS.WM_RBUTTONDOWN:

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tracker.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ public void setCursor(Cursor newCursor) {
823823
checkWidget();
824824
clientCursor = newCursor;
825825
if (newCursor != null) {
826-
if (inEvent) OS.SetCursor (clientCursor.handle);
826+
if (inEvent) OS.SetCursor (Cursor.win32_getHandle(clientCursor, getZoom()));
827827
}
828828
}
829829

@@ -892,7 +892,7 @@ long transparentProc (long hwnd, long msg, long wParam, long lParam) {
892892
break;
893893
case OS.WM_SETCURSOR:
894894
if (clientCursor != null) {
895-
OS.SetCursor (clientCursor.handle);
895+
OS.SetCursor (Cursor.win32_getHandle(clientCursor, getZoom()));
896896
return 1;
897897
}
898898
if (resizeCursor != 0) {

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4663,7 +4663,7 @@ void setCursor () {
46634663
* is IDC_ARROW.
46644664
*/
46654665
Cursor cursor = findCursor ();
4666-
long hCursor = cursor == null ? OS.LoadCursor (0, OS.IDC_ARROW) : cursor.handle;
4666+
long hCursor = cursor == null ? OS.LoadCursor (0, OS.IDC_ARROW) : Cursor.win32_getHandle(cursor, getZoom());
46674667
OS.SetCursor (hCursor);
46684668
}
46694669

0 commit comments

Comments
 (0)