From c1b770bf145a9c308c432672355bf68a291fe7c9 Mon Sep 17 00:00:00 2001 From: Andreas Koch Date: Tue, 6 Feb 2024 16:28:42 +0100 Subject: [PATCH] [win32] Use DPI dependent OS API calls This commit replaces the OS calls for OpenThemeData with calls to the dpi dependent equivalent OpenThemeDataForDpi. Therefor the handling of loading/unloading of theme in Display is refactored to be able to manage multiple DPI dependent variants of a theme in multi zoom environments Contributes to #62 nd #131 --- .../win32/org/eclipse/swt/widgets/Button.java | 4 +- .../org/eclipse/swt/widgets/Composite.java | 2 +- .../org/eclipse/swt/widgets/Display.java | 192 ++++++++++++------ .../org/eclipse/swt/widgets/ExpandBar.java | 6 +- .../org/eclipse/swt/widgets/TabFolder.java | 2 +- .../win32/org/eclipse/swt/widgets/Table.java | 4 +- .../win32/org/eclipse/swt/widgets/Text.java | 2 +- .../win32/org/eclipse/swt/widgets/Tree.java | 6 +- .../win32/org/eclipse/swt/widgets/Widget.java | 2 +- 9 files changed, 144 insertions(+), 76 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java index b09c7eaf086..9f6f9961358 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java @@ -1311,7 +1311,7 @@ private int getCheckboxTextOffset(long hdc) { SIZE size = new SIZE(); if (OS.IsAppThemed ()) { - OS.GetThemePartSize(display.hButtonTheme(), hdc, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, null, OS.TS_TRUE, size); + OS.GetThemePartSize(display.hButtonTheme(getZoom()), hdc, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, null, OS.TS_TRUE, size); result += size.cx; } else { result += DPIUtil.scaleUp(13, nativeZoom); @@ -1543,7 +1543,7 @@ LRESULT wmDrawChild (long wParam, long lParam) { boolean pressed = ((struct.itemState & OS.ODS_SELECTED) != 0); boolean enabled = getEnabled (); int iStateId = getThemeStateId(style, pressed, enabled); - OS.DrawThemeBackground (display.hScrollBarThemeAuto (), struct.hDC, OS.SBP_ARROWBTN, iStateId, rect, null); + OS.DrawThemeBackground (display.hScrollBarThemeAuto (getZoom()), struct.hDC, OS.SBP_ARROWBTN, iStateId, rect, null); } else { int uState = OS.DFCS_SCROLLLEFT; switch (style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java index 24e00a65a49..5b3490a6832 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java @@ -1856,7 +1856,7 @@ LRESULT wmNCPaint (long hwnd, long wParam, long lParam) { rect.left = rect.top = 0; int border = getSystemMetrics (OS.SM_CXEDGE); OS.ExcludeClipRect (hDC, border, border, rect.right - border, rect.bottom - border); - OS.DrawThemeBackground (display.hEditTheme (), hDC, OS.EP_EDITTEXT, OS.ETS_NORMAL, rect, null); + OS.DrawThemeBackground (display.hEditTheme (getZoom()), hDC, OS.EP_EDITTEXT, OS.ETS_NORMAL, rect, null); OS.ReleaseDC (hwnd, hDC); return new LRESULT (code); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java index 00205d39e30..9332f2652a4 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java @@ -153,7 +153,7 @@ public class Display extends Device implements Executor { } /* XP Themes */ - long hButtonTheme, hButtonThemeDark, hEditTheme, hExplorerBarTheme, hScrollBarTheme, hScrollBarThemeDark, hTabTheme; + private Map themeDataMap = new HashMap<>(); static final char [] EXPLORER = new char [] {'E', 'X', 'P', 'L', 'O', 'R', 'E', 'R', 0}; static final char [] TREEVIEW = new char [] {'T', 'R', 'E', 'E', 'V', 'I', 'E', 'W', 0}; /* Emergency switch to be used in case of regressions. Not supposed to be changed when app is running. */ @@ -2665,93 +2665,55 @@ public boolean getTouchEnabled () { return (value & (OS.NID_READY | OS.NID_MULTI_INPUT)) == (OS.NID_READY | OS.NID_MULTI_INPUT); } -long hButtonTheme () { - if (hButtonTheme != 0) return hButtonTheme; - final char[] themeName = "BUTTON\0".toCharArray(); - return hButtonTheme = OS.OpenThemeData (hwndMessage, themeName); +long hButtonTheme (int dpi) { + return getOrCreateThemeData(dpi).hButtonTheme(); } -long hButtonThemeDark () { - if (hButtonThemeDark != 0) return hButtonThemeDark; - final char[] themeName = "Darkmode_Explorer::BUTTON\0".toCharArray(); - return hButtonThemeDark = OS.OpenThemeData (hwndMessage, themeName); +long hButtonThemeDark (int dpi) { + return getOrCreateThemeData(dpi).hButtonThemeDark(); } -long hButtonThemeAuto () { +long hButtonThemeAuto (int dpi) { if (useDarkModeExplorerTheme) { - return hButtonThemeDark (); + return hButtonThemeDark (dpi); } else { - return hButtonTheme (); + return hButtonTheme (dpi); } } -long hEditTheme () { - if (hEditTheme != 0) return hEditTheme; - final char[] themeName = "EDIT\0".toCharArray(); - return hEditTheme = OS.OpenThemeData (hwndMessage, themeName); +long hEditTheme (int dpi) { + return getOrCreateThemeData(dpi).hEditTheme(); } -long hExplorerBarTheme () { - if (hExplorerBarTheme != 0) return hExplorerBarTheme; - final char[] themeName = "EXPLORERBAR\0".toCharArray(); - return hExplorerBarTheme = OS.OpenThemeData (hwndMessage, themeName); +long hExplorerBarTheme (int dpi) { + return getOrCreateThemeData(dpi).hExplorerBarTheme(); } -long hScrollBarTheme () { - if (hScrollBarTheme != 0) return hScrollBarTheme; - final char[] themeName = "SCROLLBAR\0".toCharArray(); - return hScrollBarTheme = OS.OpenThemeData (hwndMessage, themeName); +long hScrollBarTheme (int dpi) { + return getOrCreateThemeData(dpi).hScrollBarTheme(); } -long hScrollBarThemeDark () { - if (hScrollBarThemeDark != 0) return hScrollBarThemeDark; - final char[] themeName = "Darkmode_Explorer::SCROLLBAR\0".toCharArray(); - return hScrollBarThemeDark = OS.OpenThemeData (hwndMessage, themeName); +long hScrollBarThemeDark (int dpi) { + return getOrCreateThemeData(dpi).hScrollBarThemeDark(); } -long hScrollBarThemeAuto () { +long hScrollBarThemeAuto (int dpi) { if (useDarkModeExplorerTheme) { - return hScrollBarThemeDark (); + return hScrollBarThemeDark (dpi); } else { - return hScrollBarTheme (); + return hScrollBarTheme (dpi); } } -long hTabTheme () { - if (hTabTheme != 0) return hTabTheme; - final char[] themeName = "TAB\0".toCharArray(); - return hTabTheme = OS.OpenThemeData (hwndMessage, themeName); +long hTabTheme (int dpi) { + return getOrCreateThemeData(dpi).hTabTheme(); } void resetThemes() { - if (hButtonTheme != 0) { - OS.CloseThemeData (hButtonTheme); - hButtonTheme = 0; - } - if (hButtonThemeDark != 0) { - OS.CloseThemeData (hButtonThemeDark); - hButtonThemeDark = 0; - } - if (hEditTheme != 0) { - OS.CloseThemeData (hEditTheme); - hEditTheme = 0; - } - if (hExplorerBarTheme != 0) { - OS.CloseThemeData (hExplorerBarTheme); - hExplorerBarTheme = 0; - } - if (hScrollBarTheme != 0) { - OS.CloseThemeData (hScrollBarTheme); - hScrollBarTheme = 0; - } - if (hScrollBarThemeDark != 0) { - OS.CloseThemeData (hScrollBarThemeDark); - hScrollBarThemeDark = 0; - } - if (hTabTheme != 0) { - OS.CloseThemeData (hTabTheme); - hTabTheme = 0; + for (ThemeData themeData : themeDataMap.values()) { + themeData.reset(); } + themeDataMap.clear(); } /** @@ -5313,6 +5275,112 @@ static boolean isActivateShellOnForceFocus() { return "true".equals(System.getProperty("org.eclipse.swt.internal.activateShellOnForceFocus", "true")); //$NON-NLS-1$ } +private ThemeData getOrCreateThemeData(int dpi) { + if (themeDataMap.containsKey(dpi)) { + return themeDataMap.get(dpi); + } + ThemeData themeData = new ThemeData(dpi); + themeDataMap.put(dpi, themeData); + return themeData; +} + +private class ThemeData { + long hButtonTheme; + long hButtonThemeDark; + long hEditTheme; + long hExplorerBarTheme; + long hScrollBarTheme; + long hScrollBarThemeDark; + long hTabTheme; + + int dpi; + + private ThemeData(int dpi) { + this.dpi = dpi; + } + + long hButtonTheme () { + if (hButtonTheme != 0) return hButtonTheme; + final char[] themeName = "BUTTON\0".toCharArray(); + return hButtonTheme = openThemeData(themeName); + } + + long hButtonThemeDark () { + if (hButtonThemeDark != 0) return hButtonThemeDark; + final char[] themeName = "Darkmode_Explorer::BUTTON\0".toCharArray(); + return hButtonThemeDark = openThemeData(themeName); + } + + long hEditTheme () { + if (hEditTheme != 0) return hEditTheme; + final char[] themeName = "EDIT\0".toCharArray(); + return hEditTheme = openThemeData(themeName); + } + + long hExplorerBarTheme () { + if (hExplorerBarTheme != 0) return hExplorerBarTheme; + final char[] themeName = "EXPLORERBAR\0".toCharArray(); + return hExplorerBarTheme = openThemeData(themeName); + } + + long hScrollBarTheme () { + if (hScrollBarTheme != 0) return hScrollBarTheme; + final char[] themeName = "SCROLLBAR\0".toCharArray(); + return hScrollBarTheme = openThemeData(themeName); + } + + long hScrollBarThemeDark () { + if (hScrollBarThemeDark != 0) return hScrollBarThemeDark; + final char[] themeName = "Darkmode_Explorer::SCROLLBAR\0".toCharArray(); + return hScrollBarThemeDark = openThemeData(themeName); + } + + long hTabTheme () { + if (hTabTheme != 0) return hTabTheme; + final char[] themeName = "TAB\0".toCharArray(); + return hTabTheme = openThemeData(themeName); + } + + + public void reset() { + if (hButtonTheme != 0) { + OS.CloseThemeData (hButtonTheme); + hButtonTheme = 0; + } + if (hButtonThemeDark != 0) { + OS.CloseThemeData (hButtonThemeDark); + hButtonThemeDark = 0; + } + if (hEditTheme != 0) { + OS.CloseThemeData (hEditTheme); + hEditTheme = 0; + } + if (hExplorerBarTheme != 0) { + OS.CloseThemeData (hExplorerBarTheme); + hExplorerBarTheme = 0; + } + if (hScrollBarTheme != 0) { + OS.CloseThemeData (hScrollBarTheme); + hScrollBarTheme = 0; + } + if (hScrollBarThemeDark != 0) { + OS.CloseThemeData (hScrollBarThemeDark); + hScrollBarThemeDark = 0; + } + if (hTabTheme != 0) { + OS.CloseThemeData (hTabTheme); + hTabTheme = 0; + } + } + + private long openThemeData(final char[] themeName) { + if (OS.WIN32_BUILD >= OS.WIN32_BUILD_WIN10_1809) { + return OS.OpenThemeDataForDpi(hwndMessage, themeName, dpi); + } else { + return OS.OpenThemeData(hwndMessage, themeName); + } + } +} /** * {@return whether rescaling of shells at runtime when the DPI scaling of a * shell's monitor changes is activated for this device} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java index fb623d0a72a..3009514f642 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java @@ -137,7 +137,7 @@ static int checkStyle (int style) { long hDC = OS.GetDC (handle); long hTheme = 0; if (isAppThemed ()) { - hTheme = display.hExplorerBarTheme (); + hTheme = display.hExplorerBarTheme (getZoom()); } long hCurrentFont = 0, oldFont = 0; if (hTheme == 0) { @@ -247,13 +247,13 @@ void drawThemeBackground (long hDC, long hwnd, RECT rect) { RECT rect2 = new RECT (); OS.GetClientRect (handle, rect2); OS.MapWindowPoints (handle, hwnd, rect2, 2); - OS.DrawThemeBackground (display.hExplorerBarTheme (), hDC, OS.EBP_NORMALGROUPBACKGROUND, 0, rect2, null); + OS.DrawThemeBackground (display.hExplorerBarTheme (getZoom()), hDC, OS.EBP_NORMALGROUPBACKGROUND, 0, rect2, null); } void drawWidget (GC gc, RECT clipRect) { long hTheme = 0; if (isAppThemed ()) { - hTheme = display.hExplorerBarTheme (); + hTheme = display.hExplorerBarTheme (getZoom()); } if (hTheme != 0) { RECT rect = new RECT (); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabFolder.java index c8550413372..1b4ca5aebb3 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabFolder.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabFolder.java @@ -298,7 +298,7 @@ void drawThemeBackground (long hDC, long hwnd, RECT rect) { OS.GetClientRect (handle, rect2); OS.MapWindowPoints (handle, hwnd, rect2, 2); if (OS.IntersectRect (new RECT (), rect2, rect)) { - OS.DrawThemeBackground (display.hTabTheme (), hDC, OS.TABP_BODY, 0, rect2, null); + OS.DrawThemeBackground (display.hTabTheme (getZoom()), hDC, OS.TABP_BODY, 0, rect2, null); } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java index 1e0baa9c18b..f463c4765e4 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java @@ -4263,14 +4263,14 @@ void setCheckboxImageList (int width, int height, boolean fixScroll) { * artifacts, limit the rectangle to actual checkbox bitmap size. */ SIZE size = new SIZE(); - OS.GetThemePartSize(display.hButtonTheme(), memDC, OS.BP_CHECKBOX, 0, null, OS.TS_TRUE, size); + OS.GetThemePartSize(display.hButtonTheme(getZoom()), memDC, OS.BP_CHECKBOX, 0, null, OS.TS_TRUE, size); itemWidth = Math.min (size.cx, itemWidth); itemHeight = Math.min (size.cy, itemHeight); } int left = (width - itemWidth) / 2, top = (height - itemHeight) / 2; OS.SetRect (rect, left, top, left + itemWidth, top + itemHeight); if (OS.IsAppThemed ()) { - long hTheme = display.hButtonTheme (); + long hTheme = display.hButtonTheme(getZoom()); OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, rect, null); rect.left += width; rect.right += width; OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_CHECKEDNORMAL, rect, null); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java index 8d9a4609724..c655fd691ec 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java @@ -2751,7 +2751,7 @@ LRESULT WM_DRAWITEM (long wParam, long lParam) { drawBackground (struct.hDC, rect, -1, pt.x, pt.y); if (struct.CtlID == SWT.ICON_CANCEL && struct.hwndItem == hwndActiveIcon && OS.IsAppThemed()) { int state = OS.GetKeyState (OS.VK_LBUTTON) < 0 ? OS.PBS_PRESSED : OS.PBS_HOT; - OS.DrawThemeBackground (display.hButtonThemeAuto (), struct.hDC, OS.BP_PUSHBUTTON, state, rect, null); + OS.DrawThemeBackground (display.hButtonThemeAuto (getZoom()), struct.hDC, OS.BP_PUSHBUTTON, state, rect, null); } int width = rect.right - rect.left; int height = rect.bottom - rect.top; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java index 318d0868f1b..d25161dc44e 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java @@ -710,7 +710,7 @@ LRESULT CDDS_ITEMPOSTPAINT (NMTVCUSTOMDRAW nmcd, long wParam, long lParam) { backgroundRect = selectionRect; } } - long hTheme = OS.OpenThemeData (handle, Display.TREEVIEW); + long hTheme = OS.OpenThemeDataForDpi(handle, Display.TREEVIEW, getZoom()); int iStateId = selected ? OS.TREIS_SELECTED : OS.TREIS_HOT; if (OS.GetFocus () != handle && selected && !hot) iStateId = OS.TREIS_SELECTEDNOTFOCUS; OS.DrawThemeBackground (hTheme, hDC, OS.TVP_TREEITEM, iStateId, pRect, backgroundRect); @@ -4781,14 +4781,14 @@ void setCheckboxImageList () { * artifacts, limit the rectangle to actual checkbox bitmap size. */ SIZE size = new SIZE(); - OS.GetThemePartSize(display.hButtonTheme(), memDC, OS.BP_CHECKBOX, 0, null, OS.TS_TRUE, size); + OS.GetThemePartSize(display.hButtonTheme(getZoom()), memDC, OS.BP_CHECKBOX, 0, null, OS.TS_TRUE, size); itemWidth = Math.min (size.cx, itemWidth); itemHeight = Math.min (size.cy, itemHeight); } int left = (width - itemWidth) / 2, top = (height - itemHeight) / 2 + 1; OS.SetRect (rect, left + width, top, left + width + itemWidth, top + itemHeight); if (OS.IsAppThemed ()) { - long hTheme = display.hButtonTheme (); + long hTheme = display.hButtonTheme(getZoom()); OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, rect, null); rect.left += width; rect.right += width; OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_CHECKEDNORMAL, rect, null); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java index ccee2e698db..609e3eeb8af 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java @@ -2350,7 +2350,7 @@ LRESULT wmPrint (long hwnd, long wParam, long lParam) { rect.left = rect.top = 0; int border = getSystemMetrics (OS.SM_CXEDGE); OS.ExcludeClipRect (wParam, border, border, rect.right - border, rect.bottom - border); - OS.DrawThemeBackground (display.hEditTheme (), wParam, OS.EP_EDITTEXT, OS.ETS_NORMAL, rect, null); + OS.DrawThemeBackground (display.hEditTheme (getZoom()), wParam, OS.EP_EDITTEXT, OS.ETS_NORMAL, rect, null); return new LRESULT (code); } }