diff --git a/doc/css-variables.md b/doc/css-variables.md index c0d811cb224c2fb9cb1f9aa9ef7bfd0286689a34..6049c150b820cf4e1dec180852f5432e11a4319a 100644 --- a/doc/css-variables.md +++ b/doc/css-variables.md @@ -94,37 +94,180 @@ large surfaces, or on too many items on the same view. The [`.accent`](style-classes.html#colors) style class allows to use it for widgets such as [class@Gtk.Label]. +The background color is available as `--accent-bg-color`, the foreground as +`--accent-fg-color` and the standalone color as `--accent-color`. + The `--accent-color` color is derived from `--accent-bg-color` as detailed above. +The default values of these colors depend on the system preferences, and will +always be one of the following: + - + + + + + - - - + + + + + + + - + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameColor - LightBackground - DarkForeground + Standalone (Light) + Standalone (Dark)
--accent-bg-color
#3584e4Blue
#3584e4
#ffffff
#0461be
#81d0ff
--accent-fg-colorTeal
#2190a4
#ffffff
#007184
#7bdff4
Green
#3a944a
#ffffff
#15772e
#8de698
--accent-color
#0461be
#81d0ffYellow
#c88800
#ffffff
#905300
#ffc057
Orange
#ed5b00
#ffffff
#b62200
#ff9c5b
Red
#e62d42
#ffffff
#c00023
#ff888c
Pink
#d56199
#ffffff
#a2326c
#ffa0d8
Purple
#9141ac
#ffffff
#8939a4
#fba7ff
Slate
#6f8396
#ffffff
#526678
#bbd1e5
+ +Each background color is also available as a variable, as follows: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name + Value
--accent-blue
#3584e4
--accent-teal
#2190a4
--accent-green
#3a944a
--accent-yellow
#c88800
--accent-orange
#ed5b00
--accent-red
#e62d42
--accent-pink
#d56199
--accent-purple
#9141ac
--accent-slate
#6f8396
diff --git a/doc/styles-and-appearance.md b/doc/styles-and-appearance.md index e3881e7b398be71991e081f8357467e314a88ee1..257d152a08e22b3b9590f52ba6b852267458ac16 100644 --- a/doc/styles-and-appearance.md +++ b/doc/styles-and-appearance.md @@ -84,6 +84,54 @@ remains legible in both appearances: * [class@Application] allows loading additional styles for dark appearance via the `style-dark.css` resource. +## Accent Color + +Libadwaita applications follow the system accent color by default. Applications +with custom drawing or styles may need to ensure that they use the actual accent +color instead of harcoding blue: + +* Use [accent color variables](css-variables.html#accent-colors) and the + [`.accent`](style-classes.html#colors) style class in CSS. + +* Use [property@StyleManager:accent-color-rgba] to get the background accent + color programmatically. + +* Use [property@StyleManager:accent-color] and + [func@AccentColor.to_standalone_rgba] to get the standalone accent color + programmatically. + +Applications can override the accent color using CSS, as follows: + +```css +:root { + --accent-bg-color: var(--accent-green); /* Always use the green color */ +} +``` + +Accent can also be overridden for an individual widget. In this case +`--accent-color` must be manually overridden as well: + +```css +my-widget { + --accent-bg-color: var(--accent-purple); /* Always use the purple color */ + --accent-color: oklab(from var(--accent-bg-color) var(--standalone-color-oklab)); +} +``` + +All of the default accent colors use white text as the foreground color. If the +custom accent color is too bright, use a dark foreground color instead: + +```css +:root { + --accent-bg-color: var(--yellow-3); + --accent-fg-color: rgb(0 0 0 / 80%); +} +``` + +::: note + When accent color is overridden, [class@StyleManager] API will still return + the system color. + ## High Contrast The system can provide a high contrast preference. Libadwaita applications diff --git a/src/adw-accent-color-private.h b/src/adw-accent-color-private.h new file mode 100644 index 0000000000000000000000000000000000000000..19a0bb2c5582f0bed07537281827d3355e91357b --- /dev/null +++ b/src/adw-accent-color-private.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2023 Christopher Davis + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#pragma once + +#if !defined(_ADWAITA_INSIDE) && !defined(ADWAITA_COMPILATION) +#error "Only can be included directly." +#endif + +#include "adw-accent-color.h" + +G_BEGIN_DECLS + +AdwAccentColor adw_accent_color_nearest_from_rgba (GdkRGBA *original_color); + +G_END_DECLS diff --git a/src/adw-accent-color.c b/src/adw-accent-color.c new file mode 100644 index 0000000000000000000000000000000000000000..207e22bffbb30dbc593ba844416b7162bffa216b --- /dev/null +++ b/src/adw-accent-color.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2023 Christopher Davis + * Copyright (C) 2024 Alice Mikhaylenko + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "config.h" + +#include "adw-accent-color-private.h" + +#include "adw-color-utils-private.h" + +/** + * AdwAccentColor: + * @ADW_ACCENT_COLOR_BLUE: Use a blue color (`#3584e4`). This is the default value. + * @ADW_ACCENT_COLOR_TEAL: Use a teal color (`#2190a4`). + * @ADW_ACCENT_COLOR_GREEN: Use a green color (`#3a944a`). + * @ADW_ACCENT_COLOR_YELLOW: Use a yellow color (`#c88800`). + * @ADW_ACCENT_COLOR_ORANGE: Use a orange color (`#ed5b00`). + * @ADW_ACCENT_COLOR_RED: Use a red color (`#e62d42`). + * @ADW_ACCENT_COLOR_PINK: Use a pink color (`#d56199`). + * @ADW_ACCENT_COLOR_PURPLE: Use a purple color (`#9141ac`). + * @ADW_ACCENT_COLOR_SLATE: Use a slate color (`#6f8396`). + * + * Describes the available system accent colors. + * + * Since: 1.6 + */ + +/** + * adw_accent_color_to_rgba: + * @self: an accent color + * @rgba: return location for the color + * + * Converts @self to a `GdkRGBA` representing its background color. + * + * The matching foreground color is white. + * + * Since: 1.6 + */ +void +adw_accent_color_to_rgba (AdwAccentColor self, + GdkRGBA *rgba) +{ + const char *hex = NULL; + + g_return_if_fail (self >= ADW_ACCENT_COLOR_BLUE); + g_return_if_fail (self <= ADW_ACCENT_COLOR_SLATE); + g_return_if_fail (rgba != NULL); + + switch (self) { + case ADW_ACCENT_COLOR_BLUE: + hex = "#3584e4"; + break; + case ADW_ACCENT_COLOR_TEAL: + hex = "#2190a4"; + break; + case ADW_ACCENT_COLOR_GREEN: + hex = "#3a944a"; + break; + case ADW_ACCENT_COLOR_YELLOW: + hex = "#c88800"; + break; + case ADW_ACCENT_COLOR_ORANGE: + hex = "#ed5b00"; + break; + case ADW_ACCENT_COLOR_RED: + hex = "#e62d42"; + break; + case ADW_ACCENT_COLOR_PINK: + hex = "#d56199"; + break; + case ADW_ACCENT_COLOR_PURPLE: + hex = "#9141ac"; + break; + case ADW_ACCENT_COLOR_SLATE: + hex = "#6f8396"; + break; + default: + g_assert_not_reached (); + } + + if (rgba) + gdk_rgba_parse (rgba, hex); +} + +/** + * adw_accent_color_to_standalone_rgba: + * @self: an accent color + * @dark: Whether to calculate standalone color for light or dark background + * @rgba: return location for the color + * + * Converts @self to a `GdkRGBA` representing its standalone color. + * + * It will typically be darker for light background, and lighter for dark + * background, ensuring contrast. + * + * Since: 1.6 + */ +void +adw_accent_color_to_standalone_rgba (AdwAccentColor self, + gboolean dark, + GdkRGBA *rgba) +{ + g_return_if_fail (self >= ADW_ACCENT_COLOR_BLUE); + g_return_if_fail (self <= ADW_ACCENT_COLOR_SLATE); + g_return_if_fail (rgba != NULL); + + dark = !!dark; + + adw_accent_color_to_rgba (self, rgba); + adw_rgba_to_standalone (rgba, dark, rgba); +} + +/** + * adw_rgba_to_standalone: + * @rgba: a background color + * @dark: Whether to calculate standalone color for light or dark background + * @standalone_rgba: return location for the standalone color + * + * Adjusts @rgba to be suitable as a standalone color. + * + * It will typically be darker for light background, and lighter for dark + * background, ensuring contrast. + * + * Since: 1.6 + */ +void +adw_rgba_to_standalone (GdkRGBA *rgba, + gboolean dark, + GdkRGBA *standalone_rgba) +{ + float L, a, b; + + g_return_if_fail (rgba != NULL); + g_return_if_fail (standalone_rgba != NULL); + + dark = !!dark; + + adw_rgb_to_oklab (rgba->red, rgba->green, rgba->blue, &L, &a, &b); + + if (dark) + L = MAX (L, 0.85); + else + L = MIN (L, 0.5); + + adw_oklab_to_rgb (L, a, b, + &standalone_rgba->red, + &standalone_rgba->green, + &standalone_rgba->blue); + + standalone_rgba->red = CLAMP (standalone_rgba->red, 0, 1); + standalone_rgba->green = CLAMP (standalone_rgba->green, 0, 1); + standalone_rgba->blue = CLAMP (standalone_rgba->blue, 0, 1); + standalone_rgba->alpha = rgba->alpha; +} + +AdwAccentColor +adw_accent_color_nearest_from_rgba (GdkRGBA *original_color) +{ + float L, c, h; + + g_return_val_if_fail (original_color != NULL, ADW_ACCENT_COLOR_BLUE); + + adw_rgb_to_oklch (original_color->red, + original_color->green, + original_color->blue, + &L, &c, &h); + + if (c < 0.04) + return ADW_ACCENT_COLOR_SLATE; + + if (h > 345) + return ADW_ACCENT_COLOR_PINK; + + if (h > 280) + return ADW_ACCENT_COLOR_PURPLE; + + if (h > 230) + return ADW_ACCENT_COLOR_BLUE; + + if (h > 175) + return ADW_ACCENT_COLOR_TEAL; + + if (h > 130) + return ADW_ACCENT_COLOR_GREEN; + + if (h > 75) + return ADW_ACCENT_COLOR_YELLOW; + + if (h > 35) + return ADW_ACCENT_COLOR_ORANGE; + + if (h > 10) + return ADW_ACCENT_COLOR_RED; + + return ADW_ACCENT_COLOR_PINK; +} diff --git a/src/adw-accent-color.h b/src/adw-accent-color.h new file mode 100644 index 0000000000000000000000000000000000000000..5db09121145d1086afd89d558725b67805713d47 --- /dev/null +++ b/src/adw-accent-color.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2023 Christopher Davis + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#pragma once + +#if !defined(_ADWAITA_INSIDE) && !defined(ADWAITA_COMPILATION) +#error "Only can be included directly." +#endif + +#include "adw-version.h" + +#include + +G_BEGIN_DECLS + +typedef enum { + ADW_ACCENT_COLOR_BLUE, + ADW_ACCENT_COLOR_TEAL, + ADW_ACCENT_COLOR_GREEN, + ADW_ACCENT_COLOR_YELLOW, + ADW_ACCENT_COLOR_ORANGE, + ADW_ACCENT_COLOR_RED, + ADW_ACCENT_COLOR_PINK, + ADW_ACCENT_COLOR_PURPLE, + ADW_ACCENT_COLOR_SLATE, +} AdwAccentColor; + +ADW_AVAILABLE_IN_1_6 +void adw_accent_color_to_rgba (AdwAccentColor self, + GdkRGBA *rgba); + +ADW_AVAILABLE_IN_1_6 +void adw_accent_color_to_standalone_rgba (AdwAccentColor self, + gboolean dark, + GdkRGBA *rgba); + +ADW_AVAILABLE_IN_1_6 +void adw_rgba_to_standalone (GdkRGBA *rgba, + gboolean dark, + GdkRGBA *standalone_rgba); + +G_END_DECLS diff --git a/src/adw-color-utils-private.h b/src/adw-color-utils-private.h new file mode 100644 index 0000000000000000000000000000000000000000..cfe3e211f4c4fbb5b87f1cca2698bf37c36e4b14 --- /dev/null +++ b/src/adw-color-utils-private.h @@ -0,0 +1,52 @@ +/* Color utilities + * + * Copyright (C) 1999 The Free Software Foundation + * + * Authors: Simon Budig (original code) + * Federico Mena-Quintero (cleanup for GTK+) + * Jonathan Blandford (cleanup for GTK+) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#pragma once + +#if !defined(_ADWAITA_INSIDE) && !defined(ADWAITA_COMPILATION) +#error "Only can be included directly." +#endif + +#include "adw-version.h" + +#include + +G_BEGIN_DECLS + +void adw_oklab_to_rgb (float L, float a, float b, + float *red, float *green, float *blue); +void adw_rgb_to_oklab (float red, float green, float blue, + float *L, float *a, float *b); + +void adw_oklch_to_rgb (float L, float c, float h, + float *red, float *green, float *blue); +void adw_rgb_to_oklch (float red, float green, float blue, + float *L, float *c, float *h); + +G_END_DECLS diff --git a/src/adw-color-utils.c b/src/adw-color-utils.c new file mode 100644 index 0000000000000000000000000000000000000000..0d7f3ccba6a6c020f7f5fd9fbad7e12552d1b2c6 --- /dev/null +++ b/src/adw-color-utils.c @@ -0,0 +1,177 @@ +/* Color utilities + * + * Copyright (C) 1999 The Free Software Foundation + * + * Authors: Simon Budig (original code) + * Federico Mena-Quintero (cleanup for GTK+) + * Jonathan Blandford (cleanup for GTK+) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include "config.h" +#include "adw-color-utils-private.h" + +#include + +#define DEG_TO_RAD(x) ((x) * G_PI / 180) +#define RAD_TO_DEG(x) ((x) * 180 / G_PI) + +static inline void +_sincosf (float angle, + float *out_s, + float *out_c) +{ +#ifdef HAVE_SINCOSF + sincosf (angle, out_s, out_c); +#else + *out_s = sinf (angle); + *out_c = cosf (angle); +#endif +} + +static void +oklab_to_oklch (float L, float a, float b, + float *L2, float *C, float *H) +{ + *L2 = L; + *C = hypotf (a, b); + *H = RAD_TO_DEG (atan2 (b, a)); + *H = fmod (*H, 360); + if (*H < 0) + *H += 360; +} + +static void +oklch_to_oklab (float L, float C, float H, + float *L2, float *a, float *b) +{ + *L2 = L; + _sincosf (DEG_TO_RAD (H), b, a); + *a *= C; + *b *= C; +} + +static float +apply_gamma (float v) +{ + if (v > 0.0031308) + return 1.055 * pow (v, 1/2.4) - 0.055; + else + return 12.92 * v; +} + +static float +unapply_gamma (float v) +{ + if (v >= 0.04045) + return pow (((v + 0.055)/(1 + 0.055)), 2.4); + else + return v / 12.92; +} + +static void +oklab_to_linear_srgb (float L, float a, float b, + float *red, float *green, float *blue) +{ + float l = L + 0.3963377774f * a + 0.2158037573f * b; + float m = L - 0.1055613458f * a - 0.0638541728f * b; + float s = L - 0.0894841775f * a - 1.2914855480f * b; + + l = powf (l, 3); + m = powf (m, 3); + s = powf (s, 3); + + *red = +4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s; + *green = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s; + *blue = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s; +} + +static void +linear_srgb_to_oklab (float red, float green, float blue, + float *L, float *a, float *b) +{ + float l = 0.4122214708f * red + 0.5363325363f * green + 0.0514459929f * blue; + float m = 0.2119034982f * red + 0.6806995451f * green + 0.1073969566f * blue; + float s = 0.0883024619f * red + 0.2817188376f * green + 0.6299787005f * blue; + + l = cbrtf (l); + m = cbrtf (m); + s = cbrtf (s); + + *L = 0.2104542553f*l + 0.7936177850f*m - 0.0040720468f*s; + *a = 1.9779984951f*l - 2.4285922050f*m + 0.4505937099f*s; + *b = 0.0259040371f*l + 0.7827717662f*m - 0.8086757660f*s; +} + +static void +rgb_to_linear_srgb (float red, float green, float blue, + float *linear_red, float *linear_green, float *linear_blue) +{ + *linear_red = unapply_gamma (red); + *linear_green = unapply_gamma (green); + *linear_blue = unapply_gamma (blue); +} + +static void +linear_srgb_to_rgb (float linear_red, float linear_green, float linear_blue, + float *red, float *green, float *blue) +{ + *red = apply_gamma (linear_red); + *green = apply_gamma (linear_green); + *blue = apply_gamma (linear_blue); +} + +void +adw_oklab_to_rgb (float L, float a, float b, + float *red, float *green, float *blue) +{ + float linear_red, linear_green, linear_blue; + oklab_to_linear_srgb (L, a, b, &linear_red, &linear_green, &linear_blue); + linear_srgb_to_rgb (linear_red, linear_green, linear_blue, red, green, blue); +} + +void +adw_rgb_to_oklab (float red, float green, float blue, + float *L, float *a, float *b) +{ + float linear_red, linear_green, linear_blue; + rgb_to_linear_srgb (red, green, blue, &linear_red, &linear_green, &linear_blue); + linear_srgb_to_oklab (linear_red, linear_green, linear_blue, L, a, b); +} + +void +adw_oklch_to_rgb (float L, float c, float h, + float *red, float *green, float *blue) +{ + float l, a, b; + oklch_to_oklab (L, c, h, &l, &a, &b); + adw_oklab_to_rgb (l, a, b, red, green, blue); +} + +void +adw_rgb_to_oklch (float red, float green, float blue, + float *L, float *c, float *h) +{ + float l, a, b; + adw_rgb_to_oklab (red, green, blue, &l, &a, &b); + oklab_to_oklch (l, a, b, L, c, h); +} diff --git a/src/adw-inspector-page.c b/src/adw-inspector-page.c index fa28678d219ac96b0012255b675186ffb5f87bef..43b450f1b240a81326907b776511b1a802b11d7f 100644 --- a/src/adw-inspector-page.c +++ b/src/adw-inspector-page.c @@ -12,6 +12,7 @@ #include "adw-inspector-page-private.h" #include +#include "adw-gizmo-private.h" #include "adw-settings-private.h" struct _AdwInspectorPage @@ -23,6 +24,8 @@ struct _AdwInspectorPage AdwSwitchRow *support_color_schemes_row; AdwComboRow *color_scheme_row; AdwSwitchRow *high_contrast_row; + AdwSwitchRow *support_accent_colors_row; + AdwComboRow *accent_color_row; GObject *object; }; @@ -66,6 +69,26 @@ high_contrast_changed_cb (AdwInspectorPage *self) adw_settings_override_high_contrast (self->settings, hc); } +static void +accent_color_changed_cb (AdwInspectorPage *self) +{ + AdwEnumListItem *item = adw_combo_row_get_selected_item (self->accent_color_row); + AdwAccentColor accent_color = adw_enum_list_item_get_value (item); + + adw_settings_override_accent_color (self->settings, accent_color); +} + +static void +support_accent_colors_changed_cb (AdwInspectorPage *self) +{ + gboolean supports = adw_switch_row_get_active (self->support_accent_colors_row); + + adw_settings_override_system_supports_accent_colors (self->settings, supports); + + if (supports) + accent_color_changed_cb (self); +} + static char * get_system_color_scheme_name (AdwEnumListItem *item, gpointer user_data) @@ -83,6 +106,156 @@ get_system_color_scheme_name (AdwEnumListItem *item, return ""; } +static char * +get_accent_color_name (AdwEnumListItem *item, + gpointer user_data) +{ + switch (adw_enum_list_item_get_value (item)) { + case ADW_ACCENT_COLOR_BLUE: + return g_strdup (_("Blue")); + case ADW_ACCENT_COLOR_TEAL: + return g_strdup (_("Teal")); + case ADW_ACCENT_COLOR_GREEN: + return g_strdup (_("Green")); + case ADW_ACCENT_COLOR_YELLOW: + return g_strdup (_("Yellow")); + case ADW_ACCENT_COLOR_ORANGE: + return g_strdup (_("Orange")); + case ADW_ACCENT_COLOR_RED: + return g_strdup (_("Red")); + case ADW_ACCENT_COLOR_PINK: + return g_strdup (_("Pink")); + case ADW_ACCENT_COLOR_PURPLE: + return g_strdup (_("Purple")); + case ADW_ACCENT_COLOR_SLATE: + return g_strdup (_("Slate")); + default: + g_assert_not_reached (); + } +} + +static void +selected_item_changed (AdwComboRow *row, + GParamSpec *pspec, + GtkListItem *item) +{ + GtkWidget *checkmark = g_object_get_data (G_OBJECT (item), "checkmark"); + + if (adw_combo_row_get_selected_item (row) == gtk_list_item_get_item (item)) + gtk_widget_set_opacity (checkmark, 1); + else + gtk_widget_set_opacity (checkmark, 0); +} + +static void +color_snapshot_cb (AdwGizmo *color, + GtkSnapshot *snapshot) +{ + GtkListItem *item = g_object_get_data (G_OBJECT (color), "item"); + AdwEnumListItem *enum_list_item; + AdwAccentColor accent; + GdkRGBA rgba; + int w, h; + + w = gtk_widget_get_width (GTK_WIDGET (color)); + h = gtk_widget_get_height (GTK_WIDGET (color)); + + enum_list_item = ADW_ENUM_LIST_ITEM (gtk_list_item_get_item (item)); + accent = adw_enum_list_item_get_value (enum_list_item); + + adw_accent_color_to_rgba (accent, &rgba); + + gtk_snapshot_append_color (snapshot, &rgba, &GRAPHENE_RECT_INIT (0, 0, w, h)); +} + +static void +accent_color_item_setup_cb (GtkSignalListItemFactory *factory, + GtkListItem *item) +{ + GtkWidget *box, *color, *title, *checkmark; + + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + + color = adw_gizmo_new_with_role ("color", + GTK_ACCESSIBLE_ROLE_PRESENTATION, + NULL, NULL, + color_snapshot_cb, + NULL, NULL, NULL); + gtk_widget_set_valign (color, GTK_ALIGN_CENTER); + gtk_widget_set_overflow (color, GTK_OVERFLOW_HIDDEN); + gtk_box_append (GTK_BOX (box), color); + + title = gtk_label_new (NULL); + gtk_label_set_xalign (GTK_LABEL (title), 0.0); + gtk_label_set_ellipsize (GTK_LABEL (title), PANGO_ELLIPSIZE_END); + gtk_label_set_max_width_chars (GTK_LABEL (title), 20); + gtk_widget_set_valign (title, GTK_ALIGN_CENTER); + gtk_box_append (GTK_BOX (box), title); + + checkmark = g_object_new (GTK_TYPE_IMAGE, + "accessible-role", GTK_ACCESSIBLE_ROLE_PRESENTATION, + "icon-name", "object-select-symbolic", + NULL); + gtk_box_append (GTK_BOX (box), checkmark); + + g_object_set_data (G_OBJECT (item), "box", box); + g_object_set_data (G_OBJECT (item), "color", color); + g_object_set_data (G_OBJECT (item), "title", title); + g_object_set_data (G_OBJECT (item), "checkmark", checkmark); + + g_object_set_data (G_OBJECT (color), "item", item); + + gtk_list_item_set_child (item, box); +} + +static void +accent_color_item_bind_cb (GtkSignalListItemFactory *factory, + GtkListItem *item, + AdwInspectorPage *self) +{ + AdwComboRow *row = self->accent_color_row; + GtkWidget *box, *color, *title, *checkmark; + AdwEnumListItem *enum_list_item; + char *accent_name; + GtkWidget *popup; + + enum_list_item = ADW_ENUM_LIST_ITEM (gtk_list_item_get_item (item)); + accent_name = get_accent_color_name (enum_list_item, NULL); + + box = g_object_get_data (G_OBJECT (item), "box"); + color = g_object_get_data (G_OBJECT (item), "color"); + title = g_object_get_data (G_OBJECT (item), "title"); + checkmark = g_object_get_data (G_OBJECT (item), "checkmark"); + + gtk_label_set_label (GTK_LABEL (title), accent_name); + + gtk_widget_queue_draw (color); + + popup = gtk_widget_get_ancestor (title, GTK_TYPE_POPOVER); + if (popup && gtk_widget_is_ancestor (popup, GTK_WIDGET (row))) { + gtk_box_set_spacing (GTK_BOX (box), 0); + gtk_widget_set_visible (checkmark, TRUE); + g_signal_connect (row, "notify::selected-item", + G_CALLBACK (selected_item_changed), item); + selected_item_changed (row, NULL, item); + } else { + gtk_box_set_spacing (GTK_BOX (box), 6); + gtk_widget_set_visible (checkmark, FALSE); + } + + g_free (accent_name); +} + +static void +accent_color_item_unbind_cb (GtkSignalListItemFactory *factory, + GtkListItem *item, + AdwInspectorPage *self) +{ + AdwComboRow *row = self->accent_color_row; + + g_signal_handlers_disconnect_by_func (row, selected_item_changed, item); +} + static void adw_inspector_page_get_property (GObject *object, guint prop_id, @@ -164,17 +337,26 @@ adw_inspector_page_class_init (AdwInspectorPageClass *klass) gtk_widget_class_bind_template_child (widget_class, AdwInspectorPage, support_color_schemes_row); gtk_widget_class_bind_template_child (widget_class, AdwInspectorPage, color_scheme_row); gtk_widget_class_bind_template_child (widget_class, AdwInspectorPage, high_contrast_row); + gtk_widget_class_bind_template_child (widget_class, AdwInspectorPage, support_accent_colors_row); + gtk_widget_class_bind_template_child (widget_class, AdwInspectorPage, accent_color_row); gtk_widget_class_bind_template_callback (widget_class, get_system_color_scheme_name); + gtk_widget_class_bind_template_callback (widget_class, get_accent_color_name); + gtk_widget_class_bind_template_callback (widget_class, accent_color_item_setup_cb); + gtk_widget_class_bind_template_callback (widget_class, accent_color_item_bind_cb); + gtk_widget_class_bind_template_callback (widget_class, accent_color_item_unbind_cb); gtk_widget_class_bind_template_callback (widget_class, support_color_schemes_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, support_accent_colors_changed_cb); gtk_widget_class_bind_template_callback (widget_class, color_scheme_changed_cb); gtk_widget_class_bind_template_callback (widget_class, high_contrast_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, accent_color_changed_cb); } static void adw_inspector_page_init (AdwInspectorPage *self) { AdwSystemColorScheme color_scheme; + AdwAccentColor accent_color; gboolean supports, hc; self->settings = adw_settings_get_default (); @@ -191,4 +373,10 @@ adw_inspector_page_init (AdwInspectorPage *self) hc = adw_settings_get_high_contrast (self->settings); adw_switch_row_set_active (self->high_contrast_row, hc); + + accent_color = adw_settings_get_accent_color (self->settings); + adw_combo_row_set_selected (self->accent_color_row, accent_color); + + supports = adw_settings_get_system_supports_accent_colors (self->settings); + adw_switch_row_set_active (self->support_accent_colors_row, supports); } diff --git a/src/adw-inspector-page.ui b/src/adw-inspector-page.ui index 5bb93b0238004fc5a0eb201f551c65f754db4f77..19cf2e509b3da757e679c5f68cae3e264bbaefd8 100644 --- a/src/adw-inspector-page.ui +++ b/src/adw-inspector-page.ui @@ -32,6 +32,49 @@ + + + + + Accent Color + + + System Supports Accent Colors + + + + + + Preferred Accent Color + + + + AdwAccentColor + + + + + + + + + + + + + + support_accent_colors_row + + + + + + + + + Accessibility High Contrast diff --git a/src/adw-settings-impl-gsettings.c b/src/adw-settings-impl-gsettings.c index 1a2cee3676c73ac64cd92ed127b84411b210f285..5a3cfe99da4e37fe44b74c8b447e005d79c1f0e7 100644 --- a/src/adw-settings-impl-gsettings.c +++ b/src/adw-settings-impl-gsettings.c @@ -50,6 +50,15 @@ high_contrast_changed_cb (AdwSettingsImplGSettings *self) adw_settings_impl_set_high_contrast (ADW_SETTINGS_IMPL (self), high_contrast); } +static void +accent_color_changed_cb (AdwSettingsImplGSettings *self) +{ + AdwAccentColor accent_color = + g_settings_get_enum (self->interface_settings, "accent-color"); + + adw_settings_impl_set_accent_color (ADW_SETTINGS_IMPL (self), accent_color); +} + static void adw_settings_impl_gsettings_dispose (GObject *object) { @@ -76,12 +85,14 @@ adw_settings_impl_gsettings_init (AdwSettingsImplGSettings *self) AdwSettingsImpl * adw_settings_impl_gsettings_new (gboolean enable_color_scheme, - gboolean enable_high_contrast) + gboolean enable_high_contrast, + gboolean enable_accent_colors) { AdwSettingsImplGSettings *self = g_object_new (ADW_TYPE_SETTINGS_IMPL_GSETTINGS, NULL); GSettingsSchemaSource *source; gboolean found_color_scheme = FALSE; gboolean found_high_contrast = FALSE; + gboolean found_accent_colors = FALSE; /* While we can access gsettings in flatpak, we can't do anything useful with * them as they aren't propagated from the system. */ @@ -90,20 +101,34 @@ adw_settings_impl_gsettings_new (gboolean enable_color_scheme, source = g_settings_schema_source_get_default (); - if (enable_color_scheme && adw_get_disable_portal ()) { + if ((enable_color_scheme || enable_accent_colors) && adw_get_disable_portal ()) { GSettingsSchema *schema = g_settings_schema_source_lookup (source, "org.gnome.desktop.interface", TRUE); - if (schema && g_settings_schema_has_key (schema, "color-scheme")) { - found_color_scheme = TRUE; + if (schema) { self->interface_settings = g_settings_new ("org.gnome.desktop.interface"); - color_scheme_changed_cb (self); + if (g_settings_schema_has_key (schema, "color-scheme")) { + found_color_scheme = TRUE; - g_signal_connect_swapped (self->interface_settings, - "changed::color-scheme", - G_CALLBACK (color_scheme_changed_cb), - self); + color_scheme_changed_cb (self); + + g_signal_connect_swapped (self->interface_settings, + "changed::color-scheme", + G_CALLBACK (color_scheme_changed_cb), + self); + } + + if (g_settings_schema_has_key (schema, "accent-color")) { + found_accent_colors = TRUE; + + accent_color_changed_cb (self); + + g_signal_connect_swapped (self->interface_settings, + "changed::accent-color", + G_CALLBACK (accent_color_changed_cb), + self); + } } g_clear_pointer (&schema, g_settings_schema_unref); @@ -130,7 +155,8 @@ adw_settings_impl_gsettings_new (gboolean enable_color_scheme, adw_settings_impl_set_features (ADW_SETTINGS_IMPL (self), found_color_scheme, - found_high_contrast); + found_high_contrast, + found_accent_colors); return ADW_SETTINGS_IMPL (self); } diff --git a/src/adw-settings-impl-legacy.c b/src/adw-settings-impl-legacy.c index 87519a975690319dfcfab7e0b82aa192c204376d..b7da8dbb85e285448f773189490fe673abd079d7 100644 --- a/src/adw-settings-impl-legacy.c +++ b/src/adw-settings-impl-legacy.c @@ -62,7 +62,8 @@ adw_settings_impl_legacy_init (AdwSettingsImplLegacy *self) AdwSettingsImpl * adw_settings_impl_legacy_new (gboolean enable_color_scheme, - gboolean enable_high_contrast) + gboolean enable_high_contrast, + gboolean enable_accent_colors) { AdwSettingsImplLegacy *self = g_object_new (ADW_TYPE_SETTINGS_IMPL_LEGACY, NULL); GdkDisplay *display; @@ -79,7 +80,8 @@ adw_settings_impl_legacy_new (gboolean enable_color_scheme, is_theme_high_contrast (display)); adw_settings_impl_set_features (ADW_SETTINGS_IMPL (self), /* has_color_scheme */ FALSE, - /* has_high_contrast */ TRUE); + /* has_high_contrast */ TRUE, + /* has_accent_colors */ FALSE); g_signal_connect_swapped (display, "setting-changed", diff --git a/src/adw-settings-impl-macos.c b/src/adw-settings-impl-macos.c index 2d20b486ef3958aaec41c6717d09497d308af73c..50bec95ac3872343ee881186de0e1f89f6dbf47d 100644 --- a/src/adw-settings-impl-macos.c +++ b/src/adw-settings-impl-macos.c @@ -84,7 +84,8 @@ adw_settings_impl_macos_init (AdwSettingsImplMacOS *self) AdwSettingsImpl * adw_settings_impl_macos_new (gboolean enable_color_scheme, - gboolean enable_high_contrast) + gboolean enable_high_contrast, + gboolean enable_accent_colors) { AdwSettingsImplMacOS *self = g_object_new (ADW_TYPE_SETTINGS_IMPL_MACOS, NULL); @@ -106,7 +107,8 @@ adw_settings_impl_macos_new (gboolean enable_color_scheme, adw_settings_impl_set_features (ADW_SETTINGS_IMPL (self), /* has_color_scheme */ TRUE, - /* has_high_contrast */ FALSE); + /* has_high_contrast */ FALSE, + /* has_accent_colors */ FALSE); } return ADW_SETTINGS_IMPL (self); diff --git a/src/adw-settings-impl-portal.c b/src/adw-settings-impl-portal.c index 7f50a79c5dd09fd538292a436d17eedf581a7cbd..6984aa181757f23929604127c10becbd2e63d819 100644 --- a/src/adw-settings-impl-portal.c +++ b/src/adw-settings-impl-portal.c @@ -32,6 +32,8 @@ struct _AdwSettingsImplPortal HIGH_CONTRAST_STATE_FDO, HIGH_CONTRAST_STATE_GNOME, } high_contrast_portal_state; + + gboolean found_accent_colors; }; G_DEFINE_FINAL_TYPE (AdwSettingsImplPortal, adw_settings_impl_portal, ADW_TYPE_SETTINGS_IMPL) @@ -116,6 +118,25 @@ get_fdo_color_scheme (GVariant *variant) return color_scheme; } +static AdwAccentColor +get_fdo_accent_color (GVariant *variant) +{ + double r = -1, g = -1, b = -1; + GdkRGBA rgba; + + g_variant_get (variant, "(ddd)", &r, &g, &b); + + if (r < 0 || g < 0 || b < 0 || r > 1 || g > 1 || b > 1) + return ADW_ACCENT_COLOR_BLUE; + + rgba.red = r; + rgba.green = g; + rgba.blue = b; + rgba.alpha = 1.0; + + return adw_accent_color_nearest_from_rgba (&rgba); +} + static void changed_cb (GDBusProxy *proxy, const char *sender_name, @@ -151,6 +172,15 @@ changed_cb (GDBusProxy *proxy, return; } + + if (!g_strcmp0 (name, "accent-color") && self->found_accent_colors) { + adw_settings_impl_set_accent_color (ADW_SETTINGS_IMPL (self), + get_fdo_accent_color (value)); + + g_variant_unref (value); + + return; + } } if (!g_strcmp0 (namespace, "org.gnome.desktop.a11y.interface") && @@ -188,7 +218,8 @@ adw_settings_impl_portal_init (AdwSettingsImplPortal *self) AdwSettingsImpl * adw_settings_impl_portal_new (gboolean enable_color_scheme, - gboolean enable_high_contrast) + gboolean enable_high_contrast, + gboolean enable_accent_colors) { AdwSettingsImplPortal *self = g_object_new (ADW_TYPE_SETTINGS_IMPL_PORTAL, NULL); GError *error = NULL; @@ -226,7 +257,7 @@ adw_settings_impl_portal_new (gboolean enable_color_scheme, if (enable_high_contrast) { if (read_setting (self, "org.freedesktop.appearance", - "contrast", "u", &variant)) { + "contrast", "u", &variant)) { self->high_contrast_portal_state = HIGH_CONTRAST_STATE_FDO; adw_settings_impl_set_high_contrast (ADW_SETTINGS_IMPL (self), @@ -243,13 +274,28 @@ adw_settings_impl_portal_new (gboolean enable_color_scheme, } } + if (enable_accent_colors && + read_setting (self, "org.freedesktop.appearance", + "accent-color", "(ddd)", &variant)) { + self->found_accent_colors = TRUE; + + adw_settings_impl_set_accent_color (ADW_SETTINGS_IMPL (self), + get_fdo_accent_color (variant)); + + g_variant_unref (variant); + } + adw_settings_impl_set_features (ADW_SETTINGS_IMPL (self), self->found_color_scheme, - self->high_contrast_portal_state != HIGH_CONTRAST_STATE_NONE); + self->high_contrast_portal_state != HIGH_CONTRAST_STATE_NONE, + self->found_accent_colors); - if (self->found_color_scheme || self->high_contrast_portal_state != HIGH_CONTRAST_STATE_NONE) + if (self->found_color_scheme || + self->high_contrast_portal_state != HIGH_CONTRAST_STATE_NONE || + self->found_accent_colors) { g_signal_connect (self->settings_portal, "g-signal", G_CALLBACK (changed_cb), self); + } return ADW_SETTINGS_IMPL (self); } diff --git a/src/adw-settings-impl-private.h b/src/adw-settings-impl-private.h index 54c3f6fb6314bd7c54e6c6961b6bc3acb448c27d..347523d12dd1ed0a1c67a5438e8228d5ce440591 100644 --- a/src/adw-settings-impl-private.h +++ b/src/adw-settings-impl-private.h @@ -28,9 +28,11 @@ struct _AdwSettingsImplClass gboolean adw_settings_impl_get_has_color_scheme (AdwSettingsImpl *self); gboolean adw_settings_impl_get_has_high_contrast (AdwSettingsImpl *self); +gboolean adw_settings_impl_get_has_accent_colors (AdwSettingsImpl *self); void adw_settings_impl_set_features (AdwSettingsImpl *self, gboolean has_color_scheme, - gboolean has_high_contrast); + gboolean has_high_contrast, + gboolean has_accent_colors); AdwSystemColorScheme adw_settings_impl_get_color_scheme (AdwSettingsImpl *self); void adw_settings_impl_set_color_scheme (AdwSettingsImpl *self, @@ -40,6 +42,10 @@ gboolean adw_settings_impl_get_high_contrast (AdwSettingsImpl *self); void adw_settings_impl_set_high_contrast (AdwSettingsImpl *self, gboolean high_contrast); +AdwAccentColor adw_settings_impl_get_accent_color (AdwSettingsImpl *self); +void adw_settings_impl_set_accent_color (AdwSettingsImpl *self, + AdwAccentColor accent_color); + gboolean adw_get_disable_portal (void); #ifdef __APPLE__ @@ -48,21 +54,24 @@ gboolean adw_get_disable_portal (void); G_DECLARE_FINAL_TYPE (AdwSettingsImplMacOS, adw_settings_impl_macos, ADW, SETTINGS_IMPL_MACOS, AdwSettingsImpl) AdwSettingsImpl *adw_settings_impl_macos_new (gboolean enable_color_scheme, - gboolean enable_high_contrast) G_GNUC_WARN_UNUSED_RESULT; + gboolean enable_high_contrast, + gboolean enable_accent_colors) G_GNUC_WARN_UNUSED_RESULT; #elif defined(G_OS_WIN32) #define ADW_TYPE_SETTINGS_IMPL_WIN32 (adw_settings_impl_win32_get_type()) G_DECLARE_FINAL_TYPE (AdwSettingsImplWin32, adw_settings_impl_win32, ADW, SETTINGS_IMPL_WIN32, AdwSettingsImpl) AdwSettingsImpl *adw_settings_impl_win32_new (gboolean enable_color_scheme, - gboolean enable_high_contrast) G_GNUC_WARN_UNUSED_RESULT; + gboolean enable_high_contrast, + gboolean enable_accent_colors) G_GNUC_WARN_UNUSED_RESULT; #else #define ADW_TYPE_SETTINGS_IMPL_PORTAL (adw_settings_impl_portal_get_type()) G_DECLARE_FINAL_TYPE (AdwSettingsImplPortal, adw_settings_impl_portal, ADW, SETTINGS_IMPL_PORTAL, AdwSettingsImpl) AdwSettingsImpl *adw_settings_impl_portal_new (gboolean enable_color_scheme, - gboolean enable_high_contrast) G_GNUC_WARN_UNUSED_RESULT; + gboolean enable_high_contrast, + gboolean enable_accent_colors) G_GNUC_WARN_UNUSED_RESULT; #endif #define ADW_TYPE_SETTINGS_IMPL_GSETTINGS (adw_settings_impl_gsettings_get_type()) @@ -70,13 +79,15 @@ AdwSettingsImpl *adw_settings_impl_portal_new (gboolean enable_color_scheme, G_DECLARE_FINAL_TYPE (AdwSettingsImplGSettings, adw_settings_impl_gsettings, ADW, SETTINGS_IMPL_GSETTINGS, AdwSettingsImpl) AdwSettingsImpl *adw_settings_impl_gsettings_new (gboolean enable_color_scheme, - gboolean enable_high_contrast) G_GNUC_WARN_UNUSED_RESULT; + gboolean enable_high_contrast, + gboolean enable_accent_colors) G_GNUC_WARN_UNUSED_RESULT; #define ADW_TYPE_SETTINGS_IMPL_LEGACY (adw_settings_impl_legacy_get_type()) G_DECLARE_FINAL_TYPE (AdwSettingsImplLegacy, adw_settings_impl_legacy, ADW, SETTINGS_IMPL_LEGACY, AdwSettingsImpl) AdwSettingsImpl *adw_settings_impl_legacy_new (gboolean enable_color_scheme, - gboolean enable_high_contrast) G_GNUC_WARN_UNUSED_RESULT; + gboolean enable_high_contrast, + gboolean enable_accent_colors) G_GNUC_WARN_UNUSED_RESULT; G_END_DECLS diff --git a/src/adw-settings-impl-win32.c b/src/adw-settings-impl-win32.c index 484e3f807055718e8a520d991057b0c5f9808912..f17f496ddd2f6629e386e958d9228ef8f163f6c0 100644 --- a/src/adw-settings-impl-win32.c +++ b/src/adw-settings-impl-win32.c @@ -375,7 +375,8 @@ adw_settings_impl_win32_init (AdwSettingsImplWin32 *self) AdwSettingsImpl * adw_settings_impl_win32_new (gboolean enable_color_scheme, - gboolean enable_high_contrast) + gboolean enable_high_contrast, + gboolean enable_accent_colors) { AdwSettingsImplWin32 *self = g_object_new (ADW_TYPE_SETTINGS_IMPL_WIN32, NULL); GdkDisplay *display = gdk_display_get_default (); @@ -401,7 +402,8 @@ adw_settings_impl_win32_new (gboolean enable_color_scheme, adw_settings_impl_set_features (ADW_SETTINGS_IMPL (self), found_color_scheme, - enable_high_contrast); + enable_high_contrast, + /* has_accent_colors */ FALSE); return ADW_SETTINGS_IMPL (self); } diff --git a/src/adw-settings-impl.c b/src/adw-settings-impl.c index 9bbcffdebeb513f73378da0dc3316ce5915ca5f0..536eca6ac743d8bda7dad12e2b813521d6be93b9 100644 --- a/src/adw-settings-impl.c +++ b/src/adw-settings-impl.c @@ -16,9 +16,11 @@ typedef struct { gboolean has_color_scheme; gboolean has_high_contrast; + gboolean has_accent_colors; AdwSystemColorScheme color_scheme; gboolean high_contrast; + AdwAccentColor accent_color; } AdwSettingsImplPrivate; G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (AdwSettingsImpl, adw_settings_impl, G_TYPE_OBJECT) @@ -27,6 +29,7 @@ enum { SIGNAL_PREPARE, SIGNAL_COLOR_SCHEME_CHANGED, SIGNAL_HIGH_CONTRAST_CHANGED, + SIGNAL_ACCENT_COLOR_CHANGED, SIGNAL_LAST_SIGNAL, }; @@ -62,6 +65,20 @@ adw_settings_impl_class_init (AdwSettingsImplClass *klass) g_signal_set_va_marshaller (signals[SIGNAL_HIGH_CONTRAST_CHANGED], G_TYPE_FROM_CLASS (klass), adw_marshal_VOID__BOOLEANv); + + signals[SIGNAL_ACCENT_COLOR_CHANGED] = + g_signal_new ("accent-color-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + adw_marshal_VOID__ENUM, + G_TYPE_NONE, + 1, + ADW_TYPE_ACCENT_COLOR); + g_signal_set_va_marshaller (signals[SIGNAL_ACCENT_COLOR_CHANGED], + G_TYPE_FROM_CLASS (klass), + adw_marshal_VOID__ENUMv); } static void @@ -89,10 +106,21 @@ adw_settings_impl_get_has_high_contrast (AdwSettingsImpl *self) return priv->has_high_contrast; } +gboolean +adw_settings_impl_get_has_accent_colors (AdwSettingsImpl *self) +{ + AdwSettingsImplPrivate *priv = adw_settings_impl_get_instance_private (self); + + g_return_val_if_fail (ADW_IS_SETTINGS_IMPL (self), FALSE); + + return priv->has_accent_colors; +} + void adw_settings_impl_set_features (AdwSettingsImpl *self, gboolean has_color_scheme, - gboolean has_high_contrast) + gboolean has_high_contrast, + gboolean has_accent_colors) { AdwSettingsImplPrivate *priv = adw_settings_impl_get_instance_private (self); @@ -100,6 +128,7 @@ adw_settings_impl_set_features (AdwSettingsImpl *self, priv->has_color_scheme = !!has_color_scheme; priv->has_high_contrast = !!has_high_contrast; + priv->has_accent_colors = !!has_accent_colors; } AdwSystemColorScheme @@ -158,6 +187,33 @@ adw_settings_impl_set_high_contrast (AdwSettingsImpl *self, g_signal_emit (G_OBJECT (self), signals[SIGNAL_HIGH_CONTRAST_CHANGED], 0, high_contrast); } +AdwAccentColor +adw_settings_impl_get_accent_color (AdwSettingsImpl *self) +{ + AdwSettingsImplPrivate *priv = adw_settings_impl_get_instance_private (self); + + g_return_val_if_fail (ADW_IS_SETTINGS_IMPL (self), ADW_ACCENT_COLOR_BLUE); + + return priv->accent_color; +} + +void +adw_settings_impl_set_accent_color (AdwSettingsImpl *self, + AdwAccentColor accent_color) +{ + AdwSettingsImplPrivate *priv = adw_settings_impl_get_instance_private (self); + + g_return_if_fail (ADW_IS_SETTINGS_IMPL (self)); + + if (priv->accent_color == accent_color) + return; + + priv->accent_color = accent_color; + + if (priv->has_accent_colors) + g_signal_emit (G_OBJECT (self), signals[SIGNAL_ACCENT_COLOR_CHANGED], 0, accent_color); +} + gboolean adw_get_disable_portal (void) { diff --git a/src/adw-settings-private.h b/src/adw-settings-private.h index dc11df58fa181ff0f777682b2ca5cd9f3a929a2f..f4921f4d27a9ae34a32b11798039de8cc2c1c88c 100644 --- a/src/adw-settings-private.h +++ b/src/adw-settings-private.h @@ -13,6 +13,7 @@ #endif #include +#include "adw-accent-color-private.h" #include "adw-enums-private.h" G_BEGIN_DECLS @@ -39,6 +40,12 @@ AdwSystemColorScheme adw_settings_get_color_scheme (AdwSettings *self); ADW_AVAILABLE_IN_ALL gboolean adw_settings_get_high_contrast (AdwSettings *self); +ADW_AVAILABLE_IN_1_6 +gboolean adw_settings_get_system_supports_accent_colors (AdwSettings *self); + +ADW_AVAILABLE_IN_1_6 +AdwAccentColor adw_settings_get_accent_color (AdwSettings *self); + ADW_AVAILABLE_IN_ALL void adw_settings_start_override (AdwSettings *self); ADW_AVAILABLE_IN_ALL @@ -56,4 +63,10 @@ ADW_AVAILABLE_IN_ALL void adw_settings_override_high_contrast (AdwSettings *self, gboolean high_contrast); +void adw_settings_override_system_supports_accent_colors (AdwSettings *self, + gboolean system_supports_accent_colors); + +void adw_settings_override_accent_color (AdwSettings *self, + AdwAccentColor accent_color); + G_END_DECLS diff --git a/src/adw-settings.c b/src/adw-settings.c index cf0e81c0e3ff026d9f17ea0f82c858aab71f5c88..4187f798a34902a125f90883dc120ce61597e16c 100644 --- a/src/adw-settings.c +++ b/src/adw-settings.c @@ -25,11 +25,15 @@ struct _AdwSettings AdwSystemColorScheme color_scheme; gboolean high_contrast; gboolean system_supports_color_schemes; + AdwAccentColor accent_color; + gboolean system_supports_accent_colors; gboolean override; gboolean system_supports_color_schemes_override; AdwSystemColorScheme color_scheme_override; gboolean high_contrast_override; + gboolean system_supports_accent_colors_override; + AdwAccentColor accent_color_override; }; G_DEFINE_FINAL_TYPE (AdwSettings, adw_settings, G_TYPE_OBJECT); @@ -39,6 +43,8 @@ enum { PROP_SYSTEM_SUPPORTS_COLOR_SCHEMES, PROP_COLOR_SCHEME, PROP_HIGH_CONTRAST, + PROP_SYSTEM_SUPPORTS_ACCENT_COLORS, + PROP_ACCENT_COLOR, LAST_PROP, }; @@ -72,10 +78,24 @@ set_high_contrast (AdwSettings *self, g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HIGH_CONTRAST]); } +static void +set_accent_color (AdwSettings *self, + AdwAccentColor accent_color) +{ + if (accent_color == self->accent_color) + return; + + self->accent_color = accent_color; + + if (!self->override) + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACCENT_COLOR]); +} + static void init_debug (AdwSettings *self, gboolean *found_color_scheme, - gboolean *found_high_contrast) + gboolean *found_high_contrast, + gboolean *found_accent_colors) { const char *env = g_getenv ("ADW_DEBUG_HIGH_CONTRAST"); if (env && *env) { @@ -105,13 +125,41 @@ init_debug (AdwSettings *self, g_warning ("Invalid color scheme %s (Expected one of: default, prefer-dark, prefer-light)", env); } } + + env = g_getenv ("ADW_DEBUG_ACCENT_COLOR"); + if (env) { + *found_accent_colors = TRUE; + if (!g_strcmp0 (env, "blue")) { + self->accent_color = ADW_ACCENT_COLOR_BLUE; + } else if (!g_strcmp0 (env, "teal")) { + self->accent_color = ADW_ACCENT_COLOR_TEAL; + } else if (!g_strcmp0 (env, "green")) { + self->accent_color = ADW_ACCENT_COLOR_GREEN; + } else if (!g_strcmp0 (env, "yellow")) { + self->accent_color = ADW_ACCENT_COLOR_YELLOW; + } else if (!g_strcmp0 (env, "orange")) { + self->accent_color = ADW_ACCENT_COLOR_ORANGE; + } else if (!g_strcmp0 (env, "red")) { + self->accent_color = ADW_ACCENT_COLOR_RED; + } else if (!g_strcmp0 (env, "pink")) { + self->accent_color = ADW_ACCENT_COLOR_PINK; + } else if (!g_strcmp0 (env, "purple")) { + self->accent_color = ADW_ACCENT_COLOR_PURPLE; + } else if (!g_strcmp0 (env, "slate")) { + self->accent_color = ADW_ACCENT_COLOR_SLATE; + } else { + g_warning ("Invalid accent color %s (Expected one of: blue, teal, green," + "yellow, orange, red, pink, purple, slate)", env); + } + } } static void register_impl (AdwSettings *self, AdwSettingsImpl *impl, gboolean *found_color_scheme, - gboolean *found_high_contrast) + gboolean *found_high_contrast, + gboolean *found_accent_colors) { if (adw_settings_impl_get_has_color_scheme (impl)) { *found_color_scheme = TRUE; @@ -130,6 +178,15 @@ register_impl (AdwSettings *self, g_signal_connect_swapped (impl, "high-contrast-changed", G_CALLBACK (set_high_contrast), self); } + + if (adw_settings_impl_get_has_accent_colors (impl)) { + *found_accent_colors = TRUE; + + set_accent_color (self, adw_settings_impl_get_accent_color (impl)); + + g_signal_connect_swapped (impl, "accent-color-changed", + G_CALLBACK (set_accent_color), self); + } } static void @@ -138,34 +195,49 @@ adw_settings_constructed (GObject *object) AdwSettings *self = ADW_SETTINGS (object); gboolean found_color_scheme = FALSE; gboolean found_high_contrast = FALSE; + gboolean found_accent_colors = FALSE; G_OBJECT_CLASS (adw_settings_parent_class)->constructed (object); - init_debug (self, &found_color_scheme, &found_high_contrast); + init_debug (self, &found_color_scheme, &found_high_contrast, &found_accent_colors); - if (!found_color_scheme || !found_high_contrast) { + if (!found_color_scheme || !found_high_contrast || !found_accent_colors) { #ifdef __APPLE__ - self->platform_impl = adw_settings_impl_macos_new (!found_color_scheme, !found_high_contrast); + self->platform_impl = adw_settings_impl_macos_new (!found_color_scheme, + !found_high_contrast, + !found_accent_colors); #elif defined(G_OS_WIN32) - self->platform_impl = adw_settings_impl_win32_new (!found_color_scheme, !found_high_contrast); + self->platform_impl = adw_settings_impl_win32_new (!found_color_scheme, + !found_high_contrast, + !found_accent_colors); #else - self->platform_impl = adw_settings_impl_portal_new (!found_color_scheme, !found_high_contrast); + self->platform_impl = adw_settings_impl_portal_new (!found_color_scheme, + !found_high_contrast, + !found_accent_colors); #endif - register_impl (self, self->platform_impl, &found_color_scheme, &found_high_contrast); + register_impl (self, self->platform_impl, &found_color_scheme, + &found_high_contrast, &found_accent_colors); } - if (!found_color_scheme || !found_high_contrast) { - self->gsettings_impl = adw_settings_impl_gsettings_new (!found_color_scheme, !found_high_contrast); - register_impl (self, self->gsettings_impl, &found_color_scheme, &found_high_contrast); + if (!found_color_scheme || !found_high_contrast || !found_accent_colors) { + self->gsettings_impl = adw_settings_impl_gsettings_new (!found_color_scheme, + !found_high_contrast, + !found_accent_colors); + register_impl (self, self->gsettings_impl, &found_color_scheme, + &found_high_contrast, &found_accent_colors); } - if (!found_color_scheme || !found_high_contrast) { - self->legacy_impl = adw_settings_impl_legacy_new (!found_color_scheme, !found_high_contrast); - register_impl (self, self->legacy_impl, &found_color_scheme, &found_high_contrast); + if (!found_color_scheme || !found_high_contrast || !found_accent_colors) { + self->legacy_impl = adw_settings_impl_legacy_new (!found_color_scheme, + !found_high_contrast, + !found_accent_colors); + register_impl (self, self->legacy_impl, &found_color_scheme, + &found_high_contrast, &found_accent_colors); } self->system_supports_color_schemes = found_color_scheme; + self->system_supports_accent_colors = found_accent_colors; } static void @@ -201,6 +273,14 @@ adw_settings_get_property (GObject *object, g_value_set_boolean (value, adw_settings_get_high_contrast (self)); break; + case PROP_SYSTEM_SUPPORTS_ACCENT_COLORS: + g_value_set_boolean (value, adw_settings_get_system_supports_accent_colors (self)); + break; + + case PROP_ACCENT_COLOR: + g_value_set_enum (value, adw_settings_get_accent_color (self)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -231,6 +311,17 @@ adw_settings_class_init (AdwSettingsClass *klass) FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + props[PROP_SYSTEM_SUPPORTS_ACCENT_COLORS] = + g_param_spec_boolean ("system-supports-accent-colors", NULL, NULL, + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + props[PROP_ACCENT_COLOR] = + g_param_spec_enum ("accent-color", NULL, NULL, + ADW_TYPE_ACCENT_COLOR, + ADW_ACCENT_COLOR_BLUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, LAST_PROP, props); } @@ -281,6 +372,28 @@ adw_settings_get_high_contrast (AdwSettings *self) return self->high_contrast; } +gboolean +adw_settings_get_system_supports_accent_colors (AdwSettings *self) +{ + g_return_val_if_fail (ADW_IS_SETTINGS (self), FALSE); + + if (self->override) + return self->system_supports_accent_colors_override; + + return self->system_supports_accent_colors; +} + +AdwAccentColor +adw_settings_get_accent_color (AdwSettings *self) +{ + g_return_val_if_fail (ADW_IS_SETTINGS (self), ADW_ACCENT_COLOR_BLUE); + + if (self->override) + return self->accent_color_override; + + return self->accent_color; +} + void adw_settings_start_override (AdwSettings *self) { @@ -294,12 +407,15 @@ adw_settings_start_override (AdwSettings *self) self->system_supports_color_schemes_override = self->system_supports_color_schemes; self->color_scheme_override = self->color_scheme; self->high_contrast_override = self->high_contrast; + self->system_supports_accent_colors_override = self->system_supports_accent_colors; + self->accent_color_override = self->accent_color; } void adw_settings_end_override (AdwSettings *self) { - gboolean notify_system_supports_color_scheme, notify_color_scheme, notify_hc; + gboolean notify_system_supports_color_scheme, notify_color_scheme, notify_hc, + notify_system_supports_accent_colors, notify_accent_color; g_return_if_fail (ADW_IS_SETTINGS (self)); @@ -309,11 +425,15 @@ adw_settings_end_override (AdwSettings *self) notify_system_supports_color_scheme = self->system_supports_color_schemes_override != self->system_supports_color_schemes; notify_color_scheme = self->color_scheme_override != self->color_scheme; notify_hc = self->high_contrast_override != self->high_contrast; + notify_system_supports_accent_colors = self->system_supports_accent_colors_override != self->system_supports_accent_colors; + notify_accent_color= self->accent_color_override != self->accent_color; self->override = FALSE; self->system_supports_color_schemes_override = FALSE; self->color_scheme_override = ADW_SYSTEM_COLOR_SCHEME_DEFAULT; self->high_contrast_override = FALSE; + self->system_supports_accent_colors_override = FALSE; + self->accent_color_override = ADW_ACCENT_COLOR_BLUE; if (notify_system_supports_color_scheme) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SYSTEM_SUPPORTS_COLOR_SCHEMES]); @@ -321,6 +441,10 @@ adw_settings_end_override (AdwSettings *self) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_COLOR_SCHEME]); if (notify_hc) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HIGH_CONTRAST]); + if (notify_system_supports_accent_colors) + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SYSTEM_SUPPORTS_ACCENT_COLORS]); + if (notify_accent_color) + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACCENT_COLOR]); } void @@ -375,3 +499,39 @@ adw_settings_override_high_contrast (AdwSettings *self, g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HIGH_CONTRAST]); } + +void +adw_settings_override_system_supports_accent_colors (AdwSettings *self, + gboolean system_supports_accent_colors) +{ + g_return_if_fail (ADW_IS_SETTINGS (self)); + g_return_if_fail (self->override); + + system_supports_accent_colors = !!system_supports_accent_colors; + + if (system_supports_accent_colors == self->system_supports_accent_colors_override) + return; + + if (!system_supports_accent_colors) + adw_settings_override_accent_color (self, ADW_ACCENT_COLOR_BLUE); + + self->system_supports_accent_colors_override = system_supports_accent_colors; + + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SYSTEM_SUPPORTS_ACCENT_COLORS]); +} + +void +adw_settings_override_accent_color (AdwSettings *self, + AdwAccentColor accent_color) +{ + g_return_if_fail (ADW_IS_SETTINGS (self)); + g_return_if_fail (self->override); + + if (accent_color == self->accent_color_override || + !self->system_supports_accent_colors_override) + return; + + self->accent_color_override = accent_color; + + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACCENT_COLOR]); +} diff --git a/src/adw-style-manager.c b/src/adw-style-manager.c index cf2c14237c3e333283bad3143ed596fb7959bb92..39b800edae20d0f4c268f4abf65b0f275b95ea7f 100644 --- a/src/adw-style-manager.c +++ b/src/adw-style-manager.c @@ -10,6 +10,7 @@ #include "adw-style-manager-private.h" +#include "adw-accent-color-private.h" #include "adw-main-private.h" #include "adw-settings-private.h" #include @@ -37,11 +38,13 @@ * 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. + * styles, such as whether to use dark style, the system accent color or high + * contrast appearance. * * It allows to set the color scheme via the * [property@StyleManager:color-scheme] property, and to query the current - * appearance, as well as whether a system-wide color scheme preference exists. + * appearance, as well as whether a system-wide color scheme and accent color + * preferences exists. */ struct _AdwStyleManager @@ -52,6 +55,7 @@ struct _AdwStyleManager AdwSettings *settings; GtkCssProvider *provider; GtkCssProvider *colors_provider; + GtkCssProvider *accent_provider; AdwColorScheme color_scheme; gboolean dark; @@ -70,6 +74,9 @@ enum { PROP_SYSTEM_SUPPORTS_COLOR_SCHEMES, PROP_DARK, PROP_HIGH_CONTRAST, + PROP_SYSTEM_SUPPORTS_ACCENT_COLORS, + PROP_ACCENT_COLOR, + PROP_ACCENT_COLOR_RGBA, LAST_PROP, }; @@ -126,6 +133,25 @@ enable_animations_cb (AdwStyleManager *self) self->animation_timeout_id = 0; } +static char* +generate_accent_css (AdwStyleManager *self) +{ + AdwAccentColor accent = adw_style_manager_get_accent_color (self); + GString *str = g_string_new (""); + GdkRGBA rgba; + char *rgba_str; + + adw_accent_color_to_rgba (accent, &rgba); + rgba_str = gdk_rgba_to_string (&rgba); + + g_string_append_printf (str, "@define-color accent_bg_color %s;\n", rgba_str); + g_string_append (str, "@define-color accent_fg_color white;\n"); + + g_free (rgba_str); + + return g_string_free (str, FALSE); +} + static void update_stylesheet (AdwStyleManager *self) { @@ -169,6 +195,12 @@ update_stylesheet (AdwStyleManager *self) "/org/gnome/Adwaita/styles/defaults-light.css"); } + if (self->accent_provider) { + char *accent_css = generate_accent_css (self); + gtk_css_provider_load_from_string (self->accent_provider, accent_css); + g_free (accent_css); + } + self->animation_timeout_id = g_timeout_add_once (SWITCH_DURATION, (GSourceOnceFunc) enable_animations_cb, @@ -219,6 +251,21 @@ notify_system_supports_color_schemes_cb (AdwStyleManager *self) g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SYSTEM_SUPPORTS_COLOR_SCHEMES]); } +static void +notify_accent_color_cb (AdwStyleManager *self) +{ + update_stylesheet (self); + + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACCENT_COLOR]); + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACCENT_COLOR_RGBA]); +} + +static void +notify_system_supports_accent_colors_cb (AdwStyleManager *self) +{ + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SYSTEM_SUPPORTS_ACCENT_COLORS]); +} + static void notify_high_contrast_cb (AdwStyleManager *self) { @@ -265,6 +312,11 @@ adw_style_manager_constructed (GObject *object) gtk_style_context_add_provider_for_display (self->display, GTK_STYLE_PROVIDER (self->colors_provider), GTK_STYLE_PROVIDER_PRIORITY_THEME); + + self->accent_provider = gtk_css_provider_new (); + gtk_style_context_add_provider_for_display (self->display, + GTK_STYLE_PROVIDER (self->accent_provider), + GTK_STYLE_PROVIDER_PRIORITY_THEME); } self->animations_provider = gtk_css_provider_new (); @@ -284,6 +336,16 @@ adw_style_manager_constructed (GObject *object) G_CALLBACK (update_dark), self, G_CONNECT_SWAPPED); + g_signal_connect_object (self->settings, + "notify::system-supports-accent-colors", + G_CALLBACK (notify_system_supports_accent_colors_cb), + self, + G_CONNECT_SWAPPED); + g_signal_connect_object (self->settings, + "notify::accent-color", + G_CALLBACK (notify_accent_color_cb), + self, + G_CONNECT_SWAPPED); g_signal_connect_object (self->settings, "notify::high-contrast", G_CALLBACK (notify_high_contrast_cb), @@ -303,6 +365,7 @@ adw_style_manager_dispose (GObject *object) g_clear_object (&self->provider); g_clear_object (&self->colors_provider); g_clear_object (&self->animations_provider); + g_clear_object (&self->accent_provider); G_OBJECT_CLASS (adw_style_manager_parent_class)->dispose (object); } @@ -336,6 +399,18 @@ adw_style_manager_get_property (GObject *object, g_value_set_boolean (value, adw_style_manager_get_high_contrast (self)); break; + case PROP_SYSTEM_SUPPORTS_ACCENT_COLORS: + g_value_set_boolean (value, adw_style_manager_get_system_supports_accent_colors (self)); + break; + + case PROP_ACCENT_COLOR: + g_value_set_enum (value, adw_style_manager_get_accent_color (self)); + break; + + case PROP_ACCENT_COLOR_RGBA: + g_value_take_boxed (value, adw_style_manager_get_accent_color_rgba (self)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -468,6 +543,56 @@ adw_style_manager_class_init (AdwStyleManagerClass *klass) FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + /** + * AdwStyleManager:system-supports-accent-colors: + * + * Whether the system supports accent colors. + * + * This property can be used to check if the current environment provides an + * accent color preference. For example, applications might want to show a + * preference for choosing accent color if it's set to `FALSE`. + * + * See [property@StyleManager:accent-color]. + * + * Since: 1.6 + */ + props[PROP_SYSTEM_SUPPORTS_ACCENT_COLORS] = + g_param_spec_boolean ("system-supports-accent-colors", NULL, NULL, + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + /** + * AdwStyleManager:accent-color: + * + * The current system accent color. + * + * See also [property@StyleManager:accent-color-rgba]. + * + * Since: 1.6 + */ + props[PROP_ACCENT_COLOR] = + g_param_spec_enum ("accent-color", NULL, NULL, + ADW_TYPE_ACCENT_COLOR, + ADW_ACCENT_COLOR_BLUE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + /** + * AdwStyleManager:accent-color-rgba: + * + * The current system accent color as a `GdkRGBA`. + * + * Equivalent to calling [func@AccentColor.to_rgba] on the value of + * [property@StyleManager:accent-color]. + * + * This is a background color. The matching foreground color is white. + * + * Since: 1.6 + */ + props[PROP_ACCENT_COLOR_RGBA] = + g_param_spec_boxed ("accent-color-rgba", NULL, NULL, + GDK_TYPE_RGBA, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, LAST_PROP, props); } @@ -712,3 +837,75 @@ adw_style_manager_get_high_contrast (AdwStyleManager *self) return adw_settings_get_high_contrast (self->settings); } + +/** + * adw_style_manager_get_system_supports_accent_colors: + * @self: a style manager + * + * Gets whether the system supports accent colors. + * + * This can be used to check if the current environment provides an accent color + * preference. For example, applications might want to show a preference for + * choosing accent color if it's set to `FALSE`. + * + * See [property@StyleManager:accent-color]. + * + * Since: 1.6 + */ +gboolean +adw_style_manager_get_system_supports_accent_colors (AdwStyleManager *self) +{ + g_return_val_if_fail (ADW_IS_STYLE_MANAGER (self), FALSE); + + return adw_settings_get_system_supports_accent_colors (self->settings); +} + +/** + * adw_style_manager_get_accent_color: + * @self: a style manager + * + * Gets the current system accent color. + * + * See also [property@StyleManager:accent-color-rgba]. + * + * Returns: the current system accent color + * + * Since: 1.6 + */ +AdwAccentColor +adw_style_manager_get_accent_color (AdwStyleManager *self) +{ + g_return_val_if_fail (ADW_IS_STYLE_MANAGER (self), ADW_ACCENT_COLOR_BLUE); + + return adw_settings_get_accent_color (self->settings); +} + +/** + * adw_style_manager_get_accent_color_rgba: + * @self: a style manager + * + * Gets the current system accent color as a `GdkRGBA`. + * + * Equivalent to calling [func@AccentColor.to_rgba] on the value of + * [property@StyleManager:accent-color]. + * + * This is a background color. The matching foreground color is white. + * + * Returns: the current system accent color + * + * Since: 1.6 + */ +GdkRGBA * +adw_style_manager_get_accent_color_rgba (AdwStyleManager *self) +{ + AdwAccentColor color; + GdkRGBA rgba; + + g_return_val_if_fail (ADW_IS_STYLE_MANAGER (self), NULL); + + color = adw_style_manager_get_accent_color (self); + + adw_accent_color_to_rgba (color, &rgba); + + return gdk_rgba_copy (&rgba); +} diff --git a/src/adw-style-manager.h b/src/adw-style-manager.h index dce27c2e0df5824ad9a3a2fe6aaa9ddedc8a14a5..b00b6c99a13771db56c764c7c73af69744902456 100644 --- a/src/adw-style-manager.h +++ b/src/adw-style-manager.h @@ -15,6 +15,8 @@ #include "adw-version.h" #include + +#include "adw-accent-color.h" #include "adw-enums.h" G_BEGIN_DECLS @@ -54,4 +56,13 @@ gboolean adw_style_manager_get_dark (AdwStyleManager *self); ADW_AVAILABLE_IN_ALL gboolean adw_style_manager_get_high_contrast (AdwStyleManager *self); +ADW_AVAILABLE_IN_1_6 +gboolean adw_style_manager_get_system_supports_accent_colors (AdwStyleManager *self); + +ADW_AVAILABLE_IN_1_6 +AdwAccentColor adw_style_manager_get_accent_color (AdwStyleManager *self); + +ADW_AVAILABLE_IN_1_6 +GdkRGBA *adw_style_manager_get_accent_color_rgba (AdwStyleManager *self); + G_END_DECLS diff --git a/src/adwaita.h b/src/adwaita.h index 6593b55e87d5883fca8c5d607a9049905eb8134a..bca7880798ad73d5a409273e0c73cea51bf332c5 100644 --- a/src/adwaita.h +++ b/src/adwaita.h @@ -23,6 +23,7 @@ G_BEGIN_DECLS #include "adw-version.h" #include "adw-about-dialog.h" #include "adw-about-window.h" +#include "adw-accent-color.h" #include "adw-action-row.h" #include "adw-alert-dialog.h" #include "adw-animation.h" diff --git a/src/meson.build b/src/meson.build index b1b43f90049567c2e2d054e19f33f1cd8508b2e3..19be77d217d331c752ca1e0715e2eee8220c3c45 100644 --- a/src/meson.build +++ b/src/meson.build @@ -11,6 +11,7 @@ libadwaita_resources = gnome.compile_resources( ) adw_public_enum_headers = [ + 'adw-accent-color.h', 'adw-alert-dialog.h', 'adw-animation.h', 'adw-banner.h', @@ -98,6 +99,7 @@ libadwaita_private_sources += adw_marshalers src_headers = [ 'adw-about-dialog.h', 'adw-about-window.h', + 'adw-accent-color.h', 'adw-action-row.h', 'adw-alert-dialog.h', 'adw-animation.h', @@ -183,6 +185,7 @@ libadwaita_init_public_types = custom_target('adw-public-types.c', src_sources = [ 'adw-about-dialog.c', 'adw-about-window.c', + 'adw-accent-color.c', 'adw-action-row.c', 'adw-alert-dialog.c', 'adw-animation.c', @@ -261,6 +264,8 @@ src_sources = [ libadwaita_private_sources += files([ 'adw-back-button.c', 'adw-bidi.c', + 'adw-bottom-sheet.c', + 'adw-color-utils.c', 'adw-dialog-host.c', 'adw-fading-label.c', 'adw-floating-sheet.c', @@ -390,7 +395,6 @@ endif libadwaita = library( 'adwaita-' + apiversion, libadwaita_sources, - soversion: soversion, c_args: libadwaita_c_args, dependencies: libadwaita_deps, @@ -408,6 +412,28 @@ libadwaita_dep = declare_dependency( include_directories: include_directories('.'), ) +if get_option('tests') + libadwaita_internal = library( + 'adwaita-' + apiversion + '-internal', + libadwaita_sources, + + soversion: soversion, + c_args: libadwaita_c_args, + dependencies: libadwaita_deps, + include_directories: [ root_inc, src_inc ], + install: true, + link_args: libadwaita_link_args, + install_dir: adwaita_libdir, + ) + + libadwaita_internal_dep = declare_dependency( + sources: libadwaita_generated_headers, + dependencies: libadwaita_public_deps, + link_with: libadwaita_internal, + include_directories: include_directories('.'), + ) +endif + meson.override_dependency(package_api_name, libadwaita_dep) if introspection @@ -458,4 +484,3 @@ pkgg.generate( requires: 'gtk4', install_dir: libdir / 'pkgconfig', ) - diff --git a/src/stylesheet/_colors.scss b/src/stylesheet/_colors.scss index 3eea3fef268a07e3e1920557f8d257e974b40d26..b1524a0475bd2900d81668996257a3d0223f8cdf 100644 --- a/src/stylesheet/_colors.scss +++ b/src/stylesheet/_colors.scss @@ -4,6 +4,16 @@ $focus_border_opacity: if($contrast == 'high', 80%, 50%); // Colors from _defaults.scss :root { + --accent-blue: #3584e4; + --accent-teal: #2190a4; + --accent-green: #3a944a; + --accent-yellow: #c88800; + --accent-orange: #ed5b00; + --accent-red: #e62d42; + --accent-pink: #d56199; + --accent-purple: #9141ac; + --accent-slate: #6f8396; + --accent-bg-color: @accent_bg_color; --accent-fg-color: @accent_fg_color; diff --git a/src/stylesheet/_defaults.scss b/src/stylesheet/_defaults.scss index c505894592f49cc175b562ff711161f2cc44768a..b24acf2186590aa6013ed9b01e74c650725db661 100644 --- a/src/stylesheet/_defaults.scss +++ b/src/stylesheet/_defaults.scss @@ -8,10 +8,6 @@ // These are the colors apps are can override. We define the defaults here and // define variables for them in _colors.scss -// The main accent color and the matching text value -@define-color accent_bg_color @blue_3; -@define-color accent_fg_color white; - // destructive-action buttons @define-color destructive_bg_color #{if($variant == 'light', "@red_3", "@red_4")}; @define-color destructive_fg_color white; diff --git a/src/stylesheet/_widgets.scss b/src/stylesheet/_widgets.scss index 471d0a9045fd8744a0dc6fd390a469f9ee8da1cc..9dacdd555e55ae6020938bcca47d2299927934fe 100644 --- a/src/stylesheet/_widgets.scss +++ b/src/stylesheet/_widgets.scss @@ -13,6 +13,7 @@ @import 'widgets/expanders'; @import 'widgets/file-chooser'; @import 'widgets/header-bar'; +@import 'widgets/inspector'; @import 'widgets/labels'; @import 'widgets/level-bar'; @import 'widgets/linked'; diff --git a/src/stylesheet/meson.build b/src/stylesheet/meson.build index f1f09dc4bab0ba7c975304d03e9e4aef2a11dab1..733585108bbb3f76bf3fc24a809d49a22d89da92 100644 --- a/src/stylesheet/meson.build +++ b/src/stylesheet/meson.build @@ -37,6 +37,7 @@ if not fs.exists('base.css') 'widgets/_expanders.scss', 'widgets/_file-chooser.scss', 'widgets/_header-bar.scss', + 'widgets/_inspector.scss', 'widgets/_labels.scss', 'widgets/_level-bar.scss', 'widgets/_linked.scss', diff --git a/src/stylesheet/widgets/_inspector.scss b/src/stylesheet/widgets/_inspector.scss new file mode 100644 index 0000000000000000000000000000000000000000..b9f00cbcbd1005a5f0de3e33066c60df3a37a94e --- /dev/null +++ b/src/stylesheet/widgets/_inspector.scss @@ -0,0 +1,9 @@ +.accent-color-row color { + min-width: 16px; + min-height: 16px; + border-radius: 16px; +} + +.accent-color-row color:disabled { + opacity: var(--disabled-opacity); +} diff --git a/tests/meson.build b/tests/meson.build index 933a33b34b953df1a56724dd52cb809e86debed1..6e8d5581ffcbb9e5d214dd2e70db98bc982d17de 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -34,6 +34,7 @@ endif test_names = [ 'test-about-dialog', 'test-about-window', + 'test-accent-color', 'test-action-row', 'test-alert-dialog', 'test-animation', @@ -99,7 +100,7 @@ foreach test_name : test_names t = executable(test_name, test_sources, c_args: test_cflags, link_args: test_link_args, - dependencies: libadwaita_deps + [libadwaita_dep], + dependencies: libadwaita_deps + [libadwaita_internal_dep], pie: use_pie, ) test(test_name, t, env: test_env) diff --git a/tests/test-accent-color.c b/tests/test-accent-color.c new file mode 100644 index 0000000000000000000000000000000000000000..9625735ff757a5d07e196bf2a8ebce4eb171adef --- /dev/null +++ b/tests/test-accent-color.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2024 Alice Mikhaylenko + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include + +#include "adw-accent-color-private.h" + +#include + +static inline int +rgba_to_hex (GdkRGBA *rgba) +{ + return (int) (round (rgba->red * 0xff)) << 16 | + (int) (round (rgba->green * 0xff)) << 8 | + (int) (round (rgba->blue * 0xff)); +} + +static inline void +hex_to_rgba (int hex, + GdkRGBA *rgba) +{ + rgba->red = (float) ((hex >> 16) & 0xff) / 0xff; + rgba->green = (float) ((hex >> 8) & 0xff) / 0xff; + rgba->blue = (float) ((hex) & 0xff) / 0xff; + rgba->alpha = 1; +} + +#define TEST_NEAREST_ACCENT(rgba_str, expected) \ + gdk_rgba_parse (&rgba, rgba_str); \ + g_assert_cmpint (expected, ==, adw_accent_color_nearest_from_rgba (&rgba)); + +#define TEST_ACCENT_TO_RGBA(accent, expected) \ + adw_accent_color_to_rgba (accent, &rgba); \ + hex = rgba_to_hex (&rgba); \ + g_assert_cmphex (expected, ==, hex); + +#define TEST_ACCENT_TO_STANDALONE_RGBA(accent, dark, expected) \ + adw_accent_color_to_standalone_rgba (accent, dark, &rgba); \ + hex = rgba_to_hex (&rgba); \ + g_assert_cmphex (expected, ==, hex); + +#define TEST_RGBA_TO_STANDALONE(rgba_str, dark, expected) \ + hex_to_rgba (rgba_str, &rgba); \ + adw_rgba_to_standalone (&rgba, dark, &rgba); \ + hex = rgba_to_hex (&rgba); \ + g_assert_cmphex (expected, ==, hex); + +static void +test_adw_accent_color_nearest_from_rgba (void) +{ + GdkRGBA rgba; + + /* Roundtrip */ + for (int i = 0; i <= ADW_ACCENT_COLOR_SLATE; i++) { + adw_accent_color_to_rgba (i, &rgba); + g_assert_cmpint (i, ==, adw_accent_color_nearest_from_rgba (&rgba)); + } + + /* Icon palette */ + TEST_NEAREST_ACCENT ("#99c1f1", ADW_ACCENT_COLOR_BLUE); /* blue 1 */ + TEST_NEAREST_ACCENT ("#62a0ea", ADW_ACCENT_COLOR_BLUE); /* blue 2 */ + TEST_NEAREST_ACCENT ("#3584e4", ADW_ACCENT_COLOR_BLUE); /* blue 3 */ + TEST_NEAREST_ACCENT ("#1c71d8", ADW_ACCENT_COLOR_BLUE); /* blue 4 */ + TEST_NEAREST_ACCENT ("#1a5fb4", ADW_ACCENT_COLOR_BLUE); /* blue 5 */ + TEST_NEAREST_ACCENT ("#8ff0a4", ADW_ACCENT_COLOR_GREEN); /* green 1 */ + TEST_NEAREST_ACCENT ("#57e389", ADW_ACCENT_COLOR_GREEN); /* green 2 */ + TEST_NEAREST_ACCENT ("#33d17a", ADW_ACCENT_COLOR_GREEN); /* green 3 */ + TEST_NEAREST_ACCENT ("#2ec27e", ADW_ACCENT_COLOR_GREEN); /* green 4 */ + TEST_NEAREST_ACCENT ("#26a269", ADW_ACCENT_COLOR_GREEN); /* green 5 */ + TEST_NEAREST_ACCENT ("#f9f06b", ADW_ACCENT_COLOR_YELLOW); /* yellow 1 */ + TEST_NEAREST_ACCENT ("#f8e45c", ADW_ACCENT_COLOR_YELLOW); /* yellow 2 */ + TEST_NEAREST_ACCENT ("#f6d32d", ADW_ACCENT_COLOR_YELLOW); /* yellow 3 */ + TEST_NEAREST_ACCENT ("#f5c211", ADW_ACCENT_COLOR_YELLOW); /* yellow 4 */ + TEST_NEAREST_ACCENT ("#e5a50a", ADW_ACCENT_COLOR_YELLOW); /* yellow 5 */ + TEST_NEAREST_ACCENT ("#ffbe6f", ADW_ACCENT_COLOR_ORANGE); /* orange 1 */ + TEST_NEAREST_ACCENT ("#ffa348", ADW_ACCENT_COLOR_ORANGE); /* orange 2 */ + TEST_NEAREST_ACCENT ("#ff7800", ADW_ACCENT_COLOR_ORANGE); /* orange 3 */ + TEST_NEAREST_ACCENT ("#e66100", ADW_ACCENT_COLOR_ORANGE); /* orange 4 */ + TEST_NEAREST_ACCENT ("#c64600", ADW_ACCENT_COLOR_ORANGE); /* orange 5 */ + TEST_NEAREST_ACCENT ("#f66151", ADW_ACCENT_COLOR_RED); /* red 1 */ + TEST_NEAREST_ACCENT ("#ed333b", ADW_ACCENT_COLOR_RED); /* red 2 */ + TEST_NEAREST_ACCENT ("#e01b24", ADW_ACCENT_COLOR_RED); /* red 3 */ + TEST_NEAREST_ACCENT ("#c01c28", ADW_ACCENT_COLOR_RED); /* red 4 */ + TEST_NEAREST_ACCENT ("#a51d2d", ADW_ACCENT_COLOR_RED); /* red 5 */ + TEST_NEAREST_ACCENT ("#dc8add", ADW_ACCENT_COLOR_PURPLE); /* purple 1 */ + TEST_NEAREST_ACCENT ("#c061cb", ADW_ACCENT_COLOR_PURPLE); /* purple 2 */ + TEST_NEAREST_ACCENT ("#9141ac", ADW_ACCENT_COLOR_PURPLE); /* purple 3 */ + TEST_NEAREST_ACCENT ("#813d9c", ADW_ACCENT_COLOR_PURPLE); /* purple 4 */ + TEST_NEAREST_ACCENT ("#613583", ADW_ACCENT_COLOR_PURPLE); /* purple 5 */ + TEST_NEAREST_ACCENT ("#cdab8f", ADW_ACCENT_COLOR_ORANGE); /* brown 1 */ + TEST_NEAREST_ACCENT ("#b5835a", ADW_ACCENT_COLOR_ORANGE); /* brown 2 */ + TEST_NEAREST_ACCENT ("#986a44", ADW_ACCENT_COLOR_ORANGE); /* brown 3 */ + TEST_NEAREST_ACCENT ("#865e3c", ADW_ACCENT_COLOR_ORANGE); /* brown 4 */ + TEST_NEAREST_ACCENT ("#63452c", ADW_ACCENT_COLOR_ORANGE); /* brown 5 */ + TEST_NEAREST_ACCENT ("#ffffff", ADW_ACCENT_COLOR_SLATE); /* light 1 */ + TEST_NEAREST_ACCENT ("#f6f5f4", ADW_ACCENT_COLOR_SLATE); /* light 2 */ + TEST_NEAREST_ACCENT ("#deddda", ADW_ACCENT_COLOR_SLATE); /* light 3 */ + TEST_NEAREST_ACCENT ("#c0bfbc", ADW_ACCENT_COLOR_SLATE); /* light 4 */ + TEST_NEAREST_ACCENT ("#9a9996", ADW_ACCENT_COLOR_SLATE); /* light 5 */ + TEST_NEAREST_ACCENT ("#77767b", ADW_ACCENT_COLOR_SLATE); /* dark 1 */ + TEST_NEAREST_ACCENT ("#5e5c64", ADW_ACCENT_COLOR_SLATE); /* dark 2 */ + TEST_NEAREST_ACCENT ("#3d3846", ADW_ACCENT_COLOR_SLATE); /* dark 3 */ + TEST_NEAREST_ACCENT ("#241f31", ADW_ACCENT_COLOR_SLATE); /* dark 4 */ + TEST_NEAREST_ACCENT ("#000000", ADW_ACCENT_COLOR_SLATE); /* dark 5 */ + + /* elementary */ + TEST_NEAREST_ACCENT ("#3689e6", ADW_ACCENT_COLOR_BLUE); /* blueberry */ + TEST_NEAREST_ACCENT ("#28bca3", ADW_ACCENT_COLOR_TEAL); /* mint */ + TEST_NEAREST_ACCENT ("#68b723", ADW_ACCENT_COLOR_GREEN); /* lime */ + TEST_NEAREST_ACCENT ("#f9c440", ADW_ACCENT_COLOR_YELLOW); /* banana */ + TEST_NEAREST_ACCENT ("#ffa154", ADW_ACCENT_COLOR_ORANGE); /* orange */ + TEST_NEAREST_ACCENT ("#ed5353", ADW_ACCENT_COLOR_RED); /* strawberry */ + TEST_NEAREST_ACCENT ("#de3e80", ADW_ACCENT_COLOR_PINK); /* bubblegum */ + TEST_NEAREST_ACCENT ("#a56de2", ADW_ACCENT_COLOR_PURPLE); /* grape */ + TEST_NEAREST_ACCENT ("#8a715e", ADW_ACCENT_COLOR_ORANGE); /* cocoa */ + TEST_NEAREST_ACCENT ("#667885", ADW_ACCENT_COLOR_SLATE); /* slate */ + + /* KDE (light) */ + TEST_NEAREST_ACCENT ("#ef75b8", ADW_ACCENT_COLOR_PINK); + TEST_NEAREST_ACCENT ("#ef778a", ADW_ACCENT_COLOR_RED); + TEST_NEAREST_ACCENT ("#ef9275", ADW_ACCENT_COLOR_ORANGE); + TEST_NEAREST_ACCENT ("#eeda6b", ADW_ACCENT_COLOR_YELLOW); + TEST_NEAREST_ACCENT ("#77e066", ADW_ACCENT_COLOR_GREEN); + TEST_NEAREST_ACCENT ("#4ce0cd", ADW_ACCENT_COLOR_TEAL); + TEST_NEAREST_ACCENT ("#77c6ef", ADW_ACCENT_COLOR_BLUE); + TEST_NEAREST_ACCENT ("#cd9ee6", ADW_ACCENT_COLOR_PURPLE); + TEST_NEAREST_ACCENT ("#b299ec", ADW_ACCENT_COLOR_PURPLE); + TEST_NEAREST_ACCENT ("#95979a", ADW_ACCENT_COLOR_SLATE); + + /* KDE (dark) */ + TEST_NEAREST_ACCENT ("#ab3175", ADW_ACCENT_COLOR_PINK); + TEST_NEAREST_ACCENT ("#ab3347", ADW_ACCENT_COLOR_RED); + TEST_NEAREST_ACCENT ("#ab4f32", ADW_ACCENT_COLOR_ORANGE); + TEST_NEAREST_ACCENT ("#aa9729", ADW_ACCENT_COLOR_YELLOW); + TEST_NEAREST_ACCENT ("#329d23", ADW_ACCENT_COLOR_GREEN); + TEST_NEAREST_ACCENT ("#089c8a", ADW_ACCENT_COLOR_TEAL); + TEST_NEAREST_ACCENT ("#3282ac", ADW_ACCENT_COLOR_BLUE); + TEST_NEAREST_ACCENT ("#885aa3", ADW_ACCENT_COLOR_PURPLE); + TEST_NEAREST_ACCENT ("#6e56a9", ADW_ACCENT_COLOR_PURPLE); + TEST_NEAREST_ACCENT ("#505357", ADW_ACCENT_COLOR_SLATE); + + /* Ubuntu */ + TEST_NEAREST_ACCENT ("#e95420", ADW_ACCENT_COLOR_ORANGE); + TEST_NEAREST_ACCENT ("#787859", ADW_ACCENT_COLOR_YELLOW); /* bark */ + TEST_NEAREST_ACCENT ("#657b69", ADW_ACCENT_COLOR_SLATE); /* sage */ + TEST_NEAREST_ACCENT ("#4b8501", ADW_ACCENT_COLOR_GREEN); /* olive */ + TEST_NEAREST_ACCENT ("#03875b", ADW_ACCENT_COLOR_GREEN); /* viridian */ + TEST_NEAREST_ACCENT ("#308280", ADW_ACCENT_COLOR_TEAL); /* prussian green */ + TEST_NEAREST_ACCENT ("#0073e5", ADW_ACCENT_COLOR_BLUE); + TEST_NEAREST_ACCENT ("#7764d8", ADW_ACCENT_COLOR_PURPLE); + TEST_NEAREST_ACCENT ("#b34cb3", ADW_ACCENT_COLOR_PURPLE); /* magenta */ + TEST_NEAREST_ACCENT ("#da3450", ADW_ACCENT_COLOR_RED); + + /* Cinnamon */ + TEST_NEAREST_ACCENT ("#0c75de", ADW_ACCENT_COLOR_BLUE); + TEST_NEAREST_ACCENT ("#1f9ede", ADW_ACCENT_COLOR_BLUE); + TEST_NEAREST_ACCENT ("#199ca8", ADW_ACCENT_COLOR_TEAL); + TEST_NEAREST_ACCENT ("#35a854", ADW_ACCENT_COLOR_GREEN); + TEST_NEAREST_ACCENT ("#c5a07c", ADW_ACCENT_COLOR_ORANGE); + TEST_NEAREST_ACCENT ("#70737a", ADW_ACCENT_COLOR_SLATE); + TEST_NEAREST_ACCENT ("#ff7139", ADW_ACCENT_COLOR_ORANGE); + TEST_NEAREST_ACCENT ("#e82127", ADW_ACCENT_COLOR_RED); + TEST_NEAREST_ACCENT ("#e54980", ADW_ACCENT_COLOR_PINK); + TEST_NEAREST_ACCENT ("#8c5dd9", ADW_ACCENT_COLOR_PURPLE); + + /* COSMIC */ + TEST_NEAREST_ACCENT ("#63d0df", ADW_ACCENT_COLOR_TEAL); + TEST_NEAREST_ACCENT ("#a1c0eb", ADW_ACCENT_COLOR_BLUE); + TEST_NEAREST_ACCENT ("#e79cfe", ADW_ACCENT_COLOR_PURPLE); + TEST_NEAREST_ACCENT ("#ff9cb1", ADW_ACCENT_COLOR_PINK); + TEST_NEAREST_ACCENT ("#fda1a0", ADW_ACCENT_COLOR_RED); + TEST_NEAREST_ACCENT ("#ffad00", ADW_ACCENT_COLOR_ORANGE); + TEST_NEAREST_ACCENT ("#f7e062", ADW_ACCENT_COLOR_YELLOW); + TEST_NEAREST_ACCENT ("#92cf9c", ADW_ACCENT_COLOR_GREEN); + TEST_NEAREST_ACCENT ("#cabab4", ADW_ACCENT_COLOR_SLATE); + + /* macOS */ + TEST_NEAREST_ACCENT ("#017bff", ADW_ACCENT_COLOR_BLUE); + TEST_NEAREST_ACCENT ("#a550a7", ADW_ACCENT_COLOR_PURPLE); + TEST_NEAREST_ACCENT ("#f8509e", ADW_ACCENT_COLOR_PINK); + TEST_NEAREST_ACCENT ("#ff5257", ADW_ACCENT_COLOR_RED); + TEST_NEAREST_ACCENT ("#f7821a", ADW_ACCENT_COLOR_ORANGE); + TEST_NEAREST_ACCENT ("#ffc602", ADW_ACCENT_COLOR_YELLOW); + TEST_NEAREST_ACCENT ("#62ba46", ADW_ACCENT_COLOR_GREEN); + TEST_NEAREST_ACCENT ("#8c8c8c", ADW_ACCENT_COLOR_SLATE); +} + +static void +test_adw_accent_color_to_rgba (void) +{ + GdkRGBA rgba; + int hex; + + TEST_ACCENT_TO_RGBA (ADW_ACCENT_COLOR_BLUE, 0x3584e4); + TEST_ACCENT_TO_RGBA (ADW_ACCENT_COLOR_TEAL, 0x2190a4); + TEST_ACCENT_TO_RGBA (ADW_ACCENT_COLOR_GREEN, 0x3a944a); + TEST_ACCENT_TO_RGBA (ADW_ACCENT_COLOR_YELLOW, 0xc88800); + TEST_ACCENT_TO_RGBA (ADW_ACCENT_COLOR_ORANGE, 0xed5b00); + TEST_ACCENT_TO_RGBA (ADW_ACCENT_COLOR_RED, 0xe62d42); + TEST_ACCENT_TO_RGBA (ADW_ACCENT_COLOR_PINK, 0xd56199); + TEST_ACCENT_TO_RGBA (ADW_ACCENT_COLOR_PURPLE, 0x9141ac); + TEST_ACCENT_TO_RGBA (ADW_ACCENT_COLOR_SLATE, 0x6f8396); +} + +static void +test_adw_accent_color_to_standalone_rgba (void) +{ + GdkRGBA rgba; + int hex; + + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_BLUE, FALSE, 0x0461be); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_TEAL, FALSE, 0x007184); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_GREEN, FALSE, 0x15772e); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_YELLOW, FALSE, 0x905300); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_ORANGE, FALSE, 0xb62200); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_RED, FALSE, 0xc00023); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_PINK, FALSE, 0xa2326c); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_PURPLE, FALSE, 0x8939a4); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_SLATE, FALSE, 0x526678); + + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_BLUE, TRUE, 0x81d0ff); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_TEAL, TRUE, 0x7bdff4); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_GREEN, TRUE, 0x8de698); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_YELLOW, TRUE, 0xffc057); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_ORANGE, TRUE, 0xff9c5b); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_RED, TRUE, 0xff888c); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_PINK, TRUE, 0xffa0d8); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_PURPLE, TRUE, 0xfba7ff); + TEST_ACCENT_TO_STANDALONE_RGBA (ADW_ACCENT_COLOR_SLATE, TRUE, 0xbbd1e5); +} + +static void +test_adw_accent_color_rgba_to_standalone (void) +{ + GdkRGBA rgba; + int hex; + + TEST_RGBA_TO_STANDALONE (0x3584e4, FALSE, 0x0461be); + TEST_RGBA_TO_STANDALONE (0x3584e4, TRUE, 0x81d0ff); + + TEST_RGBA_TO_STANDALONE (0xffffff, FALSE, 0x636363); + TEST_RGBA_TO_STANDALONE (0xffffff, TRUE, 0xffffff); + + TEST_RGBA_TO_STANDALONE (0x000000, FALSE, 0x000000); + TEST_RGBA_TO_STANDALONE (0x000000, TRUE, 0xcecece); + + TEST_RGBA_TO_STANDALONE (0x959595, FALSE, 0x636363); + TEST_RGBA_TO_STANDALONE (0x959595, TRUE, 0xcecece); +} + +int +main (int argc, + char *argv[]) +{ + gtk_test_init (&argc, &argv, NULL); + adw_init (); + + g_test_add_func ("/Adwaita/AccentColor/nearest_from_rgba", test_adw_accent_color_nearest_from_rgba); + g_test_add_func ("/Adwaita/AccentColor/to_rgba", test_adw_accent_color_to_rgba); + g_test_add_func ("/Adwaita/AccentColor/to_standalone_rgba", test_adw_accent_color_to_standalone_rgba); + g_test_add_func ("/Adwaita/AccentColor/rgba_to_standalone", test_adw_accent_color_rgba_to_standalone); + + return g_test_run (); +}