Merge branch 'wip/settings-portal' into 'master'

settings portal

See merge request GNOME/gtk!403
This commit is contained in:
Matthias Clasen 2018-11-04 20:57:26 +00:00
commit 5028cb35bc
10 changed files with 338 additions and 77 deletions

View File

@ -32,6 +32,7 @@ void gdk_display_set_cursor_theme (GdkDisplay *display,
const char *theme,
int size);
gboolean gdk_running_in_sandbox (void);
gboolean gdk_should_use_portal (void);
const gchar * gdk_get_startup_notification_id (void);

View File

@ -269,14 +269,27 @@ gdk_get_startup_notification_id (void)
gboolean
gdk_running_in_sandbox (void)
{
char *path;
gboolean ret;
return g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
}
path = g_build_filename (g_get_user_runtime_dir (), "flatpak-info", NULL);
ret = g_file_test (path, G_FILE_TEST_EXISTS);
g_free (path);
gboolean
gdk_should_use_portal (void)
{
static const char *use_portal = NULL;
return ret;
if (G_UNLIKELY (use_portal == NULL))
{
if (gdk_running_in_sandbox ())
use_portal = "1";
else
{
use_portal = g_getenv ("GTK_USE_PORTAL");
if (!use_portal)
use_portal = "";
}
}
return use_portal[0] == '1';
}
/**

View File

@ -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 *
@ -1625,6 +1703,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)
{
@ -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);

View File

@ -77,6 +77,7 @@ struct _GdkWaylandDisplay
GHashTable *settings;
GsdXftSettings xft_settings;
GDBusProxy *settings_portal;
guint32 shell_capabilities;

View File

@ -259,7 +259,7 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
dbus->object_path = g_application_get_dbus_object_path (G_APPLICATION (impl->application));
dbus->unique_name = g_dbus_connection_get_unique_name (dbus->session);
if (gtk_should_use_portal ())
if (gdk_should_use_portal ())
goto out;
g_debug ("Connecting to session manager");

View File

@ -53,7 +53,7 @@ gtk_color_picker_portal_initable_init (GInitable *initable,
GVariant *ret;
guint version;
if (!gtk_should_use_portal ())
if (!gdk_should_use_portal ())
return FALSE;
picker->portal_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,

View File

@ -406,7 +406,7 @@ gtk_file_chooser_native_portal_show (GtkFileChooserNative *self)
GtkFileChooserAction action;
const char *method_name;
if (!gtk_should_use_portal ())
if (!gdk_should_use_portal ())
return FALSE;
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);

View File

@ -1217,7 +1217,7 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
GtkWindow *parent,
gboolean *do_print)
{
if (gtk_should_use_portal ())
if (gdk_should_use_portal ())
return gtk_print_operation_portal_run_dialog (op, show_dialog, parent, do_print);
else
return gtk_print_operation_unix_run_dialog (op, show_dialog, parent, do_print);
@ -1228,7 +1228,7 @@ _gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation
GtkWindow *parent,
GtkPrintOperationPrintFunc print_cb)
{
if (gtk_should_use_portal ())
if (gdk_should_use_portal ())
gtk_print_operation_portal_run_dialog_async (op, show_dialog, parent, print_cb);
else
gtk_print_operation_unix_run_dialog_async (op, show_dialog, parent, print_cb);
@ -1240,7 +1240,7 @@ _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
GtkWindow *parent,
const gchar *filename)
{
if (gtk_should_use_portal ())
if (gdk_should_use_portal ())
gtk_print_operation_portal_launch_preview (op, surface, parent, filename);
else
gtk_print_operation_unix_launch_preview (op, surface, parent, filename);

View File

@ -268,30 +268,6 @@ _gtk_ensure_resources (void)
g_once (&register_resources_once, register_resources, NULL);
}
gboolean
gtk_should_use_portal (void)
{
static const char *use_portal = NULL;
if (G_UNLIKELY (use_portal == NULL))
{
char *path;
path = g_build_filename (g_get_user_runtime_dir (), "flatpak-info", NULL);
if (g_file_test (path, G_FILE_TEST_EXISTS))
use_portal = "1";
else
{
use_portal = g_getenv ("GTK_USE_PORTAL");
if (!use_portal)
use_portal = "";
}
g_free (path);
}
return use_portal[0] == '1';
}
static char *
get_portal_path (GDBusConnection *connection,
const char *kind,

View File

@ -27,6 +27,7 @@
#include <glib-object.h>
#include <gdk/gdk.h>
#include <gdk/gdk-private.h>
#include "gtkcsstypesprivate.h"
#include "gtktexthandleprivate.h"
@ -109,7 +110,6 @@ GtkWidget * _gtk_toplevel_pick (GtkWindow *toplevel,
gdouble _gtk_get_slowdown (void);
void _gtk_set_slowdown (gdouble slowdown_factor);
gboolean gtk_should_use_portal (void);
char *gtk_get_portal_request_path (GDBusConnection *connection,
char **token);
char *gtk_get_portal_session_path (GDBusConnection *connection,