Skip to content

Commit db034ee

Browse files
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 d9d9bf0 commit db034ee

File tree

5 files changed

+85
-7
lines changed

5 files changed

+85
-7
lines changed

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

Lines changed: 80 additions & 2 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
/**
@@ -59,9 +62,18 @@ public final class Cursor extends Resource {
5962
* @noreference This field is not intended to be referenced by clients.
6063
*/
6164
public long handle;
65+
/**
66+
* Attribute to cache current native zoom level
67+
*/
68+
private static int DEFAULT_ZOOM = 100;
6269

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

72+
boolean isIcon;
73+
private ImageData source;
74+
private ImageData mask;
75+
private int hotspotX;
76+
private int hotspotY;
6577
/**
6678
* Prevents uninitialized instances from being created outside the package.
6779
*/
@@ -184,6 +196,10 @@ public Cursor(Device device, int style) {
184196
*/
185197
public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY) {
186198
super(device);
199+
this.source = source;
200+
this.mask = mask;
201+
this.hotspotX = hotspotX;
202+
this.hotspotY = hotspotY;
187203
if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
188204
if (mask == null) {
189205
if (source.getTransparencyType() != SWT.TRANSPARENCY_MASK) {
@@ -246,6 +262,9 @@ public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int
246262
*/
247263
public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) {
248264
super(device);
265+
this.source = source;
266+
this.hotspotX = hotspotX;
267+
this.hotspotY = hotspotY;
249268
if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
250269
/* Check the hotspots */
251270
if (hotspotX >= source.width || hotspotX < 0 ||
@@ -319,6 +338,55 @@ public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) {
319338
init();
320339
}
321340

341+
/**
342+
* <b>IMPORTANT:</b> This method is not part of the public
343+
* API for Image. It is marked public only so that it
344+
* can be shared within the packages provided by SWT. It is not
345+
* available on all platforms, and should never be called from
346+
* application code.
347+
*
348+
* Updates zoom and refresh the Cursor based on the native zoom level, if required.
349+
*
350+
* @param cursor the cursor to get the handle of
351+
* @param zoom device zoom in % of the monitor on which the image is painted
352+
*
353+
* @return true if cursor is refreshed
354+
*
355+
* @noreference This method is not intended to be referenced by clients.
356+
*/
357+
public static Long win32_getHandle (Cursor cursor, int zoom) {
358+
if (cursor.isDisposed()) {
359+
return cursor.handle;
360+
}
361+
if (cursor.zoomLevelToHandle.get(zoom) != null) {
362+
return cursor.zoomLevelToHandle.get(zoom);
363+
}
364+
365+
if (cursor.source == null) {
366+
cursor.setHandleForZoomLevel(cursor.handle, zoom);
367+
} else {
368+
ImageData source = DPIUtil.scaleImageData(cursor.device, cursor.source, zoom, DEFAULT_ZOOM);
369+
if (cursor.isIcon) {
370+
Cursor newCursor = new Cursor(cursor.device, source, cursor.hotspotX, cursor.hotspotY);
371+
cursor.setHandleForZoomLevel(newCursor.handle, zoom);
372+
} else {
373+
ImageData mask = DPIUtil.scaleImageData(cursor.device, cursor.mask, zoom, DEFAULT_ZOOM);
374+
Cursor newCursor = new Cursor(cursor.device, source, mask, cursor.hotspotX, cursor.hotspotY);
375+
cursor.setHandleForZoomLevel(newCursor.handle, zoom);
376+
}
377+
}
378+
return cursor.zoomLevelToHandle.get(zoom);
379+
}
380+
381+
private void setHandleForZoomLevel(long handle, Integer zoom) {
382+
if (this.handle == 0) {
383+
this.handle = handle; // Set handle for default zoom level
384+
}
385+
if (zoom != null && !zoomLevelToHandle.containsKey(zoom)) {
386+
zoomLevelToHandle.put(zoom, handle);
387+
}
388+
}
389+
322390
@Override
323391
void destroy () {
324392
/*
@@ -333,7 +401,18 @@ void destroy () {
333401
// if (OS.GetCursor() == handle) {
334402
// OS.SetCursor(OS.LoadCursor(0, OS.IDC_ARROW));
335403
// }
404+
destroyHandle();
405+
}
406+
407+
private void destroyHandle () {
408+
for (Long handle : zoomLevelToHandle.values()) {
409+
destroyHandle(handle);
410+
}
411+
zoomLevelToHandle.clear();
412+
handle = 0;
413+
}
336414

415+
private void destroyHandle(long handle) {
337416
if (isIcon) {
338417
OS.DestroyIcon(handle);
339418
} else {
@@ -347,7 +426,6 @@ void destroy () {
347426
*/
348427
OS.DestroyCursor(handle);
349428
}
350-
handle = 0;
351429
}
352430

353431
/**

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
@@ -5410,7 +5410,7 @@ LRESULT WM_SETCURSOR (long wParam, long lParam) {
54105410
if (control == null) return null;
54115411
Cursor cursor = control.findCursor ();
54125412
if (cursor != null) {
5413-
OS.SetCursor (cursor.handle);
5413+
OS.SetCursor (Cursor.win32_getHandle(cursor, getZoom()));
54145414
return LRESULT.ONE;
54155415
}
54165416
}

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
@@ -2610,7 +2610,7 @@ LRESULT WM_SETCURSOR (long wParam, long lParam) {
26102610
RECT rect = new RECT ();
26112611
OS.GetClientRect (handle, rect);
26122612
if (OS.PtInRect (rect, pt)) {
2613-
OS.SetCursor (cursor.handle);
2613+
OS.SetCursor (Cursor.win32_getHandle(cursor, getZoom()));
26142614
switch (msg) {
26152615
case OS.WM_LBUTTONDOWN:
26162616
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)