|
|
# Design
|
|
|
1. Apps that didn't have their own appearance preference (e.g. **Contacts** or **Clocks**) should normally be light and become dark if the system prefers that.
|
|
|
* Apps that synchronized their appearance with the system night light mode (e.g. **Calendar** or **Builder**), should stop doing that, this will be done system-wide instead.
|
|
|
2. Apps that didn't have a preference but used dark appearance by default (e.g. **Photos** or **Videos**) should be dark unless the system prefers light appearance, such as for the high contrast mode. If it's not possible to support light appearance, they can be always dark.
|
|
|
3. Apps that had provided a preference, but only because there wasn't a system-wide one (e.g. **Shortwave** or **dconf-editor**) should drop their preference for GNOME 42. They can still show it when running on older systems.
|
|
|
4. Apps that had provided a prominent preference and want to keep it going forward (e.g. **Apostrophe**, [**Text Editor**](https://gitlab.gnome.org/GNOME/gnome-text-editor) or **Builder**) should add a state where the application follows the system preference, for example like on [this mockup](https://gitlab.gnome.org/Teams/Design/os-mockups/-/blob/master/prefer-dark/prefer-dark.png). That state may be omitted when running on older systems.
|
|
|
5. Apps that use completely custom styles (e.g. **Contrast**) shouldn't try to follow the preference at all if it doesn't make sense for them.
|
|
|
6. Libraries that provide widgets should try to follow the app's appearance if possible and makes sense - for example, **WebKitGTK** should use dark color scheme for pages that support it when the application it's embedded into is dark — either automatically, or via API that the app would use. They should not follow the system preference directly, as there's no guarantee the application follows it.
|
|
|
|
|
|
# Implementation
|
|
|
## GTK4 + libadwaita
|
|
|
Applications follow the preference by default, so design 1 doesn't require any changes.
|
|
|
|
|
|
To implement design 2 can use the following snippet to request dark variant and still support light appearance:
|
|
|
|
|
|
```c
|
|
|
adw_style_manager_set_color_scheme (adw_style_manager_get_default (),
|
|
|
ADW_COLOR_SCHEME_PREFER_DARK);
|
|
|
```
|
|
|
|
|
|
or the following one otherwise:
|
|
|
|
|
|
```c
|
|
|
adw_style_manager_set_color_scheme (adw_style_manager_get_default (),
|
|
|
ADW_COLOR_SCHEME_FORCE_DARK);
|
|
|
```
|
|
|
|
|
|
A good place to do that would be the `startup()` handler of your `GApplication`.
|
|
|
|
|
|
Applications that provide color scheme preferences as per designs 3 and 4 should use `ADW_COLOR_SCHEME_FORCE_LIGHT` and `ADW_COLOR_SCHEME_FORCE_DARK` color schemes, as they will ignore the system preference. The "follow system" state can be implemented as `ADW_COLOR_SCHEME_PREFER_LIGHT`.
|
|
|
|
|
|
See [`AdwStyleManager:color-scheme`](color-scheme) for more details.
|
|
|
|
|
|
Important: Don't use [`GtkSettings:gtk-application-prefer-dark-theme`](prefer-dark-theme) or [`GtkSettings:gtk-theme-name`](gtk-theme-name) for checking if the application is currently using dark appearance! Neither of them will change in this case.
|
|
|
|
|
|
Instead, if you need to vary other aspects of the UI (e.g. the `GtkSourceView` color scheme), use the [`AdwStyleManager:dark`](dark) property, and to check for the high contrast mode, use [`AdwStyleManager:high-contrast`](high-contrast).
|
|
|
|
|
|
To only show a switch when running on an system without a system-wide preference, the [`AdwStyleManager:system-supports-color-schemes`](supports-color-schemes) property can be used; libadwaita demo has [an example](https://gitlab.gnome.org/GNOME/libadwaita/-/blob/2bf94101/examples/adw-demo-window.c#L41-62).
|
|
|
|
|
|
If the application bundles custom CSS which needs changes for dark appearance or vice versa, [`AdwApplication`](AdwApplication) provides an easy way to do that via `style.css` and `style-dark.css` resoures.
|
|
|
|
|
|
## GTK3 + libhandy
|
|
|
If possible, consider porting to GTK4 and libadwaita first. libadwaita has a significant amount of changes in its stylesheet, aimed to improve the contrast in dark variant. For example:
|
|
|
|
|
|
| GTK3 | GTK4 + libadwaita |
|
|
|
| :--: | :---------------: |
|
|
|
| ![libhandy example](uploads/81af07e893f68272b4d676757ffc05a8/Screenshot_from_2021-09-29_02-38-52.png) | ![libadwaita example](uploads/f00ae6c5923bd0e056d3ad7ce0bee62d/Screenshot_from_2021-09-29_02-38-56.png)|
|
|
|
|
|
|
Cases like this will need custom styles in the application.
|
|
|
|
|
|
Other than that, the steps mostly match libadwaita, with one exception: applications don't follow the preference by default, so design 1 requires apps to opt in using the following snippet:
|
|
|
|
|
|
```c
|
|
|
hdy_style_manager_set_color_scheme (hdy_style_manager_get_default (),
|
|
|
HDY_COLOR_SCHEME_PREFER_LIGHT);
|
|
|
```
|
|
|
|
|
|
Additionally, since `AdwApplication` is not available, loading a CSS snippet only for dark appearance is instead done as follows:
|
|
|
|
|
|
```c
|
|
|
struct _MyApplication
|
|
|
{
|
|
|
...
|
|
|
|
|
|
GtkStyleProvider *dark_provider;
|
|
|
};
|
|
|
|
|
|
...
|
|
|
|
|
|
static void
|
|
|
update_dark_style (MyApplication *self)
|
|
|
{
|
|
|
HdyStyleManager *manager = hdy_style_manager_get_default ();
|
|
|
GdkScreen *screen = gdk_screen_get_default ();
|
|
|
|
|
|
if (hdy_style_manager_get_dark (manager))
|
|
|
gtk_style_context_add_provider_for_screen (screen,
|
|
|
self->dark_provider,
|
|
|
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
|
|
|
else
|
|
|
gtk_style_context_remove_provider_for_screen (screen,
|
|
|
self->dark_provider);
|
|
|
}
|
|
|
|
|
|
...
|
|
|
|
|
|
static void
|
|
|
my_application_dispose (GObject *self)
|
|
|
{
|
|
|
...
|
|
|
|
|
|
g_clear_object (&self->dark_provider);
|
|
|
}
|
|
|
|
|
|
...
|
|
|
|
|
|
static void
|
|
|
my_application_startup (MyApplication *self)
|
|
|
{
|
|
|
...
|
|
|
|
|
|
self->dark_provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
|
|
|
|
|
|
gtk_css_provider_load_from_resource (GTK_CSS_PROVIDER (self->dark_provider),
|
|
|
"/my/application/style-dark.css");
|
|
|
|
|
|
update_dark_style (self);
|
|
|
|
|
|
g_signal_connect_object (hdy_style_manager_get_default (),
|
|
|
"notify::dark",
|
|
|
G_CALLBACK (update_dark_style),
|
|
|
self,
|
|
|
G_CONNECT_SWAPPED);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
## Other
|
|
|
If it's not possible to use libadwaita or libhandy, use DBus to manually access the settings portal and fetch the preference.
|
|
|
|
|
|
Do _not_ use the gsettings key backing the settings portal implementation other than as a fallback if the portal isn't present: that key only exists on GNOME and is an implementation detail.
|
|
|
|
|
|
Don't add any animation for the transition; the whole screen will be animated on the compositor side instead.
|
|
|
|
|
|
A self-contained SDL+GDBus example that supports the dark style preference: [hello.c](uploads/76dfcc9b07d234cb8922cf800e743f02/hello.c)
|
|
|
|
|
|
Building: `gcc $(pkg-config --libs --cflags sdl2 gio-2.0) hello.c -o hello"`
|
|
|
|
|
|
Screenshots:
|
|
|
|
|
|
![Screenshot_from_2021-09-29_03-54-35](uploads/a6b95700ea1e2b9487131b6d399998e6/Screenshot_from_2021-09-29_03-54-35.png)
|
|
|
|
|
|
![Screenshot_from_2021-09-29_03-54-40](uploads/7ebfb46ec97d191ceef36c217eea554e/Screenshot_from_2021-09-29_03-54-40.png)
|
|
|
|
|
|
# Testing
|
|
|
## GNOME 42
|
|
|
If you have a GNOME 42 system, for example a jhbuild session or a GNOME OS VM, use dconf-editor or `gsettings` CLI to edit the following preference: `org.gnome.desktop.interface.color-scheme`.
|
|
|
|
|
|
## libadwaita
|
|
|
Libadwaita provides a `GtkInspector` page. If libadwaita is present in the SDK, it should work out of the box, and for apps that bundle libadwaita, it can be enabled via `"--env=GTK_PATH=/app/lib/gtk-4.0"` in `finish-args` in their manifest.
|
|
|
|
|
|
If it's set up correctly, open inspector with `Ctrl+Shift+D` and there should be a libadwaita page providing toggles for the system color scheme, high contrast and emulating an older system without color schemes.
|
|
|
|
|
|
## Other
|
|
|
The following project can be used to test the preference: https://gitlab.gnome.org/exalm/color-scheme-simulator
|
|
|
|
|
|
It provides a settings portal implementation (providing `color-scheme` and nothing else) that can run on older GNOME versions together with `xdg-desktop-portal-gnome/gtk`, and a simple GUI for changing the preference.
|
|
|
|
|
|
[AdwApplication]: https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Application.html
|
|
|
[AdwStyleManager]: https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.StyleManager.html
|
|
|
[prefer-dark-theme]: https://docs.gtk.org/gtk4/property.Settings.gtk-application-prefer-dark-theme.html
|
|
|
[gtk-theme-name]: https://docs.gtk.org/gtk4/property.Settings.gtk-theme-name.html
|
|
|
[color-scheme]: https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/property.StyleManager.color-scheme.html
|
|
|
[supports-color-schemes]: https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/property.StyleManager.system-supports-color-schemes.html
|
|
|
[dark]: https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/property.StyleManager.dark.html
|
|
|
[high-contrast]: https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/property.StyleManager.high-contrast.html |
|
|
\ No newline at end of file |