[gnome-settings-daemon/shell-keygrab: 3/5] keygrab: Refer key grabbing to the shell
- From: Florian MÃllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon/shell-keygrab: 3/5] keygrab: Refer key grabbing to the shell
- Date: Wed, 5 Dec 2012 08:43:26 +0000 (UTC)
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]