Bug 566222 - [Win32][Dark theme] Combos dark light in the dark theme
This patch has 2 changes:
* Use undocumented 'DarkMode_CFD::Combobox' theme for Combo.
* Apply the usual dark scrollbars theme to Combo's dropdown
Change-Id: I86a6231d13d08815a9d76f303bd20a5a0c11b94d
Signed-off-by: Alexandr Miloslavskiy <alexandr.miloslavskiy@syntevo.com>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java
index 11dd7f7..e182761 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java
@@ -2230,6 +2230,7 @@
display.setData("org.eclipse.swt.internal.win32.Tree.use_WS_BORDER", isDarkTheme);
display.setData("org.eclipse.swt.internal.win32.Table.headerLineColor", isDarkTheme ? new Color(display, 0x50, 0x50, 0x50) : null);
display.setData("org.eclipse.swt.internal.win32.Label.disabledForegroundColor", isDarkTheme ? new Color(display, 0x80, 0x80, 0x80) : null);
+ display.setData("org.eclipse.swt.internal.win32.Combo.useDarkTheme", isDarkTheme);
}
public static final boolean SetWindowText (long hWnd, TCHAR lpString) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java
index f38673a..a42e0de 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java
@@ -724,6 +724,11 @@
}
state &= ~(CANVAS | THEME_BACKGROUND);
+ if (display.comboUseDarkTheme) {
+ OS.AllowDarkModeForWindow(handle, true);
+ OS.SetWindowTheme(handle, "CFD\0".toCharArray(), null);
+ }
+
stateFlagsUsable = stateFlagsTest();
/* Get the text and list window procs */
@@ -2485,6 +2490,18 @@
}
}
+void updateDropDownTheme () {
+ COMBOBOXINFO pcbi = new COMBOBOXINFO ();
+ pcbi.cbSize = COMBOBOXINFO.sizeof;
+ if (!OS.GetComboBoxInfo(handle, pcbi))
+ return;
+
+ if (pcbi.hwndList == 0)
+ return;
+
+ maybeEnableDarkSystemTheme(pcbi.hwndList);
+}
+
@Override
boolean updateTextDirection(int textDirection) {
if (super.updateTextDirection(textDirection)) {
@@ -3216,6 +3233,7 @@
case OS.CBN_DROPDOWN:
setCursor ();
updateDropDownHeight ();
+ updateDropDownTheme ();
break;
case OS.CBN_KILLFOCUS:
sendFocusEvent (SWT.FocusOut);
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 202fb6e..49cedcc 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
@@ -230,6 +230,17 @@
*/
static final String LABEL_DISABLED_FOREGROUND_COLOR_KEY = "org.eclipse.swt.internal.win32.Label.disabledForegroundColor"; //$NON-NLS-1$
int disabledLabelForegroundPixel = -1;
+ /**
+ * Use dark theme for Combo.
+ * Limitations:<br>
+ * <ul>
+ * <li>Only available since Win10 version 1903.</li>
+ * <li>Does not affect already created controls.</li>
+ * </ul>
+ * Expects a <code>boolean</code> value.
+ */
+ static final String COMBO_USE_DARK_THEME = "org.eclipse.swt.internal.win32.Combo.useDarkTheme"; //$NON-NLS-1$
+ boolean comboUseDarkTheme = false;
/* Custom icons */
long hIconSearch;
@@ -4399,6 +4410,11 @@
case LABEL_DISABLED_FOREGROUND_COLOR_KEY:
disabledLabelForegroundPixel = disableCustomThemeTweaks ? -1 : _toColorPixel(value);
break;
+ case COMBO_USE_DARK_THEME:
+ comboUseDarkTheme = _toBoolean(value) &&
+ !disableCustomThemeTweaks &&
+ OS.IsDarkModeAvailable();
+ break;
}
/* Remove the key/value pair */
diff --git a/tests/org.eclipse.swt.tests.win32/ManualTests/org/eclipse/swt/tests/win32/snippets/Bug566222_DarkCombo.java b/tests/org.eclipse.swt.tests.win32/ManualTests/org/eclipse/swt/tests/win32/snippets/Bug566222_DarkCombo.java
new file mode 100644
index 0000000..c1798b0
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.win32/ManualTests/org/eclipse/swt/tests/win32/snippets/Bug566222_DarkCombo.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Syntevo and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Syntevo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.win32.snippets;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+
+public class Bug566222_DarkCombo {
+ static void setColors(Control control, Color backColor, Color foreColor) {
+ control.setBackground(backColor);
+ control.setForeground(foreColor);
+
+ if (control instanceof Composite) {
+ for (Control child : ((Composite)control).getChildren()) {
+ setColors(child, backColor, foreColor);
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ final Display display = new Display();
+ OS.setTheme(true);
+
+ final Shell shell = new Shell(display);
+ GridLayout layout = new GridLayout(1, true);
+ layout.horizontalSpacing = 10;
+ shell.setLayout(layout);
+
+ Label hint = new Label(shell, 0);
+ hint.setText("The Combo shall look good in Dark Theme");
+
+ for (int iStyle = 0; iStyle < 2; iStyle++) {
+ int style = (iStyle == 0) ? 0 : SWT.READ_ONLY;
+ Combo combo = new Combo(shell, style);
+
+ for (int iItem = 0; iItem < 100; iItem++) {
+ combo.add("Item #" + iItem);
+ }
+
+ combo.select(0);
+ }
+
+ Color backColor = new Color(display, 0x30, 0x30, 0x30);
+ Color foreColor = new Color(display, 0xD0, 0xD0, 0xD0);
+ setColors(shell, backColor, foreColor);
+
+ shell.pack();
+ shell.open();
+
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+
+ display.dispose();
+ }
+}