[libadwaita/wip/exalm/dark: 1/3] Add AdwStyleManager
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libadwaita/wip/exalm/dark: 1/3] Add AdwStyleManager
- Date: Mon, 20 Sep 2021 13:37:57 +0000 (UTC)
commit ce063dbef151353cb6e3858eb3582565e105453a
Author: Alexander Mikhaylenko <exalm7659 gmail com>
Date: Thu Aug 26 14:21:34 2021 +0500
Add AdwStyleManager
Move the stylesheet handling from adw-main.c there. Provide API for
influencing and inspecting color scheme.
src/adw-enums.c.in | 1 +
src/adw-main.c | 108 +------
src/adw-style-manager-private.h | 21 ++
src/adw-style-manager.c | 675 ++++++++++++++++++++++++++++++++++++++++
src/adw-style-manager.h | 57 ++++
src/adwaita.h | 1 +
src/meson.build | 3 +
7 files changed, 766 insertions(+), 100 deletions(-)
---
diff --git a/src/adw-enums.c.in b/src/adw-enums.c.in
index 238a7283..b151b1ed 100644
--- a/src/adw-enums.c.in
+++ b/src/adw-enums.c.in
@@ -8,6 +8,7 @@
#include "adw-leaflet.h"
#include "adw-navigation-direction.h"
#include "adw-squeezer.h"
+#include "adw-style-manager.h"
#include "adw-view-switcher.h"
/*** END file-header ***/
diff --git a/src/adw-main.c b/src/adw-main.c
index afad88e0..0c1273a5 100644
--- a/src/adw-main.c
+++ b/src/adw-main.c
@@ -1,112 +1,18 @@
/*
- * Copyright (C) 2018-2020 Purism SPC
+ * Copyright (C) 2018-2021 Purism SPC
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
+
#include "adw-main-private.h"
-#include <gio/gio.h>
+
+#include "adw-style-manager-private.h"
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
static int adw_initialized = FALSE;
-static gboolean
-is_high_contrast (void)
-{
- GdkDisplay *display = gdk_display_get_default ();
- g_auto (GValue) value = G_VALUE_INIT;
- const char *theme_name;
-
- g_value_init (&value, G_TYPE_STRING);
- if (!gdk_display_get_setting (display, "gtk-theme-name", &value))
- return FALSE;
-
- theme_name = g_value_get_string (&value);
-
- /* TODO: HighContrast shouldn't be a theme */
- return !g_strcmp0 (theme_name, "HighContrast") ||
- !g_strcmp0 (theme_name, "HighContrastInverse");
-}
-
-static void
-update_theme (void)
-{
- GtkSettings *settings = gtk_settings_get_default ();
- g_autofree char *new_theme_name = NULL;
- gboolean prefer_dark_theme;
- const char *variant;
-
- g_object_get (settings,
- "gtk-application-prefer-dark-theme", &prefer_dark_theme,
- NULL);
-
- if (is_high_contrast ())
- variant = prefer_dark_theme ? "hc-dark" : "hc";
- else
- variant = prefer_dark_theme ? "dark" : "light";
-
- new_theme_name = g_strdup_printf ("Adwaita-%s", variant);
-
- g_object_set (settings, "gtk-theme-name", new_theme_name, NULL);
-}
-
-static void
-setting_changed_cb (GdkDisplay *display,
- const char *setting)
-{
- if (!g_strcmp0 (setting, "gtk-theme-name"))
- update_theme ();
-}
-
-static void
-adw_style_init (void)
-{
- static gsize guard = 0;
- GtkSettings *settings;
-
- if (!g_once_init_enter (&guard))
- return;
-
- settings = gtk_settings_get_default ();
-
- if (!settings) {
- g_once_init_leave (&guard, 1);
-
- return;
- }
-
- g_signal_connect (settings,
- "notify::gtk-application-prefer-dark-theme",
- G_CALLBACK (update_theme),
- NULL);
-
- /* If gtk_settings_get_default() has worked, GdkDisplay
- * exists, so we don't need to check that separately. */
- g_signal_connect (gdk_display_get_default (),
- "setting-changed",
- G_CALLBACK (setting_changed_cb),
- NULL);
-
- update_theme ();
-
- g_once_init_leave (&guard, 1);
-}
-
-static void
-adw_icons_init (void)
-{
- static gsize guard = 0;
-
- if (!g_once_init_enter (&guard))
- return;
-
- gtk_icon_theme_add_resource_path (gtk_icon_theme_get_for_display (gdk_display_get_default ()),
- "/org/gnome/Adwaita/icons");
-
- g_once_init_leave (&guard, 1);
-}
-
/**
* adw_init:
*
@@ -134,8 +40,10 @@ adw_init (void)
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
adw_init_public_types ();
- adw_style_init ();
- adw_icons_init ();
+ gtk_icon_theme_add_resource_path (gtk_icon_theme_get_for_display (gdk_display_get_default ()),
+ "/org/gnome/Adwaita/icons");
+
+ adw_style_manager_ensure ();
adw_initialized = TRUE;
}
diff --git a/src/adw-style-manager-private.h b/src/adw-style-manager-private.h
new file mode 100644
index 00000000..6e435b98
--- /dev/null
+++ b/src/adw-style-manager-private.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 Purism SPC
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * Author: Alexander Mikhaylenko <alexander mikhaylenko puri sm>
+ */
+
+#pragma once
+
+#if !defined(_ADWAITA_INSIDE) && !defined(ADWAITA_COMPILATION)
+#error "Only <adwaita.h> can be included directly."
+#endif
+
+#include "adw-style-manager.h"
+
+G_BEGIN_DECLS
+
+void adw_style_manager_ensure (void);
+
+G_END_DECLS
diff --git a/src/adw-style-manager.c b/src/adw-style-manager.c
new file mode 100644
index 00000000..a077156e
--- /dev/null
+++ b/src/adw-style-manager.c
@@ -0,0 +1,675 @@
+/*
+ * Copyright (C) 2021 Purism SPC
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * Author: Alexander Mikhaylenko <alexander mikhaylenko puri sm>
+ */
+
+#include "config.h"
+
+#include "adw-style-manager-private.h"
+
+#include "adw-settings-private.h"
+#include <gtk/gtk.h>
+
+#define SWITCH_DURATION 250
+
+/**
+ * AdwColorScheme:
+ * @ADW_COLOR_SCHEME_DEFAULT: Inherit the parent color-scheme. When set on the
+ * `AdwStyleManager` returned by [func@Adw.StyleManager.get_default], it's
+ * equivalent to `ADW_COLOR_SCHEME_LIGHT_DARK`.
+ * @ADW_COLOR_SCHEME_LIGHT: Always use light appearance.
+ * @ADW_COLOR_SCHEME_LIGHT_DARK: Use light appearance unless the system prefers
+ * dark colors.
+ * @ADW_COLOR_SCHEME_DARK_LIGHT: Use dark appearance unless the system prefers
+ * light colors.
+ * @ADW_COLOR_SCHEME_DARK: Always use dark appearance.
+ *
+ * Application color schemes for [property@Adw.StyleManager:color-scheme].
+ *
+ * Since: 1.0
+ */
+
+/**
+ * AdwStyleManager:
+ *
+ * A class for managing application-wide styling.
+ *
+ * `AdwStyleManager` provides a way to query and influence the application
+ * styles, such as whether to use dark or high contrast appearance.
+ *
+ * It allows to set the color scheme via the
+ * [property@Adw.StyleManager:color-scheme] property, and to query the current
+ * appearance, as well as whether a system-wide color scheme preference exists.
+ *
+ * Since: 1.0
+ */
+
+struct _AdwStyleManager
+{
+ GObject parent_instance;
+
+ GdkDisplay *display;
+ AdwSettings *settings;
+
+ AdwColorScheme color_scheme;
+ gboolean dark;
+
+ guint animation_timeout_id;
+};
+
+G_DEFINE_TYPE (AdwStyleManager, adw_style_manager, G_TYPE_OBJECT);
+
+enum {
+ PROP_0,
+ PROP_DISPLAY,
+ PROP_COLOR_SCHEME,
+ PROP_SYSTEM_SUPPORTS_COLOR_SCHEMES,
+ PROP_DARK,
+ PROP_HIGH_CONTRAST,
+ LAST_PROP,
+};
+
+static GParamSpec *props[LAST_PROP];
+
+static GHashTable *display_style_managers = NULL;
+static AdwStyleManager *default_instance = NULL;
+
+static void
+warn_prefer_dark_theme (void)
+{
+ g_warning ("Using GtkSettings:gtk-application-prefer-dark-theme with "
+ "libadwaita is unsupported. Please use "
+ "AdwStyleManager:color-scheme or AdwApplication:color-scheme "
+ "instead.");
+}
+
+static void
+unregister_display (GdkDisplay *display)
+{
+ g_assert (!g_hash_table_contains (display_style_managers, display));
+
+ g_hash_table_remove (display_style_managers, display);
+}
+
+static void
+register_display (GdkDisplayManager *display_manager,
+ GdkDisplay *display)
+{
+ AdwStyleManager *style_manager;
+
+ style_manager = g_object_new (ADW_TYPE_STYLE_MANAGER,
+ "display", display,
+ NULL);
+
+ g_assert (!g_hash_table_contains (display_style_managers, display));
+
+ g_hash_table_insert (display_style_managers, display, style_manager);
+
+ g_signal_connect (display,
+ "closed",
+ G_CALLBACK (unregister_display),
+ NULL);
+}
+
+static gboolean
+enable_animations_cb (AdwStyleManager *self)
+{
+ g_object_set (gtk_settings_get_for_display (self->display),
+ "gtk-enable-animations", TRUE,
+ NULL);
+
+ self->animation_timeout_id = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+update_stylesheet (AdwStyleManager *self)
+{
+ const char *variant;
+ g_autofree char *new_theme_name = NULL;
+ GtkSettings *gtk_settings;
+ gboolean enable_animations;
+
+ if (!self->display)
+ return;
+
+ gtk_settings = gtk_settings_get_for_display (self->display);
+
+ if (adw_settings_get_high_contrast (self->settings))
+ variant = self->dark ? "hc-dark" : "hc";
+ else
+ variant = self->dark ? "dark" : "light";
+
+ new_theme_name = g_strdup_printf ("Adwaita-%s", variant);
+
+ if (self->animation_timeout_id) {
+ g_clear_handle_id (&self->animation_timeout_id, g_source_remove);
+ enable_animations = TRUE;
+ } else {
+ g_object_get (gtk_settings,
+ "gtk-enable-animations", &enable_animations,
+ NULL);
+ }
+
+ g_object_set (gtk_settings,
+ "gtk-enable-animations", FALSE,
+ "gtk-theme-name", new_theme_name,
+ NULL);
+
+ if (enable_animations) {
+ self->animation_timeout_id =
+ g_timeout_add (SWITCH_DURATION,
+ G_SOURCE_FUNC (enable_animations_cb),
+ self);
+ }
+}
+
+static gboolean
+get_is_dark (AdwStyleManager *self)
+{
+ AdwSystemColorScheme system_scheme = adw_settings_get_color_scheme (self->settings);
+
+ switch (self->color_scheme) {
+ case ADW_COLOR_SCHEME_DEFAULT:
+ if (self->display)
+ return get_is_dark (default_instance);
+ return (system_scheme == ADW_SYSTEM_COLOR_SCHEME_PREFER_DARK);
+ case ADW_COLOR_SCHEME_LIGHT:
+ return FALSE;
+ case ADW_COLOR_SCHEME_LIGHT_DARK:
+ return (system_scheme == ADW_SYSTEM_COLOR_SCHEME_PREFER_DARK);
+ case ADW_COLOR_SCHEME_DARK_LIGHT:
+ return (system_scheme == ADW_SYSTEM_COLOR_SCHEME_PREFER_DARK) ||
+ (system_scheme == ADW_SYSTEM_COLOR_SCHEME_DEFAULT);
+ case ADW_COLOR_SCHEME_DARK:
+ return TRUE;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+update_dark (AdwStyleManager *self)
+{
+ gboolean dark = get_is_dark (self);
+
+ if (dark == self->dark)
+ return;
+
+ self->dark = dark;
+
+ update_stylesheet (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DARK]);
+}
+
+static void
+notify_high_contrast_cb (AdwStyleManager *self)
+{
+ update_stylesheet (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HIGH_CONTRAST]);
+}
+
+static void
+adw_style_manager_constructed (GObject *object)
+{
+ AdwStyleManager *self = ADW_STYLE_MANAGER (object);
+
+ G_OBJECT_CLASS (adw_style_manager_parent_class)->constructed (object);
+
+ if (self->display) {
+ GtkSettings *settings = gtk_settings_get_for_display (self->display);
+ gboolean prefer_dark_theme;
+
+ g_object_get (settings,
+ "gtk-application-prefer-dark-theme", &prefer_dark_theme,
+ NULL);
+
+ if (prefer_dark_theme)
+ warn_prefer_dark_theme ();
+
+ g_signal_connect_object (settings,
+ "notify::gtk-application-prefer-dark-theme",
+ G_CALLBACK (warn_prefer_dark_theme),
+ self,
+ 0);
+ }
+
+ self->settings = adw_settings_get_default ();
+
+ g_signal_connect_object (self->settings,
+ "notify::color-scheme",
+ G_CALLBACK (update_dark),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->settings,
+ "notify::high-contrast",
+ G_CALLBACK (notify_high_contrast_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ update_dark (self);
+ update_stylesheet (self);
+}
+
+static void
+adw_style_manager_dispose (GObject *object)
+{
+ AdwStyleManager *self = ADW_STYLE_MANAGER (object);
+
+ g_clear_handle_id (&self->animation_timeout_id, g_source_remove);
+
+ G_OBJECT_CLASS (adw_style_manager_parent_class)->dispose (object);
+}
+
+static void
+adw_style_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AdwStyleManager *self = ADW_STYLE_MANAGER (object);
+
+ switch (prop_id) {
+ case PROP_DISPLAY:
+ g_value_set_object (value, adw_style_manager_get_display (self));
+ break;
+
+ case PROP_COLOR_SCHEME:
+ g_value_set_enum (value, adw_style_manager_get_color_scheme (self));
+ break;
+
+ case PROP_SYSTEM_SUPPORTS_COLOR_SCHEMES:
+ g_value_set_boolean (value, adw_style_manager_get_system_supports_color_schemes (self));
+ break;
+
+ case PROP_DARK:
+ g_value_set_boolean (value, adw_style_manager_get_dark (self));
+ break;
+
+ case PROP_HIGH_CONTRAST:
+ g_value_set_boolean (value, adw_style_manager_get_high_contrast (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+adw_style_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AdwStyleManager *self = ADW_STYLE_MANAGER (object);
+
+ switch (prop_id) {
+ case PROP_DISPLAY:
+ self->display = g_value_get_object (value);
+ break;
+
+ case PROP_COLOR_SCHEME:
+ adw_style_manager_set_color_scheme (self, g_value_get_enum (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+adw_style_manager_class_init (AdwStyleManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = adw_style_manager_constructed;
+ object_class->dispose = adw_style_manager_dispose;
+ object_class->get_property = adw_style_manager_get_property;
+ object_class->set_property = adw_style_manager_set_property;
+
+ /**
+ * AdwStyleManager:display: (attributes org.gtk.Property.get=adw_style_manager_get_display)
+ *
+ * The display the style manager is associated with.
+ *
+ * The display will be `NULL` for the style manager returned by
+ * [func@Adw.StyleManager.get_default].
+ *
+ * Since: 1.0
+ */
+ props[PROP_DISPLAY] =
+ g_param_spec_object ("display",
+ "Display",
+ "The display the style manager is associated with",
+ GDK_TYPE_DISPLAY,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+ /**
+ * AdwStyleManager:color-scheme: (attributes org.gtk.Property.get=adw_style_manager_get_color_scheme
org.gtk.Property.set=adw_style_manager_set_color_scheme)
+ *
+ * The requested application color scheme.
+ *
+ * The effective appearance will be decided based on the application color
+ * scheme and the system preferred color scheme. The
+ * [property@Adw.StyleManager:dark] property can be used to query the
+ * current effective appearance.
+ *
+ * The `ADW_COLOR_SCHEME_LIGHT_DARK` color scheme results in the application
+ * using light appearance unless the system prefers dark colors. This is the
+ * default value.
+ *
+ * The `ADW_COLOR_SCHEME_DARK` color scheme results in the application
+ * using dark appearance, but can still switch to the light appearance if the
+ * system can prefers it, for example, when the high contrast preference is
+ * enabled.
+ *
+ * The `ADW_COLOR_SCHEME_LIGHT` and `ADW_COLOR_SCHEME_DARK` values ignore the
+ * system preference entirely, they are useful if the application wants to
+ * match its UI to its content or to provide a separate color scheme switcher.
+ *
+ * If a per-[class@Gdk.Display] style manager has its color scheme set to
+ * `ADW_COLOR_SCHEME_DEFAULT`, it will inherit the color scheme from the
+ * default style manager.
+ *
+ * For the default style manager, `ADW_COLOR_SCHEME_DEFAULT` is equivalent to
+ * `ADW_COLOR_SCHEME_LIGHT_DARK`.
+ *
+ * The [property@Adw.StyleManager:system-supports-color-schemes] property can
+ * be used to check if the current environment provides a color scheme
+ * preference.
+ *
+ * Since: 1.0
+ */
+ props[PROP_COLOR_SCHEME] =
+ g_param_spec_enum ("color-scheme",
+ "Color Scheme",
+ "The current color scheme",
+ ADW_TYPE_COLOR_SCHEME,
+ ADW_COLOR_SCHEME_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * AdwStyleManager:system-supports-color-schemes: (attributes
org.gtk.Property.get=adw_style_manager_get_system_supports_color_schemes)
+ *
+ * Whether the system supports color schemes.
+ *
+ * This property can be used to check if the current environment provides a
+ * color scheme preference. For example, applications might want to show a
+ * separate appearance switcher if it's set to `FALSE`.
+ *
+ * It's only set at startup and cannot change its value later.
+ *
+ * See [property@Adw.StyleManager:color-scheme].
+ *
+ * Since: 1.0
+ */
+ props[PROP_SYSTEM_SUPPORTS_COLOR_SCHEMES] =
+ g_param_spec_boolean ("system-supports-color-schemes",
+ "System supports color schemes",
+ "Whether the system supports color schemes",
+ FALSE,
+ G_PARAM_READABLE);
+
+ /**
+ * AdwStyleManager:dark: (attributes org.gtk.Property.get=adw_style_manager_get_dark)
+ *
+ * Whether the application is using dark appearance.
+ *
+ * This property can be used to query the current appearance, as requested via
+ * [property@Adw.StyleManager:color-scheme].
+ *
+ * Since: 1.0
+ */
+ props[PROP_DARK] =
+ g_param_spec_boolean ("dark",
+ "Dark",
+ "Whether the application is using dark appearance",
+ FALSE,
+ G_PARAM_READABLE);
+
+ /**
+ * AdwStyleManager:high-contrast: (attributes org.gtk.Property.get=adw_style_manager_get_high_contrast)
+ *
+ * Whether the application is using high contrast appearance.
+ *
+ * This cannot be overridden by applications.
+ *
+ * Since: 1.0
+ */
+ props[PROP_HIGH_CONTRAST] =
+ g_param_spec_boolean ("high-contrast",
+ "High Contrast",
+ "Whether the application is using high contrast appearance",
+ FALSE,
+ G_PARAM_READABLE);
+
+ g_object_class_install_properties (object_class, LAST_PROP, props);
+}
+
+static void
+adw_style_manager_init (AdwStyleManager *self)
+{
+ self->color_scheme = ADW_COLOR_SCHEME_DEFAULT;
+}
+
+void
+adw_style_manager_ensure (void)
+{
+ GdkDisplayManager *display_manager = gdk_display_manager_get ();
+ g_autoptr (GSList) displays = NULL;
+ GSList *l;
+
+ if (display_style_managers)
+ return;
+
+ default_instance = g_object_new (ADW_TYPE_STYLE_MANAGER, NULL);
+ display_style_managers = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ g_object_unref);
+
+ displays = gdk_display_manager_list_displays (display_manager);
+
+ for (l = displays; l; l = l->next)
+ register_display (display_manager, l->data);
+
+ g_signal_connect (display_manager,
+ "display-opened",
+ G_CALLBACK (register_display),
+ NULL);
+}
+
+/**
+ * adw_style_manager_get_default:
+ *
+ * Gets the default `AdwStyleManager` instance.
+ *
+ * It manages all [class@Gdk.Display] instances unless the style manager for
+ * that display has an override.
+ *
+ * See [func@Adw.StyleManager.get_for_display].
+ *
+ * Returns: (transfer none): the default style manager
+ *
+ * Since: 1.0
+ */
+AdwStyleManager *
+adw_style_manager_get_default (void)
+{
+ if (!default_instance)
+ adw_style_manager_ensure ();
+
+ return default_instance;
+}
+
+/**
+ * adw_style_manager_get_for_display:
+ * @display: a `GdkDisplay`
+ *
+ * Gets the `AdwStyleManager` instance managing @display.
+ *
+ * It can be used to override styles for that specific display instead of the
+ * whole application.
+ *
+ * Most applications should use [func@Adw.StyleManager.get_default] instead.
+ *
+ * Returns: (transfer none): the style manager for @display
+ *
+ * Since: 1.0
+ */
+AdwStyleManager *
+adw_style_manager_get_for_display (GdkDisplay *display)
+{
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+ if (!display_style_managers)
+ adw_style_manager_ensure ();
+
+ g_return_val_if_fail (g_hash_table_contains (display_style_managers, display), NULL);
+
+ return g_hash_table_lookup (display_style_managers, display);
+}
+
+/**
+ * adw_style_manager_get_display: (attributes org.gtk.Method.get_property=display)
+ * @self: a `AdwStyleManager`
+ *
+ * Gets the display the style manager is associated with.
+ *
+ * The display will be `NULL` for the style manager returned by
+ * [func@Adw.StyleManager.get_default].
+ *
+ * Returns: (transfer none): the display
+ *
+ * Since: 1.0
+ */
+GdkDisplay *
+adw_style_manager_get_display (AdwStyleManager *self)
+{
+ g_return_val_if_fail (ADW_IS_STYLE_MANAGER (self), NULL);
+
+ return self->display;
+}
+
+/**
+ * adw_style_manager_get_color_scheme: (attributes org.gtk.Method.get_property=color-scheme)
+ * @self: a `AdwStyleManager`
+ *
+ * Gets the requested application color scheme.
+ *
+ * Returns: the color scheme
+ *
+ * Since: 1.0
+ */
+AdwColorScheme
+adw_style_manager_get_color_scheme (AdwStyleManager *self)
+{
+ g_return_val_if_fail (ADW_IS_STYLE_MANAGER (self), ADW_COLOR_SCHEME_DEFAULT);
+
+ return self->color_scheme;
+}
+
+/**
+ * adw_style_manager_set_color_scheme: (attributes org.gtk.Method.set_property=color-scheme)
+ * @self: a `AdwStyleManager`
+ * @color_scheme: the color scheme
+ *
+ * Sets the requested application color scheme.
+ *
+ * The effective appearance will be decided based on the application color
+ * scheme and the system preferred color scheme. The
+ * [property@Adw.StyleManager:dark] property can be used to query the
+ * current effective appearance.
+ *
+ * Since: 1.0
+ */
+void
+adw_style_manager_set_color_scheme (AdwStyleManager *self,
+ AdwColorScheme color_scheme)
+{
+ g_return_if_fail (ADW_IS_STYLE_MANAGER (self));
+
+ if (color_scheme == self->color_scheme)
+ return;
+
+ self->color_scheme = color_scheme;
+
+ g_object_freeze_notify (G_OBJECT (self));
+
+ update_dark (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_COLOR_SCHEME]);
+
+ g_object_thaw_notify (G_OBJECT (self));
+
+ if (!self->display) {
+ GHashTableIter iter;
+ AdwStyleManager *manager;
+
+ g_hash_table_iter_init (&iter, display_style_managers);
+
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer) &manager))
+ if (manager->color_scheme == ADW_COLOR_SCHEME_DEFAULT)
+ update_dark (manager);
+ }
+}
+
+/**
+ * adw_style_manager_get_system_supports_color_schemes: (attributes
org.gtk.Method.get_property=system-supports-color-schemes)
+ * @self: a `AdwStyleManager`
+ *
+ * Gets whether the system supports color schemes.
+ *
+ * Returns: whether the system supports color schemes
+ *
+ * Since: 1.0
+ */
+gboolean
+adw_style_manager_get_system_supports_color_schemes (AdwStyleManager *self)
+{
+ g_return_val_if_fail (ADW_IS_STYLE_MANAGER (self), FALSE);
+
+ return adw_settings_has_color_scheme (self->settings);
+}
+
+/**
+ * adw_style_manager_get_dark: (attributes org.gtk.Method.get_property=dark)
+ * @self: a `AdwStyleManager`
+ *
+ * Gets whether the application is using dark appearance.
+ *
+ * Returns: whether the application is using dark appearance
+ *
+ * Since: 1.0
+ */
+gboolean
+adw_style_manager_get_dark (AdwStyleManager *self)
+{
+ g_return_val_if_fail (ADW_IS_STYLE_MANAGER (self), FALSE);
+
+ return self->dark;
+}
+
+/**
+ * adw_style_manager_get_high_contrast: (attributes org.gtk.Method.get_property=high-contrast)
+ * @self: a `AdwStyleManager`
+ *
+ * Gets whether the application is using high contrast appearance.
+ *
+ * Returns: whether the application is using high contrast appearance
+ *
+ * Since: 1.0
+ */
+gboolean
+adw_style_manager_get_high_contrast (AdwStyleManager *self)
+{
+ g_return_val_if_fail (ADW_IS_STYLE_MANAGER (self), FALSE);
+
+ return adw_settings_get_high_contrast (self->settings);
+}
diff --git a/src/adw-style-manager.h b/src/adw-style-manager.h
new file mode 100644
index 00000000..2dc86238
--- /dev/null
+++ b/src/adw-style-manager.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 Purism SPC
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * Author: Alexander Mikhaylenko <alexander mikhaylenko puri sm>
+ */
+
+#pragma once
+
+#if !defined(_ADWAITA_INSIDE) && !defined(ADWAITA_COMPILATION)
+#error "Only <adwaita.h> can be included directly."
+#endif
+
+#include "adw-version.h"
+
+#include <gtk/gtk.h>
+#include "adw-enums.h"
+
+G_BEGIN_DECLS
+
+typedef enum {
+ ADW_COLOR_SCHEME_DEFAULT,
+ ADW_COLOR_SCHEME_LIGHT,
+ ADW_COLOR_SCHEME_LIGHT_DARK,
+ ADW_COLOR_SCHEME_DARK_LIGHT,
+ ADW_COLOR_SCHEME_DARK,
+} AdwColorScheme;
+
+#define ADW_TYPE_STYLE_MANAGER (adw_style_manager_get_type())
+
+ADW_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (AdwStyleManager, adw_style_manager, ADW, STYLE_MANAGER, GObject)
+
+ADW_AVAILABLE_IN_ALL
+AdwStyleManager *adw_style_manager_get_default (void);
+ADW_AVAILABLE_IN_ALL
+AdwStyleManager *adw_style_manager_get_for_display (GdkDisplay *display);
+
+ADW_AVAILABLE_IN_ALL
+GdkDisplay *adw_style_manager_get_display (AdwStyleManager *self);
+
+ADW_AVAILABLE_IN_ALL
+AdwColorScheme adw_style_manager_get_color_scheme (AdwStyleManager *self);
+ADW_AVAILABLE_IN_ALL
+void adw_style_manager_set_color_scheme (AdwStyleManager *self,
+ AdwColorScheme color_scheme);
+
+ADW_AVAILABLE_IN_ALL
+gboolean adw_style_manager_get_system_supports_color_schemes (AdwStyleManager *self);
+
+ADW_AVAILABLE_IN_ALL
+gboolean adw_style_manager_get_dark (AdwStyleManager *self);
+ADW_AVAILABLE_IN_ALL
+gboolean adw_style_manager_get_high_contrast (AdwStyleManager *self);
+
+G_END_DECLS
diff --git a/src/adwaita.h b/src/adwaita.h
index 2de16a19..e9fdccee 100644
--- a/src/adwaita.h
+++ b/src/adwaita.h
@@ -51,6 +51,7 @@ G_BEGIN_DECLS
#include "adw-split-button.h"
#include "adw-squeezer.h"
#include "adw-status-page.h"
+#include "adw-style-manager.h"
#include "adw-swipe-tracker.h"
#include "adw-swipeable.h"
#include "adw-tab-bar.h"
diff --git a/src/meson.build b/src/meson.build
index 3b44f905..71e6a5ff 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -15,6 +15,7 @@ adw_public_enum_headers = [
'adw-header-bar.h',
'adw-leaflet.h',
'adw-navigation-direction.h',
+ 'adw-style-manager.h',
'adw-squeezer.h',
'adw-tab-bar.h',
'adw-view-switcher.h',
@@ -99,6 +100,7 @@ src_headers = [
'adw-split-button.h',
'adw-squeezer.h',
'adw-status-page.h',
+ 'adw-style-manager.h',
'adw-swipe-tracker.h',
'adw-swipeable.h',
'adw-tab-bar.h',
@@ -158,6 +160,7 @@ src_sources = [
'adw-shadow-helper.c',
'adw-split-button.c',
'adw-squeezer.c',
+ 'adw-style-manager.c',
'adw-status-page.c',
'adw-swipe-tracker.c',
'adw-swipeable.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]