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




commit 7552f0962f6271185e80a60435756b34dbae1b14
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                        | 142 ++++++
 demo/adw-demo-color-row.h                        |  15 +
 demo/adw-demo-color-row.ui                       |  12 +
 demo/adw-demo-window.c                           |  90 ++++
 demo/adw-demo-window.ui                          |  31 ++
 demo/adwaita-demo.gresources.xml                 |   1 +
 demo/meson.build                                 |   1 +
 src/adw-color-theme.c                            | 534 +++++++++++++++++++++++
 src/adw-color-theme.h                            |  70 +++
 src/adw-macros-private.h                         |  35 ++
 src/adw-style-manager.c                          | 180 +++++++-
 src/adw-style-manager.h                          |  15 +
 src/adwaita.h                                    |   1 +
 src/meson.build                                  |   3 +
 src/stylesheet/_defaults.scss                    |  55 ---
 src/stylesheet/adwaita-stylesheet.gresources.xml |   2 -
 src/stylesheet/defaults-dark.scss                |   3 -
 src/stylesheet/defaults-light.scss               |   3 -
 src/stylesheet/meson.build                       |   3 -
 19 files changed, 1123 insertions(+), 73 deletions(-)
---
diff --git a/demo/adw-demo-color-row.c b/demo/adw-demo-color-row.c
new file mode 100644
index 00000000..09dc3fb8
--- /dev/null
+++ b/demo/adw-demo-color-row.c
@@ -0,0 +1,142 @@
+#include "adw-demo-color-row.h"
+
+struct _AdwDemoColorRow
+{
+  AdwActionRow parent_instance;
+
+  AdwColor color_key;
+  GtkColorButton *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 = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+  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;
+
+  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 (init_color),
+                           self,
+                           G_CONNECT_SWAPPED);
+}
+
+static void
+adw_demo_color_row_class_init (AdwDemoColorRowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_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);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/Adwaita1/Demo/ui/adw-demo-color-row.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, AdwDemoColorRow, color_button);
+  gtk_widget_class_bind_template_callback (widget_class, color_set_cb);
+}
+
+static void
+adw_demo_color_row_init (AdwDemoColorRow *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  self->style_manager = adw_style_manager_get_for_display (gtk_widget_get_display (GTK_WIDGET (self)));
+}
+
+AdwDemoColorRow *
+adw_demo_color_row_new (char     *title,
+                        AdwColor  color_key)
+{
+  return g_object_new (ADW_TYPE_DEMO_COLOR_ROW,
+                       "color-key", color_key,
+                       "title", title,
+                       NULL);
+}
+
diff --git a/demo/adw-demo-color-row.h b/demo/adw-demo-color-row.h
new file mode 100644
index 00000000..6793e771
--- /dev/null
+++ b/demo/adw-demo-color-row.h
@@ -0,0 +1,15 @@
+#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 (char     *title,
+                                         AdwColor  color_key);
+
+G_END_DECLS
+
diff --git a/demo/adw-demo-color-row.ui b/demo/adw-demo-color-row.ui
new file mode 100644
index 00000000..2b18ae9b
--- /dev/null
+++ b/demo/adw-demo-color-row.ui
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="AdwDemoColorRow" parent="AdwActionRow">
+    <property name="activatable-widget">color_button</property>
+    <child type="suffix">
+      <object class="GtkColorButton" id="color_button">
+        <signal name="color-set" handler="color_set_cb" swapped="yes"/>
+        <property name="valign">center</property>
+      </object>>
+    </child>
+  </template>
+</interface>
diff --git a/demo/adw-demo-window.c b/demo/adw-demo-window.c
index 44205045..97f1a749 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"
@@ -29,6 +30,7 @@ struct _AdwDemoWindow
   GtkListBox *avatar_contacts;
   int toast_undo_items;
   AdwToast *undo_toast;
+  GtkListBox *colors_list;
 };
 
 G_DEFINE_TYPE (AdwDemoWindow, adw_demo_window, ADW_TYPE_APPLICATION_WINDOW)
@@ -482,6 +484,78 @@ 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);
+  char *title;
+
+  switch (color) {
+  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_WINDOW_OUTLINE_COLOR:
+    title = _("Window Outline Color");
+    break;
+  case ADW_COLOR_WINDOW_BORDER_COLOR:
+    title = _("Window Border Color");
+    break;
+  case ADW_COLOR_WINDOW_BORDER_BACKDROP_COLOR:
+    title = _("Window Border Backdrop 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;
+  }
+
+  return GTK_WIDGET (adw_demo_color_row_new (title, color));
+}
+
 static void
 adw_demo_window_class_init (AdwDemoWindowClass *klass)
 {
@@ -509,6 +583,7 @@ adw_demo_window_class_init (AdwDemoWindowClass *klass)
   gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, avatar_remove_button);
   gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, avatar_contacts);
   gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, toast_overlay);
+  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);
@@ -558,11 +633,24 @@ avatar_page_init (AdwDemoWindow *self)
   avatar_file_remove_cb (self);
 }
 
+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)
 {
   AdwStyleManager *manager = adw_style_manager_get_default ();
 
+  g_type_ensure (ADW_TYPE_DEMO_COLOR_ROW);
+
   gtk_widget_init_template (GTK_WIDGET (self));
 
   g_signal_connect_object (manager,
@@ -575,6 +663,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 90768e02..1bd93ebd 100644
--- a/demo/adw-demo-window.ui
+++ b/demo/adw-demo-window.ui
@@ -992,6 +992,37 @@
                             </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="AdwPreferencesGroup">
+                                        <child>
+                                          <object class="GtkListBox" id="colors_list">
+                                            <property name="selection-mode">none</property>
+                                            <style>
+                                              <class name="boxed-list"/>
+                                            </style>
+                                          </object>
+                                        </child>
+                                      </object>
+                                    </property>
+                                  </object>
+                                </property>
+                              </object>
+                            </property>
+                          </object>
+                        </child>
                       </object>
                     </child>
                   </object>
diff --git a/demo/adwaita-demo.gresources.xml b/demo/adwaita-demo.gresources.xml
index 524c9f68..4ccc99b7 100644
--- a/demo/adwaita-demo.gresources.xml
+++ b/demo/adwaita-demo.gresources.xml
@@ -41,6 +41,7 @@
     <file compressed="true">style-dark.css</file>
   </gresource>
   <gresource prefix="/org/gnome/Adwaita1/Demo/ui">
+    <file preprocess="xml-stripblanks">adw-demo-color-row.ui</file>
     <file preprocess="xml-stripblanks">adw-demo-preferences-window.ui</file>
     <file preprocess="xml-stripblanks">adw-demo-window.ui</file>
     <file preprocess="xml-stripblanks">adw-flap-demo-window.ui</file>
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.c b/src/adw-color-theme.c
new file mode 100644
index 00000000..50e4fa89
--- /dev/null
+++ b/src/adw-color-theme.c
@@ -0,0 +1,534 @@
+/*
+ * Copyright (C) 2021 Christopher Davis
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * Author: Christopher Davis <christopherdavis gnome org>
+ */
+
+#include "config.h"
+
+#include "adw-color-theme.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 * 0.299) + (g * 0.587) + (b * 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_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 void
+generate_css(AdwColorTheme *self)
+{
+  GHashTableIter iter;
+  const char *name;
+  GdkRGBA *rgba;
+  GString *str = g_string_new ("");
+
+  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);
+  }
+
+  self->color_css = g_string_free (str, FALSE);
+}
+
+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;
+  GdkRGBA scrollbar_outline;
+
+  adw_hsla_from_rgba (bg, &hsla);
+
+  if (hsla.lightness < 50.0f)
+    scrollbar_outline = transparent_black (0.5);
+  else
+    scrollbar_outline = WHITE;
+
+  return scrollbar_outline;
+}
+
+static GdkRGBA
+calculate_accent_fg (GdkRGBA *bg)
+{
+  if (USE_DARK (bg->red, bg->green, bg->blue))
+    return BLACK;
+  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 = self->dark ? transparent_black (0.64) : transparent_black (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, "window_outline_color", self->dark ? white : _GDK_RGBA (0.0, 0.0, 0.0, 0.0));
+  set_color (self, "window_border_color", self->dark ? transparent_black (0.25) : transparent_black (0.77));
+  set_color (self, "window_border_backdrop_color", self->dark ? transparent_black (0.25) : transparent_black 
(0.82));
+  set_color (self, "scrollbar_outline_color", calculate_scrollbar_outline (&color));
+  generate_css (self);
+}
+
+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);
+}
+
+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_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_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_DARK] =
+    g_param_spec_boolean ("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,
+                                        (GDestroyNotify) 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:
+ *
+ * Creates a new `AdwColorTheme`.
+ *
+ * Returns: the new created `AdwColorTheme`
+ *
+ * Since: 1.0
+ */
+AdwColorTheme *
+adw_color_theme_new (gboolean dark)
+{
+  return g_object_new (ADW_TYPE_COLOR_THEME,
+                       "dark", dark,
+                       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_WINDOW_OUTLINE_COLOR:
+  case ADW_COLOR_WINDOW_BORDER_COLOR:
+  case ADW_COLOR_WINDOW_BORDER_BACKDROP_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;
+  }
+
+  generate_css (self);
+
+  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
+ */
+const char *
+adw_color_theme_get_css (AdwColorTheme *self)
+{
+  g_return_val_if_fail (ADW_IS_COLOR_THEME (self), NULL);
+
+  return self->color_css;
+}
diff --git a/src/adw-color-theme.h b/src/adw-color-theme.h
new file mode 100644
index 00000000..8097c488
--- /dev/null
+++ b/src/adw-color-theme.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 Christopher Davis
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * Author: Christopher Davis <christopherdavis gnome org>
+ */
+
+#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_WINDOW_OUTLINE_COLOR,
+  ADW_COLOR_WINDOW_BORDER_COLOR,
+  ADW_COLOR_WINDOW_BORDER_BACKDROP_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 (gboolean dark);
+
+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);
+
+ADW_AVAILABLE_IN_ALL
+const char *adw_color_theme_get_css (AdwColorTheme *self);
+
+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 ff9e7a76..6d9aa2a3 100644
--- a/src/adw-style-manager.c
+++ b/src/adw-style-manager.c
@@ -56,6 +56,8 @@ struct _AdwStyleManager
   AdwSettings *settings;
   GtkCssProvider *provider;
   GtkCssProvider *colors_provider;
+  AdwColorTheme *light_colors;
+  AdwColorTheme *dark_colors;
 
   AdwColorScheme color_scheme;
   gboolean dark;
@@ -72,6 +74,8 @@ enum {
   PROP_SYSTEM_SUPPORTS_COLOR_SCHEMES,
   PROP_DARK,
   PROP_HIGH_CONTRAST,
+  PROP_LIGHT_COLORS,
+  PROP_DARK_COLORS,
   LAST_PROP,
 };
 
@@ -162,12 +166,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) {
@@ -267,7 +272,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);
     }
   }
 
@@ -288,6 +293,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);
@@ -334,6 +349,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);
   }
@@ -356,6 +379,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);
   }
@@ -486,6 +517,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 [class@AdwColorTheme] 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);
+
+  /**
+   * 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 [class@AdwColorTheme] 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_object_class_install_properties (object_class, LAST_PROP, props);
 }
 
@@ -493,6 +552,8 @@ static void
 adw_style_manager_init (AdwStyleManager *self)
 {
   self->color_scheme = ADW_COLOR_SCHEME_DEFAULT;
+  self->light_colors = adw_color_theme_new (FALSE);
+  self->dark_colors = adw_color_theme_new (TRUE);
 }
 
 void
@@ -710,3 +771,108 @@ 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)
+{
+  g_return_if_fail (ADW_IS_STYLE_MANAGER (self));
+  g_return_if_fail (ADW_IS_COLOR_THEME (colors));
+
+  if (self->light_colors == colors)
+    return;
+
+  g_set_object (&self->light_colors, colors);
+  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)
+{
+  g_return_if_fail (ADW_IS_STYLE_MANAGER (self));
+  g_return_if_fail (ADW_IS_COLOR_THEME (colors));
+
+  if (self->dark_colors == colors)
+    return;
+
+  g_set_object (&self->dark_colors, colors);
+  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 c5aa0189..21c9b256 100644
--- a/src/adwaita.h
+++ b/src/adwaita.h
@@ -34,6 +34,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-enum-list-model.h"
diff --git a/src/meson.build b/src/meson.build
index d7329b6d..a40e462d 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -10,6 +10,7 @@ libadwaita_resources = gnome.compile_resources(
 )
 
 adw_public_enum_headers = [
+  'adw-color-theme.h',
   'adw-flap.h',
   'adw-fold-threshold-policy.h',
   'adw-header-bar.h',
@@ -92,6 +93,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-enum-list-model.h',
@@ -152,6 +154,7 @@ src_sources = [
   'adw-clamp.c',
   'adw-clamp-layout.c',
   'adw-clamp-scrollable.c',
+  'adw-color-theme.c',
   'adw-combo-row.c',
   'adw-enum-list-model.c',
   'adw-expander-row.c',
diff --git a/src/stylesheet/adwaita-stylesheet.gresources.xml 
b/src/stylesheet/adwaita-stylesheet.gresources.xml
index de729398..fb29eaf6 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]