[gnome-settings-daemon/shell-keygrab: 3/5] keygrab: Refer key grabbing to the shell



commit 619af254c4daad4f6476421f2ce2649c37537f6c
Author: Florian MÃllner <fmuellner gnome org>
Date:   Thu Nov 15 17:41:24 2012 +0100

    keygrab: Refer key grabbing to the shell

 plugins/common/Makefile.am                   |   12 +++-
 plugins/common/gsd-keygrab.c                 |  111 ++++++++++++++++++++++-
 plugins/common/gsd-keygrab.h                 |    4 +
 plugins/common/org.gnome.ShellKeyGrabber.xml |   21 +++++
 plugins/media-keys/gsd-media-keys-manager.c  |  126 ++++++++------------------
 5 files changed, 182 insertions(+), 92 deletions(-)
---
diff --git a/plugins/common/Makefile.am b/plugins/common/Makefile.am
index b0e907c..1eb5394 100644
--- a/plugins/common/Makefile.am
+++ b/plugins/common/Makefile.am
@@ -3,6 +3,7 @@ plugin_name = common
 noinst_LTLIBRARIES = libcommon.la
 
 libcommon_la_SOURCES = \
+	$(dbus_built_sources)	\
 	gsd-keygrab.c		\
 	gsd-keygrab.h		\
 	gsd-input-helper.c	\
@@ -39,4 +40,13 @@ test_egg_key_parsing_CFLAGS = $(libcommon_la_CFLAGS)
 scriptsdir = $(datadir)/gnome-settings-daemon- GSD_API_VERSION@
 scripts_DATA = input-device-example.sh
 
-EXTRA_DIST = $(scripts_DATA) test-plugin.h
+dbus_built_sources = shell-key-grabber.c shell-key-grabber.h
+shell-key-grabber.c: shell-key-grabber.h
+shell-key-grabber.h: Makefile.am org.gnome.ShellKeyGrabber.xml
+	gdbus-codegen --interface-prefix org.gnome.		\
+	              --generate-c-code shell-key-grabber	\
+	              --c-namespace Shell			\
+	              org.gnome.ShellKeyGrabber.xml
+
+EXTRA_DIST = $(scripts_DATA) test-plugin.h org.gnome.Shell.xml
+CLEANFILES = $(dbus_built_sources)
diff --git a/plugins/common/gsd-keygrab.c b/plugins/common/gsd-keygrab.c
index 6ab3afa..f1fb0ce 100644
--- a/plugins/common/gsd-keygrab.c
+++ b/plugins/common/gsd-keygrab.c
@@ -49,6 +49,20 @@ static GdkModifierType gsd_used_mods = 0;
 
 #define IN_RANGE(x, min, max) (x >= min && x <= max)
 
+#define SHELL_DBUS_NAME              "org.gnome.Shell"
+#define SHELL_DBUS_PATH              "/org/gnome/Shell"
+
+static gboolean retry_grab (gpointer data);
+static void grab_key_complete (GObject *object, GAsyncResult *result, gpointer user_data);
+
+static ShellKeyGrabber *shell_key_grabber = NULL;
+
+typedef struct {
+        guint keysym;
+        guint modifiers;
+        guint modes;
+} KeygrabData;
+
 static void
 setup_modifiers (void)
 {
@@ -72,6 +86,7 @@ setup_modifiers (void)
 	}
 }
 
+#if 0
 static void
 grab_key_real (guint      keycode,
                GdkWindow *root,
@@ -111,6 +126,74 @@ grab_key_real (guint      keycode,
                                  mods);
         }
 }
+#endif
+
+ShellKeyGrabber *
+get_key_grabber () {
+        if (shell_key_grabber)
+                return shell_key_grabber;
+
+        shell_key_grabber =
+                shell_key_grabber_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                          G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+                                                          SHELL_DBUS_NAME,
+                                                          SHELL_DBUS_PATH,
+                                                          NULL, NULL);
+        return shell_key_grabber;
+}
+
+static gboolean
+retry_grab (gpointer data)
+{
+        KeygrabData *grab_data = data;
+
+        if (grab_data->modes)
+                shell_key_grabber_call_grab_key (shell_key_grabber,
+                                                 grab_data->keysym,
+                                                 grab_data->modifiers,
+                                                 grab_data->modes,
+                                                 NULL,
+                                                 grab_key_complete, grab_data);
+        else
+                shell_key_grabber_call_ungrab_key (shell_key_grabber,
+                                                   grab_data->keysym,
+                                                   grab_data->modifiers,
+                                                   NULL,
+                                                   grab_key_complete, grab_data);
+        return FALSE;
+}
+
+static void
+grab_key_complete (GObject      *object,
+                   GAsyncResult *result,
+                   gpointer      user_data)
+{
+        gboolean success = FALSE;
+        gboolean retry = TRUE;
+        GError *error = NULL;
+        KeygrabData *grab_data = user_data;
+
+        if (grab_data->modes)
+                shell_key_grabber_call_grab_key_finish (SHELL_KEY_GRABBER (object),
+                                                        &success, result, &error); 
+        else
+                shell_key_grabber_call_ungrab_key_finish (SHELL_KEY_GRABBER (object),
+                                                          &success, result, &error); 
+
+        if (error) {
+                retry = error->code == G_DBUS_ERROR_UNKNOWN_METHOD;
+                if (!retry)
+                        g_warning ("%d: %s", error->code, error->message);
+                g_error_free (error);
+        } else {
+                retry = !success;
+        }
+
+        if (retry)
+                g_timeout_add_seconds (1, retry_grab, grab_data);
+        else
+                g_free (grab_data);
+}
 
 /* Grab the key. In order to ignore GSD_IGNORED_MODS we need to grab
  * all combinations of the ignored modifiers and those actually used
@@ -139,6 +222,7 @@ grab_key_internal (Key             *key,
                    GsdKeygrabFlags  flags,
                    GSList          *screens)
 {
+#if 0
         int     indexes[N_BITS]; /* indexes of bits we need to flip */
         int     i;
         int     bit;
@@ -147,11 +231,12 @@ grab_key_internal (Key             *key,
         guint   mask, modifiers;
         GArray *all_mods;
         GSList *l;
+#endif
+        KeygrabData *grab_data;
+        guint modifiers;
 
         setup_modifiers ();
 
-        mask = gsd_ignored_mods & ~key->state & GDK_MODIFIER_MASK;
-
         /* XGrabKey requires real modifiers, not virtual ones */
         modifiers = key->state;
         gdk_keymap_map_virtual_modifiers (gdk_keymap_get_default (), &modifiers);
@@ -188,6 +273,26 @@ grab_key_internal (Key             *key,
                 return;
         }
 
+        grab_data = g_new (KeygrabData, 1);
+        grab_data->keysym = key->keysym;
+        grab_data->modifiers = modifiers;
+        grab_data->modes = grab ? ~0 : 0;
+
+        get_key_grabber ();
+
+        if (grab)
+                shell_key_grabber_call_grab_key (shell_key_grabber,
+                                                 key->keysym, modifiers, ~0,
+                                                 NULL,
+                                                 grab_key_complete, grab_data);
+        else
+                shell_key_grabber_call_ungrab_key (shell_key_grabber,
+                                                   key->keysym, modifiers,
+                                                   NULL,
+                                                   grab_key_complete, grab_data);
+#if 0
+        mask = gsd_ignored_mods & ~key->state & GDK_MODIFIER_MASK;
+
         bit = 0;
         /* store the indexes of all set bits in mask in the array */
         for (i = 0; mask; ++i, mask >>= 1) {
@@ -197,7 +302,6 @@ grab_key_internal (Key             *key,
         }
 
         bits_set_cnt = bit;
-
 	all_mods = g_array_new (FALSE, TRUE, sizeof(XIGrabModifiers));
         uppervalue = 1 << bits_set_cnt;
         /* store all possible modifier combinations for our mask into all_mods */
@@ -234,6 +338,7 @@ grab_key_internal (Key             *key,
                 }
         }
         g_array_free (all_mods, TRUE);
+#endif
 }
 
 void
diff --git a/plugins/common/gsd-keygrab.h b/plugins/common/gsd-keygrab.h
index 4c6d560..eaba236 100644
--- a/plugins/common/gsd-keygrab.h
+++ b/plugins/common/gsd-keygrab.h
@@ -26,6 +26,8 @@ G_BEGIN_DECLS
 #include <X11/keysym.h>
 #include <X11/extensions/XInput2.h>
 
+#include "shell-key-grabber.h"
+
 typedef struct {
         guint keysym;
         guint state;
@@ -61,6 +63,8 @@ void            grab_button      (int      deviceid,
                                   gboolean grab,
                                   GSList  *screens);
 
+ShellKeyGrabber *get_key_grabber (void);
+
 G_END_DECLS
 
 #endif /* __GSD_COMMON_KEYGRAB_H */
diff --git a/plugins/common/org.gnome.ShellKeyGrabber.xml b/plugins/common/org.gnome.ShellKeyGrabber.xml
new file mode 100644
index 0000000..e89ae40
--- /dev/null
+++ b/plugins/common/org.gnome.ShellKeyGrabber.xml
@@ -0,0 +1,21 @@
+<node>
+  <interface name="org.gnome.Shell">
+    <annotation name="org.gtk.GDBus.C.Name" value="KeyGrabber"/>
+    <method name="GrabKey">
+      <arg type="u" direction="in" name="keysym"/>
+      <arg type="u" direction="in" name="modifiers"/>
+      <arg type="u" direction="in" name="flags"/>
+      <arg type="b" direction="out" name="success"/>
+    </method>
+    <method name="UngrabKey">
+      <arg type="u" direction="in" name="keysym"/>
+      <arg type="u" direction="in" name="modifiers"/>
+      <arg type="b" direction="out" name="success"/>
+    </method>
+    <signal name="KeyActivated">
+      <arg type="u" name="keysym"/>
+      <arg type="u" name="modifiers"/>
+      <arg type="u" name="device"/>
+    </signal>
+  </interface>
+</node>
diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
index e5977d0..663f64f 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -2011,89 +2011,53 @@ do_action (GsdMediaKeysManager *manager,
         return FALSE;
 }
 
-static GdkScreen *
-get_screen_from_root (GsdMediaKeysManager *manager,
-                      Window               root)
+static void
+on_shell_restart (GObject             *object,
+                  GParamSpec          *pspec,
+                  GsdMediaKeysManager *manager)
 {
-        GSList    *l;
+        guint i;
+        char *owner;
 
-        /* Look for which screen we're receiving events */
-        for (l = manager->priv->screens; l != NULL; l = l->next) {
-                GdkScreen *screen = (GdkScreen *) l->data;
-                GdkWindow *window = gdk_screen_get_root_window (screen);
+        if (manager->priv->keys == NULL)
+              return;
 
-                if (GDK_WINDOW_XID (window) == root)
-                        return screen;
-        }
+        g_object_get (object, "g-name-owner", &owner, NULL);
+        if (!owner)
+            return;
+        g_free (owner);
 
-        return NULL;
+        for (i = 0; i < manager->priv->keys->len; i++) {
+                MediaKey *key;
+
+                key = g_ptr_array_index (manager->priv->keys, i);
+                grab_media_key (key, manager);
+        }
 }
 
-static GdkFilterReturn
-filter_key_events (XEvent              *xevent,
-                   GdkEvent            *event,
-                   GsdMediaKeysManager *manager)
+static void
+on_key_activated (ShellKeyGrabber     *grabber,
+                  guint                keysym,
+                  guint                modifiers,
+                  guint                deviceid,
+                  GsdMediaKeysManager *manager)
 {
-	XIEvent             *xiev;
-	XIDeviceEvent       *xev;
-	XGenericEventCookie *cookie;
-        guint                i;
-	guint                deviceid;
-
-        /* verify we have a key event */
-	if (xevent->type != GenericEvent)
-		return GDK_FILTER_CONTINUE;
-	cookie = &xevent->xcookie;
-	if (cookie->extension != manager->priv->opcode)
-		return GDK_FILTER_CONTINUE;
-
-	xiev = (XIEvent *) xevent->xcookie.data;
-
-	if (xiev->evtype != XI_KeyPress &&
-	    xiev->evtype != XI_KeyRelease)
-		return GDK_FILTER_CONTINUE;
-
-	xev = (XIDeviceEvent *) xiev;
-
-	deviceid = xev->sourceid;
+        guint i;
 
         for (i = 0; i < manager->priv->keys->len; i++) {
                 MediaKey *key;
 
                 key = g_ptr_array_index (manager->priv->keys, i);
 
-                if (match_xi2_key (key->key, xev)) {
-                        switch (key->key_type) {
-                        case VOLUME_DOWN_KEY:
-                        case VOLUME_UP_KEY:
-                        case VOLUME_DOWN_QUIET_KEY:
-                        case VOLUME_UP_QUIET_KEY:
-                                /* auto-repeatable keys */
-                                if (xiev->evtype != XI_KeyPress)
-                                        return GDK_FILTER_CONTINUE;
-                                break;
-                        default:
-                                if (xiev->evtype != XI_KeyRelease) {
-                                        return GDK_FILTER_CONTINUE;
-                                }
-                        }
-
-                        manager->priv->current_screen = get_screen_from_root (manager, xev->root);
-
-                        if (key->key_type == CUSTOM_KEY) {
-                                do_custom_action (manager, key, xev->time);
-                                return GDK_FILTER_REMOVE;
-                        }
+                if (!match_key (key->key, keysym, modifiers))
+                        continue;
 
-                        if (do_action (manager, deviceid, key->key_type, xev->time) == FALSE) {
-                                return GDK_FILTER_REMOVE;
-                        } else {
-                                return GDK_FILTER_CONTINUE;
-                        }
-                }
+                if (key->key_type == CUSTOM_KEY)
+                        do_custom_action (manager, key, GDK_CURRENT_TIME);
+                else
+                        do_action (manager, deviceid, key->key_type, GDK_CURRENT_TIME);
+                return;
         }
-
-        return GDK_FILTER_CONTINUE;
 }
 
 static void
@@ -2120,7 +2084,7 @@ update_theme_settings (GSettings           *settings,
 static gboolean
 start_media_keys_idle_cb (GsdMediaKeysManager *manager)
 {
-        GSList *l;
+        ShellKeyGrabber *proxy;
         char *theme_name;
 
         g_debug ("Starting media_keys manager");
@@ -2169,18 +2133,11 @@ start_media_keys_idle_cb (GsdMediaKeysManager *manager)
         init_screens (manager);
         init_kbd (manager);
 
-        /* Start filtering the events */
-        for (l = manager->priv->screens; l != NULL; l = l->next) {
-                gnome_settings_profile_start ("gdk_window_add_filter");
-
-                g_debug ("adding key filter for screen: %d",
-                         gdk_screen_get_number (l->data));
-
-                gdk_window_add_filter (gdk_screen_get_root_window (l->data),
-                                       (GdkFilterFunc) filter_key_events,
-                                       manager);
-                gnome_settings_profile_end ("gdk_window_add_filter");
-        }
+        proxy = get_key_grabber ();
+        g_signal_connect (proxy, "notify::g-name-owner",
+                          G_CALLBACK (on_shell_restart), manager);
+        g_signal_connect (proxy, "key-activated",
+                          G_CALLBACK (on_key_activated), manager);
 
         gnome_settings_profile_end (NULL);
 
@@ -2247,7 +2204,6 @@ void
 gsd_media_keys_manager_stop (GsdMediaKeysManager *manager)
 {
         GsdMediaKeysManagerPrivate *priv = manager->priv;
-        GSList *ls;
         GList *l;
         int i;
 
@@ -2259,12 +2215,6 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager)
                 priv->bus_cancellable = NULL;
         }
 
-        for (ls = priv->screens; ls != NULL; ls = ls->next) {
-                gdk_window_remove_filter (gdk_screen_get_root_window (ls->data),
-                                          (GdkFilterFunc) filter_key_events,
-                                          manager);
-        }
-
         if (manager->priv->gtksettings != NULL) {
                 g_signal_handlers_disconnect_by_func (manager->priv->gtksettings, sound_theme_changed, manager);
                 manager->priv->gtksettings = NULL;



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