[Xfce4-commits] r27292 - in xfce4-settings/trunk: . xfce4-settings-helper

Jannis Pohlmann jannis at xfce.org
Tue Jul 15 12:25:25 CEST 2008


Author: jannis
Date: 2008-07-15 10:25:25 +0000 (Tue, 15 Jul 2008)
New Revision: 27292

Added:
   xfce4-settings/trunk/xfce4-settings-helper/keyboard-shortcuts.c
   xfce4-settings/trunk/xfce4-settings-helper/keyboard-shortcuts.h
Modified:
   xfce4-settings/trunk/ChangeLog
   xfce4-settings/trunk/xfce4-settings-helper/Makefile.am
   xfce4-settings/trunk/xfce4-settings-helper/main.c
Log:
	* xfce4-settings-helper/keyboard-shortcuts{c,h},
	  xfce4-settings-helper/Makefile.am,
	  xfce4-settings-helper/main.c: Add support for keyboard shortcuts.
	  Shortcuts are loaded, passive keyboard grabs are performed and
	  events with different modifier combinations are handled. The code
	  related to modifiers might not be sane, but it works quite well
	  here, even with changes made in .Xmodmap. I'd be curious to know
	  what happens if you change the keymap at runtime though.
	  xfce4-settings-helper/main.c: Add same and improved error
	* xfce4-settings-helper/accessx.c,
	* dialogs/keyboard-settings/main.c,
	  loading, saving, modifying and removing shortcuts. Not
	  supported yet: Adding new ones.
	* AUTHORS: I took the liberty to add my name here.
	* xfce4-settings-manager/xfce-settings-manager-dialog.c:
	  toplevel boxes inside notebooks to 12px for the sake of
	* dialogs/keyboard-settings/keyboard-dialog.glade: Same

Modified: xfce4-settings/trunk/ChangeLog
===================================================================
--- xfce4-settings/trunk/ChangeLog	2008-07-15 02:37:23 UTC (rev 27291)
+++ xfce4-settings/trunk/ChangeLog	2008-07-15 10:25:25 UTC (rev 27292)
@@ -1,3 +1,14 @@
+2008-07-15	Jannis Pohlmann <jannis at xfce.org>
+
+	* xfce4-settings-helper/keyboard-shortcuts{c,h},
+	  xfce4-settings-helper/Makefile.am,
+	  xfce4-settings-helper/main.c: Add support for keyboard shortcuts.
+	  Shortcuts are loaded, passive keyboard grabs are performed and
+	  events with different modifier combinations are handled. The code
+	  related to modifiers might not be sane, but it works quite well
+	  here, even with changes made in .Xmodmap. I'd be curious to know
+	  what happens if you change the keymap at runtime though.
+
 2008-07-14	Nick Schermer <nick at xfce.org>
 
 	* dialogs/display-settings/, dialogs/Makefile.am,
@@ -43,7 +54,7 @@
 	  dialogs/mouse-settings/main.c,
 	  dialogs/appearance-settings/main.c,
 	  dialogs/keyboard-settings/main.c,
-	  xfce4-settings-helper/main.c: Add same and improved error 
+	  xfce4-settings-helper/main.c: Add same and improved error
 	  messages and version information.
 
 2008-07-13	Nick Schermer <nick at xfce.org>
@@ -61,7 +72,7 @@
 	  branch code.
 	* dialogs/keyboard-settings/main.c: Release the channels
 	  after running the dialog.
-	* xfce4-settings-helper/accessx.c, 
+	* xfce4-settings-helper/accessx.c,
 	  xfce4-settings-helper/accessx.h,
 	  xfce4-settings-helper/xkb.c,
 	  xfce4-settings-helper/xkb.h: Move code into objects. Will
@@ -91,7 +102,7 @@
 	  plug a stupid leak.
 	* dialogs/appearance-settings/appearance-dialog.glade: Redesign
 	  the dialog a bit, a notebook inside a notebook is not practical.
-	* dialogs/keyboard-settings/main.c, 
+	* dialogs/keyboard-settings/main.c,
 	  dialogs/keyboard-settings/shortcut-dialog.c: Fix includes to make
 	  it compile.
 
@@ -115,8 +126,8 @@
 	  dialogs/keyboard-settings/shortcut-dialog.{c,h}:
 	  Revamped the dialog a bit. Add dialog widget for entering
 	  shortcuts. Rewrite the settings dialog and add support for
-	  loading, saving, modifying and removing shortcuts. Not 
-	  supported yet: Adding new ones. 
+	  loading, saving, modifying and removing shortcuts. Not
+	  supported yet: Adding new ones.
 
 2008-07-04	Nick Schermer <nick at xfce.org>
 
@@ -128,7 +139,7 @@
 	* dialogs/appearance-dialog/main.c: Only add the icon theme
 	  to the check list when it's actually added to the store.
 	  Revert strcmp to g_utf8_collate. Strip trailing spaces.
-	  
+
 	  Both fixes where mentioned by Jannis, thanks for that.
 
 2008-07-03	Nick Schermer <nick at xfce.org>
@@ -160,7 +171,7 @@
 
 	* dialogs/appearance-settings/main.c: Load icon themes properly.
 	  I used some of the code from the old mcs ui plugin.
-	* AUTHORS: I took the liberty to add my name here. 
+	* AUTHORS: I took the liberty to add my name here.
 
 2008-07-01	Nick Schermer <nick at xfce.org>
 
@@ -181,7 +192,7 @@
 
 2008-06-29	Jannis Pohlmann <jannis at xfce.org>
 
-	* xfce4-settings-manager/xfce-settings-manager-dialog.c: 
+	* xfce4-settings-manager/xfce-settings-manager-dialog.c:
 	  Add 6px border to the scrolled window in order to align it
 	  with the dialog buttons.
 
@@ -191,7 +202,7 @@
 	  dialogs/appearance-settings/appearance-dialog.glade,
 	  dialogs/keyboard-settings/keyboard-dialog.glade,
 	  dialogs/mouse-settings/mouse-dialog.glade: Change border of
-	  toplevel boxes inside notebooks to 12px for the sake of 
+	  toplevel boxes inside notebooks to 12px for the sake of
 	  consistency (thunar does the same). Add bottom padding of
 	  alignments below section titles to 6px.
 
@@ -223,7 +234,7 @@
 
 2008-06-28	Jannis Pohlmann <jannis at xfce.org>
 
-	* dialogs/keyboard-settings/keyboard-dialog.glade: Same 
+	* dialogs/keyboard-settings/keyboard-dialog.glade: Same
 	  procedure as before.
 
 2008-06-28	Jannis Pohlmann <jannis at xfce.org>

Modified: xfce4-settings/trunk/xfce4-settings-helper/Makefile.am
===================================================================
--- xfce4-settings/trunk/xfce4-settings-helper/Makefile.am	2008-07-15 02:37:23 UTC (rev 27291)
+++ xfce4-settings/trunk/xfce4-settings-helper/Makefile.am	2008-07-15 10:25:25 UTC (rev 27292)
@@ -18,7 +18,9 @@
 	xkb.c \
 	xkb.h \
 	pointers.c \
-	pointers.h
+	pointers.h \
+	keyboard-shortcuts.c \
+	keyboard-shortcuts.h
 
 xfce4_settings_helper_CFLAGS = \
 	$(GTK_CFLAGS) \
@@ -27,6 +29,7 @@
 	$(DBUS_GLIB_CFLAGS) \
 	$(XFCONF_CFLAGS) \
 	$(LIBXFCE4UTIL_CFLAGS) \
+	$(LIBXFCEGUI4_CFLAGS) \
 	$(XI_CFLAGS) \
 	$(LIBX11_CFLAGS)
 
@@ -41,6 +44,7 @@
 	$(DBUS_GLIB_LIBS) \
 	$(XFCONF_LIBS) \
 	$(LIBXFCE4UTIL_LIBS) \
+	$(LIBXFCEGUI4_LIBS) \
 	$(XI_LIBS) \
 	$(LIBX11_LIBS)
 

Added: xfce4-settings/trunk/xfce4-settings-helper/keyboard-shortcuts.c
===================================================================
--- xfce4-settings/trunk/xfce4-settings-helper/keyboard-shortcuts.c	                        (rev 0)
+++ xfce4-settings/trunk/xfce4-settings-helper/keyboard-shortcuts.c	2008-07-15 10:25:25 UTC (rev 27292)
@@ -0,0 +1,543 @@
+/* vi:set sw=2 sts=2 ts=2 et ai: */
+/*-
+ * Copyright (c) 2008 Jannis Pohlmann <jannis at xfce.org>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA  02111-1307  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <X11/Xlib.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#include <xfconf/xfconf.h>
+#include <libxfcegui4/libxfcegui4.h>
+
+#include "keyboard-shortcuts.h"
+
+
+
+/* Modifiers to be ignored (0x2000 is an Xkb modifier) */
+#define IGNORED_MODIFIERS (0x2000 | GDK_LOCK_MASK | GDK_HYPER_MASK)
+
+/* Modifiers to be used */
+#define USED_MODIFIERS (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_SUPER_MASK | GDK_META_MASK | \
+                        GDK_MOD1_MASK | GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK | GDK_MOD5_MASK)
+
+
+
+
+/* Property identifiers */
+enum
+{
+  PROP_0,
+};
+
+
+
+static void            xfce_keyboard_shortcuts_helper_class_init       (XfceKeyboardShortcutsHelperClass *klass);
+static void            xfce_keyboard_shortcuts_helper_init             (XfceKeyboardShortcutsHelper      *helper);
+static void            xfce_keyboard_shortcuts_helper_finalize         (GObject                          *object);
+static void            xfce_keyboard_shortcuts_helper_get_property     (GObject                          *object,
+                                                                        guint                             prop_id,
+                                                                        GValue                           *value,
+                                                                        GParamSpec                       *pspec);
+static void            xfce_keyboard_shortcuts_helper_set_property     (GObject                          *object,
+                                                                        guint                             prop_id,
+                                                                        const GValue                     *value,
+                                                                        GParamSpec                       *pspec);
+static void            xfce_keyboard_shortcuts_helper_add_filter       (XfceKeyboardShortcutsHelper      *helper);
+static GdkFilterReturn xfce_keyboard_shortcuts_helper_filter           (GdkXEvent                        *gdk_xevent,
+                                                                        GdkEvent                         *event,
+                                                                        XfceKeyboardShortcutsHelper      *helper);
+static void            xfce_keyboard_shortcuts_helper_load_shortcut    (const gchar                      *key,
+                                                                        const GValue                     *value,
+                                                                        XfceKeyboardShortcutsHelper      *helper);
+static gboolean        xfce_keyboard_shortcuts_helper_grab_shortcut    (XfceKeyboardShortcutsHelper      *helper,
+                                                                        const char                       *shortcut,
+                                                                        gboolean                          grab);
+static gboolean        xfce_keyboard_shortcuts_helper_parse_shortcut   (XfceKeyboardShortcutsHelper      *helper,
+                                                                        GdkDisplay                       *display,
+                                                                        const gchar                      *shortcut,
+                                                                        guint                            *keyval,
+                                                                        GdkModifierType                  *modifiers,
+                                                                        KeyCode                          *keycode,
+                                                                        guint                            *grab_mask);
+static gboolean        xfce_keyboard_shortcuts_helper_grab_real        (XfceKeyboardShortcutsHelper      *helper,
+                                                                        KeyCode                           keycode,
+                                                                        guint                             modifiers,
+                                                                        Display                          *display,
+                                                                        Window                            window,
+                                                                        gboolean                          grab);
+static void            xfce_keyboard_shortcuts_helper_handle_key_press (XfceKeyboardShortcutsHelper      *helper,
+                                                                        XKeyEvent                        *xevent);
+
+
+
+struct _XfceKeyboardShortcutsHelperClass
+{
+  GObjectClass __parent__;
+};
+
+struct _XfceKeyboardShortcutsHelper
+{
+  GObject __parent__;
+
+  /* Xfconf channel used for managing the keyboard shortcuts */
+  XfconfChannel *channel;
+
+  /* Hash table for (shortcut -> action) mapping */
+  GHashTable    *shortcuts;
+
+  /* Flag to avoid handling multiple key press events at the same time */
+  gboolean       waiting_for_key_release;
+};
+
+
+
+static GObjectClass *xfce_keyboard_shortcuts_helper_parent_class = NULL;
+
+
+
+GType
+xfce_keyboard_shortcuts_helper_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (XfceKeyboardShortcutsHelperClass),
+        NULL,
+        NULL,
+        (GClassInitFunc) xfce_keyboard_shortcuts_helper_class_init,
+        NULL,
+        NULL,
+        sizeof (XfceKeyboardShortcutsHelper),
+        0,
+        (GInstanceInitFunc) xfce_keyboard_shortcuts_helper_init,
+        NULL,
+      };
+
+      type = g_type_register_static (G_TYPE_OBJECT, "XfceKeyboardShortcutsHelper", &info, 0);
+    }
+
+  return type;
+}
+
+
+
+static void
+xfce_keyboard_shortcuts_helper_class_init (XfceKeyboardShortcutsHelperClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  /* Determine the parent type class */
+  xfce_keyboard_shortcuts_helper_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = xfce_keyboard_shortcuts_helper_finalize;
+  gobject_class->get_property = xfce_keyboard_shortcuts_helper_get_property;
+  gobject_class->set_property = xfce_keyboard_shortcuts_helper_set_property;
+}
+
+
+
+static void
+xfce_keyboard_shortcuts_helper_init (XfceKeyboardShortcutsHelper *helper)
+{
+  GHashTable *properties;
+
+  helper->waiting_for_key_release = FALSE;
+
+  /* Get Xfconf channel */
+  helper->channel = xfconf_channel_new ("xfce4-keyboard-shortcuts");
+
+  /* Create hash table for (shortcut -> command) mapping */
+  helper->shortcuts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+  /* Get all properties of the channel */
+  properties = xfconf_channel_get_all (helper->channel);
+
+  if (G_LIKELY (properties != NULL))
+    {
+      /* Filter shortcuts */
+      g_hash_table_foreach (properties, (GHFunc) xfce_keyboard_shortcuts_helper_load_shortcut, helper);
+
+      /* Destroy properties */
+      g_hash_table_destroy (properties);
+    }
+
+  xfce_keyboard_shortcuts_helper_add_filter (helper);
+}
+
+
+
+static void
+xfce_keyboard_shortcuts_helper_finalize (GObject *object)
+{
+  XfceKeyboardShortcutsHelper *helper = XFCE_KEYBOARD_SHORTCUTS_HELPER (object);
+
+  /* Free shortcuts hash table */
+  g_hash_table_destroy (helper->shortcuts);
+
+  /* Free Xfconf channel */
+  g_object_unref (helper->channel);
+
+  (*G_OBJECT_CLASS (xfce_keyboard_shortcuts_helper_parent_class)->finalize) (object);
+}
+
+
+
+static void
+xfce_keyboard_shortcuts_helper_get_property (GObject    *object,
+                                             guint       prop_id,
+                                             GValue     *value,
+                                             GParamSpec *pspec)
+{
+  XfceKeyboardShortcutsHelper *helper = XFCE_KEYBOARD_SHORTCUTS_HELPER (object);
+
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+xfce_keyboard_shortcuts_helper_set_property (GObject      *object,
+                                             guint         prop_id,
+                                             const GValue *value,
+                                             GParamSpec   *pspec)
+{
+  XfceKeyboardShortcutsHelper *helper = XFCE_KEYBOARD_SHORTCUTS_HELPER (object);
+
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+xfce_keyboard_shortcuts_helper_add_filter (XfceKeyboardShortcutsHelper *helper)
+{
+  GdkDisplay *display;
+  GdkScreen  *screen;
+  gint        screens;
+  gint        i;
+
+  g_return_if_fail (XFCE_IS_KEYBOARD_SHORTCUTS_HELPER (helper));
+
+  display = gdk_display_get_default ();
+  screens = gdk_display_get_n_screens (display);
+
+  /* Flush events before adding the event filter */
+  XAllowEvents (GDK_DISPLAY_XDISPLAY (display), AsyncBoth, CurrentTime);
+
+  /* Add event filter to the root window of each screen. FIXME: I'm not
+   * exactly sure which one of these two options I should use: */
+#if 0
+  for (i = 0; i < screens; ++i)
+    {
+      screen = gdk_display_get_screen (display, i);
+      gdk_window_add_filter (gdk_screen_get_root_window (screen), (GdkFilterFunc) xfce_keyboard_shortcuts_helper_filter, helper);
+    }
+#else
+  gdk_window_add_filter (NULL, (GdkFilterFunc) xfce_keyboard_shortcuts_helper_filter, helper);
+#endif
+}
+
+
+
+static GdkFilterReturn
+xfce_keyboard_shortcuts_helper_filter (GdkXEvent                   *gdk_xevent,
+                                       GdkEvent                    *event,
+                                       XfceKeyboardShortcutsHelper *helper)
+{
+  XEvent *xevent = (XEvent *) gdk_xevent;
+
+  g_return_if_fail (XFCE_IS_KEYBOARD_SHORTCUTS_HELPER (helper));
+
+  switch (xevent->type)
+    {
+      case KeyPress:
+        xfce_keyboard_shortcuts_helper_handle_key_press (helper, (XKeyEvent *) xevent);
+        break;
+      case KeyRelease:
+        helper->waiting_for_key_release = FALSE;
+        break;
+      case MappingNotify:
+        break;
+      default:
+        break;
+    }
+
+  return GDK_FILTER_CONTINUE;
+}
+
+
+
+static void
+xfce_keyboard_shortcuts_helper_load_shortcut (const gchar                 *key,
+                                              const GValue                *value,
+                                              XfceKeyboardShortcutsHelper *helper)
+{
+  const GPtrArray *array;
+  const GValue    *type_value;
+  const GValue    *action_value;
+  const gchar     *type;
+  const gchar     *action;
+  GtkTreeIter      iter;
+
+  g_return_if_fail (XFCE_IS_KEYBOARD_SHORTCUTS_HELPER (helper));
+
+  /* MAke sure we only load shortcuts from string arrays */
+  if (G_UNLIKELY (G_VALUE_TYPE (value) != dbus_g_type_get_collection ("GPtrArray", G_TYPE_VALUE)))
+    return;
+
+  /* Get the pointer array */
+  array = g_value_get_boxed (value);
+
+  /* Make sure the array has exactly two members */
+  if (G_UNLIKELY (array->len != 2))
+    return;
+
+  /* Get GValues for the array members */
+  type_value = g_ptr_array_index (array, 0);
+  action_value = g_ptr_array_index (array, 1);
+
+  /* Make sure both are string values */
+  if (G_UNLIKELY (G_VALUE_TYPE (type_value) != G_TYPE_STRING || G_VALUE_TYPE (action_value) != G_TYPE_STRING))
+    return;
+
+  /* Get shortcut type and action */
+  type = g_value_get_string (type_value);
+  action = g_value_get_string (action_value);
+
+  /* Only add shortcuts of type 'execute' */
+  if (g_utf8_collate (type, "execute") == 0)
+    {
+      /* Establish passive grab on the shortcut and add it to the hash table */
+      if (G_LIKELY (xfce_keyboard_shortcuts_helper_grab_shortcut (helper, key + 1, TRUE)))
+        {
+          /* Add shortcut -> action pair to the hash table */
+          g_hash_table_insert (helper->shortcuts, g_strdup (key + 1), g_strdup (action));
+        }
+      else
+        g_warning ("Failed to load shortcut '%s'", key + 1);
+    }
+}
+
+
+
+static gboolean
+xfce_keyboard_shortcuts_helper_grab_shortcut (XfceKeyboardShortcutsHelper *helper,
+                                              const char                  *shortcut,
+                                              gboolean                     grab)
+{
+  GdkModifierType modifiers;
+  GdkDisplay     *display;
+  GdkScreen      *screen;
+  Display        *xdisplay;
+  KeyCode         keycode;
+  Window          xwindow;
+  guint           grab_mask;
+  guint           keyval;
+  gint            bits[32];
+  gint            current_mask;
+  gint            ignore_mask;
+  gint            screens;
+  gint            n_bits;
+  gint            i;
+  gint            j;
+  gint            k;
+
+  display = gdk_display_get_default ();
+  screens = gdk_display_get_n_screens (display);
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+  /* Parse the shortcut and abort if that fails */
+  if (G_UNLIKELY (!xfce_keyboard_shortcuts_helper_parse_shortcut (helper, display, shortcut, &keyval, &modifiers, &keycode, &grab_mask)))
+    {
+      g_warning ("Could not parse shortcut '%s', most likely because it is invalid", shortcut);
+      return FALSE ;
+    }
+
+  /* Create mask containing ignored modifier bits set which are not set in the grab_mask already */
+  ignore_mask = IGNORED_MODIFIERS & ~grab_mask & GDK_MODIFIER_MASK;
+
+  /* Store indices of all set bits of the ignore mask in an array */
+  for (i = 0, n_bits = 0; ignore_mask != 0; ++i, ignore_mask >>= 1)
+    if ((ignore_mask & 0x1) != 0)
+      bits[n_bits++] = i;
+
+  for (i = 0; i < (1 << n_bits); ++i)
+    {
+      /* Map bits in the counter to those in the mask and thereby retrieve all ignored bit
+       * mask combinations */
+      for (current_mask = 0, j = 0; j < n_bits; ++j)
+        if ((i & (1 << j)) != 0)
+          current_mask |= (1 << bits[j]);
+
+      /* Grab key on all screens */
+      for (k = 0; k < screens; ++k)
+        {
+          /* Get current screen and root X window */
+          screen = gdk_display_get_screen (display, k);
+          xwindow = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
+
+          /* Really grab or ungrab the key now */
+          if (G_UNLIKELY (!xfce_keyboard_shortcuts_helper_grab_real (helper, keycode, current_mask | grab_mask, xdisplay, xwindow, grab)))
+            {
+              g_warning ("Could not grab shortcut '%s'. It might be used by another application already.", shortcut);
+              return FALSE;
+            }
+        }
+    }
+
+  return TRUE;
+}
+
+
+
+static gboolean
+xfce_keyboard_shortcuts_helper_parse_shortcut (XfceKeyboardShortcutsHelper *helper,
+                                               GdkDisplay                  *display,
+                                               const gchar                 *shortcut,
+                                               guint                       *keyval,
+                                               GdkModifierType             *modifiers,
+                                               KeyCode                     *keycode,
+                                               guint                       *grab_mask)
+{
+  g_return_if_fail (XFCE_IS_KEYBOARD_SHORTCUTS_HELPER (helper));
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+
+  /* Reset keycode and grab mask */
+  *keycode = 0;
+  *grab_mask = 0;
+
+  /* Parse the GTK+ accelerator string */
+  gtk_accelerator_parse (shortcut, keyval, modifiers);
+
+  /* Abort when the accelerator string is invalid */
+  if (G_LIKELY (*keyval == 0 && *modifiers == 0))
+    return FALSE;
+
+  /* Try to convert the keyval into a X11 keycode */
+  if ((*keycode = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (display), *keyval)) == 0)
+    return FALSE;
+
+  /* FIXME: I'm not really sure about this */
+  *grab_mask = *modifiers;
+
+  return TRUE;
+}
+
+
+
+static gboolean
+xfce_keyboard_shortcuts_helper_grab_real (XfceKeyboardShortcutsHelper *helper,
+                                          KeyCode                      keycode,
+                                          guint                        modifiers,
+                                          Display                     *display,
+                                          Window                       window,
+                                          gboolean                     grab)
+{
+  gdk_error_trap_push ();
+
+  if (G_LIKELY (grab))
+    XGrabKey (display, keycode, modifiers, window, FALSE, GrabModeAsync, GrabModeAsync);
+  else
+    XUngrabKey (display, keycode, modifiers, window);
+
+  gdk_flush ();
+
+  return gdk_error_trap_pop () == 0;
+}
+
+
+
+static void
+xfce_keyboard_shortcuts_helper_handle_key_press (XfceKeyboardShortcutsHelper *helper,
+                                                 XKeyEvent                   *xevent)
+{
+  GdkDisplay  *display;
+  GdkScreen   *screen;
+  GError      *error = NULL;
+  KeySym       keysym;
+  gchar       *accelerator_name;
+  const gchar *key;
+  const gchar *value;
+  gint         monitor;
+  gint         modifiers;
+
+  g_return_if_fail (XFCE_IS_KEYBOARD_SHORTCUTS_HELPER (helper));
+
+  /* Don't handle multiple key press events in parallel (avoid weird behaviour) */
+  if (G_UNLIKELY (helper->waiting_for_key_release))
+    return;
+
+  /* Get display information */
+  display = gdk_display_get_default ();
+
+  /* Convert event keycode to keysym */
+  keysym = XKeycodeToKeysym (GDK_DISPLAY_XDISPLAY (display), xevent->keycode, 0);
+
+  /* Remove ignored modifiers and non-modifier keys from the event state mask */
+  modifiers = xevent->state & ~IGNORED_MODIFIERS & GDK_MODIFIER_MASK;
+
+  /* Get accelerator string for the pressed keys */
+  accelerator_name = gtk_accelerator_name (keysym, modifiers);
+
+  /* Perform accelerator lookup */
+  if (G_LIKELY (g_hash_table_lookup_extended (helper->shortcuts, accelerator_name, (gpointer) &key, (gpointer) &value)))
+    {
+      /* We have to wait for a release event before handling another key press event */
+      helper->waiting_for_key_release = TRUE;
+
+      /* Determine active monitor */
+      screen = xfce_gdk_display_locate_monitor_with_pointer (display, &monitor);
+
+      /* Spawn command */
+      if (G_UNLIKELY (!xfce_gdk_spawn_command_line_on_screen (screen, value, &error)))
+        {
+          if (G_LIKELY (error != NULL))
+            {
+              g_warning ("%s", error->message);
+              g_error_free (error);
+            }
+        }
+    }
+
+  /* Free accelerator string */
+  g_free (accelerator_name);
+}

Added: xfce4-settings/trunk/xfce4-settings-helper/keyboard-shortcuts.h
===================================================================
--- xfce4-settings/trunk/xfce4-settings-helper/keyboard-shortcuts.h	                        (rev 0)
+++ xfce4-settings/trunk/xfce4-settings-helper/keyboard-shortcuts.h	2008-07-15 10:25:25 UTC (rev 27292)
@@ -0,0 +1,42 @@
+/* vi:set sw=2 sts=2 ts=2 et ai: */
+/*-
+ * Copyright (c) 2008 Jannis Pohlmann <jannis at xfce.org>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA  02111-1307  USA
+ */
+
+#ifndef __XFCE_KEYBOARD_SHORTCUTS_HELPER_H__
+#define __XFCE_KEYBOARD_SHORTCUTS_HELPER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS;
+
+typedef struct _XfceKeyboardShortcutsHelperClass   XfceKeyboardShortcutsHelperClass;
+typedef struct _XfceKeyboardShortcutsHelper        XfceKeyboardShortcutsHelper;
+
+#define XFCE_TYPE_KEYBOARD_SHORTCUTS_HELPER            (xfce_keyboard_shortcuts_helper_get_type ())
+#define XFCE_KEYBOARD_SHORTCUTS_HELPER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_KEYBOARD_SHORTCUTS_HELPER, XfceKeyboardShortcutsHelper))
+#define XFCE_KEYBOARD_SHORTCUTS_HELPER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_KEYBOARD_SHORTCUTS_HELPER, XfceKeyboardShortcutsHelperClass))
+#define XFCE_IS_KEYBOARD_SHORTCUTS_HELPER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_KEYBOARD_SHORTCUTS_HELPER))
+#define XFCE_IS_KEYBOARD_SHORTCUTS_HELPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_KEYBOARD_SHORTCUTS_HELPER)
+#define XFCE_KEYBOARD_SHORTCUTS_HELPER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_KEYBOARD_SHORTCUTS_HELPER, XfceKeyboardShortcutsHelperClass))
+
+GType xfce_keyboard_shortcuts_helper_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS;
+
+#endif /* !__XFCE_KEYBOARD_SHORTCUTS_HELPER_H__ */

Modified: xfce4-settings/trunk/xfce4-settings-helper/main.c
===================================================================
--- xfce4-settings/trunk/xfce4-settings-helper/main.c	2008-07-15 02:37:23 UTC (rev 27291)
+++ xfce4-settings/trunk/xfce4-settings-helper/main.c	2008-07-15 10:25:25 UTC (rev 27292)
@@ -2,6 +2,7 @@
 /*
  *  Copyright (c) 2008 Stephan Arts <stephan at xfce.org>
  *  Copyright (c) 2008 Nick Schermer <nick at xfce.org>
+ *  Copyright (c) 2008 Jannis Pohlmann <jannis at xfce.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -35,9 +36,10 @@
 #include <xfconf/xfconf.h>
 #include <libxfce4util/libxfce4util.h>
 
-#include <xfce4-settings-helper/pointers.h>
-#include <xfce4-settings-helper/xkb.h>
-#include <xfce4-settings-helper/accessx.h>
+#include "pointers.h"
+#include "xkb.h"
+#include "accessx.h"
+#include "keyboard-shortcuts.h"
 
 
 
@@ -59,6 +61,7 @@
     GObject *pointer_helper;
     GObject *xkb_helper;
     GObject *accessx_helper;
+    GObject *shortcuts_helper;
     pid_t    pid;
 
     /* setup translation domain */
@@ -133,7 +136,9 @@
     pointer_helper = g_object_new (XFCE_TYPE_POINTERS_HELPER, NULL);
     xkb_helper = g_object_new (XFCE_TYPE_XKB_HELPER, NULL);
     accessx_helper = g_object_new (XFCE_TYPE_ACCESSX_HELPER, NULL);
+    shortcuts_helper = g_object_new (XFCE_TYPE_KEYBOARD_SHORTCUTS_HELPER, NULL);
 
+
     /* enter the main loop */
     gtk_main();
 
@@ -141,6 +146,7 @@
     g_object_unref (G_OBJECT (pointer_helper));
     g_object_unref (G_OBJECT (xkb_helper));
     g_object_unref (G_OBJECT (accessx_helper));
+    g_object_unref (G_OBJECT (shortcuts_helper));
 
     /* shutdown xfconf */
     xfconf_shutdown ();



More information about the Xfce4-commits mailing list