From 4c6f503b316fd507f07335a3bb7761223bb4ab33 Mon Sep 17 00:00:00 2001 From: Leonhard <106322251+leolost2605@users.noreply.github.com> Date: Tue, 26 Mar 2024 18:05:32 +0100 Subject: [PATCH] Introduce a StyleManager (#1880) --- daemon/meson.build | 2 +- lib/Drawing/Color.vala | 4 +- lib/Drawing/StyleManager.vala | 128 ++++++++++++++++++ lib/meson.build | 1 + meson.build | 2 +- src/Background/BackgroundSource.vala | 6 +- src/InternalUtils.vala | 17 --- src/Widgets/DwellClickTimer.vala | 2 +- src/Widgets/IconGroup.vala | 6 +- src/Widgets/MultitaskingView.vala | 8 +- src/Widgets/PointerLocator.vala | 2 +- src/Widgets/WindowClone.vala | 2 +- .../WindowSwitcher/WindowSwitcher.vala | 10 +- .../WindowSwitcher/WindowSwitcherIcon.vala | 2 +- src/WindowManager.vala | 5 +- 15 files changed, 155 insertions(+), 42 deletions(-) create mode 100644 lib/Drawing/StyleManager.vala diff --git a/daemon/meson.build b/daemon/meson.build index 5f738276..b3edc81d 100644 --- a/daemon/meson.build +++ b/daemon/meson.build @@ -10,7 +10,7 @@ gala_daemon_sources = files( gala_daemon_bin = executable( 'gala-daemon', gala_daemon_sources, - dependencies: [gala_dep, gala_base_dep, hdy_dep], + dependencies: [gala_dep, gala_base_dep, granite_dep, hdy_dep], include_directories: config_inc_dir, install: true, ) diff --git a/lib/Drawing/Color.vala b/lib/Drawing/Color.vala index 6e5f87d6..b3d00169 100644 --- a/lib/Drawing/Color.vala +++ b/lib/Drawing/Color.vala @@ -6,13 +6,11 @@ using Gdk; -using Granite.Services; - namespace Gala.Drawing { /** * A class containing an RGBA color and methods for more powerful color manipulation. */ - public class Color : GLib.Object, SettingsSerializable { + public class Color : GLib.Object { public const Gdk.RGBA LIGHT_BACKGROUND = { (250f / 255f), (250f / 255f), (250f / 255f), 1}; public const Gdk.RGBA DARK_BACKGROUND = { (51 / 255f), (51 / 255f), (51 / 255f), 1}; public const Gdk.RGBA TOOLTIP_BACKGROUND = { 0, 0, 0, 1}; diff --git a/lib/Drawing/StyleManager.vala b/lib/Drawing/StyleManager.vala new file mode 100644 index 00000000..f92bc01d --- /dev/null +++ b/lib/Drawing/StyleManager.vala @@ -0,0 +1,128 @@ +/* + * Copyright 2024 elementary, Inc. (https://elementary.io) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Authored by: Leonhard Kargl + */ + +public class Gala.Drawing.StyleManager : Object { + public enum ColorScheme { + NO_PREFERENCE, + DARK, + LIGHT + } + + [DBus (name="org.freedesktop.Accounts")] + private interface Accounts : Object { + public abstract async string find_user_by_name (string name) throws IOError, DBusError; + } + + [DBus (name="io.elementary.pantheon.AccountsService")] + private interface AccountsService : DBusProxy { + public abstract int prefers_color_scheme { get; set; } + public abstract int prefers_accent_color { get; set; } + } + + private const string FDO_ACCOUNTS_NAME = "org.freedesktop.Accounts"; + private const string FDO_ACCOUNTS_PATH = "/org/freedesktop/Accounts"; + + private const double ACCENT_COLOR_ALPHA = 0.25; + private const Gdk.RGBA DEFAULT_ACCENT_COLOR = { 0, 0, 0, ACCENT_COLOR_ALPHA }; + + private static GLib.Once instance; + public static StyleManager get_instance () { + return instance.once (() => {return new StyleManager ();}); + } + + public ColorScheme prefers_color_scheme { get; private set; default = LIGHT; } + public Gdk.RGBA theme_accent_color { get; private set; default = DEFAULT_ACCENT_COLOR; } + + private AccountsService? accounts_service_proxy; + + construct { + Bus.watch_name (SYSTEM, FDO_ACCOUNTS_NAME, NONE, () => connect_to_accounts_service.begin (), () => accounts_service_proxy = null); + } + + private async void connect_to_accounts_service () { + try { + var accounts = yield Bus.get_proxy (SYSTEM, FDO_ACCOUNTS_NAME, FDO_ACCOUNTS_PATH); + + var path = yield accounts.find_user_by_name (Environment.get_user_name ()); + + accounts_service_proxy = yield Bus.get_proxy (SYSTEM, FDO_ACCOUNTS_NAME, path, GET_INVALIDATED_PROPERTIES); + } catch { + warning ("Could not connect to AccountsService. Default accent color will be used"); + return; + } + + update_color_scheme (accounts_service_proxy.prefers_color_scheme); + update_color (accounts_service_proxy.prefers_accent_color); + + accounts_service_proxy.g_properties_changed.connect ((changed, invalid) => { + var value = changed.lookup_value ("PrefersAccentColor", new VariantType ("i")); + if (value != null) { + update_color (value.get_int32 ()); + } + + value = changed.lookup_value ("PrefersColorScheme", new VariantType ("i")); + if (value != null) { + update_color_scheme (value.get_int32 ()); + } + }); + } + + private void update_color_scheme (int color_scheme) { + prefers_color_scheme = (ColorScheme) color_scheme; + } + + private void update_color (int color) { + var rgb = get_color (color); + + double r = ((rgb >> 16) & 255) / 255.0; + double g = ((rgb >> 8) & 255) / 255.0; + double b = (rgb & 255) / 255.0; + + theme_accent_color = { + r, + g, + b, + ACCENT_COLOR_ALPHA + }; + } + + private int get_color (int color) { + switch (color) { + case 1: // Strawberry + return 0xed5353; + + case 2: // Orange + return 0xffa154; + + case 3: // Banana + return 0xf9c440; + + case 4: // Lime + return 0x68b723; + + case 5: // Mint + return 0x28bca3; + + case 6: // Blueberry + return 0x3689e6; + + case 7: // Grape + return 0xa56de2; + + case 8: // Bubblegum + return 0xde3e80; + + case 9: // Cocoa + return 0x8a715e; + + case 10: // Slate + return 0x667885; + } + + return 0; + } +} diff --git a/lib/meson.build b/lib/meson.build index aeeb0a96..477825dd 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -11,6 +11,7 @@ gala_lib_sources = files( 'Drawing/BufferSurface.vala', 'Drawing/Canvas.vala', 'Drawing/Color.vala', + 'Drawing/StyleManager.vala', 'Drawing/Utilities.vala', 'Plugin.vala', 'ShadowEffect.vala', diff --git a/meson.build b/meson.build index 2e19fe70..cdeb9043 100644 --- a/meson.build +++ b/meson.build @@ -175,7 +175,7 @@ endif add_project_arguments(vala_flags, language: 'vala') add_project_link_arguments(['-Wl,-rpath,@0@'.format(mutter_typelib_dir)], language: 'c') -gala_base_dep = [canberra_dep, glib_dep, gobject_dep, gio_dep, gio_unix_dep, gmodule_dep, gee_dep, gtk_dep, mutter_dep, granite_dep, gnome_desktop_dep, m_dep, posix_dep, sqlite3_dep, config_dep] +gala_base_dep = [canberra_dep, glib_dep, gobject_dep, gio_dep, gio_unix_dep, gmodule_dep, gee_dep, gtk_dep, mutter_dep, gnome_desktop_dep, m_dep, posix_dep, sqlite3_dep, config_dep] if get_option('systemd') gala_base_dep += systemd_dep diff --git a/src/Background/BackgroundSource.vala b/src/Background/BackgroundSource.vala index a8fa747f..09534056 100644 --- a/src/Background/BackgroundSource.vala +++ b/src/Background/BackgroundSource.vala @@ -42,7 +42,7 @@ namespace Gala { public bool should_dim { get { return ( - Granite.Settings.get_default ().prefers_color_scheme == DARK && + Drawing.StyleManager.get_instance ().prefers_color_scheme == DARK && gala_background_settings.get_boolean ("dim-wallpaper-in-dark-style") ); } @@ -62,7 +62,7 @@ namespace Gala { gala_background_settings = new GLib.Settings ("io.elementary.desktop.background"); gala_background_settings.changed["dim-wallpaper-in-dark-style"].connect (() => changed ()); - Granite.Settings.get_default ().notify["prefers-color-scheme"].connect (() => changed ()); + Drawing.StyleManager.get_instance ().notify["prefers-color-scheme"].connect (() => changed ()); gnome_background_settings = new GLib.Settings ("org.gnome.desktop.background"); @@ -129,7 +129,7 @@ namespace Gala { } private string get_background_path () { - if (Granite.Settings.get_default ().prefers_color_scheme == DARK) { + if (Drawing.StyleManager.get_instance ().prefers_color_scheme == DARK) { var uri = gnome_background_settings.get_string ("picture-uri-dark"); var path = File.new_for_uri (uri).get_path (); if (FileUtils.test (path, EXISTS)) { diff --git a/src/InternalUtils.vala b/src/InternalUtils.vala index 6fa4b7a4..722299cc 100644 --- a/src/InternalUtils.vala +++ b/src/InternalUtils.vala @@ -318,23 +318,6 @@ namespace Gala { return (int) (Math.round ((float)value * scale_factor)); } - private static Gtk.StyleContext selection_style_context = null; - public static Gdk.RGBA get_theme_accent_color () { - if (selection_style_context == null) { - var label_widget_path = new Gtk.WidgetPath (); - label_widget_path.append_type (GLib.Type.from_name ("label")); - label_widget_path.iter_set_object_name (-1, "selection"); - - selection_style_context = new Gtk.StyleContext (); - selection_style_context.set_path (label_widget_path); - } - - return (Gdk.RGBA) selection_style_context.get_property ( - Gtk.STYLE_PROPERTY_BACKGROUND_COLOR, - Gtk.StateFlags.NORMAL - ); - } - /** * Returns the workspaces geometry following the only_on_primary settings. */ diff --git a/src/Widgets/DwellClickTimer.vala b/src/Widgets/DwellClickTimer.vala index 7b727874..393d3e5d 100644 --- a/src/Widgets/DwellClickTimer.vala +++ b/src/Widgets/DwellClickTimer.vala @@ -108,7 +108,7 @@ namespace Gala { return; } - var rgba = InternalUtils.get_theme_accent_color (); + var rgba = Drawing.StyleManager.get_instance ().theme_accent_color; /* Don't use alpha from the stylesheet to ensure contrast */ stroke_color = new Cairo.Pattern.rgb (rgba.red, rgba.green, rgba.blue); diff --git a/src/Widgets/IconGroup.vala b/src/Widgets/IconGroup.vala index 82275037..463ae024 100644 --- a/src/Widgets/IconGroup.vala +++ b/src/Widgets/IconGroup.vala @@ -236,9 +236,9 @@ namespace Gala { scale_factor = scale_factor }; - var granite_settings = Granite.Settings.get_default (); + var style_manager = Drawing.StyleManager.get_instance (); - if (granite_settings.prefers_color_scheme == DARK) { + if (style_manager.prefers_color_scheme == DARK) { const double BG_COLOR = 35.0 / 255.0; if (drag_action.dragging) { cr.set_source_rgba (BG_COLOR, BG_COLOR, BG_COLOR, 0.8); @@ -298,7 +298,7 @@ namespace Gala { InternalUtils.scale_to_int (PLUS_SIZE, scale_factor) ); - if (granite_settings.prefers_color_scheme == DARK) { + if (style_manager.prefers_color_scheme == DARK) { buffer.context.move_to (0, 1 * scale_factor); buffer.context.set_source_rgb (0, 0, 0); buffer.context.fill_preserve (); diff --git a/src/Widgets/MultitaskingView.vala b/src/Widgets/MultitaskingView.vala index 64431bf7..a3639f37 100644 --- a/src/Widgets/MultitaskingView.vala +++ b/src/Widgets/MultitaskingView.vala @@ -44,7 +44,7 @@ namespace Gala { private Clutter.BrightnessContrastEffect brightness_effect; private GLib.Settings gala_behavior_settings; - private Granite.Settings granite_settings; + private Drawing.StyleManager style_manager; private bool switching_workspace_with_gesture = false; private bool switching_workspace_in_progress { @@ -59,7 +59,7 @@ namespace Gala { construct { gala_behavior_settings = new GLib.Settings ("org.pantheon.desktop.gala.behavior"); - granite_settings = Granite.Settings.get_default (); + style_manager = Drawing.StyleManager.get_instance (); visible = false; reactive = true; @@ -150,11 +150,11 @@ namespace Gala { }); }); - granite_settings.notify["prefers-color-scheme"].connect (update_brightness_effect); + style_manager.notify["prefers-color-scheme"].connect (update_brightness_effect); } private void update_brightness_effect () { - if (granite_settings.prefers_color_scheme == DARK) { + if (style_manager.prefers_color_scheme == DARK) { brightness_effect.set_brightness (-0.4f); } else { brightness_effect.set_brightness (0.4f); diff --git a/src/Widgets/PointerLocator.vala b/src/Widgets/PointerLocator.vala index 7ebb705d..e0e93c3e 100644 --- a/src/Widgets/PointerLocator.vala +++ b/src/Widgets/PointerLocator.vala @@ -138,7 +138,7 @@ namespace Gala { transition.started.connect (() => { visible = true; }); add_transition ("circle", transition); - var rgba = InternalUtils.get_theme_accent_color (); + var rgba = Drawing.StyleManager.get_instance ().theme_accent_color; /* Don't use alpha from the stylesheet to ensure contrast */ stroke_color = new Cairo.Pattern.rgb (rgba.red, rgba.green, rgba.blue); diff --git a/src/Widgets/WindowClone.vala b/src/Widgets/WindowClone.vala index 38115bc1..ba4b4436 100644 --- a/src/Widgets/WindowClone.vala +++ b/src/Widgets/WindowClone.vala @@ -883,7 +883,7 @@ public class Gala.WindowClone : Clutter.Actor { return; } - var color = InternalUtils.get_theme_accent_color (); + var color = Drawing.StyleManager.get_instance ().theme_accent_color; cr.save (); cr.set_operator (Cairo.Operator.CLEAR); diff --git a/src/Widgets/WindowSwitcher/WindowSwitcher.vala b/src/Widgets/WindowSwitcher/WindowSwitcher.vala index b3b7b450..62fc8048 100644 --- a/src/Widgets/WindowSwitcher/WindowSwitcher.vala +++ b/src/Widgets/WindowSwitcher/WindowSwitcher.vala @@ -24,7 +24,7 @@ public class Gala.WindowSwitcher : CanvasActor { private bool handling_gesture = false; private int modifier_mask; private Gala.ModalProxy modal_proxy = null; - private Granite.Settings granite_settings; + private Drawing.StyleManager style_manager; private Clutter.Actor container; private Clutter.Text caption; private ShadowEffect shadow_effect; @@ -58,7 +58,7 @@ public class Gala.WindowSwitcher : CanvasActor { } construct { - granite_settings = Granite.Settings.get_default (); + style_manager = Drawing.StyleManager.get_instance (); container = new Clutter.Actor () { reactive = true, @@ -93,7 +93,7 @@ public class Gala.WindowSwitcher : CanvasActor { container.button_release_event.connect (container_mouse_release); // Redraw the components if the colour scheme changes. - granite_settings.notify["prefers-color-scheme"].connect (content.invalidate); + style_manager.notify["prefers-color-scheme"].connect (content.invalidate); unowned var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager (); monitor_manager.monitors_changed.connect (scale); @@ -140,7 +140,7 @@ public class Gala.WindowSwitcher : CanvasActor { protected override void draw (Cairo.Context ctx, int width, int height) { var caption_color = "#2e2e31"; - if (granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK) { + if (style_manager.prefers_color_scheme == Drawing.StyleManager.ColorScheme.DARK) { caption_color = "#fafafa"; } @@ -153,7 +153,7 @@ public class Gala.WindowSwitcher : CanvasActor { ctx.reset_clip (); var background_color = Drawing.Color.LIGHT_BACKGROUND; - if (granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK) { + if (style_manager.prefers_color_scheme == Drawing.StyleManager.ColorScheme.DARK) { background_color = Drawing.Color.DARK_BACKGROUND; } diff --git a/src/Widgets/WindowSwitcher/WindowSwitcherIcon.vala b/src/Widgets/WindowSwitcher/WindowSwitcherIcon.vala index b9bb1d95..8b594e98 100644 --- a/src/Widgets/WindowSwitcher/WindowSwitcherIcon.vala +++ b/src/Widgets/WindowSwitcher/WindowSwitcherIcon.vala @@ -62,7 +62,7 @@ public class Gala.WindowSwitcherIcon : CanvasActor { if (selected) { // draw rect - var rgba = InternalUtils.get_theme_accent_color (); + var rgba = Drawing.StyleManager.get_instance ().theme_accent_color; ctx.set_source_rgba ( rgba.red, rgba.green, diff --git a/src/WindowManager.vala b/src/WindowManager.vala index 43662931..9c12d923 100644 --- a/src/WindowManager.vala +++ b/src/WindowManager.vala @@ -137,6 +137,9 @@ namespace Gala { behavior_settings = new GLib.Settings (Config.SCHEMA + ".behavior"); new_behavior_settings = new GLib.Settings ("io.elementary.desktop.wm.behavior"); enable_animations = animations_settings.get_boolean ("enable-animations"); + + //Make it start watching the settings daemon bus + Drawing.StyleManager.get_instance (); } public override void start () { @@ -1068,7 +1071,7 @@ namespace Gala { #endif if (tile_preview == null) { tile_preview = new Clutter.Actor (); - var rgba = InternalUtils.get_theme_accent_color (); + var rgba = Drawing.StyleManager.get_instance ().theme_accent_color; tile_preview.background_color = { (uint8)(255.0 * rgba.red), (uint8)(255.0 * rgba.green),