[gtk/wip/settings-portal: 3/4] wayland: Support the settings portal



commit 5a90940a127e533252a6f8ed2c95c4db4fcfac73
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Nov 1 19:47:46 2018 -0400

    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.

 gdk/wayland/gdkdisplay-wayland.c | 343 ++++++++++++++++++++++++++++++++++-----
 gdk/wayland/gdkdisplay-wayland.h |   1 +
 2 files changed, 305 insertions(+), 39 deletions(-)
---
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c
index 0e49ce2773..d576fa8878 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);
 }
@@ -1369,6 +1372,23 @@ _gdk_wayland_is_shm_surface (cairo_surface_t *surface)
   return cairo_surface_get_user_data (surface, &gdk_wayland_shm_surface_cairo_key) != NULL;
 }
 
+/* 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;
+};
+
 typedef enum
 {
   GSD_FONT_ANTIALIASING_MODE_NONE,
@@ -1376,6 +1396,20 @@ 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;
+
+  g_warning ("antialiasing: %s not found", s);
+  return 0;
+}
+
 typedef enum
 {
   GSD_FONT_HINTING_NONE,
@@ -1384,6 +1418,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 +1440,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 +1469,10 @@ get_dpi_from_gsettings (GdkWaylandDisplay *display_wayland)
   return 96.0 * factor;
 }
 
+
+static TranslationEntry * find_translation_entry_by_schema (const char *schema,
+                                                            const char *key);
+
 static void
 update_xft_settings (GdkDisplay *display)
 {
@@ -1419,25 +1483,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 +1610,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 +1634,42 @@ 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 } }
 };
 
+
 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 *
@@ -1625,6 +1704,71 @@ 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, "PropertyChanged") == 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)
+        {
+          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)
 {
@@ -1634,6 +1778,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 +1928,41 @@ 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:
+          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 +2014,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 +2058,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;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]