From a4d8546ca014b5446e08505b6acb2cb8fbb231a1 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 28 Apr 2022 14:11:53 +0200 Subject: [PATCH 1/9] [Linux] read settings from XDG desktop portal if available Fixes: flutter/flutter#101438 --- shell/platform/linux/BUILD.gn | 2 + shell/platform/linux/fl_settings.cc | 8 +- shell/platform/linux/fl_settings_portal.cc | 251 ++++++++++++++++++ shell/platform/linux/fl_settings_portal.h | 46 ++++ .../platform/linux/fl_settings_portal_test.cc | 68 +++++ 5 files changed, 373 insertions(+), 2 deletions(-) create mode 100644 shell/platform/linux/fl_settings_portal.cc create mode 100644 shell/platform/linux/fl_settings_portal.h create mode 100644 shell/platform/linux/fl_settings_portal_test.cc diff --git a/shell/platform/linux/BUILD.gn b/shell/platform/linux/BUILD.gn index a8c2a1c4023d2..48a9f9113456d 100644 --- a/shell/platform/linux/BUILD.gn +++ b/shell/platform/linux/BUILD.gn @@ -131,6 +131,7 @@ source_set("flutter_linux_sources") { "fl_renderer_headless.cc", "fl_settings.cc", "fl_settings_plugin.cc", + "fl_settings_portal.cc", "fl_standard_message_codec.cc", "fl_standard_method_codec.cc", "fl_string_codec.cc", @@ -208,6 +209,7 @@ executable("flutter_linux_unittests") { "fl_pixel_buffer_texture_test.cc", "fl_plugin_registrar_test.cc", "fl_settings_plugin_test.cc", + "fl_settings_portal_test.cc", "fl_standard_message_codec_test.cc", "fl_standard_method_codec_test.cc", "fl_string_codec_test.cc", diff --git a/shell/platform/linux/fl_settings.cc b/shell/platform/linux/fl_settings.cc index c129da3146d26..148116417f052 100644 --- a/shell/platform/linux/fl_settings.cc +++ b/shell/platform/linux/fl_settings.cc @@ -4,6 +4,7 @@ #include "flutter/shell/platform/linux/fl_settings.h" #include "flutter/shell/platform/linux/fl_gnome_settings.h" +#include "flutter/shell/platform/linux/fl_settings_portal.h" G_DEFINE_INTERFACE(FlSettings, fl_settings, G_TYPE_OBJECT) @@ -44,6 +45,9 @@ void fl_settings_emit_changed(FlSettings* self) { } FlSettings* fl_settings_new() { - // TODO(jpnurmi): add support for other desktop environments - return FL_SETTINGS(fl_gnome_settings_new()); + g_autoptr(FlSettingsPortal) portal = fl_settings_portal_new(nullptr); + if (!fl_settings_portal_start(portal)) { + return fl_gnome_settings_new(); + } + return FL_SETTINGS(g_object_ref(portal)); } diff --git a/shell/platform/linux/fl_settings_portal.cc b/shell/platform/linux/fl_settings_portal.cc new file mode 100644 index 0000000000000..1d581bea38c78 --- /dev/null +++ b/shell/platform/linux/fl_settings_portal.cc @@ -0,0 +1,251 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/linux/fl_settings_portal.h" + +#include +#include + +static constexpr char kPortalName[] = "org.freedesktop.portal.Desktop"; +static constexpr char kPortalPath[] = "/org/freedesktop/portal/desktop"; +static constexpr char pPortalSettings[] = "org.freedesktop.portal.Settings"; + +struct FlSetting { + const gchar* ns; + const gchar* key; + const GVariantType* type; +}; + +static constexpr char kXdgAppearance[] = "org.freedesktop.appearance"; +static const FlSetting kColorScheme = { + kXdgAppearance, + "color-scheme", + G_VARIANT_TYPE_UINT32, +}; + +static constexpr char kGnomeDesktopInterface[] = "org.gnome.desktop.interface"; +static const FlSetting kClockFormat = { + kGnomeDesktopInterface, + "clock-format", + G_VARIANT_TYPE_STRING, +}; +static const FlSetting kTextScalingFactor = { + kGnomeDesktopInterface, + "text-scaling-factor", + G_VARIANT_TYPE_DOUBLE, +}; + +static const FlSetting all_settings[] = { + kClockFormat, + kColorScheme, + kTextScalingFactor, +}; + +static constexpr char kClockFormat12Hour[] = "12h"; + +typedef enum { DEFAULT, PREFER_DARK, PREFER_LIGHT } ColorScheme; + +struct _FlSettingsPortal { + GObject parent_instance; + + GDBusProxy* dbus_proxy; + GVariantDict* values; +}; + +static void fl_settings_portal_iface_init(FlSettingsInterface* iface); + +G_DEFINE_TYPE_WITH_CODE(FlSettingsPortal, + fl_settings_portal, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(fl_settings_get_type(), + fl_settings_portal_iface_init)) + +#define FL_SETTINGS_PORTAL_GET_PRIVATE(portal) \ + ((FlSettingsPortalPrivate*)fl_settings_portal_get_instance_private(portal)) + +static const gchar* fl_settings_portal_format_key(const FlSetting* setting) { + return g_strconcat(setting->ns, "::", setting->key, nullptr); +} + +static gboolean fl_settings_portal_get_value(FlSettingsPortal* self, + const FlSetting* setting, + GVariant** value) { + g_autofree const gchar* key = fl_settings_portal_format_key(setting); + *value = g_variant_dict_lookup_value(self->values, key, setting->type); + return *value != nullptr; +} + +static void fl_settings_portal_set_value(FlSettingsPortal* self, + const FlSetting* setting, + GVariant* value) { + g_autofree const gchar* key = fl_settings_portal_format_key(setting); + + // ignore redundant changes from multiple XDG desktop portal backends + g_autoptr(GVariant) old_value = + g_variant_dict_lookup_value(self->values, key, nullptr); + if (old_value != nullptr && value != nullptr && + g_variant_equal(old_value, value)) { + return; + } + + g_variant_dict_insert_value(self->values, key, value); + fl_settings_emit_changed(FL_SETTINGS(self)); +} + +static FlClockFormat fl_settings_portal_get_clock_format(FlSettings* settings) { + FlSettingsPortal* self = FL_SETTINGS_PORTAL(settings); + + FlClockFormat clock_format = FL_CLOCK_FORMAT_24H; + + g_autoptr(GVariant) value = nullptr; + if (fl_settings_portal_get_value(self, &kClockFormat, &value)) { + const gchar* clock_format_str = g_variant_get_string(value, nullptr); + if (g_strcmp0(clock_format_str, kClockFormat12Hour) == 0) { + clock_format = FL_CLOCK_FORMAT_12H; + } + } + + return clock_format; +} + +static FlColorScheme fl_settings_portal_get_color_scheme(FlSettings* settings) { + FlSettingsPortal* self = FL_SETTINGS_PORTAL(settings); + + FlColorScheme color_scheme = FL_COLOR_SCHEME_LIGHT; + + g_autoptr(GVariant) value = nullptr; + if (fl_settings_portal_get_value(self, &kColorScheme, &value)) { + if (g_variant_get_uint32(value) == PREFER_DARK) { + color_scheme = FL_COLOR_SCHEME_DARK; + } + } + + return color_scheme; +} + +static gdouble fl_settings_portal_get_text_scaling_factor( + FlSettings* settings) { + FlSettingsPortal* self = FL_SETTINGS_PORTAL(settings); + + gdouble scaling_factor = 1.0; + + g_autoptr(GVariant) value = nullptr; + if (fl_settings_portal_get_value(self, &kTextScalingFactor, &value)) { + scaling_factor = g_variant_get_double(value); + } + + return scaling_factor; +} + +static void fl_settings_portal_dispose(GObject* object) { + FlSettingsPortal* self = FL_SETTINGS_PORTAL(object); + + g_clear_object(&self->dbus_proxy); + g_clear_pointer(&self->values, g_variant_dict_unref); + + G_OBJECT_CLASS(fl_settings_portal_parent_class)->dispose(object); +} + +static void fl_settings_portal_class_init(FlSettingsPortalClass* klass) { + GObjectClass* object_class = G_OBJECT_CLASS(klass); + object_class->dispose = fl_settings_portal_dispose; +} + +static void fl_settings_portal_iface_init(FlSettingsInterface* iface) { + iface->get_clock_format = fl_settings_portal_get_clock_format; + iface->get_color_scheme = fl_settings_portal_get_color_scheme; + iface->get_text_scaling_factor = fl_settings_portal_get_text_scaling_factor; +} + +static void fl_settings_portal_init(FlSettingsPortal* self) {} + +FlSettingsPortal* fl_settings_portal_new(GVariantDict* values) { + FlSettingsPortal* portal = + FL_SETTINGS_PORTAL(g_object_new(fl_settings_portal_get_type(), nullptr)); + portal->values = + values ? g_variant_dict_ref(values) : g_variant_dict_new(nullptr); + return portal; +} + +// Based on +// https://gitlab.gnome.org/GNOME/Initiatives/-/wikis/Dark-Style-Preference#other +static gboolean settings_portal_read(GDBusProxy* proxy, + const gchar* ns, + const gchar* key, + GVariant** out) { + g_autoptr(GError) error = nullptr; + g_autoptr(GVariant) value = + g_dbus_proxy_call_sync(proxy, "Read", g_variant_new("(ss)", ns, key), + G_DBUS_CALL_FLAGS_NONE, G_MAXINT, nullptr, &error); + + if (error) { + if (error->domain == G_DBUS_ERROR && + error->code == G_DBUS_ERROR_SERVICE_UNKNOWN) { + g_debug("XDG desktop portal unavailable: %s", error->message); + return false; + } + + if (error->domain == G_DBUS_ERROR && + error->code == G_DBUS_ERROR_UNKNOWN_METHOD) { + g_debug("XDG desktop portal settings unavailable: %s", error->message); + return false; + } + + g_critical("Failed to read XDG desktop portal settings: %s", + error->message); + return false; + } + + g_autoptr(GVariant) child = nullptr; + g_variant_get(value, "(v)", &child); + g_variant_get(child, "v", out); + + return true; +} + +static void settings_portal_changed_cb(GDBusProxy* proxy, + const char* sender_name, + const char* signal_name, + GVariant* parameters, + gpointer user_data) { + FlSettingsPortal* portal = FL_SETTINGS_PORTAL(user_data); + if (g_strcmp0(signal_name, "SettingChanged")) { + return; + } + + FlSetting setting; + g_autoptr(GVariant) value = nullptr; + g_variant_get(parameters, "(&s&sv)", &setting.ns, &setting.key, &value); + fl_settings_portal_set_value(portal, &setting, value); +} + +gboolean fl_settings_portal_start(FlSettingsPortal* self) { + g_return_val_if_fail(FL_IS_SETTINGS_PORTAL(self), false); + g_return_val_if_fail(self->dbus_proxy == nullptr, false); + + g_autoptr(GError) error = nullptr; + + self->dbus_proxy = g_dbus_proxy_new_for_bus_sync( + G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, nullptr, kPortalName, + kPortalPath, pPortalSettings, nullptr, &error); + + if (error != nullptr) { + g_debug("XDG desktop portal settings unavailable: %s", error->message); + return false; + } + + for (const FlSetting setting : all_settings) { + g_autoptr(GVariant) value = nullptr; + if (settings_portal_read(self->dbus_proxy, setting.ns, setting.key, + &value)) { + fl_settings_portal_set_value(self, &setting, value); + } + } + + g_signal_connect_object(self->dbus_proxy, "g-signal", + G_CALLBACK(settings_portal_changed_cb), self, + GConnectFlags(0)); + + return true; +} diff --git a/shell/platform/linux/fl_settings_portal.h b/shell/platform/linux/fl_settings_portal.h new file mode 100644 index 0000000000000..4920dad8f44fd --- /dev/null +++ b/shell/platform/linux/fl_settings_portal.h @@ -0,0 +1,46 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_SETTINGS_PORTAL_H_ +#define FLUTTER_SHELL_PLATFORM_LINUX_FL_SETTINGS_PORTAL_H_ + +#include "flutter/shell/platform/linux/fl_settings.h" + +G_BEGIN_DECLS + +G_DECLARE_FINAL_TYPE(FlSettingsPortal, + fl_settings_portal, + FL, + SETTINGS_PORTAL, + GObject); + +/** + * FlSettingsPortal: + * #FlSettingsPortal reads settings from the XDG desktop portal. + */ + +/** + * fl_settings_portal_new: + * @values: (nullable): a #GVariantDict with values for testing. + * + * Creates a new settings portal instance. + * + * Returns: a new #FlSettingsPortal. + */ +FlSettingsPortal* fl_settings_portal_new(GVariantDict* values); + +/** + * fl_settings_portal_start: + * @portal: an #FlSettingsPortal. + * + * Reads the current settings and starts monitoring for changes in the desktop + * portal settings. + * + * Returns: %TRUE on success, or %FALSE if the portal is not available. + */ +gboolean fl_settings_portal_start(FlSettingsPortal* portal); + +G_END_DECLS + +#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_SETTINGS_PORTAL_H_ diff --git a/shell/platform/linux/fl_settings_portal_test.cc b/shell/platform/linux/fl_settings_portal_test.cc new file mode 100644 index 0000000000000..f691bc1a0ec94 --- /dev/null +++ b/shell/platform/linux/fl_settings_portal_test.cc @@ -0,0 +1,68 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/linux/fl_settings_portal.h" +#include "flutter/shell/platform/linux/testing/fl_test.h" +#include "flutter/testing/testing.h" + +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +TEST(FlSettingsPortalTest, ClockFormat) { + g_autoptr(GVariantDict) settings = g_variant_dict_new(nullptr); + + g_autoptr(FlSettings) portal = FL_SETTINGS(fl_settings_portal_new(settings)); + EXPECT_EQ(fl_settings_get_clock_format(portal), FL_CLOCK_FORMAT_24H); + + g_variant_dict_insert_value(settings, + "org.gnome.desktop.interface::clock-format", + g_variant_new_string("24h")); + EXPECT_EQ(fl_settings_get_clock_format(portal), FL_CLOCK_FORMAT_24H); + + g_variant_dict_insert_value(settings, + "org.gnome.desktop.interface::clock-format", + g_variant_new_string("12h")); + EXPECT_EQ(fl_settings_get_clock_format(portal), FL_CLOCK_FORMAT_12H); + + g_variant_dict_insert_value(settings, + "org.gnome.desktop.interface::clock-format", + g_variant_new_string("unknown")); + EXPECT_EQ(fl_settings_get_clock_format(portal), FL_CLOCK_FORMAT_24H); +} + +TEST(FlSettingsPortalTest, ColorScheme) { + g_autoptr(GVariantDict) settings = g_variant_dict_new(nullptr); + + g_autoptr(FlSettings) portal = FL_SETTINGS(fl_settings_portal_new(settings)); + EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_LIGHT); + + g_variant_dict_insert_value(settings, + "org.freedesktop.appearance::color-scheme", + g_variant_new_uint32(1)); + EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_DARK); + + g_variant_dict_insert_value(settings, + "org.freedesktop.appearance::color-scheme", + g_variant_new_uint32(2)); + EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_LIGHT); + + g_variant_dict_insert_value(settings, + "org.freedesktop.appearance::color-scheme", + g_variant_new_uint32(123)); + EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_LIGHT); +} + +TEST(FlSettingsPortalTest, TextScalingFactor) { + g_autoptr(GVariantDict) settings = g_variant_dict_new(nullptr); + + g_autoptr(FlSettings) portal = FL_SETTINGS(fl_settings_portal_new(settings)); + EXPECT_EQ(fl_settings_get_text_scaling_factor(portal), 1.0); + + g_variant_dict_insert_value( + settings, "org.gnome.desktop.interface::text-scaling-factor", + g_variant_new_double(1.5)); + EXPECT_EQ(fl_settings_get_text_scaling_factor(portal), 1.5); +} From 62824fe824399fc8e4af193633c447f02e000796 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 4 May 2022 14:43:56 +0200 Subject: [PATCH 2/9] Update licenses --- ci/licenses_golden/licenses_flutter | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 77997513f80b8..f15a4e69606b9 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -2151,6 +2151,9 @@ FILE: ../../../flutter/shell/platform/linux/fl_settings.h FILE: ../../../flutter/shell/platform/linux/fl_settings_plugin.cc FILE: ../../../flutter/shell/platform/linux/fl_settings_plugin.h FILE: ../../../flutter/shell/platform/linux/fl_settings_plugin_test.cc +FILE: ../../../flutter/shell/platform/linux/fl_settings_portal.cc +FILE: ../../../flutter/shell/platform/linux/fl_settings_portal.h +FILE: ../../../flutter/shell/platform/linux/fl_settings_portal_test.cc FILE: ../../../flutter/shell/platform/linux/fl_standard_message_codec.cc FILE: ../../../flutter/shell/platform/linux/fl_standard_message_codec_private.h FILE: ../../../flutter/shell/platform/linux/fl_standard_message_codec_test.cc From 8f3b9a3563bf99b2f085f8e28c9c2046b7f10bbf Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 4 May 2022 15:47:38 +0200 Subject: [PATCH 3/9] FlSettingsPortal: add fallback for gtk-theme --- shell/platform/linux/fl_settings_portal.cc | 12 ++++++ .../platform/linux/fl_settings_portal_test.cc | 39 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/shell/platform/linux/fl_settings_portal.cc b/shell/platform/linux/fl_settings_portal.cc index 1d581bea38c78..084ca3603c512 100644 --- a/shell/platform/linux/fl_settings_portal.cc +++ b/shell/platform/linux/fl_settings_portal.cc @@ -30,6 +30,11 @@ static const FlSetting kClockFormat = { "clock-format", G_VARIANT_TYPE_STRING, }; +static const FlSetting kGtkTheme = { + kGnomeDesktopInterface, + "gtk-theme", + G_VARIANT_TYPE_STRING, +}; static const FlSetting kTextScalingFactor = { kGnomeDesktopInterface, "text-scaling-factor", @@ -39,10 +44,12 @@ static const FlSetting kTextScalingFactor = { static const FlSetting all_settings[] = { kClockFormat, kColorScheme, + kGtkTheme, kTextScalingFactor, }; static constexpr char kClockFormat12Hour[] = "12h"; +static constexpr char kGtkThemeDarkSuffix[] = "-dark"; typedef enum { DEFAULT, PREFER_DARK, PREFER_LIGHT } ColorScheme; @@ -119,6 +126,11 @@ static FlColorScheme fl_settings_portal_get_color_scheme(FlSettings* settings) { if (g_variant_get_uint32(value) == PREFER_DARK) { color_scheme = FL_COLOR_SCHEME_DARK; } + } else if (fl_settings_portal_get_value(self, &kGtkTheme, &value)) { + const gchar* gtk_theme_str = g_variant_get_string(value, nullptr); + if (g_str_has_suffix(gtk_theme_str, kGtkThemeDarkSuffix)) { + color_scheme = FL_COLOR_SCHEME_DARK; + } } return color_scheme; diff --git a/shell/platform/linux/fl_settings_portal_test.cc b/shell/platform/linux/fl_settings_portal_test.cc index f691bc1a0ec94..52937d34b1d1c 100644 --- a/shell/platform/linux/fl_settings_portal_test.cc +++ b/shell/platform/linux/fl_settings_portal_test.cc @@ -53,6 +53,45 @@ TEST(FlSettingsPortalTest, ColorScheme) { "org.freedesktop.appearance::color-scheme", g_variant_new_uint32(123)); EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_LIGHT); + + // color-scheme takes precedence over gtk-theme + g_variant_dict_insert_value(settings, + "org.gnome.desktop.interface::gtk-theme", + g_variant_new_string("Yaru-dark")); + EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_LIGHT); +} + +TEST(FlSettingsPortalTest, GtkTheme) { + g_autoptr(GVariantDict) settings = g_variant_dict_new(nullptr); + + g_autoptr(FlSettings) portal = FL_SETTINGS(fl_settings_portal_new(settings)); + EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_LIGHT); + + g_variant_dict_insert_value(settings, + "org.gnome.desktop.interface::gtk-theme", + g_variant_new_string("Yaru-dark")); + EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_DARK); + + g_variant_dict_insert_value(settings, + "org.gnome.desktop.interface::gtk-theme", + g_variant_new_string("Yaru")); + EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_LIGHT); + + g_variant_dict_insert_value(settings, + "org.gnome.desktop.interface::gtk-theme", + g_variant_new_string("Adwaita")); + EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_LIGHT); + + g_variant_dict_insert_value(settings, + "org.gnome.desktop.interface::gtk-theme", + g_variant_new_string("Adwaita-dark")); + EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_DARK); + + // color-scheme takes precedence over gtk-theme + g_variant_dict_insert_value(settings, + "org.freedesktop.appearance::color-scheme", + g_variant_new_uint32(2)); + EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_LIGHT); } TEST(FlSettingsPortalTest, TextScalingFactor) { From 6249e87f9934ab0d49a042fe3f7db88895e5ab21 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 5 May 2022 07:32:13 +0200 Subject: [PATCH 4/9] Remove unused FL_SETTINGS_PORTAL_GET_PRIVATE() --- shell/platform/linux/fl_settings_portal.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/shell/platform/linux/fl_settings_portal.cc b/shell/platform/linux/fl_settings_portal.cc index 084ca3603c512..e89630f3fc6a5 100644 --- a/shell/platform/linux/fl_settings_portal.cc +++ b/shell/platform/linux/fl_settings_portal.cc @@ -68,9 +68,6 @@ G_DEFINE_TYPE_WITH_CODE(FlSettingsPortal, G_IMPLEMENT_INTERFACE(fl_settings_get_type(), fl_settings_portal_iface_init)) -#define FL_SETTINGS_PORTAL_GET_PRIVATE(portal) \ - ((FlSettingsPortalPrivate*)fl_settings_portal_get_instance_private(portal)) - static const gchar* fl_settings_portal_format_key(const FlSetting* setting) { return g_strconcat(setting->ns, "::", setting->key, nullptr); } From ae480a63d581f75a1f85d0269adeaf4c2bb0c1bf Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 5 May 2022 07:32:32 +0200 Subject: [PATCH 5/9] Remove const --- shell/platform/linux/fl_settings_portal.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/linux/fl_settings_portal.cc b/shell/platform/linux/fl_settings_portal.cc index e89630f3fc6a5..fad961233fe36 100644 --- a/shell/platform/linux/fl_settings_portal.cc +++ b/shell/platform/linux/fl_settings_portal.cc @@ -68,7 +68,7 @@ G_DEFINE_TYPE_WITH_CODE(FlSettingsPortal, G_IMPLEMENT_INTERFACE(fl_settings_get_type(), fl_settings_portal_iface_init)) -static const gchar* fl_settings_portal_format_key(const FlSetting* setting) { +static gchar* fl_settings_portal_format_key(const FlSetting* setting) { return g_strconcat(setting->ns, "::", setting->key, nullptr); } From 339e250c9b91a53cc418e4945002a8d93ef4ded0 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 5 May 2022 07:33:44 +0200 Subject: [PATCH 6/9] Remove fl_settings_portal_ prefix --- shell/platform/linux/fl_settings_portal.cc | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/shell/platform/linux/fl_settings_portal.cc b/shell/platform/linux/fl_settings_portal.cc index fad961233fe36..2580406b18a50 100644 --- a/shell/platform/linux/fl_settings_portal.cc +++ b/shell/platform/linux/fl_settings_portal.cc @@ -68,33 +68,33 @@ G_DEFINE_TYPE_WITH_CODE(FlSettingsPortal, G_IMPLEMENT_INTERFACE(fl_settings_get_type(), fl_settings_portal_iface_init)) -static gchar* fl_settings_portal_format_key(const FlSetting* setting) { +static gchar* format_key(const FlSetting* setting) { return g_strconcat(setting->ns, "::", setting->key, nullptr); } -static gboolean fl_settings_portal_get_value(FlSettingsPortal* self, - const FlSetting* setting, - GVariant** value) { - g_autofree const gchar* key = fl_settings_portal_format_key(setting); - *value = g_variant_dict_lookup_value(self->values, key, setting->type); +static gboolean get_value(FlSettingsPortal* portal, + const FlSetting* setting, + GVariant** value) { + g_autofree const gchar* key = format_key(setting); + *value = g_variant_dict_lookup_value(portal->values, key, setting->type); return *value != nullptr; } -static void fl_settings_portal_set_value(FlSettingsPortal* self, - const FlSetting* setting, - GVariant* value) { - g_autofree const gchar* key = fl_settings_portal_format_key(setting); +static void set_value(FlSettingsPortal* portal, + const FlSetting* setting, + GVariant* value) { + g_autofree const gchar* key = format_key(setting); // ignore redundant changes from multiple XDG desktop portal backends g_autoptr(GVariant) old_value = - g_variant_dict_lookup_value(self->values, key, nullptr); + g_variant_dict_lookup_value(portal->values, key, nullptr); if (old_value != nullptr && value != nullptr && g_variant_equal(old_value, value)) { return; } - g_variant_dict_insert_value(self->values, key, value); - fl_settings_emit_changed(FL_SETTINGS(self)); + g_variant_dict_insert_value(portal->values, key, value); + fl_settings_emit_changed(FL_SETTINGS(portal)); } static FlClockFormat fl_settings_portal_get_clock_format(FlSettings* settings) { @@ -103,7 +103,7 @@ static FlClockFormat fl_settings_portal_get_clock_format(FlSettings* settings) { FlClockFormat clock_format = FL_CLOCK_FORMAT_24H; g_autoptr(GVariant) value = nullptr; - if (fl_settings_portal_get_value(self, &kClockFormat, &value)) { + if (get_value(self, &kClockFormat, &value)) { const gchar* clock_format_str = g_variant_get_string(value, nullptr); if (g_strcmp0(clock_format_str, kClockFormat12Hour) == 0) { clock_format = FL_CLOCK_FORMAT_12H; @@ -119,11 +119,11 @@ static FlColorScheme fl_settings_portal_get_color_scheme(FlSettings* settings) { FlColorScheme color_scheme = FL_COLOR_SCHEME_LIGHT; g_autoptr(GVariant) value = nullptr; - if (fl_settings_portal_get_value(self, &kColorScheme, &value)) { + if (get_value(self, &kColorScheme, &value)) { if (g_variant_get_uint32(value) == PREFER_DARK) { color_scheme = FL_COLOR_SCHEME_DARK; } - } else if (fl_settings_portal_get_value(self, &kGtkTheme, &value)) { + } else if (get_value(self, &kGtkTheme, &value)) { const gchar* gtk_theme_str = g_variant_get_string(value, nullptr); if (g_str_has_suffix(gtk_theme_str, kGtkThemeDarkSuffix)) { color_scheme = FL_COLOR_SCHEME_DARK; @@ -140,7 +140,7 @@ static gdouble fl_settings_portal_get_text_scaling_factor( gdouble scaling_factor = 1.0; g_autoptr(GVariant) value = nullptr; - if (fl_settings_portal_get_value(self, &kTextScalingFactor, &value)) { + if (get_value(self, &kTextScalingFactor, &value)) { scaling_factor = g_variant_get_double(value); } @@ -226,7 +226,7 @@ static void settings_portal_changed_cb(GDBusProxy* proxy, FlSetting setting; g_autoptr(GVariant) value = nullptr; g_variant_get(parameters, "(&s&sv)", &setting.ns, &setting.key, &value); - fl_settings_portal_set_value(portal, &setting, value); + set_value(portal, &setting, value); } gboolean fl_settings_portal_start(FlSettingsPortal* self) { @@ -248,7 +248,7 @@ gboolean fl_settings_portal_start(FlSettingsPortal* self) { g_autoptr(GVariant) value = nullptr; if (settings_portal_read(self->dbus_proxy, setting.ns, setting.key, &value)) { - fl_settings_portal_set_value(self, &setting, value); + set_value(self, &setting, value); } } From ec65f54d6ff6bca271317a355ce809b053cd0ea4 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 5 May 2022 07:39:41 +0200 Subject: [PATCH 7/9] Move static functions to the top --- shell/platform/linux/fl_settings_portal.cc | 104 ++++++++++----------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/shell/platform/linux/fl_settings_portal.cc b/shell/platform/linux/fl_settings_portal.cc index 2580406b18a50..d0cb15727740f 100644 --- a/shell/platform/linux/fl_settings_portal.cc +++ b/shell/platform/linux/fl_settings_portal.cc @@ -97,6 +97,58 @@ static void set_value(FlSettingsPortal* portal, fl_settings_emit_changed(FL_SETTINGS(portal)); } +// Based on +// https://gitlab.gnome.org/GNOME/Initiatives/-/wikis/Dark-Style-Preference#other +static gboolean settings_portal_read(GDBusProxy* proxy, + const gchar* ns, + const gchar* key, + GVariant** out) { + g_autoptr(GError) error = nullptr; + g_autoptr(GVariant) value = + g_dbus_proxy_call_sync(proxy, "Read", g_variant_new("(ss)", ns, key), + G_DBUS_CALL_FLAGS_NONE, G_MAXINT, nullptr, &error); + + if (error) { + if (error->domain == G_DBUS_ERROR && + error->code == G_DBUS_ERROR_SERVICE_UNKNOWN) { + g_debug("XDG desktop portal unavailable: %s", error->message); + return false; + } + + if (error->domain == G_DBUS_ERROR && + error->code == G_DBUS_ERROR_UNKNOWN_METHOD) { + g_debug("XDG desktop portal settings unavailable: %s", error->message); + return false; + } + + g_critical("Failed to read XDG desktop portal settings: %s", + error->message); + return false; + } + + g_autoptr(GVariant) child = nullptr; + g_variant_get(value, "(v)", &child); + g_variant_get(child, "v", out); + + return true; +} + +static void settings_portal_changed_cb(GDBusProxy* proxy, + const char* sender_name, + const char* signal_name, + GVariant* parameters, + gpointer user_data) { + FlSettingsPortal* portal = FL_SETTINGS_PORTAL(user_data); + if (g_strcmp0(signal_name, "SettingChanged")) { + return; + } + + FlSetting setting; + g_autoptr(GVariant) value = nullptr; + g_variant_get(parameters, "(&s&sv)", &setting.ns, &setting.key, &value); + set_value(portal, &setting, value); +} + static FlClockFormat fl_settings_portal_get_clock_format(FlSettings* settings) { FlSettingsPortal* self = FL_SETTINGS_PORTAL(settings); @@ -177,58 +229,6 @@ FlSettingsPortal* fl_settings_portal_new(GVariantDict* values) { return portal; } -// Based on -// https://gitlab.gnome.org/GNOME/Initiatives/-/wikis/Dark-Style-Preference#other -static gboolean settings_portal_read(GDBusProxy* proxy, - const gchar* ns, - const gchar* key, - GVariant** out) { - g_autoptr(GError) error = nullptr; - g_autoptr(GVariant) value = - g_dbus_proxy_call_sync(proxy, "Read", g_variant_new("(ss)", ns, key), - G_DBUS_CALL_FLAGS_NONE, G_MAXINT, nullptr, &error); - - if (error) { - if (error->domain == G_DBUS_ERROR && - error->code == G_DBUS_ERROR_SERVICE_UNKNOWN) { - g_debug("XDG desktop portal unavailable: %s", error->message); - return false; - } - - if (error->domain == G_DBUS_ERROR && - error->code == G_DBUS_ERROR_UNKNOWN_METHOD) { - g_debug("XDG desktop portal settings unavailable: %s", error->message); - return false; - } - - g_critical("Failed to read XDG desktop portal settings: %s", - error->message); - return false; - } - - g_autoptr(GVariant) child = nullptr; - g_variant_get(value, "(v)", &child); - g_variant_get(child, "v", out); - - return true; -} - -static void settings_portal_changed_cb(GDBusProxy* proxy, - const char* sender_name, - const char* signal_name, - GVariant* parameters, - gpointer user_data) { - FlSettingsPortal* portal = FL_SETTINGS_PORTAL(user_data); - if (g_strcmp0(signal_name, "SettingChanged")) { - return; - } - - FlSetting setting; - g_autoptr(GVariant) value = nullptr; - g_variant_get(parameters, "(&s&sv)", &setting.ns, &setting.key, &value); - set_value(portal, &setting, value); -} - gboolean fl_settings_portal_start(FlSettingsPortal* self) { g_return_val_if_fail(FL_IS_SETTINGS_PORTAL(self), false); g_return_val_if_fail(self->dbus_proxy == nullptr, false); From c06c650bd934f256924638ddc014497ef84cbc7e Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 5 May 2022 07:44:20 +0200 Subject: [PATCH 8/9] Add error output argument to fl_settings_portal_start() --- shell/platform/linux/fl_settings.cc | 6 +++++- shell/platform/linux/fl_settings_portal.cc | 9 +++------ shell/platform/linux/fl_settings_portal.h | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/shell/platform/linux/fl_settings.cc b/shell/platform/linux/fl_settings.cc index 148116417f052..52bcc0abdb780 100644 --- a/shell/platform/linux/fl_settings.cc +++ b/shell/platform/linux/fl_settings.cc @@ -46,8 +46,12 @@ void fl_settings_emit_changed(FlSettings* self) { FlSettings* fl_settings_new() { g_autoptr(FlSettingsPortal) portal = fl_settings_portal_new(nullptr); - if (!fl_settings_portal_start(portal)) { + + g_autoptr(GError) error = nullptr; + if (!fl_settings_portal_start(portal, &error)) { + g_debug("XDG desktop portal settings unavailable: %s", error->message); return fl_gnome_settings_new(); } + return FL_SETTINGS(g_object_ref(portal)); } diff --git a/shell/platform/linux/fl_settings_portal.cc b/shell/platform/linux/fl_settings_portal.cc index d0cb15727740f..33eeaf089de0f 100644 --- a/shell/platform/linux/fl_settings_portal.cc +++ b/shell/platform/linux/fl_settings_portal.cc @@ -229,18 +229,15 @@ FlSettingsPortal* fl_settings_portal_new(GVariantDict* values) { return portal; } -gboolean fl_settings_portal_start(FlSettingsPortal* self) { +gboolean fl_settings_portal_start(FlSettingsPortal* self, GError** error) { g_return_val_if_fail(FL_IS_SETTINGS_PORTAL(self), false); g_return_val_if_fail(self->dbus_proxy == nullptr, false); - g_autoptr(GError) error = nullptr; - self->dbus_proxy = g_dbus_proxy_new_for_bus_sync( G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, nullptr, kPortalName, - kPortalPath, pPortalSettings, nullptr, &error); + kPortalPath, pPortalSettings, nullptr, error); - if (error != nullptr) { - g_debug("XDG desktop portal settings unavailable: %s", error->message); + if (self->dbus_proxy == nullptr) { return false; } diff --git a/shell/platform/linux/fl_settings_portal.h b/shell/platform/linux/fl_settings_portal.h index 4920dad8f44fd..e8b57a545d199 100644 --- a/shell/platform/linux/fl_settings_portal.h +++ b/shell/platform/linux/fl_settings_portal.h @@ -33,13 +33,14 @@ FlSettingsPortal* fl_settings_portal_new(GVariantDict* values); /** * fl_settings_portal_start: * @portal: an #FlSettingsPortal. + * @error: (allow-none): #GError location to store the error occurring, or %NULL * * Reads the current settings and starts monitoring for changes in the desktop * portal settings. * * Returns: %TRUE on success, or %FALSE if the portal is not available. */ -gboolean fl_settings_portal_start(FlSettingsPortal* portal); +gboolean fl_settings_portal_start(FlSettingsPortal* portal, GError** error); G_END_DECLS From ac16446d772038553ca9b1ed8f90f44d7f69f0c2 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 5 May 2022 07:54:29 +0200 Subject: [PATCH 9/9] Add separate fl_settings_portal_new_with_values() --- shell/platform/linux/fl_settings.cc | 2 +- shell/platform/linux/fl_settings_portal.cc | 11 ++++++++--- shell/platform/linux/fl_settings_portal.h | 13 +++++++++++-- shell/platform/linux/fl_settings_portal_test.cc | 12 ++++++++---- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/shell/platform/linux/fl_settings.cc b/shell/platform/linux/fl_settings.cc index 52bcc0abdb780..e464c46354951 100644 --- a/shell/platform/linux/fl_settings.cc +++ b/shell/platform/linux/fl_settings.cc @@ -45,7 +45,7 @@ void fl_settings_emit_changed(FlSettings* self) { } FlSettings* fl_settings_new() { - g_autoptr(FlSettingsPortal) portal = fl_settings_portal_new(nullptr); + g_autoptr(FlSettingsPortal) portal = fl_settings_portal_new(); g_autoptr(GError) error = nullptr; if (!fl_settings_portal_start(portal, &error)) { diff --git a/shell/platform/linux/fl_settings_portal.cc b/shell/platform/linux/fl_settings_portal.cc index 33eeaf089de0f..455904f4ad019 100644 --- a/shell/platform/linux/fl_settings_portal.cc +++ b/shell/platform/linux/fl_settings_portal.cc @@ -221,11 +221,16 @@ static void fl_settings_portal_iface_init(FlSettingsInterface* iface) { static void fl_settings_portal_init(FlSettingsPortal* self) {} -FlSettingsPortal* fl_settings_portal_new(GVariantDict* values) { +FlSettingsPortal* fl_settings_portal_new() { + g_autoptr(GVariantDict) values = g_variant_dict_new(nullptr); + return fl_settings_portal_new_with_values(values); +} + +FlSettingsPortal* fl_settings_portal_new_with_values(GVariantDict* values) { + g_return_val_if_fail(values != nullptr, nullptr); FlSettingsPortal* portal = FL_SETTINGS_PORTAL(g_object_new(fl_settings_portal_get_type(), nullptr)); - portal->values = - values ? g_variant_dict_ref(values) : g_variant_dict_new(nullptr); + portal->values = g_variant_dict_ref(values); return portal; } diff --git a/shell/platform/linux/fl_settings_portal.h b/shell/platform/linux/fl_settings_portal.h index e8b57a545d199..cf8d2544d1d4b 100644 --- a/shell/platform/linux/fl_settings_portal.h +++ b/shell/platform/linux/fl_settings_portal.h @@ -22,13 +22,22 @@ G_DECLARE_FINAL_TYPE(FlSettingsPortal, /** * fl_settings_portal_new: - * @values: (nullable): a #GVariantDict with values for testing. * * Creates a new settings portal instance. * * Returns: a new #FlSettingsPortal. */ -FlSettingsPortal* fl_settings_portal_new(GVariantDict* values); +FlSettingsPortal* fl_settings_portal_new(); + +/** + * fl_settings_portal_new_with_values: + * @values: (nullable): a #GVariantDict. + * + * Creates a new settings portal instance with initial values for testing. + * + * Returns: a new #FlSettingsPortal. + */ +FlSettingsPortal* fl_settings_portal_new_with_values(GVariantDict* values); /** * fl_settings_portal_start: diff --git a/shell/platform/linux/fl_settings_portal_test.cc b/shell/platform/linux/fl_settings_portal_test.cc index 52937d34b1d1c..4130a8cb1a84d 100644 --- a/shell/platform/linux/fl_settings_portal_test.cc +++ b/shell/platform/linux/fl_settings_portal_test.cc @@ -14,7 +14,8 @@ TEST(FlSettingsPortalTest, ClockFormat) { g_autoptr(GVariantDict) settings = g_variant_dict_new(nullptr); - g_autoptr(FlSettings) portal = FL_SETTINGS(fl_settings_portal_new(settings)); + g_autoptr(FlSettings) portal = + FL_SETTINGS(fl_settings_portal_new_with_values(settings)); EXPECT_EQ(fl_settings_get_clock_format(portal), FL_CLOCK_FORMAT_24H); g_variant_dict_insert_value(settings, @@ -36,7 +37,8 @@ TEST(FlSettingsPortalTest, ClockFormat) { TEST(FlSettingsPortalTest, ColorScheme) { g_autoptr(GVariantDict) settings = g_variant_dict_new(nullptr); - g_autoptr(FlSettings) portal = FL_SETTINGS(fl_settings_portal_new(settings)); + g_autoptr(FlSettings) portal = + FL_SETTINGS(fl_settings_portal_new_with_values(settings)); EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_LIGHT); g_variant_dict_insert_value(settings, @@ -64,7 +66,8 @@ TEST(FlSettingsPortalTest, ColorScheme) { TEST(FlSettingsPortalTest, GtkTheme) { g_autoptr(GVariantDict) settings = g_variant_dict_new(nullptr); - g_autoptr(FlSettings) portal = FL_SETTINGS(fl_settings_portal_new(settings)); + g_autoptr(FlSettings) portal = + FL_SETTINGS(fl_settings_portal_new_with_values(settings)); EXPECT_EQ(fl_settings_get_color_scheme(portal), FL_COLOR_SCHEME_LIGHT); g_variant_dict_insert_value(settings, @@ -97,7 +100,8 @@ TEST(FlSettingsPortalTest, GtkTheme) { TEST(FlSettingsPortalTest, TextScalingFactor) { g_autoptr(GVariantDict) settings = g_variant_dict_new(nullptr); - g_autoptr(FlSettings) portal = FL_SETTINGS(fl_settings_portal_new(settings)); + g_autoptr(FlSettings) portal = + FL_SETTINGS(fl_settings_portal_new_with_values(settings)); EXPECT_EQ(fl_settings_get_text_scaling_factor(portal), 1.0); g_variant_dict_insert_value(