diff options
author | Matthias Clasen <mclasen@redhat.com> | 2018-11-01 19:47:46 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2018-11-04 15:44:50 -0500 |
commit | 48b569eae05fdfdf59b50f974b6e8ccb0654ea0b (patch) | |
tree | a307fd882cafba5a514251ecac46aa70c38bd588 /gdk | |
parent | 809966946641af27479fc3a9c349b03cf0fdd05d (diff) | |
download | gtk+-48b569eae05fdfdf59b50f974b6e8ccb0654ea0b.tar.gz |
wayland: Support the settings portal
Under Wayland, we are currently directly using GSettings
for desktop settings. But in a sandbox, we may not have
access to dconf, so this may fail. Use the new settings
portal instead.
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/wayland/gdkdisplay-wayland.c | 350 | ||||
-rw-r--r-- | gdk/wayland/gdkdisplay-wayland.h | 1 |
2 files changed, 311 insertions, 40 deletions
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index 0e49ce2773..4ddb5e3c99 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -730,7 +730,10 @@ gdk_wayland_display_finalize (GObject *object) g_ptr_array_free (display_wayland->monitors, TRUE); - g_hash_table_destroy (display_wayland->settings); + if (display_wayland->settings) + g_hash_table_destroy (display_wayland->settings); + + g_clear_object (&display_wayland->settings_portal); G_OBJECT_CLASS (gdk_wayland_display_parent_class)->finalize (object); } @@ -1376,6 +1379,19 @@ typedef enum GSD_FONT_ANTIALIASING_MODE_RGBA } GsdFontAntialiasingMode; +static int +get_antialiasing (const char *s) +{ + const char *names[] = { "none", "grayscale", "rgba" }; + int i; + + for (i = 0; i < G_N_ELEMENTS (names); i++) + if (strcmp (s, names[i]) == 0) + return i; + + return 0; +} + typedef enum { GSD_FONT_HINTING_NONE, @@ -1384,6 +1400,19 @@ typedef enum GSD_FONT_HINTING_FULL } GsdFontHinting; +static int +get_hinting (const char *s) +{ + const char *names[] = { "none", "slight", "medium", "full" }; + int i; + + for (i = 0; i < G_N_ELEMENTS (names); i++) + if (strcmp (s, names[i]) == 0) + return i; + + return 0; +} + typedef enum { GSD_FONT_RGBA_ORDER_RGBA, @@ -1393,6 +1422,19 @@ typedef enum GSD_FONT_RGBA_ORDER_VBGR } GsdFontRgbaOrder; +static int +get_order (const char *s) +{ + const char *names[] = { "rgba", "rgb", "bgr", "vrgb", "vbgr" }; + int i; + + for (i = 0; i < G_N_ELEMENTS (names); i++) + if (strcmp (s, names[i]) == 0) + return i; + + return 0; +} + static gdouble get_dpi_from_gsettings (GdkWaylandDisplay *display_wayland) { @@ -1409,6 +1451,26 @@ get_dpi_from_gsettings (GdkWaylandDisplay *display_wayland) return 96.0 * factor; } +/* When using the Settings portal, we cache the value in + * the fallback member, and we ignore the valid field + */ +typedef struct _TranslationEntry TranslationEntry; +struct _TranslationEntry { + gboolean valid; + const gchar *schema; + const gchar *key; + const gchar *setting; + GType type; + union { + const char *s; + gint i; + gboolean b; + } fallback; +}; + +static TranslationEntry * find_translation_entry_by_schema (const char *schema, + const char *key); + static void update_xft_settings (GdkDisplay *display) { @@ -1419,25 +1481,47 @@ update_xft_settings (GdkDisplay *display) GsdFontRgbaOrder order; gboolean use_rgba = FALSE; GsdXftSettings xft_settings; + double dpi; - settings = g_hash_table_lookup (display_wayland->settings, - "org.gnome.settings-daemon.plugins.xsettings"); - - if (settings) + if (gdk_should_use_portal ()) { - antialiasing = g_settings_get_enum (settings, "antialiasing"); - hinting = g_settings_get_enum (settings, "hinting"); - order = g_settings_get_enum (settings, "rgba-order"); + TranslationEntry *entry; + + entry = find_translation_entry_by_schema ("org.gnome.settings-daemon.plugins.xsettings", "antialiasing"); + antialiasing = entry->fallback.i; + + entry = find_translation_entry_by_schema ("org.gnome.settings-daemon.plugins.xsettings", "hinting"); + hinting = entry->fallback.i; + + entry = find_translation_entry_by_schema ("org.gnome.settings-daemon.plugins.xsettings", "rgba-order"); + order = entry->fallback.i; + + entry = find_translation_entry_by_schema ("org.gnome.desktop.interface", "text-scaling-factor"); + dpi = 96.0 * entry->fallback.i / 65536.0 * 1024; /* Xft wants 1/1024th of an inch */ } else { - antialiasing = GSD_FONT_ANTIALIASING_MODE_GRAYSCALE; - hinting = GSD_FONT_HINTING_MEDIUM; - order = GSD_FONT_RGBA_ORDER_RGB; + settings = g_hash_table_lookup (display_wayland->settings, + "org.gnome.settings-daemon.plugins.xsettings"); + + if (settings) + { + antialiasing = g_settings_get_enum (settings, "antialiasing"); + hinting = g_settings_get_enum (settings, "hinting"); + order = g_settings_get_enum (settings, "rgba-order"); + } + else + { + antialiasing = GSD_FONT_ANTIALIASING_MODE_GRAYSCALE; + hinting = GSD_FONT_HINTING_MEDIUM; + order = GSD_FONT_RGBA_ORDER_RGB; + } + + dpi = get_dpi_from_gsettings (display_wayland) * 1024; } xft_settings.hinting = (hinting != GSD_FONT_HINTING_NONE); - xft_settings.dpi = get_dpi_from_gsettings (display_wayland) * 1024; /* Xft wants 1/1024ths of an inch */ + xft_settings.dpi = dpi; switch (hinting) { @@ -1524,20 +1608,6 @@ update_xft_settings (GdkDisplay *display) } } -typedef struct _TranslationEntry TranslationEntry; -struct _TranslationEntry { - gboolean valid; - const gchar *schema; - const gchar *key; - const gchar *setting; - GType type; - union { - const gchar *s; - gint i; - gboolean b; - } fallback; -}; - static TranslationEntry translations[] = { { FALSE, "org.gnome.desktop.interface", "gtk-theme", "gtk-theme-name" , G_TYPE_STRING, { .s = "Adwaita" } }, { FALSE, "org.gnome.desktop.interface", "icon-theme", "gtk-icon-theme-name", G_TYPE_STRING, { .s = "gnome" } }, @@ -1562,35 +1632,43 @@ static TranslationEntry translations[] = { { FALSE, "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hinting", G_TYPE_NONE, { .i = 0 } }, { FALSE, "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hintstyle", G_TYPE_NONE, { .i = 0 } }, { FALSE, "org.gnome.settings-daemon.plugins.xsettings", "rgba-order", "gtk-xft-rgba", G_TYPE_NONE, { .i = 0 } }, - { FALSE, "org.gnome.desktop.interface", "text-scaling-factor", "gtk-xft-dpi" , G_TYPE_NONE, { .i = 0 } }, + { FALSE, "org.gnome.desktop.interface", "text-scaling-factor", "gtk-xft-dpi" , G_TYPE_NONE, { .i = 0 } }, /* We store the factor as 16.16 */ { FALSE, "org.gnome.desktop.wm.preferences", "action-double-click-titlebar", "gtk-titlebar-double-click", G_TYPE_STRING, { .s = "toggle-maximize" } }, { FALSE, "org.gnome.desktop.wm.preferences", "action-middle-click-titlebar", "gtk-titlebar-middle-click", G_TYPE_STRING, { .s = "none" } }, { FALSE, "org.gnome.desktop.wm.preferences", "action-right-click-titlebar", "gtk-titlebar-right-click", G_TYPE_STRING, { .s = "menu" } }, - { FALSE, "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } } + { FALSE, "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } }, + { FALSE, "org.gnome.fontconfig", "serial", "gtk-fontconfig-timestamp", G_TYPE_INT, { .i = 0 } } }; + static TranslationEntry * -find_translation_entry_by_key (GSettings *settings, - const char *key) +find_translation_entry_by_schema (const char *schema, + const char *key) { guint i; - char *schema; - - g_object_get (settings, "schema", &schema, NULL); for (i = 0; i < G_N_ELEMENTS (translations); i++) { if (g_str_equal (schema, translations[i].schema) && g_str_equal (key, translations[i].key)) - { - g_free (schema); - return &translations[i]; - } + return &translations[i]; } + return NULL; +} + +static TranslationEntry * +find_translation_entry_by_key (GSettings *settings, + const char *key) +{ + char *schema; + TranslationEntry *entry; + + g_object_get (settings, "schema", &schema, NULL); + entry = find_translation_entry_by_schema (schema, key); g_free (schema); - return NULL; + return entry; } static TranslationEntry * @@ -1626,6 +1704,74 @@ settings_changed (GSettings *settings, } static void +apply_portal_setting (TranslationEntry *entry, + GVariant *value, + GdkDisplay *display) +{ + switch (entry->type) + { + case G_TYPE_STRING: + entry->fallback.s = g_intern_string (g_variant_get_string (value, NULL)); + break; + case G_TYPE_INT: + entry->fallback.i = g_variant_get_int32 (value); + break; + case G_TYPE_BOOLEAN: + entry->fallback.b = g_variant_get_boolean (value); + break; + case G_TYPE_NONE: + if (strcmp (entry->key, "antialiasing") == 0) + entry->fallback.i = get_antialiasing (g_variant_get_string (value, NULL)); + else if (strcmp (entry->key, "hinting") == 0) + entry->fallback.i = get_hinting (g_variant_get_string (value, NULL)); + else if (strcmp (entry->key, "rgba-order") == 0) + entry->fallback.i = get_order (g_variant_get_string (value, NULL)); + else if (strcmp (entry->key, "text-scaling-factor") == 0) + entry->fallback.i = (int) (g_variant_get_double (value) * 65536.0); + update_xft_settings (display); + break; + default: + break; + } +} + +static void +settings_portal_changed (GDBusProxy *proxy, + const char *sender_name, + const char *signal_name, + GVariant *parameters, + GdkDisplay *display) +{ + if (strcmp (signal_name, "SettingChanged") == 0) + { + const char *namespace; + const char *name; + GVariant *value; + TranslationEntry *entry; + + g_variant_get (parameters, "(&s&sv)", &namespace, &name, &value); + + entry = find_translation_entry_by_schema (namespace, name); + if (entry != NULL) + { + char *a = g_variant_print (value, FALSE); + g_debug ("Using changed portal setting %s %s: %s", namespace, name, a); + g_free (a); + apply_portal_setting (entry, value, display); + gdk_display_setting_changed (display, entry->setting); + } + else + g_debug ("Ignoring portal setting %s %s", namespace, name); + + g_variant_unref (value); + } +} + +#define PORTAL_BUS_NAME "org.freedesktop.portal.Desktop" +#define PORTAL_OBJECT_PATH "/org/freedesktop/portal/desktop" +#define PORTAL_SETTINGS_INTERFACE "org.freedesktop.portal.Settings" + +static void init_settings (GdkDisplay *display) { GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); @@ -1634,6 +1780,85 @@ init_settings (GdkDisplay *display) GSettings *settings; gint i; + if (gdk_should_use_portal ()) + { + GVariant *ret; + GError *error = NULL; + const char *schema; + GVariant *val; + GVariantIter *iter; + + display_wayland->settings_portal = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + PORTAL_BUS_NAME, + PORTAL_OBJECT_PATH, + PORTAL_SETTINGS_INTERFACE, + NULL, + &error); + if (error) + { + g_warning ("Settings portal not found: %s", error->message); + g_error_free (error); + + goto fallback; + } + + ret = g_dbus_proxy_call_sync (display_wayland->settings_portal, + "ReadAll", + g_variant_new ("(s)", "org.gnome.*"), + G_DBUS_CALL_FLAGS_NONE, + G_MAXINT, + NULL, + &error); + + if (error) + { + g_warning ("Failed to read portal settings: %s", error->message); + g_error_free (error); + g_clear_object (&display_wayland->settings_portal); + + goto fallback; + } + + g_variant_get (ret, "(a{sa{sv}})", &iter); + + while (g_variant_iter_loop (iter, "{s@a{sv}}", &schema, &val)) + { + GVariantIter *iter2 = g_variant_iter_new (val); + const char *key; + GVariant *v; + + while (g_variant_iter_loop (iter2, "{sv}", &key, &v)) + { + TranslationEntry *entry = find_translation_entry_by_schema (schema, key); + if (entry) + { + char *a = g_variant_print (v, FALSE); + g_debug ("Using portal setting for %s %s: %s\n", schema, key, a); + g_free (a); + apply_portal_setting (entry, v, display); + } + else + { + g_debug ("Ignoring portal setting for %s %s", schema, key); + } + } + g_variant_iter_free (iter2); + } + g_variant_iter_free (iter); + + g_variant_unref (ret); + + g_signal_connect (display_wayland->settings_portal, "g-signal", + G_CALLBACK (settings_portal_changed), display_wayland); + + return; + +fallback: + g_debug ("Failed to use Settings portal; falling back to gsettings"); + } + g_intern_static_string ("antialiasing"); g_intern_static_string ("hinting"); g_intern_static_string ("rgba-order"); @@ -1705,6 +1930,44 @@ set_value_from_entry (GdkDisplay *display, GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); GSettings *settings; + if (gdk_should_use_portal ()) + { + switch (entry->type) + { + case G_TYPE_STRING: + g_value_set_string (value, entry->fallback.s); + break; + case G_TYPE_INT: + if (g_str_equal (entry->setting, "gtk-fontconfig-timestamp")) + g_value_set_uint (value, (guint)entry->fallback.i); + else + g_value_set_int (value, entry->fallback.i); + break; + case G_TYPE_BOOLEAN: + g_value_set_boolean (value, entry->fallback.b); + break; + case G_TYPE_NONE: + if (g_str_equal (entry->setting, "gtk-xft-antialias")) + g_value_set_int (value, display_wayland->xft_settings.antialias); + else if (g_str_equal (entry->setting, "gtk-xft-hinting")) + g_value_set_int (value, display_wayland->xft_settings.hinting); + else if (g_str_equal (entry->setting, "gtk-xft-hintstyle")) + g_value_set_static_string (value, display_wayland->xft_settings.hintstyle); + else if (g_str_equal (entry->setting, "gtk-xft-rgba")) + g_value_set_static_string (value, display_wayland->xft_settings.rgba); + else if (g_str_equal (entry->setting, "gtk-xft-dpi")) + g_value_set_int (value, display_wayland->xft_settings.dpi); + else + g_assert_not_reached (); + break; + default: + g_assert_not_reached (); + break; + } + + return; + } + settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, entry->schema); switch (entry->type) { @@ -1756,7 +2019,13 @@ set_decoration_layout_from_entry (GdkDisplay *display, GValue *value) { GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); - GSettings *settings; + GSettings *settings = NULL; + + if (gdk_should_use_portal ()) + { + g_value_set_string (value, entry->fallback.s); + return; + } settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, entry->schema); @@ -1794,7 +2063,8 @@ gdk_wayland_display_get_setting (GdkDisplay *display, { TranslationEntry *entry; - if (g_hash_table_size (GDK_WAYLAND_DISPLAY (display)->settings) == 0) + if (GDK_WAYLAND_DISPLAY (display)->settings != NULL && + g_hash_table_size (GDK_WAYLAND_DISPLAY (display)->settings) == 0) return FALSE; entry = find_translation_entry_by_setting (name); diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index fa2647cfdb..8f06188841 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -77,6 +77,7 @@ struct _GdkWaylandDisplay GHashTable *settings; GsdXftSettings xft_settings; + GDBusProxy *settings_portal; guint32 shell_capabilities; |