[Initiatives.wiki] Create Dark Style Preference



commit 83fbdedcea3abfe1f0054bed3e181c777ad030d0
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Wed Sep 29 10:31:37 2021 +0000

    Create Dark Style Preference

 Dark-Style-Preference.md | 155 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 155 insertions(+)
---
diff --git a/Dark-Style-Preference.md b/Dark-Style-Preference.md
new file mode 100644
index 0000000..f962d15
--- /dev/null
+++ b/Dark-Style-Preference.md
@@ -0,0 +1,155 @@
+# 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]