Skip to content

Commit b4248f7

Browse files
committed
Implement Cross-Platform Dark Theme Preferred API in SWT
1 parent cad012b commit b4248f7

File tree

7 files changed

+150
-3
lines changed

7 files changed

+150
-3
lines changed

bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1774,6 +1774,20 @@ public static boolean isSystemDarkTheme () {
17741774
return OS.isSystemDarkAppearance();
17751775
}
17761776

1777+
/**
1778+
* Informs the operating system that the application prefers a dark
1779+
* theme for native components such as title bars, scrollbars, and
1780+
* native dialogs.
1781+
*
1782+
* @param preferred true if the dark theme is preferred, false otherwise.
1783+
*
1784+
* @since 3.134
1785+
*/
1786+
public void setDarkThemePreferred(boolean preferred) {
1787+
checkDevice();
1788+
OS.setTheme(preferred);
1789+
}
1790+
17771791
int getLastEventTime () {
17781792
NSEvent event = application != null ? application.currentEvent() : null;
17791793
if (event == null) return 0;

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2063,6 +2063,26 @@ void setScrolling () {
20632063
view.performSelector(OS.sel_clearDeferFlushing, null, 0.0, display.runLoopModes());
20642064
}
20652065

2066+
/**
2067+
* Informs the operating system that the application prefers a dark
2068+
* theme for native components such as title bars, scrollbars, and
2069+
* native dialogs.
2070+
*
2071+
* @param preferred true if the dark theme is preferred, false otherwise.
2072+
*
2073+
* @since 3.134
2074+
*/
2075+
public void setDarkThemePreferred(boolean preferred) {
2076+
checkWidget();
2077+
if (OS.VERSION < OS.VERSION (10, 14, 0)) return;
2078+
if (window == null) return;
2079+
String appearanceName = preferred ? "NSAppearanceNameDarkAqua" : "NSAppearanceNameAqua";
2080+
NSAppearance appearance = NSAppearance.appearanceNamed (NSString.stringWith (appearanceName));
2081+
if (appearance != null) {
2082+
OS.objc_msgSend(window.id, OS.sel_setAppearance_, appearance.id);
2083+
}
2084+
}
2085+
20662086
@Override
20672087
public void setText (String string) {
20682088
checkWidget();

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2619,6 +2619,20 @@ public static boolean isSystemDarkTheme () {
26192619
return themeDark;
26202620
}
26212621

2622+
/**
2623+
* Informs the operating system that the application prefers a dark
2624+
* theme for native components such as title bars, scrollbars, and
2625+
* native dialogs.
2626+
*
2627+
* @param preferred true if the dark theme is preferred, false otherwise.
2628+
*
2629+
* @since 3.134
2630+
*/
2631+
public void setDarkThemePreferred(boolean preferred) {
2632+
checkDevice();
2633+
OS.setTheme(preferred);
2634+
}
2635+
26222636
int getLastEventTime () {
26232637
return lastEventTime;
26242638
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2879,6 +2879,20 @@ static Region mirrorRegion (Region region) {
28792879
void setRelations() {
28802880
}
28812881

2882+
/**
2883+
* Informs the operating system that the application prefers a dark
2884+
* theme for native components such as title bars, scrollbars, and
2885+
* native dialogs.
2886+
*
2887+
* @param preferred true if the dark theme is preferred, false otherwise.
2888+
*
2889+
* @since 3.134
2890+
*/
2891+
public void setDarkThemePreferred(boolean preferred) {
2892+
checkWidget();
2893+
display.setDarkThemePreferred(preferred);
2894+
}
2895+
28822896
@Override
28832897
public void setText (String string) {
28842898
super.setText (string);

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,6 +2179,20 @@ public static boolean isSystemDarkTheme () {
21792179
return isDarkTheme;
21802180
}
21812181

2182+
/**
2183+
* Informs the operating system that the application prefers a dark
2184+
* theme for native components such as title bars, scrollbars, and
2185+
* native dialogs.
2186+
*
2187+
* @param preferred true if the dark theme is preferred, false otherwise.
2188+
*
2189+
* @since 3.134
2190+
*/
2191+
public void setDarkThemePreferred(boolean preferred) {
2192+
checkDevice();
2193+
OS.setTheme(preferred);
2194+
}
2195+
21822196
int getLastEventTime () {
21832197
return OS.GetMessageTime ();
21842198
}

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ void createBalloonTipHandle () {
576576
OS.SetWindowLongPtr (balloonTipHandle, OS.GWLP_WNDPROC, display.windowProc);
577577
}
578578

579-
void setTitleColoring() {
579+
void setTitleColoring(boolean preferred) {
580580
int attributeID = 0;
581581
if (OsVersion.IS_WIN10_2004) {
582582
// Documented since build 20348, but was already present since build 19041
@@ -590,10 +590,24 @@ void setTitleColoring() {
590590
return;
591591
}
592592

593-
int[] value = new int[] {1};
593+
int[] value = new int[] {preferred ? 1 : 0};
594594
OS.DwmSetWindowAttribute (handle, attributeID, value, 4);
595595
}
596596

597+
/**
598+
* Informs the operating system that the application prefers a dark
599+
* theme for native components such as title bars, scrollbars, and
600+
* native dialogs.
601+
*
602+
* @param preferred true if the dark theme is preferred, false otherwise.
603+
*
604+
* @since 3.134
605+
*/
606+
public void setDarkThemePreferred(boolean preferred) {
607+
checkWidget();
608+
setTitleColoring(preferred);
609+
}
610+
597611
@Override
598612
void createHandle () {
599613
boolean embedded = handle != 0 && (state & FOREIGN_HANDLE) == 0;
@@ -627,7 +641,7 @@ void createHandle () {
627641

628642
if (!embedded) {
629643
if (display.useShellTitleColoring) {
630-
setTitleColoring();
644+
setTitleColoring(true);
631645
}
632646

633647
int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Eclipse Foundation and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Eclipse Foundation - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.swt.snippets;
15+
16+
import org.eclipse.swt.*;
17+
import org.eclipse.swt.layout.*;
18+
import org.eclipse.swt.widgets.*;
19+
20+
/**
21+
* Dark Theme Preferred API snippet: demonstrate how to request a dark theme for
22+
* native components (title bars, scrollbars, and native dialogs).
23+
*
24+
* For a list of all SWT example snippets see
25+
* http://www.eclipse.org/swt/snippets/
26+
*/
27+
public class Snippet393 {
28+
29+
public static void main (String [] args) {
30+
Display display = new Display ();
31+
32+
/* Signal that the application prefers a dark theme */
33+
display.setDarkThemePreferred(true);
34+
35+
Shell shell = new Shell (display);
36+
shell.setText("Snippet 393 - Dark Theme Preferred");
37+
shell.setLayout(new GridLayout(1, false));
38+
39+
Label label = new Label(shell, SWT.NONE);
40+
label.setText("The title bar and native dialogs should appear dark if supported by the OS.");
41+
42+
Button button = new Button(shell, SWT.PUSH);
43+
button.setText("Open DirectoryDialog");
44+
button.addListener(SWT.Selection, event -> {
45+
DirectoryDialog dialog = new DirectoryDialog(shell);
46+
dialog.setMessage("Select a directory (dialog should be dark)");
47+
dialog.open();
48+
});
49+
50+
shell.pack ();
51+
shell.open ();
52+
while (!shell.isDisposed ()) {
53+
if (!display.readAndDispatch ()) display.sleep ();
54+
}
55+
display.dispose ();
56+
}
57+
}

0 commit comments

Comments
 (0)