|
42 | 42 | import org.eclipse.core.runtime.Status; |
43 | 43 | import org.eclipse.core.runtime.jobs.Job; |
44 | 44 | import org.eclipse.core.runtime.preferences.ConfigurationScope; |
| 45 | +import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
45 | 46 | import org.eclipse.equinox.app.IApplication; |
46 | 47 | import org.eclipse.equinox.app.IApplicationContext; |
47 | 48 | import org.eclipse.jface.dialogs.IDialogConstants; |
|
53 | 54 | import org.eclipse.osgi.util.NLS; |
54 | 55 | import org.eclipse.swt.SWT; |
55 | 56 | import org.eclipse.swt.layout.FillLayout; |
| 57 | +import org.eclipse.swt.graphics.Color; |
56 | 58 | import org.eclipse.swt.widgets.Composite; |
| 59 | +import org.eclipse.ui.forms.widgets.ExpandableComposite; |
57 | 60 | import org.eclipse.swt.widgets.Control; |
58 | 61 | import org.eclipse.swt.widgets.Display; |
59 | 62 | import org.eclipse.swt.widgets.Label; |
@@ -94,6 +97,8 @@ public class IDEApplication implements IApplication, IExecutableExtension { |
94 | 97 |
|
95 | 98 | private static final String USER_NAME = "user.name"; //$NON-NLS-1$ |
96 | 99 |
|
| 100 | + private boolean isDarkTheme; |
| 101 | + |
97 | 102 | // Use the branding plug-in of the platform feature since this is most likely |
98 | 103 | // to change on an update of the IDE. |
99 | 104 | private static final String WORKSPACE_CHECK_REFERENCE_BUNDLE_NAME = "org.eclipse.platform"; //$NON-NLS-1$ |
@@ -145,6 +150,15 @@ public Object start(IApplicationContext appContext) throws Exception { |
145 | 150 | Job.getJobManager().suspend(); |
146 | 151 |
|
147 | 152 | Display display = createDisplay(); |
| 153 | + |
| 154 | + IEclipsePreferences configurationScopeNode = ConfigurationScope.INSTANCE |
| 155 | + .getNode("org.eclipse.e4.ui.css.swt.theme"); //$NON-NLS-1$ |
| 156 | + String defaultThemeId = configurationScopeNode.get("themeid", null); //$NON-NLS-1$ |
| 157 | + isDarkTheme = defaultThemeId != null && defaultThemeId.toLowerCase().contains("dark"); //$NON-NLS-1$ |
| 158 | + if (isDarkTheme) { |
| 159 | + requestDarkWindowDecorations(display); |
| 160 | + } |
| 161 | + |
148 | 162 | // processor must be created before we start event loop |
149 | 163 | DelayedEventsProcessor processor = new DelayedEventsProcessor(display); |
150 | 164 |
|
@@ -587,9 +601,51 @@ protected Shell getParentShell() { |
587 | 601 | return null; |
588 | 602 | } |
589 | 603 |
|
| 604 | + @Override |
| 605 | + protected Control createContents(Composite parent) { |
| 606 | + Control contents = super.createContents(parent); |
| 607 | + if (isDarkTheme) { |
| 608 | + applyDarkColors(getShell()); |
| 609 | + } |
| 610 | + return contents; |
| 611 | + } |
590 | 612 | }.prompt(force); |
591 | 613 | } |
592 | 614 |
|
| 615 | + private static void requestDarkWindowDecorations(Display display) { |
| 616 | + // On GTK, request dark window decorations via the SWT internal API. |
| 617 | + // Use reflection to avoid a hard compile-time dependency on GTK internals. |
| 618 | + if ("gtk".equals(SWT.getPlatform())) { //$NON-NLS-1$ |
| 619 | + try { |
| 620 | + Class.forName("org.eclipse.swt.internal.gtk.OS") //$NON-NLS-1$ |
| 621 | + .getMethod("setDarkThemePreferred", boolean.class) //$NON-NLS-1$ |
| 622 | + .invoke(null, true); |
| 623 | + } catch (ReflectiveOperationException e) { |
| 624 | + // GTK OS API unavailable — ignore |
| 625 | + } |
| 626 | + } |
| 627 | + } |
| 628 | + |
| 629 | + private static void applyDarkColors(Shell shell) { |
| 630 | + // Colors matching org-eclipse-ui-workbench-DARK_BACKGROUND / DARK_FOREGROUND |
| 631 | + Color background = new Color(0x48, 0x48, 0x4c); |
| 632 | + Color foreground = new Color(0xee, 0xee, 0xee); |
| 633 | + applyColorsRecursively(shell, background, foreground); |
| 634 | + } |
| 635 | + |
| 636 | + private static void applyColorsRecursively(Control control, Color background, Color foreground) { |
| 637 | + control.setBackground(background); |
| 638 | + control.setForeground(foreground); |
| 639 | + if (control instanceof ExpandableComposite expandable) { |
| 640 | + expandable.setTitleBarForeground(foreground); |
| 641 | + } |
| 642 | + if (control instanceof Composite composite) { |
| 643 | + for (Control child : composite.getChildren()) { |
| 644 | + applyColorsRecursively(child, background, foreground); |
| 645 | + } |
| 646 | + } |
| 647 | + } |
| 648 | + |
593 | 649 | /** |
594 | 650 | * Result of the {@link IDEApplication#checkValidWorkspace(Shell, URL)} |
595 | 651 | * operation |
|
0 commit comments