Skip to content

Commit 1e7c92e

Browse files
committed
First draft for Program Scaling Improvement
1 parent 857ac0b commit 1e7c92e

File tree

9 files changed

+116
-18
lines changed

9 files changed

+116
-18
lines changed

bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com.c

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2022 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -870,6 +870,24 @@ JNIEXPORT jlong JNICALL COM_NATIVE(SHCreateMemStream)
870870
}
871871
#endif
872872

873+
#ifndef NO_SHGetImageList
874+
JNIEXPORT jlong JNICALL COM_NATIVE(SHGetImageList)
875+
(JNIEnv *env, jclass that, jint arg0, jobject arg1, jlongArray arg2)
876+
{
877+
GUID _arg1, *lparg1=NULL;
878+
jlong *lparg2=NULL;
879+
jlong rc = 0;
880+
COM_NATIVE_ENTER(env, that, SHGetImageList_FUNC);
881+
if (arg1) if ((lparg1 = getGUIDFields(env, arg1, &_arg1)) == NULL) goto fail;
882+
if (arg2) if ((lparg2 = (*env)->GetPrimitiveArrayCritical(env, arg2, NULL)) == NULL) goto fail;
883+
rc = (jlong)SHGetImageList(arg0, lparg1, (VOID **)lparg2);
884+
fail:
885+
if (arg2 && lparg2) (*env)->ReleasePrimitiveArrayCritical(env, arg2, lparg2, 0);
886+
COM_NATIVE_EXIT(env, that, SHGetImageList_FUNC);
887+
return rc;
888+
}
889+
#endif
890+
873891
#ifndef NO_STGMEDIUM_1sizeof
874892
JNIEXPORT jint JNICALL COM_NATIVE(STGMEDIUM_1sizeof)
875893
(JNIEnv *env, jclass that)

bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_stats.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2023 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -83,6 +83,7 @@ typedef enum {
8383
RevokeDragDrop_FUNC,
8484
SHCreateItemFromParsingName_FUNC,
8585
SHCreateMemStream_FUNC,
86+
SHGetImageList_FUNC,
8687
STGMEDIUM_1sizeof_FUNC,
8788
StgCreateDocfile_FUNC,
8889
StgIsStorageFile_FUNC,

bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c

+12
Original file line numberDiff line numberDiff line change
@@ -3981,6 +3981,18 @@ JNIEXPORT void JNICALL OS_NATIVE(ImageList_1EndDrag)
39813981
}
39823982
#endif
39833983

3984+
#ifndef NO_ImageList_1GetIcon
3985+
JNIEXPORT jlong JNICALL OS_NATIVE(ImageList_1GetIcon)
3986+
(JNIEnv *env, jclass that, jlong arg0, jint arg1, jint arg2)
3987+
{
3988+
jlong rc = 0;
3989+
OS_NATIVE_ENTER(env, that, ImageList_1GetIcon_FUNC);
3990+
rc = (jlong)ImageList_GetIcon((HIMAGELIST)arg0, arg1, (UINT)arg2);
3991+
OS_NATIVE_EXIT(env, that, ImageList_1GetIcon_FUNC);
3992+
return rc;
3993+
}
3994+
#endif
3995+
39843996
#ifndef NO_ImageList_1GetIconSize
39853997
JNIEXPORT jboolean JNICALL OS_NATIVE(ImageList_1GetIconSize)
39863998
(JNIEnv *env, jclass that, jlong arg0, jintArray arg1, jintArray arg2)

bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h

+1
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ typedef enum {
310310
ImageList_1DragMove_FUNC,
311311
ImageList_1DragShowNolock_FUNC,
312312
ImageList_1EndDrag_FUNC,
313+
ImageList_1GetIcon_FUNC,
313314
ImageList_1GetIconSize_FUNC,
314315
ImageList_1GetImageCount_FUNC,
315316
ImageList_1Remove_FUNC,

bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2022 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0

bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2021 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0

bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/ole/win32/COM.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public class COM extends OS {
107107
public static final GUID IIDIAccessibleImage = IIDFromString("{FE5ABB3D-615E-4f7b-909F-5F0EDA9E8DDE}"); //$NON-NLS-1$
108108
public static final GUID IIDIAccessibleApplication = IIDFromString("{D49DED83-5B25-43F4-9B95-93B44595979E}"); //$NON-NLS-1$
109109
public static final GUID IIDIAccessibleContext = IIDFromString("{77A123E4-5794-44e0-B8BF-DE600C9D29BD}"); //$NON-NLS-1$
110-
110+
public static final GUID IID_IImageList = IIDFromString("{46EB5926-582E-4017-9FDF-E8998DAA0950}");
111111
/** Constants */
112112
public static final int CF_TEXT = 1;
113113
public static final int CF_BITMAP = 2;
@@ -465,6 +465,11 @@ private static GUID IIDFromString(String lpsz) {
465465
* @param ppv cast=(void **)
466466
*/
467467
public static final native int SHCreateItemFromParsingName (char [] pszName, long pbc, GUID riid, long [] ppv);
468+
/**
469+
* @param riid flags=no_out
470+
* @param ppvObj cast=(VOID **),flags=no_in critical
471+
*/
472+
public static final native long SHGetImageList (int iImageList, GUID riid, long[] ppvObj);
468473
/**
469474
* @param pwcsName cast=(const WCHAR *),flags=no_out
470475
* @param ppstgOpen cast=(IStorage **)

bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java

+11
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@ public class OS extends C {
661661
public static final int ILC_COLOR8 = 0x8;
662662
public static final int ILC_MASK = 0x1;
663663
public static final int ILC_MIRROR = 0x2000;
664+
public static final int ILD_TRANSPARENT = 0x00000001;
664665
public static final int IMAGE_ICON = 0x1;
665666
public static final int IME_CMODE_FULLSHAPE = 0x8;
666667
public static final int IME_CMODE_KATAKANA = 0x2;
@@ -1209,9 +1210,14 @@ public class OS extends C {
12091210
public static final int SET_FEATURE_ON_PROCESS = 0x2;
12101211
public static final int SHADEBLENDCAPS = 120;
12111212
public static final int SHGFI_ICON = 0x000000100;
1213+
public static final int SHGFI_ICONLOCATION = 0x000001000;
12121214
public static final int SHGFI_SMALLICON= 0x1;
12131215
public static final int SHGFI_LARGEICON= 0x0;
12141216
public static final int SHGFI_USEFILEATTRIBUTES = 0x000000010;
1217+
public static final int SHIL_LARGE = 0x0;
1218+
public static final int SHIL_SMALL = 0x1;
1219+
public static final int SHIL_EXTRALARGE = 0x2;
1220+
public static final int SHIL_SYSSMALL = 0x3;
12151221
public static final int SIGDN_FILESYSPATH = 0x80058000;
12161222
public static final int SIF_ALL = 0x17;
12171223
public static final int SIF_DISABLENOSCROLL = 0x8;
@@ -4458,6 +4464,11 @@ public static int HRESULT_FROM_WIN32(int x) {
44584464
public static final native boolean ShowScrollBar (long hWnd, int wBar, boolean bShow);
44594465
/** @param hWnd cast=(HWND) */
44604466
public static final native boolean ShowWindow (long hWnd, int nCmdShow);
4467+
/**
4468+
* @param himl cast=(HIMAGELIST)
4469+
* @param flags cast=(UINT)
4470+
*/
4471+
public static final native long ImageList_GetIcon (long himl, int i, int flags);
44614472
/**
44624473
* @param hdc cast=(HDC)
44634474
* @param lpdi flags=no_out

bundles/org.eclipse.swt/Eclipse SWT Program/win32/org/eclipse/swt/program/Program.java

+63-13
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
import org.eclipse.swt.*;
2121
import org.eclipse.swt.graphics.*;
2222
import org.eclipse.swt.internal.*;
23+
import org.eclipse.swt.internal.ole.win32.*;
2324
import org.eclipse.swt.internal.win32.*;
25+
import org.eclipse.swt.widgets.*;
2426

2527
/**
2628
* Instances of this class represent programs and
@@ -381,26 +383,20 @@ public ImageData getImageData () {
381383
public ImageData getImageData (int zoom) {
382384
// OS.SHGetFileInfo is System DPI-aware, hence it retrieves the icon with zoom
383385
// of primary monitor at the application startup
384-
int initialNativeZoom = getPrimaryMonitorZoomAtStartup();
385386
if (extension != null) {
386387
SHFILEINFO shfi = new SHFILEINFO ();
387-
int flags = OS.SHGFI_ICON | OS.SHGFI_USEFILEATTRIBUTES;
388-
boolean useLargeIcon = 100 * zoom / initialNativeZoom >= 200;
389-
if(useLargeIcon) {
390-
flags |= OS.SHGFI_LARGEICON;
391-
initialNativeZoom *= 2;
392-
} else {
393-
flags |= OS.SHGFI_SMALLICON;
394-
}
388+
int flags = OS.SHGFI_USEFILEATTRIBUTES | OS.SHGFI_ICONLOCATION;
395389
TCHAR pszPath = new TCHAR (0, extension, true);
396390
OS.SHGetFileInfo (pszPath.chars, OS.FILE_ATTRIBUTE_NORMAL, shfi, SHFILEINFO.sizeof, flags);
397-
if (shfi.hIcon != 0) {
398-
Image image = Image.win32_new (null, SWT.ICON, shfi.hIcon, initialNativeZoom);
399-
ImageData imageData = image.getImageData (zoom);
400-
image.dispose ();
391+
if (shfi.iIcon >= 0) {
392+
Image icon = getImageForZoom(zoom, shfi.iIcon);
393+
ImageData imageData = icon.getImageData(zoom);
394+
icon.dispose();
401395
return imageData;
402396
}
403397
}
398+
399+
int initialNativeZoom = getPrimaryMonitorZoomAtStartup();
404400
int nIconIndex = 0;
405401
String fileName = iconName;
406402
int index = iconName.indexOf (',');
@@ -434,6 +430,60 @@ private int getPrimaryMonitorZoomAtStartup() {
434430
return DPIUtil.mapDPIToZoom(dpi);
435431
}
436432

433+
private NavigableMap<Integer, Long> getImageListinAllAvailableSizesMappedWithZoom() {
434+
TreeMap<Integer, Long> zoomToHImageList = new TreeMap<>();
435+
int primaryMonitorZoomAtStartup = getPrimaryMonitorZoomAtStartup();
436+
// SHIL_SYSSMALL is the size of icon at startup zoom of the primary monitor. The
437+
// sizes can differ as specified by OS.GetSystemMetrics.
438+
long hImageListAtPrimaryMonitorZoomAtStartup = getImageListForSize(OS.SHIL_SYSSMALL);
439+
int sizeAtPrimaryMonitorZoomAtStartup = getIconSizeOfImageList(hImageListAtPrimaryMonitorZoomAtStartup);
440+
zoomToHImageList.put(primaryMonitorZoomAtStartup, hImageListAtPrimaryMonitorZoomAtStartup);
441+
// SHIL_* (SMALL, LARGE and EXTRALARGE) are typically 1x, 2x, 3x relative to the
442+
// primary monitor zoom at startup, e.g., 16px, 32px and 48px
443+
// respectively.
444+
int[] allSizes = new int[] { OS.SHIL_SMALL, OS.SHIL_LARGE, OS.SHIL_EXTRALARGE };
445+
for (int size : allSizes) {
446+
long hImageList = getImageListForSize(size);
447+
int iconSize = getIconSizeOfImageList(hImageList);
448+
int zoom = (iconSize / sizeAtPrimaryMonitorZoomAtStartup) * primaryMonitorZoomAtStartup;
449+
if (!zoomToHImageList.containsKey(zoom)) {
450+
zoomToHImageList.put(zoom, hImageList);
451+
} else {
452+
OS.ImageList_Destroy(hImageList);
453+
}
454+
}
455+
return zoomToHImageList;
456+
}
457+
458+
private int getIconSizeOfImageList(long hImageList) {
459+
int [] cx = new int [1];
460+
int [] cy = new int [1];
461+
OS.ImageList_GetIconSize(hImageList, cx, cy);
462+
return cx[0];
463+
}
464+
465+
private Image getImageForZoom(int zoom, int index) {
466+
NavigableMap<Integer, Long> zoomToHImageList = getImageListinAllAvailableSizesMappedWithZoom();
467+
int closestZoomAvailable = getClosestKey(zoomToHImageList, zoom);
468+
long hIcon = OS.ImageList_GetIcon(zoomToHImageList.get(closestZoomAvailable), index, OS.ILD_TRANSPARENT);
469+
zoomToHImageList.values().forEach(handle -> OS.ImageList_Destroy(handle));
470+
return Image.win32_new(Display.getCurrent(), SWT.ICON, hIcon, closestZoomAvailable);
471+
}
472+
473+
private long getImageListForSize(int size) {
474+
long [] ppv = new long [1];
475+
COM.SHGetImageList(size, COM.IID_IImageList, ppv);
476+
return ppv[0];
477+
}
478+
479+
private Integer getClosestKey(NavigableMap<Integer, Long> map, int x) {
480+
Integer floorKey = map.floorKey(x);
481+
Integer ceilingKey = map.ceilingKey(x);
482+
if (floorKey == null) return ceilingKey;
483+
if (ceilingKey == null) return floorKey;
484+
return (Math.abs(x - floorKey) <= Math.abs(x - ceilingKey)) ? floorKey : ceilingKey;
485+
}
486+
437487
/**
438488
* Returns the receiver's name. This is as short and
439489
* descriptive a name as possible for the program. If

0 commit comments

Comments
 (0)