From 519a0fd93d4ff9e825a7318709ec27f7642b1873 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Fri, 1 Sep 2017 13:53:18 +0200 Subject: [PATCH] settings: Add xwayland grab settings Add new settings to control which X11 windows are allowed to issue Xwayland grabs. https://bugzilla.gnome.org/show_bug.cgi?id=783342 --- configure.ac | 16 +++ data/Makefile.am | 1 + data/org.gnome.mutter.wayland.gschema.xml.in | 44 +++++++ src/backends/meta-settings-private.h | 6 + src/backends/meta-settings.c | 120 +++++++++++++++++++ 5 files changed, 187 insertions(+) diff --git a/configure.ac b/configure.ac index 69548673d..44b84da78 100644 --- a/configure.ac +++ b/configure.ac @@ -105,6 +105,7 @@ MUTTER_PC_MODULES=" xcb-randr xcb-res " +XWAYLAND_GRAB_DEFAULT_ACCESS_RULES="gnome-boxes,remote-viewer,virt-viewer,virt-manager,vinagre,vncviewer,Xephyr" GLIB_GSETTINGS @@ -312,6 +313,21 @@ AS_IF([test "$have_wayland" = "yes"], [ ]) AM_CONDITIONAL([HAVE_WAYLAND],[test "$have_wayland" = "yes"]) +AC_ARG_WITH([xwayland-grab-default-access-rules], + [AS_HELP_STRING([--with-xwayland-grab-default-access-rules="app-res1,app-res2,..."], + [comma delimited list of applications ressources or class allowed to issue X11 grabs in Xwayland"])], + [with_XWAYLAND_GRAB_DEFAULT_ACCESS_RULES="$withval"], + [with_XWAYLAND_GRAB_DEFAULT_ACCESS_RULES="$XWAYLAND_GRAB_DEFAULT_ACCESS_RULES"]) + +case "$with_XWAYLAND_GRAB_DEFAULT_ACCESS_RULES" in + yes) with_XWAYLAND_GRAB_DEFAULT_ACCESS_RULES="$XWAYLAND_GRAB_DEFAULT_ACCESS_RULES" ;; + no) with_XWAYLAND_GRAB_DEFAULT_ACCESS_RULES='' ;; +esac +AC_DEFINE_UNQUOTED([XWAYLAND_GRAB_DEFAULT_ACCESS_RULES], + "$with_XWAYLAND_GRAB_DEFAULT_ACCESS_RULES", + [Xwayland applications allowed to issue keyboard grabs]) +AC_SUBST(XWAYLAND_GRAB_DEFAULT_ACCESS_RULES) + PKG_CHECK_EXISTS([xi >= 1.6.99.1], AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater])) diff --git a/data/Makefile.am b/data/Makefile.am index 5129b8e57..4a8ff6f67 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -24,6 +24,7 @@ gsettings_SCHEMAS = $(gschema_in_files:.xml.in=.xml) %.gschema.xml: %.gschema.xml.in Makefile $(AM_V_GEN) sed -e 's|@GETTEXT_DOMAIN[@]|$(GETTEXT_PACKAGE)|g' \ + -e 's|@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES[@]|$(XWAYLAND_GRAB_DEFAULT_ACCESS_RULES)|g' \ $< > $@ || rm $@ @GSETTINGS_RULES@ diff --git a/data/org.gnome.mutter.wayland.gschema.xml.in b/data/org.gnome.mutter.wayland.gschema.xml.in index f85e7b7ab..33b691f1d 100644 --- a/data/org.gnome.mutter.wayland.gschema.xml.in +++ b/data/org.gnome.mutter.wayland.gschema.xml.in @@ -54,4 +54,48 @@ Re-enable shortcuts + + + + + + false + Allow grabs with Xwayland + + Allow keyboard grabs issued by X11 applications running in Xwayland + to be taken into account. + + For a X11 grab to be taken into account under Wayland, the client must + also either send a specific X11 ClientMessage to the root window or be + among the applications white-listed in key “xwayland-grab-access-rules“. + + + + + [] + Xwayland applications allowed to issue keyboard grabs + + List the resource names or resource class of X11 windows either + allowed or not allowed to issue X11 keyboard grabs under Xwayland. + + The resource name or resource class of a given X11 window can be + obtained using the command “xprop WM_CLASS“. + + Wildcards '*' and jokers '?' in the values are supported. + + Values starting with '!' are blacklisted, which has precedence over + the whitelist, to revoke applications from the default system list. + + The default system list includes the following applications: + + “@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@“ + + Users can break an existing grab by using the specific keyboard + short-cut defined by the keybinding key “restore-shortcuts“. + + + + + diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h index 1507807ea..874767f7d 100644 --- a/src/backends/meta-settings-private.h +++ b/src/backends/meta-settings-private.h @@ -58,4 +58,10 @@ void meta_settings_override_experimental_features (MetaSettings *settings); void meta_settings_enable_experimental_feature (MetaSettings *settings, MetaExperimentalFeature feature); +void meta_settings_get_xwayland_grab_patterns (MetaSettings *settings, + GPtrArray **whitelist_patterns, + GPtrArray **blacklist_patterns); + +gboolean meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings); + #endif /* META_SETTINGS_PRIVATE_H */ diff --git a/src/backends/meta-settings.c b/src/backends/meta-settings.c index cb22bf33c..8593a17d1 100644 --- a/src/backends/meta-settings.c +++ b/src/backends/meta-settings.c @@ -30,6 +30,11 @@ #include "backends/meta-monitor-manager-private.h" #include "ui/theme-private.h" +#ifndef XWAYLAND_GRAB_DEFAULT_ACCESS_RULES +# warning "XWAYLAND_GRAB_DEFAULT_ACCESS_RULES is not set" +# define XWAYLAND_GRAB_DEFAULT_ACCESS_RULES "" +#endif + enum { UI_SCALING_FACTOR_CHANGED, @@ -50,6 +55,7 @@ struct _MetaSettings GSettings *interface_settings; GSettings *mutter_settings; + GSettings *wayland_settings; int ui_scaling_factor; int global_scaling_factor; @@ -58,6 +64,10 @@ struct _MetaSettings MetaExperimentalFeature experimental_features; gboolean experimental_features_overridden; + + gboolean xwayland_allow_grabs; + GPtrArray *xwayland_grab_whitelist_patterns; + GPtrArray *xwayland_grab_blacklist_patterns; }; G_DEFINE_TYPE (MetaSettings, meta_settings, G_TYPE_OBJECT) @@ -299,6 +309,105 @@ mutter_settings_changed (GSettings *mutter_settings, (unsigned int) old_experimental_features); } +static void +xwayland_grab_list_add_item (MetaSettings *settings, + char *item) +{ + /* If first character is '!', it's a blacklisted item */ + if (item[0] != '!') + g_ptr_array_add (settings->xwayland_grab_whitelist_patterns, + g_pattern_spec_new (item)); + else if (item[1] != 0) + g_ptr_array_add (settings->xwayland_grab_blacklist_patterns, + g_pattern_spec_new (&item[1])); +} + +static gboolean +xwayland_grab_access_rules_handler (GVariant *variant, + gpointer *result, + gpointer data) +{ + MetaSettings *settings = data; + GVariantIter iter; + char *item; + + /* Create a GPatternSpec for each element */ + g_variant_iter_init (&iter, variant); + while (g_variant_iter_loop (&iter, "s", &item)) + xwayland_grab_list_add_item (settings, item); + + *result = GINT_TO_POINTER (TRUE); + + return TRUE; +} + +static void +update_xwayland_grab_access_rules (MetaSettings *settings) +{ + gchar **system_defaults; + int i; + + /* Free previous patterns and create new arrays */ + g_ptr_array_free (settings->xwayland_grab_whitelist_patterns, TRUE); + settings->xwayland_grab_whitelist_patterns = + g_ptr_array_new_with_free_func ((GDestroyNotify) g_pattern_spec_free); + + g_ptr_array_free (settings->xwayland_grab_blacklist_patterns, TRUE); + settings->xwayland_grab_blacklist_patterns = + g_ptr_array_new_with_free_func ((GDestroyNotify) g_pattern_spec_free); + + /* Add system defaults values */ + system_defaults = g_strsplit (XWAYLAND_GRAB_DEFAULT_ACCESS_RULES, ",", -1); + for (i = 0; system_defaults[i]; i++) + xwayland_grab_list_add_item (settings, system_defaults[i]); + g_strfreev (system_defaults); + + /* Then add gsettings values */ + g_settings_get_mapped (settings->wayland_settings, + "xwayland-grab-access-rules", + xwayland_grab_access_rules_handler, + settings); +} + +static void +update_xwayland_allow_grabs (MetaSettings *settings) +{ + settings->xwayland_allow_grabs = + g_settings_get_boolean (settings->wayland_settings, + "xwayland-allow-grabs"); +} + +static void +wayland_settings_changed (GSettings *wayland_settings, + gchar *key, + MetaSettings *settings) +{ + + if (g_str_equal (key, "xwayland-allow-grabs")) + { + update_xwayland_allow_grabs (settings); + } + else if (g_str_equal (key, "xwayland-grab-access-rules")) + { + update_xwayland_grab_access_rules (settings); + } +} + +void +meta_settings_get_xwayland_grab_patterns (MetaSettings *settings, + GPtrArray **whitelist_patterns, + GPtrArray **blacklist_patterns) +{ + *whitelist_patterns = settings->xwayland_grab_whitelist_patterns; + *blacklist_patterns = settings->xwayland_grab_blacklist_patterns; +} + +gboolean + meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings) +{ + return (settings->xwayland_allow_grabs); +} + MetaSettings * meta_settings_new (MetaBackend *backend) { @@ -317,6 +426,11 @@ meta_settings_dispose (GObject *object) g_clear_object (&settings->mutter_settings); g_clear_object (&settings->interface_settings); + g_clear_object (&settings->wayland_settings); + g_clear_pointer (&settings->xwayland_grab_whitelist_patterns, + g_ptr_array_unref); + g_clear_pointer (&settings->xwayland_grab_blacklist_patterns, + g_ptr_array_unref); G_OBJECT_CLASS (meta_settings_parent_class)->dispose (object); } @@ -332,6 +446,10 @@ meta_settings_init (MetaSettings *settings) g_signal_connect (settings->mutter_settings, "changed", G_CALLBACK (mutter_settings_changed), settings); + settings->wayland_settings = g_settings_new ("org.gnome.mutter.wayland"); + g_signal_connect (settings->wayland_settings, "changed", + G_CALLBACK (wayland_settings_changed), + settings); /* Chain up inter-dependent settings. */ g_signal_connect (settings, "global-scaling-factor-changed", @@ -341,6 +459,8 @@ meta_settings_init (MetaSettings *settings) update_global_scaling_factor (settings); update_experimental_features (settings); + update_xwayland_grab_access_rules (settings); + update_xwayland_allow_grabs (settings); } static void