[libadwaita/wip/cdavis/recoloring-api] Add AdwColorTheme for recoloring API




commit ffc743189b6e15ab77f6b2e30ef614dc2b5d58b9
Author: Christopher Davis <christopherdavis gnome org>
Date:   Sun Nov 21 15:27:02 2021 -0800

    Add AdwColorTheme for recoloring API
    
    Adds the AdwColorTheme object and an
    API to use it for global recoloring of apps.

 demo/adw-demo-color-row.c                        | 211 +++++++++
 demo/adw-demo-color-row.h                        |  13 +
 demo/adw-demo-window.c                           |  24 +
 demo/adw-demo-window.ui                          |  27 ++
 demo/meson.build                                 |   1 +
 src/adw-color-theme-private.h                    |  24 +
 src/adw-color-theme.c                            | 535 +++++++++++++++++++++++
 src/adw-color-theme.h                            |  64 +++
 src/adw-macros-private.h                         |  35 ++
 src/adw-style-manager.c                          | 219 +++++++++-
 src/adw-style-manager.h                          |  15 +
 src/adwaita.h                                    |   1 +
 src/meson.build                                  |   3 +
 src/stylesheet/_defaults.scss                    |  52 ---
 src/stylesheet/adwaita-stylesheet.gresources.xml |   2 -
 src/stylesheet/defaults-dark.scss                |   3 -
 src/stylesheet/defaults-light.scss               |   3 -
 src/stylesheet/meson.build                       |   3 -
 18 files changed, 1165 insertions(+), 70 deletions(-)
---
diff --git a/demo/adw-demo-color-row.c b/demo/adw-demo-color-row.c
new file mode 100644
index 00000000..969d6ba8
--- /dev/null
+++ b/demo/adw-demo-color-row.c
@@ -0,0 +1,211 @@
+#include <glib/gi18n.h>
+#include "adw-demo-color-row.h"
+
+struct _AdwDemoColorRow
+{
+  AdwActionRow parent_instance;
+
+  AdwColor color_key;
+  GtkWidget *color_button;
+  AdwStyleManager *style_manager;
+};
+
+G_DEFINE_TYPE (AdwDemoColorRow, adw_demo_color_row, ADW_TYPE_ACTION_ROW)
+
+enum {
+  PROP_0,
+  PROP_COLOR_KEY,
+  LAST_PROP,
+};
+
+static GParamSpec *props[LAST_PROP];
+
+static void
+color_set_cb (AdwDemoColorRow *self,
+              GtkColorButton  *color_button)
+{
+  GdkRGBA new_color;
+
+  gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (color_button), &new_color);
+
+  adw_style_manager_set_color_from_rgba (self->style_manager,
+                                         self->color_key,
+                                         &new_color);
+}
+
+static void
+init_color (AdwDemoColorRow *self)
+{
+  AdwColorTheme *theme;
+  const char *title;
+
+  switch (self->color_key) {
+  case ADW_COLOR_ACCENT_BG_COLOR:
+    title = _("Accent Color");
+    break;
+  case ADW_COLOR_DESTRUCTIVE_BG_COLOR:
+    title = _("Destructive Color");
+    break;
+  case ADW_COLOR_SUCCESS_COLOR:
+    title = _("Success Color");
+    break;
+  case ADW_COLOR_WARNING_COLOR:
+    title = _("Warning Color");
+    break;
+  case ADW_COLOR_ERROR_COLOR:
+    title = _("Error Color");
+    break;
+  case ADW_COLOR_WINDOW_BG_COLOR:
+    title = _("Window Background Color");
+    break;
+  case ADW_COLOR_WINDOW_FG_COLOR:
+    title = _("Window Foreground Color");
+    break;
+  case ADW_COLOR_HEADERBAR_BG_COLOR:
+    title = _("Headerbar Background Color");
+    break;
+  case ADW_COLOR_HEADERBAR_FG_COLOR:
+    title = _("Headerbar Foreground Color");
+    break;
+  case ADW_COLOR_HEADERBAR_BORDER_COLOR:
+    title = _("Headerbar Border Color");
+    break;
+  case ADW_COLOR_CARD_BG_COLOR:
+    title = _("Card Background Color");
+    break;
+  case ADW_COLOR_CARD_FG_COLOR:
+    title = _("Card Foreground Color");
+    break;
+  case ADW_COLOR_VIEW_BG_COLOR:
+    title = _("View Background Color");
+    break;
+  case ADW_COLOR_VIEW_FG_COLOR:
+    title = _("View Foreground Color");
+    break;
+  case ADW_COLOR_POPOVER_BG_COLOR:
+    title = _("Popover Background Color");
+    break;
+  case ADW_COLOR_POPOVER_FG_COLOR:
+    title = _("Popover Foreground Color");
+    break;
+  default:
+    g_assert_not_reached ();
+    break;
+  }
+
+  adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self), title);
+
+  if (adw_style_manager_get_dark (self->style_manager))
+    theme = adw_style_manager_get_dark_colors (self->style_manager);
+  else
+    theme = adw_style_manager_get_light_colors (self->style_manager);
+
+  self->color_button = gtk_color_button_new_with_rgba (adw_color_theme_get_color (theme, self->color_key));
+  gtk_widget_set_valign (self->color_button, GTK_ALIGN_CENTER);
+
+  adw_action_row_add_suffix (ADW_ACTION_ROW (self), self->color_button);
+  adw_action_row_set_activatable_widget (ADW_ACTION_ROW (self), self->color_button);
+}
+
+static void
+dark_changed_cb (AdwDemoColorRow *self)
+{
+  AdwColorTheme *theme;
+
+  if (adw_style_manager_get_dark (self->style_manager))
+    theme = adw_style_manager_get_dark_colors (self->style_manager);
+  else
+    theme = adw_style_manager_get_light_colors (self->style_manager);
+
+  gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (self->color_button),
+                              adw_color_theme_get_color (theme, self->color_key));
+}
+
+static void
+adw_demo_color_row_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  AdwDemoColorRow *self = ADW_DEMO_COLOR_ROW (object);
+
+  switch (prop_id) {
+  case PROP_COLOR_KEY:
+    g_value_set_enum (value, self->color_key);
+    break;
+  default:
+    g_assert_not_reached ();
+    break;
+  }
+}
+
+static void
+adw_demo_color_row_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  AdwDemoColorRow *self = ADW_DEMO_COLOR_ROW (object);
+
+  switch (prop_id) {
+  case PROP_COLOR_KEY:
+    self->color_key = g_value_get_enum (value);
+    break;
+  default:
+    g_assert_not_reached ();
+    break;
+  }
+}
+
+static void
+adw_demo_color_row_constructed (GObject *object)
+{
+  AdwDemoColorRow *self = ADW_DEMO_COLOR_ROW (object);
+
+  init_color (self);
+
+  g_signal_connect_object (self->style_manager,
+                           "notify::dark",
+                           G_CALLBACK (dark_changed_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+  g_signal_connect_object (self->color_button,
+                           "color-set",
+                           G_CALLBACK (color_set_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+}
+
+static void
+adw_demo_color_row_class_init (AdwDemoColorRowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->get_property = adw_demo_color_row_get_property;
+  object_class->set_property = adw_demo_color_row_set_property;
+  object_class->constructed = adw_demo_color_row_constructed;
+
+  props[PROP_COLOR_KEY] =
+    g_param_spec_enum ("color-key",
+                       "Color Key",
+                       "The enum value representing the color this row sets",
+                       ADW_TYPE_COLOR,
+                       ADW_COLOR_ACCENT_BG_COLOR,
+                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+  g_object_class_install_properties (object_class, LAST_PROP, props);
+}
+
+static void
+adw_demo_color_row_init (AdwDemoColorRow *self)
+{
+  self->style_manager = adw_style_manager_get_for_display (gtk_widget_get_display (GTK_WIDGET (self)));
+}
+
+AdwDemoColorRow *
+adw_demo_color_row_new (AdwColor  color_key)
+{
+  return g_object_new (ADW_TYPE_DEMO_COLOR_ROW,
+                       "color-key", color_key,
+                       NULL);
+}
diff --git a/demo/adw-demo-color-row.h b/demo/adw-demo-color-row.h
new file mode 100644
index 00000000..b7219cd4
--- /dev/null
+++ b/demo/adw-demo-color-row.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_DEMO_COLOR_ROW (adw_demo_color_row_get_type ())
+
+G_DECLARE_FINAL_TYPE (AdwDemoColorRow, adw_demo_color_row, ADW, DEMO_COLOR_ROW, AdwActionRow)
+
+AdwDemoColorRow *adw_demo_color_row_new (AdwColor  color_key);
+
+G_END_DECLS
diff --git a/demo/adw-demo-window.c b/demo/adw-demo-window.c
index 81324159..3e785462 100644
--- a/demo/adw-demo-window.c
+++ b/demo/adw-demo-window.c
@@ -1,6 +1,7 @@
 #include "adw-demo-window.h"
 
 #include <glib/gi18n.h>
+#include "adw-demo-color-row.h"
 #include "adw-flap-demo-window.h"
 #include "adw-style-demo-window.h"
 #include "adw-tab-view-demo-window.h"
@@ -37,6 +38,7 @@ struct _AdwDemoWindow
   GtkSwitch *timed_animation_alternate;
   GtkSpinButton *timed_animation_duration;
   AdwComboRow *timed_animation_easing;
+  GtkListBox *colors_list;
 };
 
 G_DEFINE_TYPE (AdwDemoWindow, adw_demo_window, ADW_TYPE_APPLICATION_WINDOW)
@@ -703,6 +705,14 @@ toast_dismiss_cb (AdwDemoWindow *self)
     adw_toast_dismiss (self->undo_toast);
 }
 
+static GtkWidget *
+color_row_create_cb (AdwEnumListItem *item)
+{
+  AdwColor color = adw_enum_list_item_get_value (item);
+
+  return GTK_WIDGET (adw_demo_color_row_new (color));
+}
+
 static void
 adw_demo_window_class_init (AdwDemoWindowClass *klass)
 {
@@ -741,6 +751,7 @@ adw_demo_window_class_init (AdwDemoWindowClass *klass)
   gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, timed_animation_alternate);
   gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, timed_animation_duration);
   gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, timed_animation_easing);
+  gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, colors_list);
   gtk_widget_class_bind_template_callback (widget_class, notify_visible_child_cb);
   gtk_widget_class_bind_template_callback (widget_class, back_clicked_cb);
   gtk_widget_class_bind_template_callback (widget_class, leaflet_back_clicked_cb);
@@ -852,6 +863,17 @@ animation_page_init (AdwDemoWindow *self)
   gtk_widget_set_direction (self->timed_animation_button_box, GTK_TEXT_DIR_LTR);
 }
 
+static void
+recoloring_page_init (AdwDemoWindow *self)
+{
+  AdwEnumListModel *model = adw_enum_list_model_new (ADW_TYPE_COLOR);
+
+  gtk_list_box_bind_model (self->colors_list,
+                           G_LIST_MODEL (model),
+                           (GtkListBoxCreateWidgetFunc) color_row_create_cb,
+                           NULL, NULL);
+}
+
 static void
 adw_demo_window_init (AdwDemoWindow *self)
 {
@@ -869,6 +891,8 @@ adw_demo_window_init (AdwDemoWindow *self)
 
   avatar_page_init (self);
 
+  recoloring_page_init (self);
+
   adw_leaflet_set_visible_child (self->content_box, GTK_WIDGET (self->right_box));
 
   gtk_widget_action_set_enabled (GTK_WIDGET (self), "toast.dismiss", FALSE);
diff --git a/demo/adw-demo-window.ui b/demo/adw-demo-window.ui
index b895625c..c8ebad2d 100644
--- a/demo/adw-demo-window.ui
+++ b/demo/adw-demo-window.ui
@@ -1212,6 +1212,33 @@
                             </property>
                           </object>
                         </child>
+                        <child>
+                          <object class="GtkStackPage">
+                            <property name="name">recoloring</property>
+                            <property name="title" translatable="yes">Recoloring</property>
+                            <property name="child">
+                              <object class="AdwStatusPage">
+                                <property name="icon-name">color-select-symbolic</property>
+                                <property name="title" translatable="yes">Recoloring</property>
+                                <property name="description" translatable="yes">Globally change the colors 
of your app.</property>
+                                <property name="child">
+                                  <object class="AdwClamp">
+                                    <property name="maximum-size">400</property>
+                                    <property name="tightening-threshold">300</property>
+                                    <property name="child">
+                                      <object class="GtkListBox" id="colors_list">
+                                        <property name="selection-mode">none</property>
+                                        <style>
+                                          <class name="boxed-list"/>
+                                        </style>
+                                      </object>
+                                    </property>
+                                  </object>
+                                </property>
+                              </object>
+                            </property>
+                          </object>
+                        </child>
                       </object>
                     </child>
                   </object>
diff --git a/demo/meson.build b/demo/meson.build
index 90e07d3a..0ff43ee8 100644
--- a/demo/meson.build
+++ b/demo/meson.build
@@ -12,6 +12,7 @@ adwaita_demo_resources = gnome.compile_resources(
 adwaita_demo_sources = [
   adwaita_demo_resources,
   'adwaita-demo.c',
+  'adw-demo-color-row.c',
   'adw-demo-preferences-window.c',
   'adw-demo-window.c',
   'adw-flap-demo-window.c',
diff --git a/src/adw-color-theme-private.h b/src/adw-color-theme-private.h
new file mode 100644
index 00000000..6949a355
--- /dev/null
+++ b/src/adw-color-theme-private.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 Christopher Davis <christopherdavis gnome org>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#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"
+#include "adw-color-theme.h"
+
+G_BEGIN_DECLS
+
+ADW_AVAILABLE_IN_ALL
+char *adw_color_theme_get_css (AdwColorTheme *self);
+
+G_END_DECLS
diff --git a/src/adw-color-theme.c b/src/adw-color-theme.c
new file mode 100644
index 00000000..0551efa0
--- /dev/null
+++ b/src/adw-color-theme.c
@@ -0,0 +1,535 @@
+/*
+ * Copyright (C) 2021 Christopher Davis <christopherdavis gnome org>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "adw-color-theme-private.h"
+
+#include "adw-macros-private.h"
+#include "adw-settings-private.h"
+#include <math.h>
+#include <gtk/gtk.h>
+
+struct _AdwColorTheme
+{
+  GObject parent_instance;
+
+  GHashTable *colors;
+  gboolean dark;
+  char *color_css;
+};
+
+G_DEFINE_FINAL_TYPE (AdwColorTheme, adw_color_theme, G_TYPE_OBJECT);
+
+#define WHITE GDK_RGBA ("ffffff")
+#define BLACK GDK_RGBA ("000000")
+/*
+ * Adapted from 
https://gitlab.gnome.org/World/design/palette/-/blob/4aaa771584f3084f56502597d823c867500b90ef/src/palette.vala#L202
+ * (C) Zander Brown, Tobias Bernard
+ */
+#define USE_DARK(r, g, b) (((r * 255.0) * 0.299) + ((g * 255.0) * 0.587) + ((b * 255.0) * 0.114)) > 160.0
+
+typedef struct {
+  float hue;
+  float saturation;
+  float lightness;
+  float alpha;
+} AdwHSLA;
+
+enum {
+  SIGNAL_COLORS_CHANGED,
+  SIGNAL_LAST_SIGNAL,
+};
+
+static guint signals[SIGNAL_LAST_SIGNAL];
+
+enum {
+  PROP_0,
+  PROP_IS_DARK,
+  LAST_PROP,
+};
+
+static GParamSpec *props[LAST_PROP];
+
+static void
+adw_hsla_from_rgba (GdkRGBA *rgba,
+                    AdwHSLA *out)
+{
+  float cmin = MIN (MIN (rgba->red, rgba->green), rgba->blue);
+  float cmax = MAX (MAX (rgba->red, rgba->green), rgba->blue);
+  float delta = cmax - cmin;
+
+  if (delta == 0.0f)
+    out->hue = 0.0f;
+  else if (cmax == rgba->red)
+    out->hue = fmodf ((rgba->green - rgba->blue) / delta, 6.0f);
+  else if (cmax == rgba->green)
+    out->hue = (rgba->blue - rgba->red) / delta + 2.0f;
+  else
+    out->hue = (rgba->red - rgba->green) / delta + 4.0f;
+
+  out->hue = roundf (out->hue * 60.0f);
+  if (out->hue < 0.0f)
+    out->hue += 360.0f;
+
+  out->lightness = (cmax + cmin) / 2.0f;
+
+  out->saturation = delta == 0.0f ? 0.0f : delta / (1.0f - fabsf (2.0f * out->lightness - 1.0f));
+
+  out->saturation *= 100.0f;
+  out->lightness *= 100.0f;
+
+  out->alpha = rgba->alpha;
+}
+
+static void
+adw_hsla_to_rgba (AdwHSLA *hsla,
+                  GdkRGBA *out)
+{
+  float hue = hsla->hue;
+  float saturation = hsla->saturation / 100.0f;
+  float lightness = hsla->lightness / 100.0f;
+  float chroma = (1.0f - fabsf (2.0f * lightness - 1.0f)) * saturation;
+  float secondary_component = chroma * (1.0f - fabsf (fmodf (hue / 60.0f, 2.0f) - 1.0f));
+  float match = lightness - chroma / 2.0f;
+
+  out->red = 0.0f;
+  out->green = 0.0f;
+  out->blue = 0.0f;
+
+  if (0.0f <= hue && hue < 60.0f) {
+    out->red = chroma;
+    out->green = secondary_component;
+    out->blue = 0.0f;
+  } else if (60.0f <= hue && hue < 120.0f) {
+    out->red = secondary_component;
+    out->green = chroma;
+    out->blue = 0.0f;
+  } else if (120.0f <= hue && hue < 180.0f) {
+    out->red = 0.0f;
+    out->green = chroma;
+    out->blue = secondary_component;
+  } else if  (180.0f <= hue && hue < 240.0f) {
+    out->red = 0.0f;
+    out->green = secondary_component;
+    out->blue = chroma;
+  } else if (240.0f <= hue && hue < 300.0f) {
+    out->red = secondary_component;
+    out->green = 0.0f;
+    out->blue = chroma;
+  } else if (300.0f <= hue && hue < 360.0f) {
+    out->red = chroma;
+    out->green = 0.0f;
+    out->blue = secondary_component;
+  }
+
+  out->red = roundf ((out->red + match) * 255.0f) / 255.0f;
+  out->green = roundf ((out->green + match) * 255.0f) / 255.0f;
+  out->blue = roundf ((out->blue + match) * 255.0f) / 255.0f;
+  out->alpha = hsla->alpha;
+}
+
+static void
+set_color (AdwColorTheme *self,
+           const char    *color,
+           GdkRGBA       rgba)
+{
+  g_hash_table_replace (self->colors, g_strdup (color), gdk_rgba_copy (&rgba));
+}
+
+static GdkRGBA
+transparent_black (float alpha)
+{
+  return (GdkRGBA) {
+    0.0f,
+    0.0f,
+    0.0f,
+    1.0f - alpha,
+  };
+}
+
+static GdkRGBA
+transparent_white (float alpha)
+{
+  return (GdkRGBA) {
+    1.0f,
+    1.0f,
+    1.0f,
+    1.0f - alpha,
+  };
+}
+
+static GdkRGBA
+calculate_shade (GdkRGBA *bg)
+{
+  float alpha;
+
+  if (USE_DARK (bg->red, bg->green, bg->blue))
+    alpha = 0.93;
+  else
+    alpha = 0.64;
+
+  return transparent_black (alpha);
+}
+
+static GdkRGBA
+calculate_backdrop (GdkRGBA *bg)
+{
+  AdwHSLA hsla;
+  GdkRGBA out;
+
+  adw_hsla_from_rgba (bg, &hsla);
+
+  if (hsla.lightness < 50.0f)
+    hsla.lightness -= 5.0f;
+  else
+    hsla.lightness += 6.0f;
+
+  adw_hsla_to_rgba (&hsla, &out);
+
+  return out;
+}
+
+static GdkRGBA
+calculate_scrollbar_outline (GdkRGBA *bg)
+{
+  AdwHSLA hsla;
+
+  adw_hsla_from_rgba (bg, &hsla);
+
+  if (hsla.lightness < 50.0f)
+    return transparent_black (0.5);
+  else
+    return WHITE;
+}
+
+static GdkRGBA
+calculate_accent_fg (GdkRGBA *bg)
+{
+  if (USE_DARK (bg->red, bg->green, bg->blue))
+    return transparent_black (0.2);
+  else
+    return WHITE;
+}
+
+static GdkRGBA
+hueshift_accent (AdwColorTheme *self,
+                 GdkRGBA       *accent)
+{
+  AdwHSLA hsla;
+  GdkRGBA out;
+
+  adw_hsla_from_rgba (accent, &hsla);
+
+  if (self->dark) {
+    hsla.lightness += 22.0f;
+  } else {
+    hsla.saturation += 1.0f;
+    hsla.lightness -= 7.0f;
+  }
+
+  adw_hsla_to_rgba (&hsla, &out);
+
+  return out;
+}
+
+static void
+adw_color_theme_constructed (GObject *object)
+{
+  AdwColorTheme *self = ADW_COLOR_THEME (object);
+  GdkRGBA black = BLACK;
+  GdkRGBA white = WHITE;
+  GdkRGBA color;
+  GdkRGBA default_shade;
+  GdkRGBA default_fg;
+
+  G_OBJECT_CLASS (adw_color_theme_parent_class)->constructed (object);
+
+  default_shade = transparent_black (self->dark ? 0.64 : 0.93);
+  default_fg = self->dark ? white : transparent_black (0.2);
+
+  color = GDK_RGBA ("3584e4");
+  set_color (self, "accent_bg_color", color);
+  set_color (self, "accent_fg_color", calculate_accent_fg (&color));
+  set_color (self, "accent_color", hueshift_accent (self, &color));
+
+  color = GDK_RGBA ("e01b24");
+  set_color (self, "destructive_bg_color", color);
+  set_color (self, "destructive_fg_color", calculate_accent_fg (&color));
+  set_color (self, "destructive_color", hueshift_accent (self, &color));
+
+  set_color (self, "success_color", GDK_RGBA ("33d17a"));
+  set_color (self, "warning_color", GDK_RGBA ("e5a50a"));
+  set_color (self, "error_color", GDK_RGBA ("e01b24"));
+
+  set_color (self, "view_bg_color", self->dark ? GDK_RGBA ("1e1e1e") : white);
+  set_color (self, "view_fg_color", self->dark ? white : black);
+
+  color = self->dark ? GDK_RGBA ("303030") : GDK_RGBA ("ebebeb");
+  set_color (self, "headerbar_bg_color", color);
+  set_color (self, "headerbar_fg_color", default_fg);
+  set_color (self, "headerbar_border_color", default_fg);
+  set_color (self, "headerbar_backdrop_color", calculate_backdrop (&color));
+  set_color (self, "headerbar_shade_color", default_shade);
+
+  set_color (self, "card_bg_color", self->dark ? transparent_white (0.92) : white);
+  set_color (self, "card_fg_color", default_fg);
+  set_color (self, "card_shade_color", default_shade);
+
+  set_color (self, "popover_bg_color", self->dark ? GDK_RGBA ("383838") : white);
+  set_color (self, "popover_fg_color", default_fg);
+
+  color = self->dark ? GDK_RGBA ("242424") : GDK_RGBA ("fafafa");
+  set_color (self, "window_bg_color", color);
+  set_color (self, "window_fg_color", default_fg);
+  set_color (self, "shade_color", default_shade);
+  set_color (self, "scrollbar_outline_color", calculate_scrollbar_outline (&color));
+}
+
+static void
+adw_color_theme_dispose (GObject *object)
+{
+  AdwColorTheme *self = ADW_COLOR_THEME (object);
+
+  g_clear_pointer (&self->colors, g_hash_table_unref);
+  g_clear_pointer (&self->color_css, g_free);
+
+  G_OBJECT_CLASS (adw_color_theme_parent_class)->dispose (object);
+}
+
+static void
+adw_color_theme_get_property (GObject    *object,
+                              guint       prop_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+  AdwColorTheme *self = ADW_COLOR_THEME (object);
+
+  switch (prop_id) {
+  case PROP_IS_DARK:
+    g_value_set_boolean (value, self->dark);
+    break;
+  default:
+    g_assert_not_reached ();
+    break;
+  }
+}
+
+static void
+adw_color_theme_set_property (GObject      *object,
+                              guint         prop_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+  AdwColorTheme *self = ADW_COLOR_THEME (object);
+
+  switch (prop_id) {
+  case PROP_IS_DARK:
+    self->dark = g_value_get_boolean (value);
+    break;
+  default:
+    g_assert_not_reached ();
+    break;
+  }
+}
+
+static void
+adw_color_theme_class_init (AdwColorThemeClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = adw_color_theme_constructed;
+  object_class->dispose = adw_color_theme_dispose;
+  object_class->get_property = adw_color_theme_get_property;
+  object_class->set_property = adw_color_theme_set_property;
+
+  props[PROP_IS_DARK] =
+    g_param_spec_boolean ("is-dark",
+                          "Dark",
+                          "Whether the color theme is for a dark style or not",
+                          FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+  signals[SIGNAL_COLORS_CHANGED] =
+    g_signal_new ("colors-changed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE,
+                  0);
+
+  g_object_class_install_properties (object_class, LAST_PROP, props);
+}
+
+static void
+adw_color_theme_init (AdwColorTheme *self)
+{
+  self->colors = g_hash_table_new_full (g_str_hash,
+                                        g_str_equal,
+                                        g_free,
+                                        (GDestroyNotify) gdk_rgba_free);
+}
+
+static char *
+color_to_string (AdwColor color)
+{
+  g_autoptr (GEnumClass) klass = g_type_class_ref (ADW_TYPE_COLOR);
+  GEnumValue *val = g_enum_get_value (klass, color);
+  GString *str = g_string_new (val->value_nick);
+
+  g_string_replace (str, "-", "_", 0);
+
+  return g_string_free (str, FALSE);
+}
+
+/**
+ * adw_color_theme_new_light:
+ *
+ * Creates a new light `AdwColorTheme`.
+ *
+ * Returns: the newly created `AdwColorTheme`
+ *
+ * Since: 1.0
+ */
+AdwColorTheme *
+adw_color_theme_new_light (void)
+{
+  return g_object_new (ADW_TYPE_COLOR_THEME,
+                       "is-dark", FALSE,
+                       NULL);
+}
+
+/**
+ * adw_color_theme_new_dark:
+ *
+ * Creates a new dark `AdwColorTheme`.
+ *
+ * Returns: the newly created `AdwColorTheme`
+ *
+ * Since: 1.0
+ */
+AdwColorTheme *
+adw_color_theme_new_dark (void)
+{
+  return g_object_new (ADW_TYPE_COLOR_THEME,
+                       "is-dark", TRUE,
+                       NULL);
+}
+
+/**
+ * adw_color_theme_set_color_from_rgba:
+ * @self: a `AdwColorTheme`
+ * @color: which color to set
+ * @rgba: A [struct@GdkRGBA] color value
+ *
+ * Sets the `color` to `rgba`
+ *
+ * Since: 1.0
+ */
+void
+adw_color_theme_set_color_from_rgba (AdwColorTheme *self,
+                                     AdwColor       color,
+                                     GdkRGBA       *rgba)
+{
+  g_autofree char *color_key = color_to_string (color);
+
+  g_return_if_fail (ADW_IS_COLOR_THEME (self));
+
+  switch (color) {
+  case ADW_COLOR_ACCENT_BG_COLOR:
+    set_color (self, "accent_bg_color", *rgba);
+    set_color (self, "accent_fg_color", calculate_accent_fg (rgba));
+    set_color (self, "accent_color", hueshift_accent (self, rgba));
+    break;
+  case ADW_COLOR_DESTRUCTIVE_BG_COLOR:
+    set_color (self, "destructive_bg_color", *rgba);
+    set_color (self, "destructive_fg_color", calculate_accent_fg (rgba));
+    set_color (self, "destructive_color", hueshift_accent (self, rgba));
+    break;
+  case ADW_COLOR_WINDOW_BG_COLOR:
+    set_color (self, color_key, *rgba);
+    set_color (self, "shade_color", calculate_shade (rgba));
+    set_color (self, "scrollbar_outline_color", calculate_scrollbar_outline (rgba));
+    break;
+  case ADW_COLOR_HEADERBAR_BG_COLOR:
+    set_color (self, color_key, *rgba);
+    set_color (self, "headerbar_shade_color", calculate_shade (rgba));
+    set_color (self, "headerbar_backdrop_color", calculate_backdrop (rgba));
+    break;
+  case ADW_COLOR_CARD_BG_COLOR:
+    set_color (self, color_key, *rgba);
+    set_color (self, "card_shade_color", calculate_shade (rgba));
+    break;
+  case ADW_COLOR_SUCCESS_COLOR:
+  case ADW_COLOR_WARNING_COLOR:
+  case ADW_COLOR_ERROR_COLOR:
+  case ADW_COLOR_WINDOW_FG_COLOR:
+  case ADW_COLOR_VIEW_FG_COLOR:
+  case ADW_COLOR_VIEW_BG_COLOR:
+  case ADW_COLOR_HEADERBAR_FG_COLOR:
+  case ADW_COLOR_HEADERBAR_BORDER_COLOR:
+  case ADW_COLOR_CARD_FG_COLOR:
+  case ADW_COLOR_POPOVER_FG_COLOR:
+  case ADW_COLOR_POPOVER_BG_COLOR:
+    set_color (self, color_key, *rgba);
+    break;
+  default:
+    g_assert_not_reached ();
+    break;
+  }
+
+  g_signal_emit (self, signals[SIGNAL_COLORS_CHANGED], 0);
+}
+
+/**
+ * adw_color_theme_get_color:
+ * @self: a `AdwColorTheme`
+ * @color: which color to get
+ *
+ * Gets the [struct@GdkRGBA] representation of `color`
+ *
+ * Returns: (transfer none): A [struct@GdkRGBA] color value
+ *
+ * Since: 1.0
+ */
+GdkRGBA *
+adw_color_theme_get_color (AdwColorTheme *self,
+                           AdwColor       color)
+{
+  g_return_val_if_fail (ADW_IS_COLOR_THEME (self), NULL);
+
+  return (GdkRGBA *) g_hash_table_lookup (self->colors, color_to_string (color));
+}
+
+/**
+ * adw_color_theme_get_css:
+ * @self: a `AdwColorTheme`
+ *
+ * Gets the css generated by the `AdwColorTheme`
+ *
+ * Returns: (transfer none): the css generated by the `AdwColorTheme`
+ *
+ * Since: 1.0
+ */
+char *
+adw_color_theme_get_css (AdwColorTheme *self)
+{
+  GHashTableIter iter;
+  const char *name;
+  GdkRGBA *rgba;
+  GString *str = g_string_new ("");
+
+  g_return_val_if_fail (ADW_IS_COLOR_THEME (self), NULL);
+
+  g_hash_table_iter_init (&iter, self->colors);
+
+  while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &rgba)) {
+    g_autofree char *rgba_string = gdk_rgba_to_string (rgba);
+    g_string_append_printf (str, "@define-color %s %s;\n", name, rgba_string);
+  }
+
+  return g_string_free (str, FALSE);
+}
diff --git a/src/adw-color-theme.h b/src/adw-color-theme.h
new file mode 100644
index 00000000..ce8fd6cc
--- /dev/null
+++ b/src/adw-color-theme.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 Christopher Davis <christopherdavis gnome org>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#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_ACCENT_BG_COLOR,
+
+  ADW_COLOR_DESTRUCTIVE_BG_COLOR,
+
+  ADW_COLOR_SUCCESS_COLOR,
+  ADW_COLOR_WARNING_COLOR,
+  ADW_COLOR_ERROR_COLOR,
+
+  ADW_COLOR_WINDOW_BG_COLOR,
+  ADW_COLOR_WINDOW_FG_COLOR,
+
+  ADW_COLOR_VIEW_BG_COLOR,
+  ADW_COLOR_VIEW_FG_COLOR,
+
+  ADW_COLOR_HEADERBAR_BG_COLOR,
+  ADW_COLOR_HEADERBAR_FG_COLOR,
+  ADW_COLOR_HEADERBAR_BORDER_COLOR,
+
+  ADW_COLOR_CARD_BG_COLOR,
+  ADW_COLOR_CARD_FG_COLOR,
+
+  ADW_COLOR_POPOVER_BG_COLOR,
+  ADW_COLOR_POPOVER_FG_COLOR,
+} AdwColor;
+
+#define ADW_TYPE_COLOR_THEME (adw_color_theme_get_type ())
+
+ADW_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (AdwColorTheme, adw_color_theme, ADW, COLOR_THEME, GObject)
+
+ADW_AVAILABLE_IN_ALL
+AdwColorTheme *adw_color_theme_new_light (void) G_GNUC_WARN_UNUSED_RESULT;
+ADW_AVAILABLE_IN_ALL
+AdwColorTheme *adw_color_theme_new_dark  (void) G_GNUC_WARN_UNUSED_RESULT;
+
+ADW_AVAILABLE_IN_ALL
+void     adw_color_theme_set_color_from_rgba (AdwColorTheme *self,
+                                              AdwColor       color,
+                                              GdkRGBA       *rgba);
+ADW_AVAILABLE_IN_ALL
+GdkRGBA *adw_color_theme_get_color           (AdwColorTheme *self,
+                                              AdwColor       color);
+
+G_END_DECLS
diff --git a/src/adw-macros-private.h b/src/adw-macros-private.h
index cf436d94..68a729bc 100644
--- a/src/adw-macros-private.h
+++ b/src/adw-macros-private.h
@@ -29,4 +29,39 @@ G_STMT_START { \
               G_OBJECT_TYPE_NAME ((GObject*) (parent))); \
 } G_STMT_END
 
+/*
+ * Copyright (C) 2018 Christian Hergert
+ *
+ * Copied from https://gist.github.com/chergert/acc7f41c4d5a45ba254188bb19764f72
+ */
+# define _GDK_RGBA_DECODE(c) ((unsigned)((c >= 'A' && c <= 'F') ? (c-'A'+10) : (c >= 'a' && c <= 'f') ? 
(c-'a'+10) : (c >= '0' && c <= '9') ? (c-'0') : -1))
+# define _GDK_RGBA_HIGH(c) (_GDK_RGBA_DECODE(c) << 4)
+# define _GDK_RGBA_LOW(c) _GDK_RGBA_DECODE(c)
+# define _GDK_RGBA(r,g,b,a) ((GdkRGBA){(r)/255.,(g)/255.,(b)/255.,(a)/255.})
+# define _GDK_RGBA8(str) \
+  _GDK_RGBA(_GDK_RGBA_HIGH(str[0]) | _GDK_RGBA_LOW(str[1]), \
+            _GDK_RGBA_HIGH(str[2]) | _GDK_RGBA_LOW(str[3]), \
+            _GDK_RGBA_HIGH(str[4]) | _GDK_RGBA_LOW(str[5]), \
+            _GDK_RGBA_HIGH(str[6]) | _GDK_RGBA_LOW(str[7]))
+# define _GDK_RGBA6(str) \
+  _GDK_RGBA(_GDK_RGBA_HIGH(str[0]) | _GDK_RGBA_LOW(str[1]), \
+            _GDK_RGBA_HIGH(str[2]) | _GDK_RGBA_LOW(str[3]), \
+            _GDK_RGBA_HIGH(str[4]) | _GDK_RGBA_LOW(str[5]), \
+            0xFF)
+# define _GDK_RGBA4(str) \
+  _GDK_RGBA(_GDK_RGBA_HIGH(str[0]) | _GDK_RGBA_LOW(str[0]), \
+            _GDK_RGBA_HIGH(str[1]) | _GDK_RGBA_LOW(str[1]), \
+            _GDK_RGBA_HIGH(str[2]) | _GDK_RGBA_LOW(str[2]), \
+            _GDK_RGBA_HIGH(str[3]) | _GDK_RGBA_LOW(str[3]))
+# define _GDK_RGBA3(str) \
+  _GDK_RGBA(_GDK_RGBA_HIGH(str[0]) | _GDK_RGBA_LOW(str[0]), \
+            _GDK_RGBA_HIGH(str[1]) | _GDK_RGBA_LOW(str[1]), \
+            _GDK_RGBA_HIGH(str[2]) | _GDK_RGBA_LOW(str[2]), \
+            0xFF)
+# define GDK_RGBA(str) ((sizeof(str) == 9) ? _GDK_RGBA8(str) : \
+                        (sizeof(str) == 7) ? _GDK_RGBA6(str) : \
+                        (sizeof(str) == 5) ? _GDK_RGBA4(str) : \
+                        (sizeof(str) == 4) ? _GDK_RGBA3(str) : \
+                        ((GdkRGBA){0,0,0,0}))
+
 G_END_DECLS
diff --git a/src/adw-style-manager.c b/src/adw-style-manager.c
index c642d3d4..81f488ad 100644
--- a/src/adw-style-manager.c
+++ b/src/adw-style-manager.c
@@ -8,6 +8,7 @@
 
 #include "config.h"
 
+#include "adw-color-theme-private.h"
 #include "adw-style-manager-private.h"
 
 #include "adw-macros-private.h"
@@ -56,6 +57,8 @@ struct _AdwStyleManager
   AdwSettings *settings;
   GtkCssProvider *provider;
   GtkCssProvider *colors_provider;
+  AdwColorTheme *light_colors;
+  AdwColorTheme *dark_colors;
 
   AdwColorScheme color_scheme;
   gboolean dark;
@@ -73,6 +76,8 @@ enum {
   PROP_SYSTEM_SUPPORTS_COLOR_SCHEMES,
   PROP_DARK,
   PROP_HIGH_CONTRAST,
+  PROP_LIGHT_COLORS,
+  PROP_DARK_COLORS,
   LAST_PROP,
 };
 
@@ -172,12 +177,13 @@ update_stylesheet (AdwStyleManager *self)
   }
 
   if (self->colors_provider) {
-    if (self->dark)
-      gtk_css_provider_load_from_resource (self->colors_provider,
-                                           "/org/gnome/Adwaita/styles/defaults-dark.css");
-    else
-      gtk_css_provider_load_from_resource (self->colors_provider,
-                                           "/org/gnome/Adwaita/styles/defaults-light.css");
+    if (self->dark) {
+      gtk_css_provider_load_from_data (self->colors_provider,
+                                       adw_color_theme_get_css (self->dark_colors), -1);
+    } else {
+      gtk_css_provider_load_from_data (self->colors_provider,
+                                       adw_color_theme_get_css (self->light_colors), -1);
+    }
   }
 
   if (enable_animations) {
@@ -277,7 +283,7 @@ adw_style_manager_constructed (GObject *object)
       self->colors_provider = gtk_css_provider_new ();
       gtk_style_context_add_provider_for_display (self->display,
                                                   GTK_STYLE_PROVIDER (self->colors_provider),
-                                                  GTK_STYLE_PROVIDER_PRIORITY_THEME);
+                                                  GTK_STYLE_PROVIDER_PRIORITY_THEME + 1);
     }
   }
 
@@ -298,6 +304,16 @@ adw_style_manager_constructed (GObject *object)
                            G_CALLBACK (notify_high_contrast_cb),
                            self,
                            G_CONNECT_SWAPPED);
+  g_signal_connect_object (self->light_colors,
+                           "colors-changed",
+                           G_CALLBACK (update_stylesheet),
+                           self,
+                           G_CONNECT_SWAPPED);
+  g_signal_connect_object (self->dark_colors,
+                           "colors-changed",
+                           G_CALLBACK (update_stylesheet),
+                           self,
+                           G_CONNECT_SWAPPED);
 
   update_dark (self);
   update_stylesheet (self);
@@ -344,6 +360,14 @@ adw_style_manager_get_property (GObject    *object,
     g_value_set_boolean (value, adw_style_manager_get_high_contrast (self));
     break;
 
+  case PROP_LIGHT_COLORS:
+    g_value_set_object (value, adw_style_manager_get_light_colors (self));
+    break;
+
+  case PROP_DARK_COLORS:
+    g_value_set_object (value, adw_style_manager_get_dark_colors (self));
+    break;
+
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   }
@@ -366,6 +390,14 @@ adw_style_manager_set_property (GObject      *object,
     adw_style_manager_set_color_scheme (self, g_value_get_enum (value));
     break;
 
+  case PROP_LIGHT_COLORS:
+    adw_style_manager_set_light_colors (self, g_value_get_object (value));
+    break;
+
+  case PROP_DARK_COLORS:
+    adw_style_manager_set_dark_colors (self, g_value_get_object (value));
+    break;
+
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   }
@@ -496,6 +528,34 @@ adw_style_manager_class_init (AdwStyleManagerClass *klass)
                           FALSE,
                           G_PARAM_READABLE);
 
+  /**
+   * AdwStyleManager:light-colors: (attributes org.gtk.Property.get=adw_style_manager_get_light_colors 
org.gtk.Property.set=adw_style_manager_set_light_colors)
+   *
+   * The color theme to use when the app is using the light style preference.
+   *
+   * Since: 1.0
+   */
+  props[PROP_LIGHT_COLORS] =
+    g_param_spec_object ("light-colors",
+                         "Light Colors",
+                         "The color theme to use when the app is using the light style preference",
+                         ADW_TYPE_COLOR_THEME,
+                         G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  /**
+   * AdwStyleManager:dark-colors: (attributes org.gtk.Property.get=adw_style_manager_get_dark_colors 
org.gtk.Property.set=adw_style_manager_set_dark_colors)
+   *
+   * The color theme to use when the app is using the dark style preference.
+   *
+   * Since: 1.0
+   */
+  props[PROP_DARK_COLORS] =
+    g_param_spec_object ("dark-colors",
+                         "Dark Colors",
+                         "The color theme to use when the app is using the dark style preference",
+                         ADW_TYPE_COLOR_THEME,
+                         G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
   g_object_class_install_properties (object_class, LAST_PROP, props);
 }
 
@@ -503,6 +563,8 @@ static void
 adw_style_manager_init (AdwStyleManager *self)
 {
   self->color_scheme = ADW_COLOR_SCHEME_DEFAULT;
+  adw_style_manager_set_light_colors (self, adw_color_theme_new_light ());
+  adw_style_manager_set_dark_colors (self, adw_color_theme_new_dark ());
 }
 
 void
@@ -720,3 +782,146 @@ adw_style_manager_get_high_contrast (AdwStyleManager *self)
 
   return adw_settings_get_high_contrast (self->settings);
 }
+
+/**
+ * adw_style_manager_get_light_colors: (attributes org.gtk.Method.get_property=light-colors)
+ * @self: a `AdwStyleManager`
+ *
+ * Gets the color theme to use when the app is using the light style preference.
+ *
+ * Returns: (transfer none): the color theme to use when the app is using the
+ * light style preference.
+ *
+ * Since: 1.0
+ */
+AdwColorTheme *
+adw_style_manager_get_light_colors (AdwStyleManager *self)
+{
+  g_return_val_if_fail (ADW_IS_STYLE_MANAGER (self), NULL);
+
+  return self->light_colors;
+}
+
+/**
+ * adw_style_manager_set_light_colors: (attributes org.gtk.Method.set_property=light-colors)
+ * @self: a `AdwStyleManager`
+ * @colors: the color theme
+ *
+ * Sets the color theme to use when the app is using the light style preference.
+ *
+ * Since: 1.0
+ */
+void
+adw_style_manager_set_light_colors (AdwStyleManager *self,
+                                    AdwColorTheme   *colors)
+{
+  gboolean is_initializing = TRUE;
+
+  g_return_if_fail (ADW_IS_STYLE_MANAGER (self));
+  g_return_if_fail (ADW_IS_COLOR_THEME (colors));
+
+  if (self->light_colors == colors)
+    return;
+
+  if (self->light_colors) {
+    is_initializing = FALSE;
+    g_signal_handlers_disconnect_by_func (self->light_colors,
+                                          G_CALLBACK (update_stylesheet),
+                                          self);
+  }
+
+  g_set_object (&self->light_colors, colors);
+
+  g_signal_connect_object (self->light_colors,
+                           "colors-changed",
+                           G_CALLBACK (update_stylesheet),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  if (!is_initializing) {
+    update_stylesheet (self);
+    g_object_notify_by_pspec (G_OBJECT (self), props[PROP_LIGHT_COLORS]);
+  }
+}
+
+/**
+ * adw_style_manager_get_dark_colors: (attributes org.gtk.Method.get_property=dark-colors)
+ * @self: a `AdwStyleManager`
+ *
+ * Gets the color theme to use when the app is using the dark style preference.
+ *
+ * Returns: (transfer none): the color theme to use when the app is using the
+ * dark style preference.
+ *
+ * Since: 1.0
+ */
+AdwColorTheme *
+adw_style_manager_get_dark_colors (AdwStyleManager *self)
+{
+  g_return_val_if_fail (ADW_IS_STYLE_MANAGER (self), NULL);
+
+  return self->dark_colors;
+}
+
+/**
+ * adw_style_manager_set_dark_colors: (attributes org.gtk.Method.set_property=dark-colors)
+ * @self: a `AdwStyleManager`
+ * @colors: the color theme
+ *
+ * Sets the color theme to use when the app is using the dark style preference.
+ *
+ * Since: 1.0
+ */
+void
+adw_style_manager_set_dark_colors (AdwStyleManager *self,
+                                   AdwColorTheme   *colors)
+{
+  gboolean is_initializing = TRUE;
+
+  g_return_if_fail (ADW_IS_STYLE_MANAGER (self));
+  g_return_if_fail (ADW_IS_COLOR_THEME (colors));
+
+  if (self->dark_colors == colors)
+    return;
+
+  if (self->dark_colors) {
+    is_initializing = FALSE;
+    g_signal_handlers_disconnect_by_func (self->dark_colors,
+                                          G_CALLBACK (update_stylesheet),
+                                          self);
+  }
+
+  g_set_object (&self->dark_colors, colors);
+
+  g_signal_connect_object (self->dark_colors,
+                           "colors-changed",
+                           G_CALLBACK (update_stylesheet),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  if (!is_initializing) {
+    update_stylesheet (self);
+    g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DARK_COLORS]);
+  }
+}
+
+/**
+ * adw_style_manager_set_color_from_rgba:
+ * @self: a `AdwStyleManager`
+ * @color: which color to set
+ * @rgba: A [struct@GdkRGBA] color value
+ *
+ * Sets the `color` to `rgba` for both light and dark styles.
+ *
+ * Since: 1.0
+ */
+void
+adw_style_manager_set_color_from_rgba (AdwStyleManager *self,
+                                       AdwColor         color,
+                                       GdkRGBA         *rgba)
+{
+  g_return_if_fail (ADW_IS_STYLE_MANAGER (self));
+
+  adw_color_theme_set_color_from_rgba (self->light_colors, color, rgba);
+  adw_color_theme_set_color_from_rgba (self->dark_colors, color, rgba);
+}
diff --git a/src/adw-style-manager.h b/src/adw-style-manager.h
index 62706a00..85abca62 100644
--- a/src/adw-style-manager.h
+++ b/src/adw-style-manager.h
@@ -15,6 +15,7 @@
 #include "adw-version.h"
 
 #include <gtk/gtk.h>
+#include "adw-color-theme.h"
 #include "adw-enums.h"
 
 G_BEGIN_DECLS
@@ -54,4 +55,18 @@ gboolean adw_style_manager_get_dark          (AdwStyleManager *self);
 ADW_AVAILABLE_IN_ALL
 gboolean adw_style_manager_get_high_contrast (AdwStyleManager *self);
 
+ADW_AVAILABLE_IN_ALL
+AdwColorTheme *adw_style_manager_get_light_colors (AdwStyleManager *self);
+ADW_AVAILABLE_IN_ALL
+void           adw_style_manager_set_light_colors (AdwStyleManager *self,
+                                                   AdwColorTheme   *colors);
+ADW_AVAILABLE_IN_ALL
+AdwColorTheme *adw_style_manager_get_dark_colors  (AdwStyleManager *self);
+ADW_AVAILABLE_IN_ALL
+void           adw_style_manager_set_dark_colors  (AdwStyleManager *self,
+                                                   AdwColorTheme   *colors);
+ADW_AVAILABLE_IN_ALL
+void adw_style_manager_set_color_from_rgba (AdwStyleManager *self,
+                                            AdwColor         color,
+                                            GdkRGBA         *rgba);
 G_END_DECLS
diff --git a/src/adwaita.h b/src/adwaita.h
index 62e2e154..43b809cf 100644
--- a/src/adwaita.h
+++ b/src/adwaita.h
@@ -36,6 +36,7 @@ G_BEGIN_DECLS
 #include "adw-clamp.h"
 #include "adw-clamp-layout.h"
 #include "adw-clamp-scrollable.h"
+#include "adw-color-theme.h"
 #include "adw-combo-row.h"
 #include "adw-deprecation-macros.h"
 #include "adw-easing.h"
diff --git a/src/meson.build b/src/meson.build
index 041e4df5..63207b9d 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -11,6 +11,7 @@ libadwaita_resources = gnome.compile_resources(
 
 adw_public_enum_headers = [
   'adw-animation.h',
+  'adw-color-theme.h',
   'adw-flap.h',
   'adw-fold-threshold-policy.h',
   'adw-easing.h',
@@ -95,6 +96,7 @@ src_headers = [
   'adw-clamp.h',
   'adw-clamp-layout.h',
   'adw-clamp-scrollable.h',
+  'adw-color-theme.h',
   'adw-combo-row.h',
   'adw-deprecation-macros.h',
   'adw-easing.h',
@@ -157,6 +159,7 @@ src_sources = [
   'adw-clamp.c',
   'adw-clamp-layout.c',
   'adw-clamp-scrollable.c',
+  'adw-color-theme.c',
   'adw-combo-row.c',
   'adw-easing.c',
   'adw-enum-list-model.c',
diff --git a/src/stylesheet/adwaita-stylesheet.gresources.xml 
b/src/stylesheet/adwaita-stylesheet.gresources.xml
index 4a6d2fa0..504978bc 100644
--- a/src/stylesheet/adwaita-stylesheet.gresources.xml
+++ b/src/stylesheet/adwaita-stylesheet.gresources.xml
@@ -3,8 +3,6 @@
   <gresource prefix="/org/gnome/Adwaita/styles">
     <file>base.css</file>
     <file>base-hc.css</file>
-    <file>defaults-light.css</file>
-    <file>defaults-dark.css</file>
 
     <file>assets/bullet-symbolic.symbolic.png</file>
     <file>assets/bullet 2-symbolic symbolic png</file>
diff --git a/src/stylesheet/meson.build b/src/stylesheet/meson.build
index 2c0fa82c..ee5a0e66 100644
--- a/src/stylesheet/meson.build
+++ b/src/stylesheet/meson.build
@@ -17,7 +17,6 @@ if not fs.exists('base.css')
       '_colors.scss',
       '_common.scss',
       '_compat-colors.scss',
-      '_defaults.scss',
       '_drawing.scss',
       '_functions.scss',
       '_widgets.scss',
@@ -68,8 +67,6 @@ if not fs.exists('base.css')
     scss_files = [
       'base',
       'base-hc',
-      'defaults-light',
-      'defaults-dark',
     ]
 
     foreach scss: scss_files


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