eclipse-platform / eclipse.platform.ui

Eclipse Platform
https://projects.eclipse.org/projects/eclipse.platform
Eclipse Public License 2.0
81 stars 184 forks source link

Dark mode or theme API with documented standard Eclipse colors (on Windows 10/11) + Eclipse themes #246

Open minduch opened 2 years ago

minduch commented 2 years ago

The problems: SWT / Eclipse Platform / API or Documentation

This applies to SWT and/or RCP/Eclipse-plugins UI.

The colors can be retrieved by Display.getSystemColor(SWT.COLOR...) etc. These values are always the same regardless of dark mode and/or Eclipse theme. The APIs Display.isSystemDarkTheme() and for Windows OS.IsAppThemed()are not sufficient, e.g. OS.IsAppThemed() returns true even if Windows 11 is set to dark mode but not for apps themselves, and Display.isSystemDarkTheme() does exactly what it is supposed to do: get the system setting for Dark Theme, not the current app dark theme flag. I know there has been threads talking about these issues for years...

Then themes, using PlatformUI.getWorkbench().getThemeManager(), can be retrieved and when platform is running, and you can add a listener using e.g.:

PlatformUI.getWorkbench().getThemeManager().addPropertyChangeListener((themeEvent) -> {
  if ( themeEvent.getProperty().equals(IThemeManager.CHANGE_CURRENT_THEME)
    && themeEvent.getSource() instanceof IThemeManager
    && themeEvent.getNewValue() instanceof ITheme ) {
    ITheme newTheme = (ITheme)themeEvent.getNewValue();
    ITheme oldTheme = (ITheme)themeEvent.getOldValue();

The problem is that I can't find any documentation on the color names for the ColorRegistry retrieved from the ITheme instance. Many colors in the registry are unchanged when changing Eclipse theme from Light to Dark and vice versa. But the system colors are not there. It becomes pretty hard to figure out a way to match an Eclipse plugin's colors to the theme set by the user, but also - preferable - use system colors or derive colors from there (or better from the theme).

Environment:

  1. Select the platform(s) on which the behavior is seen:

      • [x] All OS
      • [x] Windows
      • [ ] Linux
      • [ ] macOS
  2. Additional OS info (e.g. OS version, Linux Desktop, etc) Typically Windows 10 and Windows 11. But it would most certainly apply to macOS and Linux too.

Eclipse SWT Version 4.24

Even earlier versions of Eclipse or SWT, but I'm on Eclipse 2022-09 (M1) 4.25.

Workaround

I had an idea to perhaps figure out the dark mode by checking some theme or system color (that changes with the theme) with a MacGyver'y such as:

Color color = ...themed-color-that-normally-is light-or-dark-depending-on-mode...
boolean isDarkTheme = ( color.getRed() < 129 && color.getGreen() < 129 && color.getBlue()<129 );

but it feels a little "off" to do so. I think the problem should be addressed in the SWT/Eclipse API and more/better documentation on color names for the ColorRegistry. I also know that I could provide my own color setting + themes using some Preference settings code, but shouldn't there be a consistent way of doing it?

I would be very happy to write some OS-low-level code to fix this problem myself, but somehow that doesn't feel right as the APIs should be sufficient for developers. Does anyone have a work-around that could apply for me in the short-term (like right now in e.g. Eclipse 4.20 or better)?

niraj-modi commented 2 years ago

Currently SWT doesn't directly support theming, it's done via CSS engine. Moving this issue to Platform UI.

niraj-modi commented 2 years ago

@vogella: Hi Lars, Any idea if we have a detailed documentation somewhere ? or similar that can help here, Thanks!

mickaelistria commented 2 years ago

Do you have an actual proposal of some API that could help, and how it would do so?

For some context: SWT.COLOR_* are system colors as provided by the OS according to the OS theme. On Windows, there isn't really an idea of a system/OS theme that applications can rely on, so those are not changing according to the OS setting. How SWT.COLOR_* are loaded from the OS is not something that can nor should be changed as it's a very important part of SWT's "native" strategy. The Workbench Theme doesn't necessarily reuse the System colors. The colors are defined in *.e4css files ( (eg https://github.com/eclipse-platform/eclipse.platform.ui/blob/master/bundles/org.eclipse.ui.themes/css/dark/e4-dark_ide_colorextensions.css ) andd may reference system colors, or registry colors, or even hardcoded color codes. The registry colors are defined in *.e4css files as well. Different themes may use different colors definitions, different registry ids. So there is not a single set of all registry colors a theme can use and the set of registry colors become dependent on the current theme.

Usually, your code shouldn't really query the theme. Looking at the parent widget color or other more contextual information is likely to drive to better -more adaptative- results. Your workaround is somehow that most sustainable approach to varying colors.

minduch commented 2 years ago

In reference to @vogella and @niraj-modi, documentation would be pretty nice. I have opened an issue #250 that may be relevant in this case too.

And sorry, I do not have any API to think of other than the ones that exist, but they can't be used due to #250 in "early" stages when the E4 engine is not ready (all bundles are dependencies are probably not ready). But the API issue in #250 shouldn't happen as I think. The bundles should load and initialize properly, or there must be a documentation about it that tells developers to expect a NullPointerException if the e4context is null, or an API call to wait for the ready state. There are so many E4-bundles and so little or cryptic documentation (oh: I know, there are tons of articles, discussions, API, JavaDoc, etc, even Lars tutorials), but here is a missing red thread to tie it together.

I also know and understand that the Windows themeing is in the early stages (for Win32 APIs and Eclipse SWT attempts to handle it), but not Eclipse themes - that has been around for quite some time, but few have used it until now that Windows 10 and 11 (!) really almost imposes it.