From 375d01913ec4e57d8cbedeec3904acea75ccfde4 Mon Sep 17 00:00:00 2001
From: Jannis Pohlmann <jannis@xfce.org>
Date: Mon, 20 Oct 2008 16:59:45 +0000
Subject: [PATCH] Implement shortcut editing.

(Old svn revision: 28327)
---
 settings-dialogs/Makefile.am                  |   4 +-
 settings-dialogs/frap-shortcuts-dialog.c      | 114 ++-
 settings-dialogs/frap-shortcuts-dialog.h      |  16 +-
 settings-dialogs/frap-shortcuts-provider.h    |  87 ---
 settings-dialogs/frap-shortcuts.c             | 625 +---------------
 settings-dialogs/frap-shortcuts.h             |  39 +-
 ...s-provider.c => xfce-shortcuts-provider.c} | 200 +++---
 settings-dialogs/xfce-shortcuts-provider.h    |  87 +++
 settings-dialogs/xfwm4-dialog.glade           | 115 +--
 settings-dialogs/xfwm4-settings.c             | 667 +++++++++++++++---
 10 files changed, 953 insertions(+), 1001 deletions(-)
 delete mode 100644 settings-dialogs/frap-shortcuts-provider.h
 rename settings-dialogs/{frap-shortcuts-provider.c => xfce-shortcuts-provider.c} (70%)
 create mode 100644 settings-dialogs/xfce-shortcuts-provider.h

diff --git a/settings-dialogs/Makefile.am b/settings-dialogs/Makefile.am
index 3acfe17a4..8e61a4872 100644
--- a/settings-dialogs/Makefile.am
+++ b/settings-dialogs/Makefile.am
@@ -40,10 +40,10 @@ xfwm4_workspace_settings_LDADD = \
 xfwm4_settings_SOURCES = \
 	xfwm4-settings.c \
 	xfwm4-dialog_glade.h \
+	xfce-shortcuts-provider.h \
+	xfce-shortcuts-provider.c \
 	frap-shortcuts.h \
 	frap-shortcuts.c \
-	frap-shortcuts-provider.h \
-	frap-shortcuts-provider.c \
 	frap-shortcuts-dialog.h \
 	frap-shortcuts-dialog.c
 
diff --git a/settings-dialogs/frap-shortcuts-dialog.c b/settings-dialogs/frap-shortcuts-dialog.c
index 8862d7060..001ca5237 100644
--- a/settings-dialogs/frap-shortcuts-dialog.c
+++ b/settings-dialogs/frap-shortcuts-dialog.c
@@ -40,11 +40,15 @@ static void     frap_shortcuts_dialog_dispose          (GObject
 static void     frap_shortcuts_dialog_finalize         (GObject                  *object);
 static void     frap_shortcuts_dialog_create_contents  (FrapShortcutsDialog      *dialog,
                                                         const gchar              *provider,
+                                                        const gchar              *action_name,
                                                         const gchar              *action);
 static gboolean frap_shortcuts_dialog_key_pressed      (FrapShortcutsDialog      *dialog,
                                                         GdkEventKey              *event);
 static gboolean frap_shortcuts_dialog_key_released     (FrapShortcutsDialog      *dialog,
                                                         GdkEventKey              *event);
+static gchar   *frap_shortcuts_dialog_shortcut_name    (FrapShortcutsDialog      *dialog,
+                                                        guint                     keyval,
+                                                        guint                     modifiers);
 
 
 
@@ -65,6 +69,7 @@ struct _FrapShortcutsDialog
 
   GtkWidget *shortcut_label;
 
+  gchar     *action_name;
   gchar     *action;
   gchar     *shortcut;
 };
@@ -199,6 +204,7 @@ frap_shortcuts_dialog_finalize (GObject *object)
 {
   FrapShortcutsDialog *dialog = FRAP_SHORTCUTS_DIALOG (object);
 
+  g_free (dialog->action_name);
   g_free (dialog->action);
   g_free (dialog->shortcut);
 
@@ -209,14 +215,16 @@ frap_shortcuts_dialog_finalize (GObject *object)
 
 GtkWidget*
 frap_shortcuts_dialog_new (const gchar *provider,
+                           const gchar *action_name,
                            const gchar *action)
 {
   FrapShortcutsDialog *dialog;
   
   dialog = g_object_new (FRAP_TYPE_SHORTCUTS_DIALOG, NULL);
+  dialog->action_name = g_strdup (action_name);
   dialog->action = g_strdup (action);
 
-  frap_shortcuts_dialog_create_contents (dialog, provider, action);
+  frap_shortcuts_dialog_create_contents (dialog, provider, action_name, action);
 
   return GTK_WIDGET (dialog);
 }
@@ -226,6 +234,7 @@ frap_shortcuts_dialog_new (const gchar *provider,
 static void
 frap_shortcuts_dialog_create_contents (FrapShortcutsDialog *dialog,
                                        const gchar         *provider,
+                                       const gchar         *action_name,
                                        const gchar         *action)
 {
   GtkWidget   *button;
@@ -237,17 +246,17 @@ frap_shortcuts_dialog_create_contents (FrapShortcutsDialog *dialog,
   if (g_utf8_collate (provider, "xfwm4") == 0)
     {
       title = _("Enter window manager action shortcut");
-      subtitle = g_strdup_printf (_("Action: %s"), action);
+      subtitle = g_strdup_printf (_("Action: %s"), action_name);
     }
   else if (g_utf8_collate (provider, "commands") == 0)
     {
       title = _("Enter command shortcut");
-      subtitle = g_strdup_printf (_("Command: %s"), action);
+      subtitle = g_strdup_printf (_("Command: %s"), action_name);
     }
   else
     {
       title = _("Enter shortcut");
-      subtitle = g_strdup_printf (_("Action: %s"), action);
+      subtitle = g_strdup_printf (_("Action: %s"), action_name);
     }
 
   /* Set dialog title */
@@ -339,7 +348,7 @@ frap_shortcuts_dialog_key_pressed (FrapShortcutsDialog *dialog,
   g_free (dialog->shortcut);
 
   /* Determine and remember the current shortcut */
-  dialog->shortcut = frap_shortcuts_get_accelerator_name (event->keyval, event->state);
+  dialog->shortcut = frap_shortcuts_dialog_shortcut_name (dialog, event->keyval, event->state);
 
   shortcut = g_markup_escape_text (dialog->shortcut, -1);
   text = g_strdup_printf (_("<span size='large'><b>%s</b></span>"), shortcut);
@@ -372,12 +381,98 @@ frap_shortcuts_dialog_key_released (FrapShortcutsDialog *dialog,
       /* Exit dialog with positive response */
       gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
     }
+  else
+    {
+      /* Clear label */
+      gtk_label_set_markup (GTK_LABEL (dialog->shortcut_label), "");
+    }
 
   return FALSE;
 }
 
 
 
+static gchar *
+frap_shortcuts_dialog_shortcut_name (FrapShortcutsDialog *dialog,
+                                     guint                keyval,
+                                     guint                modifiers)
+{
+  XModifierKeymap *modmap;
+  Display         *display;
+  const KeySym    *keysyms;
+  KeyCode          keycode;
+  KeySym          *keymap;
+  gint             keysyms_per_keycode = 0;
+  gint             min_keycode = 0;
+  gint             max_keycode = 0;
+  gint             mask;
+  gint             i;
+  gint             j;
+
+  g_return_val_if_fail (FRAP_IS_SHORTCUTS_DIALOG (dialog), NULL);
+
+  display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+  gdk_error_trap_push ();
+
+  XDisplayKeycodes (display, &min_keycode, &max_keycode);
+
+  keymap = XGetKeyboardMapping (display, min_keycode, max_keycode - min_keycode + 1, &keysyms_per_keycode);
+
+  if (G_LIKELY (keymap != NULL))
+    {
+      modmap = XGetModifierMapping (display);
+
+      if (G_LIKELY (modmap != NULL))
+        {
+          for (i = 0; i < 8 * modmap->max_keypermod; ++i)
+            {
+              keycode = modmap->modifiermap[i];
+
+              if (keycode == 0 || keycode < min_keycode || keycode > max_keycode)
+                continue;
+
+              keysyms = keymap + (keycode - min_keycode) * keysyms_per_keycode;
+              mask = 1 << (i / modmap->max_keypermod);
+
+              for (j = 0; j < keysyms_per_keycode; ++j)
+                {
+                  if (keysyms[j] == GDK_Super_L || keysyms[j] == GDK_Super_R)
+                    modifiers &= ~mask;
+
+#if 0
+                  if (keysyms[j] == GDK_Meta_L || keysyms[j] == GDK_Meta_R)
+                    modifiers &= ~mask;
+#endif
+
+                  if (keysyms[j] == GDK_Hyper_L || keysyms[j] == GDK_Hyper_R)
+                    modifiers &= ~mask;
+
+                  if (keysyms[j] == GDK_Scroll_Lock)
+                    modifiers &= ~mask;
+
+                  if (keysyms[j] == GDK_Num_Lock)
+                    modifiers &= ~mask;
+
+                  if (keysyms[j] == GDK_Caps_Lock)
+                    modifiers &= ~mask;
+                }
+            }
+
+          XFreeModifiermap (modmap);
+        }
+
+      XFree (keymap);
+    }
+
+  gdk_flush ();
+  gdk_error_trap_pop ();
+
+  return gtk_accelerator_name (keyval, modifiers);
+}
+
+
+
 const gchar*
 frap_shortcuts_dialog_get_shortcut (FrapShortcutsDialog *dialog)
 {
@@ -393,3 +488,12 @@ frap_shortcuts_dialog_get_action (FrapShortcutsDialog *dialog)
   g_return_val_if_fail (FRAP_IS_SHORTCUTS_DIALOG (dialog), NULL);
   return dialog->action;
 }
+
+
+
+const gchar *
+frap_shortcuts_dialog_get_action_name (FrapShortcutsDialog *dialog)
+{
+  g_return_val_if_fail (FRAP_IS_SHORTCUTS_DIALOG (dialog), NULL);
+  return dialog->action_name;
+}
diff --git a/settings-dialogs/frap-shortcuts-dialog.h b/settings-dialogs/frap-shortcuts-dialog.h
index 7e397e9c1..4cee40fda 100644
--- a/settings-dialogs/frap-shortcuts-dialog.h
+++ b/settings-dialogs/frap-shortcuts-dialog.h
@@ -37,13 +37,15 @@ typedef struct _FrapShortcutsDialog      FrapShortcutsDialog;
 #define FRAP_IS_SHORTCUTS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FRAP_TYPE_SHORTCUTS_DIALOG))
 #define FRAP_SHORTCUTS_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), FRAP_TYPE_SHORTCUTS_DIALOG, FrapShortcutsDialogClass))
 
-GType        frap_shortcuts_dialog_get_type     (void) G_GNUC_CONST;
-
-GtkWidget   *frap_shortcuts_dialog_new          (const gchar         *provider,
-                                                 const gchar         *action);
-gint         frap_shortcuts_dialog_run          (FrapShortcutsDialog *dialog);
-const gchar *frap_shortcuts_dialog_get_shortcut (FrapShortcutsDialog *dialog);
-const gchar *frap_shortcuts_dialog_get_action   (FrapShortcutsDialog *action);
+GType        frap_shortcuts_dialog_get_type        (void) G_GNUC_CONST;
+
+GtkWidget   *frap_shortcuts_dialog_new             (const gchar         *provider,
+                                                    const gchar         *action_name,
+                                                    const gchar         *action);
+gint         frap_shortcuts_dialog_run             (FrapShortcutsDialog *dialog);
+const gchar *frap_shortcuts_dialog_get_shortcut    (FrapShortcutsDialog *dialog);
+const gchar *frap_shortcuts_dialog_get_action      (FrapShortcutsDialog *action);
+const gchar *frap_shortcuts_dialog_get_action_name (FrapShortcutsDialog *action);
 
 G_END_DECLS;
 
diff --git a/settings-dialogs/frap-shortcuts-provider.h b/settings-dialogs/frap-shortcuts-provider.h
deleted file mode 100644
index be485f9c5..000000000
--- a/settings-dialogs/frap-shortcuts-provider.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* vi:set sw=2 sts=2 ts=2 et ai: */
-/*-
- * Copyright (c) 2008 Jannis Pohlmann <jannis@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 __FRAP_SHORTCUTS_PROVIDER_H__
-#define __FRAP_SHORTCUTS_PROVIDER_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS;
-
-typedef struct _FrapShortcut                 FrapShortcut;
-
-typedef struct _FrapShortcutsProviderPrivate FrapShortcutsProviderPrivate;
-typedef struct _FrapShortcutsProviderClass   FrapShortcutsProviderClass;
-typedef struct _FrapShortcutsProvider        FrapShortcutsProvider;
-
-#define FRAP_TYPE_SHORTCUTS_PROVIDER            (frap_shortcuts_provider_get_type ())
-#define FRAP_SHORTCUTS_PROVIDER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), FRAP_TYPE_SHORTCUTS_PROVIDER, FrapShortcutsProvider))
-#define FRAP_SHORTCUTS_PROVIDER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), FRAP_TYPE_SHORTCUTS_PROVIDER, FrapShortcutsProviderClass))
-#define FRAP_IS_SHORTCUTS_PROVIDER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FRAP_TYPE_SHORTCUTS_PROVIDER))
-#define FRAP_IS_SHORTCUTS_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FRAP_TYPE_SHORTCUTS_PROVIDER)
-#define FRAP_SHORTCUTS_PROVIDER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), FRAP_TYPE_SHORTCUTS_PROVIDER, FrapShortcutsProviderClass))
-
-GType frap_shortcuts_provider_get_type (void) G_GNUC_CONST;
-
-FrapShortcutsProvider  *frap_shortcuts_provider_new               (const gchar           *name) G_GNUC_MALLOC;
-GList                  *frap_shortcuts_provider_get_providers     (void) G_GNUC_MALLOC;
-void                    frap_shortcuts_provider_free_providers    (GList                 *providers);
-const gchar            *frap_shortcuts_provider_get_name          (FrapShortcutsProvider *provider);
-gboolean                frap_shortcuts_provider_is_custom         (FrapShortcutsProvider *provider);
-void                    frap_shortcuts_provider_reset_to_defaults (FrapShortcutsProvider *provider);
-void                    frap_shortcuts_provider_clone_defaults    (FrapShortcutsProvider *provider);
-GList                  *frap_shortcuts_provider_get_shortcuts     (FrapShortcutsProvider *provider);
-FrapShortcut           *frap_shortcuts_provider_get_shortcut      (FrapShortcutsProvider *provider,
-                                                                   const gchar           *shortcut);
-gboolean                frap_shortcuts_provider_has_shortcut      (FrapShortcutsProvider *provider,
-                                                                   const gchar           *shortcut);
-void                    frap_shortcuts_provider_set_shortcut      (FrapShortcutsProvider *provider,
-                                                                   const gchar           *shortcut,
-                                                                   const gchar           *command);
-void                    frap_shortcuts_provider_reset_shortcut    (FrapShortcutsProvider *provider,
-                                                                   const gchar           *shortcut);
-
-void                    frap_shortcuts_free_shortcuts             (GList                 *shortcuts);
-void                    frap_shortcuts_free_shortcut              (FrapShortcut          *shortcut);
-
-
-
-struct _FrapShortcutsProviderClass
-{
-  GObjectClass __parent__;
-};
-
-struct _FrapShortcutsProvider
-{
-  GObject __parent__;
-
-  FrapShortcutsProviderPrivate *priv;
-};
-
-struct _FrapShortcut
-{
-  gchar *property_name;
-  gchar *shortcut;
-  gchar *command;
-};
-
-G_END_DECLS;
-
-#endif /* !__FRAP_SHORTCUTS_PROVIDER_H__ */
diff --git a/settings-dialogs/frap-shortcuts.c b/settings-dialogs/frap-shortcuts.c
index 88f583a22..8cbc93f9e 100644
--- a/settings-dialogs/frap-shortcuts.c
+++ b/settings-dialogs/frap-shortcuts.c
@@ -26,14 +26,8 @@
 
 #include <X11/Xlib.h>
 
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-#include <gdk/gdkkeysyms.h>
-
 #include <gtk/gtk.h>
 
-#include <dbus/dbus-glib.h>
-
 #include <libxfce4util/libxfce4util.h>
 #include <libxfcegui4/libxfcegui4.h>
 
@@ -43,32 +37,6 @@
 
 
 
-typedef struct _FrapShortcutsCallbackContext FrapShortcutsCallbackContext;
-
-
-
-
-static guint           frap_shortcuts_x11_get_ignore_mask            (void);
-static guint           frap_shortcuts_x11_get_use_mask               (void);
-static guint           frap_shortcuts_gdk_remove_duplicate_modifiers (guint      modifiers);
-static guint           frap_shortcuts_x11_add_gdk_modifiers          (guint      modifiers);
-static guint           frap_shortcuts_gdk_add_x11_modifiers          (guint      modifiers);
-#if 0
-static void            frap_shortcuts_print_gdk_modifiers            (guint      modifiers);
-#endif
-static GdkFilterReturn frap_shortcuts_default_filter                 (GdkXEvent *gdk_xevent,
-                                                                      GdkEvent  *event,
-                                                                      gpointer   user_data);
-static void            frap_shortcuts_handle_key_press               (XKeyEvent *xevent);
-
-
-
-struct _FrapShortcutsCallbackContext
-{
-  FrapShortcutsCallback callback;
-  gpointer              user_data;
-};
-
 typedef struct
 {
   const gchar      *owner_name;
@@ -80,20 +48,13 @@ typedef struct
 
 
 
-
-
-
-static FrapShortcutsCallbackContext frap_shortcuts_callback_context = { 0 };
-
-
-
 static FrapShortcutsConflictMessage conflict_messages[] = {
   { "xfwm4", "xfwm4", 
     N_("This shortcut is already being used by <b>another window manager action</b>. Which action do you want to use?"), 
-    N_("Use this action"), N_("Keep the other one") },
+    N_("Use %s"), N_("Keep the other one") },
   { "xfwm4", "commands",
     N_("The shortcut is already being used for the command <b>%s</b>. Which action do you want to use?"), 
-    N_("Use this action"), N_("Keep %s") },
+    N_("Use %s"), N_("Keep %s") },
   { "commands","commands",
     N_("The shortcut is already being used for the command <b>%s</b>. Which action do you want to use?"),
     N_("Use %s"), N_("Keep %s") },
@@ -177,585 +138,3 @@ frap_shortcuts_conflict_dialog (const gchar *owner,
 
   return response;
 }
-
-
-
-gchar *
-frap_shortcuts_get_accelerator_name (guint keyval,
-                                     guint modifiers)
-{
-  modifiers = frap_shortcuts_x11_add_gdk_modifiers (modifiers);
-  modifiers = frap_shortcuts_gdk_remove_duplicate_modifiers (modifiers);
-
-  return gtk_accelerator_name (keyval, modifiers);
-}
-
-
-
-void
-frap_shortcuts_parse_accelerator (const gchar *name,
-                                  guint       *keyval,
-                                  guint       *modifiers)
-{
-  gtk_accelerator_parse (name, keyval, modifiers);
-
-  *modifiers = frap_shortcuts_gdk_add_x11_modifiers (*modifiers);
-  *modifiers &= ~ frap_shortcuts_x11_get_ignore_mask ();
-}
-
-
-
-void
-frap_shortcuts_set_shortcut_callback (FrapShortcutsCallback callback,
-                                      gpointer              user_data)
-{
-  frap_shortcuts_callback_context.callback = callback;
-  frap_shortcuts_callback_context.user_data = user_data;
-
-  frap_shortcuts_add_filter (frap_shortcuts_default_filter, NULL);
-}
-
-
-
-void
-frap_shortcuts_add_filter (GdkFilterFunc callback,
-                           gpointer      user_data)
-{
-  GdkDisplay *display;
-
-  display = gdk_display_get_default ();
-
-  /* Flush events before adding the event filter */
-  XAllowEvents (GDK_DISPLAY_XDISPLAY (display), AsyncBoth, CurrentTime);
-
-  /* Add event filter to the root window of each screen */
-#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), callback, helper);
-    }
-#else
-  gdk_window_add_filter (NULL, callback, user_data);
-#endif
-}
-
-
-
-gboolean
-frap_shortcuts_grab_shortcut (const gchar *shortcut,
-                              gboolean     ungrab)
-{
-  GdkDisplay *display;
-  GdkScreen  *screen;
-  KeyCode     keycode;
-  guint       keyval;
-  guint       modifiers;
-  guint       bits[32];
-  guint       current_mask;
-  guint       ignore_mask;
-  guint       use_mask;
-  guint       n_bits;
-  guint       screens;
-  guint       i;
-  guint       j;
-  guint       k;
-
-  display = gdk_display_get_default ();
-  screens = gdk_display_get_n_screens (display);
-
-  /* Parse the shortcut */
-  frap_shortcuts_parse_accelerator (shortcut, &keyval, &modifiers);
-
-  DBG ("grab_shortcut: shortcut = %s, keyval = 0x%x, modifiers = 0x%x, ungrab = %i", shortcut, keyval, modifiers, ungrab);
-
-  /* Determine mask containing ignored modifier bits */
-  ignore_mask = frap_shortcuts_x11_get_ignore_mask ();
-  use_mask = frap_shortcuts_x11_get_use_mask ();
-
-  /* Mask used modifiers */
-  modifiers = frap_shortcuts_gdk_add_x11_modifiers (modifiers);
-  modifiers &= use_mask;
-
-  /* Determine keycode */
-  keycode = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (display), keyval);
-
-  /* Store indices of all 1 bits of the ignore mask in an array */
-  for (i = 0, n_bits = 0; i < 32; ++i, ignore_mask >>= 1)
-    if ((ignore_mask & 0x1) == 0x1)
-      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);
-          
-          /* Really grab or ungrab the key now */
-          frap_shortcuts_grab_shortcut_real (GDK_DISPLAY_XDISPLAY (display), 
-                                             GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)),
-                                             keycode,
-                                             current_mask | modifiers,
-                                             ungrab);
-        }
-    }
-
-  return TRUE;
-}
-
-
-
-gboolean
-frap_shortcuts_grab_shortcut_real (Display *display,
-                                   Window   window,
-                                   KeyCode  keycode,
-                                   guint    modifiers,
-                                   gboolean ungrab)
-{
-  gdk_error_trap_push ();
-
-  if (ungrab)
-    XUngrabKey (display, keycode, modifiers, window);
-  else
-    XGrabKey (display, keycode, modifiers, window, FALSE, GrabModeAsync, GrabModeAsync);
-
-  gdk_flush ();
-
-  return gdk_error_trap_pop () == 0;
-}
-
-
-
-static guint 
-frap_shortcuts_x11_get_ignore_mask (void)
-{
-  XModifierKeymap *modmap;
-  const KeySym    *keysyms;
-  Display         *display;
-  KeyCode          keycode;
-  KeySym          *keymap;
-  guint            ignored_modifiers = 0;
-  gint             keysyms_per_keycode = 0;
-  gint             min_keycode = 0;
-  gint             max_keycode = 0;
-  gint             mask;
-  gint             i;
-  gint             j;
-
-  display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-
-  gdk_error_trap_push ();
-
-  XDisplayKeycodes (display, &min_keycode, &max_keycode);
-
-  keymap = XGetKeyboardMapping (display, min_keycode, max_keycode - min_keycode + 1, &keysyms_per_keycode);
-
-  if (keymap == NULL)
-    return ignored_modifiers;
-
-  modmap = XGetModifierMapping (display);
-
-  if (modmap == NULL)
-    {
-      XFree (keymap);
-      return ignored_modifiers;
-    }
-
-  for (i = 0; i < 8 * modmap->max_keypermod; ++i)
-    {
-      keycode = modmap->modifiermap[i];
-
-      if (keycode == 0 || keycode < min_keycode || keycode > max_keycode)
-        continue;
-
-      keysyms = keymap + (keycode - min_keycode) * keysyms_per_keycode;
-
-      mask = 1 << (i / modmap->max_keypermod);
-
-      for (j = 0; j < keysyms_per_keycode; ++j)
-        {
-          if (keysyms[j] == GDK_Caps_Lock ||
-              keysyms[j] == GDK_Num_Lock ||
-              keysyms[j] == GDK_Scroll_Lock)
-            {
-              ignored_modifiers |= mask;
-            }
-        }
-    }
-
-  XFreeModifiermap (modmap);
-  XFree (keymap);
-
-  gdk_flush ();
-  gdk_error_trap_pop ();
-
-  return ignored_modifiers | 0x2000 | GDK_LOCK_MASK | GDK_HYPER_MASK | GDK_SUPER_MASK | GDK_META_MASK;
-}
-
-
-
-static guint 
-frap_shortcuts_x11_get_use_mask (void)
-{
-  return GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK | GDK_MOD5_MASK;
-}
-
-
-
-static guint
-frap_shortcuts_gdk_remove_duplicate_modifiers (guint modifiers)
-{
-  XModifierKeymap *modmap;
-  const KeySym    *keysyms;
-  Display         *display;
-  KeyCode          keycode;
-  KeySym          *keymap;
-  guint            modifiers_result = modifiers;
-  gint             keysyms_per_keycode = 0;
-  gint             min_keycode = 0;
-  gint             max_keycode = 0;
-  gint             mask;
-  gint             i;
-  gint             j;
-
-  display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-
-  gdk_error_trap_push ();
-
-  XDisplayKeycodes (display, &min_keycode, &max_keycode);
-
-  keymap = XGetKeyboardMapping (display, min_keycode, max_keycode - min_keycode + 1, &keysyms_per_keycode);
-
-  if (keymap == NULL)
-    return modifiers_result;
-
-  modmap = XGetModifierMapping (display);
-
-  if (modmap == NULL)
-    {
-      XFree (keymap);
-      return modifiers_result;
-    }
-
-  for (i = 0; i < 8 * modmap->max_keypermod; ++i)
-    {
-      keycode = modmap->modifiermap[i];
-
-      if (keycode == 0 || keycode < min_keycode || keycode > max_keycode)
-        continue;
-
-      keysyms = keymap + (keycode - min_keycode) * keysyms_per_keycode;
-
-      mask = 1 << (i / modmap->max_keypermod);
-
-      for (j = 0; j < keysyms_per_keycode; ++j)
-        {
-          if (keysyms[j] == GDK_Caps_Lock ||
-              keysyms[j] == GDK_Num_Lock ||
-              keysyms[j] == GDK_Scroll_Lock ||
-#if 0
-              keysyms[j] == GDK_Hyper_L ||
-              keysyms[j] == GDK_Hyper_R ||
-#endif
-              keysyms[j] == GDK_Meta_L ||
-              keysyms[j] == GDK_Meta_R ||
-              keysyms[j] == GDK_Super_L ||
-              keysyms[j] == GDK_Super_R)
-            {
-              if ((modifiers & mask) == mask)
-                modifiers_result &= ~mask;
-            }
-        }
-    }
-
-  XFreeModifiermap (modmap);
-  XFree (keymap);
-
-  gdk_flush ();
-  gdk_error_trap_pop ();
-
-  return modifiers_result;
-}
-
-
-
-static guint
-frap_shortcuts_x11_add_gdk_modifiers (guint modifiers)
-{
-  XModifierKeymap *modmap;
-  const KeySym    *keysyms;
-  Display         *display;
-  KeyCode          keycode;
-  KeySym          *keymap;
-  guint            modifiers_result = modifiers;
-  gint             keysyms_per_keycode = 0;
-  gint             min_keycode = 0;
-  gint             max_keycode = 0;
-  gint             mask;
-  gint             i;
-  gint             j;
-
-  display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-
-  gdk_error_trap_push ();
-
-  XDisplayKeycodes (display, &min_keycode, &max_keycode);
-
-  keymap = XGetKeyboardMapping (display, min_keycode, max_keycode - min_keycode + 1, &keysyms_per_keycode);
-
-  if (keymap == NULL)
-    return modifiers_result;
-
-  modmap = XGetModifierMapping (display);
-
-  if (modmap == NULL)
-    {
-      XFree (keymap);
-      return modifiers_result;
-    }
-
-  for (i = 0; i < 8 * modmap->max_keypermod; ++i)
-    {
-      keycode = modmap->modifiermap[i];
-
-      if (keycode == 0 || keycode < min_keycode || keycode > max_keycode)
-        continue;
-
-      keysyms = keymap + (keycode - min_keycode) * keysyms_per_keycode;
-
-      mask = 1 << (i / modmap->max_keypermod);
-
-      for (j = 0; j < keysyms_per_keycode; ++j)
-        {
-          switch (keysyms[j])
-            {
-            case GDK_Super_L:
-            case GDK_Super_R:
-              if ((modifiers & mask) == mask)
-                modifiers_result |= GDK_SUPER_MASK;
-              break;
-
-#if 0
-            case GDK_Hyper_L:
-            case GDK_Hyper_R:
-              if ((modifiers & mask) == mask)
-                modifiers_result |= GDK_HYPER_MASK;
-              break;
-#endif
-
-            case GDK_Meta_L:
-            case GDK_Meta_R:
-              if ((modifiers & mask) == mask)
-                modifiers_result |= GDK_META_MASK;
-              break;
-
-            default:
-              break;
-            }
-        }
-    }
-
-  XFreeModifiermap (modmap);
-  XFree (keymap);
-
-  gdk_flush ();
-  gdk_error_trap_pop ();
-
-  return modifiers_result;
-}
-
-
-
-static guint
-frap_shortcuts_gdk_add_x11_modifiers (guint modifiers)
-{
-  XModifierKeymap *modmap;
-  const KeySym    *keysyms;
-  Display         *display;
-  KeyCode          keycode;
-  KeySym          *keymap;
-  guint            modifiers_result = modifiers;
-  gint             keysyms_per_keycode = 0;
-  gint             min_keycode = 0;
-  gint             max_keycode = 0;
-  gint             mask;
-  gint             i;
-  gint             j;
-
-  display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-
-  gdk_error_trap_push ();
-
-  XDisplayKeycodes (display, &min_keycode, &max_keycode);
-
-  keymap = XGetKeyboardMapping (display, min_keycode, max_keycode - min_keycode + 1, &keysyms_per_keycode);
-
-  if (keymap == NULL)
-    return modifiers_result;
-
-  modmap = XGetModifierMapping (display);
-
-  if (modmap == NULL)
-    {
-      XFree (keymap);
-      return modifiers_result;
-    }
-
-  for (i = 0; i < 8 * modmap->max_keypermod; ++i)
-    {
-      keycode = modmap->modifiermap[i];
-
-      if (keycode == 0 || keycode < min_keycode || keycode > max_keycode)
-        continue;
-
-      keysyms = keymap + (keycode - min_keycode) * keysyms_per_keycode;
-
-      mask = 1 << (i / modmap->max_keypermod);
-
-      for (j = 0; j < keysyms_per_keycode; ++j)
-        {
-          switch (keysyms[j])
-            {
-            case GDK_Super_L:
-            case GDK_Super_R:
-              if ((modifiers & GDK_SUPER_MASK) == GDK_SUPER_MASK)
-                modifiers_result |= mask;
-              break;
-
-#if 0
-            case GDK_Hyper_L:
-            case GDK_Hyper_R:
-              if ((modifiers & GDK_HYPER_MASK) == GDK_HYPER_MASK)
-                modifiers_result |= mask;
-              break;
-#endif
-
-            case GDK_Meta_L:
-            case GDK_Meta_R:
-              if ((modifiers & GDK_META_MASK) == GDK_META_MASK)
-                modifiers_result |= mask;
-              break;
-
-            default:
-              break;
-            }
-        }
-    }
-
-  XFreeModifiermap (modmap);
-  XFree (keymap);
-
-  gdk_flush ();
-  gdk_error_trap_pop ();
-
-  return modifiers_result;
-}
-
-
-
-#if 0
-static void
-frap_shortcuts_print_gdk_modifiers (guint modifiers)
-{
-  GList *strings = NULL;
-  gint   i;
-
-  if ((modifiers & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
-    strings = g_list_append (strings, " GDK_SHIFT_MASK");
-
-  if ((modifiers & GDK_LOCK_MASK) == GDK_LOCK_MASK)
-    strings = g_list_append (strings, " GDK_LOCK_MASK");
-
-  if ((modifiers & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
-    strings = g_list_append (strings, "GDK_CONTROL_MASK");
-
-  if ((modifiers & GDK_MOD1_MASK) == GDK_MOD1_MASK)
-    strings = g_list_append (strings, "GDK_MOD1_MASK");
-
-  if ((modifiers & GDK_MOD2_MASK) == GDK_MOD2_MASK)
-    strings = g_list_append (strings, "GDK_MOD2_MASK");
-
-  if ((modifiers & GDK_MOD3_MASK) == GDK_MOD3_MASK)
-    strings = g_list_append (strings, "GDK_MOD3_MASK");
-
-  if ((modifiers & GDK_MOD4_MASK) == GDK_MOD4_MASK)
-    strings = g_list_append (strings, "GDK_MOD4_MASK");
-
-  if ((modifiers & GDK_MOD5_MASK) == GDK_MOD5_MASK)
-    strings = g_list_append (strings, "GDK_MOD5_MASK");
-
-  if ((modifiers & GDK_SUPER_MASK) == GDK_SUPER_MASK)
-    strings = g_list_append (strings, "GDK_SUPER_MASK");
-
-  if ((modifiers & GDK_HYPER_MASK) == GDK_HYPER_MASK)
-    strings = g_list_append (strings, "GDK_HYPER_MASK");
-
-  if ((modifiers & GDK_META_MASK) == GDK_META_MASK)
-    strings = g_list_append (strings, "GDK_META_MASK");
-
-  g_print ("MODIFIERS: ");
-
-  for (i = 0; i < g_list_length (strings); ++i)
-    if (i < g_list_length (strings)-1)
-      g_print ("%s | ", (const gchar *) g_list_nth (strings, i)->data);
-    else
-      g_print ("%s\n", (const gchar *) g_list_nth (strings, i)->data);
-
-  if (g_list_length (strings) == 0)
-    g_print ("\n");
-
-  g_list_free (strings);
-}
-#endif
-
-
-
-static GdkFilterReturn 
-frap_shortcuts_default_filter (GdkXEvent *gdk_xevent,
-                               GdkEvent  *event,
-                               gpointer   user_data)
-{
-  XEvent *xevent = (XEvent *) gdk_xevent;
-
-  switch (xevent->type)
-    {
-    case KeyPress:
-      frap_shortcuts_handle_key_press ((XKeyEvent *) xevent);
-      break;
-    default:
-      break;
-    }
-
-  return GDK_FILTER_CONTINUE;
-}
-
-
-
-static void
-frap_shortcuts_handle_key_press (XKeyEvent *xevent)
-{
-  GdkDisplay *display;
-  KeySym      keysym;
-  gchar      *shortcut;
-
-  display = gdk_display_get_default ();
-
-  /* FIXME: The first keysym might not be sufficient, maybe try them all and fire up the
-   * callback for each of them */
-  keysym = XKeycodeToKeysym (GDK_DISPLAY_XDISPLAY (display), xevent->keycode, 0);
-
-  shortcut = frap_shortcuts_get_accelerator_name (keysym, xevent->state);
-  
-  if (frap_shortcuts_callback_context.callback != NULL)
-    frap_shortcuts_callback_context.callback (shortcut, frap_shortcuts_callback_context.user_data);
-
-  g_free (shortcut);
-}
diff --git a/settings-dialogs/frap-shortcuts.h b/settings-dialogs/frap-shortcuts.h
index 9baf251a5..9a6b93623 100644
--- a/settings-dialogs/frap-shortcuts.h
+++ b/settings-dialogs/frap-shortcuts.h
@@ -24,38 +24,11 @@
 #include <X11/Xlib.h>
 #include <xfconf/xfconf.h>
 
-
-
-typedef void (*FrapShortcutsCallback) (const gchar *shortcut,
-                                       gpointer     user_data);
-
-
-
-gboolean       frap_shortcuts_conflict_dialog       (const gchar           *owner,
-                                                     const gchar           *other,
-                                                     const gchar           *shortcut,
-                                                     const gchar           *owner_action,
-                                                     const gchar           *other_action,
-                                                     gboolean               ignore_same_provider);
+gboolean frap_shortcuts_conflict_dialog (const gchar *owner,
+                                         const gchar *other,
+                                         const gchar *shortcut,
+                                         const gchar *owner_action,
+                                         const gchar *other_action,
+                                         gboolean     ignore_same_provider);
                                                      
-gchar         *frap_shortcuts_get_accelerator_name  (guint                  keyval,
-                                                     guint                  modifiers);
-void           frap_shortcuts_parse_accelerator     (const gchar           *name,
-                                                     guint                 *keyval,
-                                                     guint                 *modifiers);
-
-void           frap_shortcuts_set_shortcut_callback (FrapShortcutsCallback  callback,
-                                                     gpointer               user_data);
-void           frap_shortcuts_add_filter            (GdkFilterFunc          callback,
-                                                     gpointer               user_data);
-gboolean       frap_shortcuts_grab_shortcut         (const gchar           *shortcut,
-                                                     gboolean               ungrab);
-gboolean       frap_shortcuts_grab_shortcut_real    (Display               *display,
-                                                     Window                 window,
-                                                     KeyCode                keycode,
-                                                     guint                  modifiers,
-                                                     gboolean               ungrab);
-
-
-
 #endif /* !__FRAP_SHORTCUTS_H__ */
diff --git a/settings-dialogs/frap-shortcuts-provider.c b/settings-dialogs/xfce-shortcuts-provider.c
similarity index 70%
rename from settings-dialogs/frap-shortcuts-provider.c
rename to settings-dialogs/xfce-shortcuts-provider.c
index f9a3b2339..97ff14e82 100644
--- a/settings-dialogs/frap-shortcuts-provider.c
+++ b/settings-dialogs/xfce-shortcuts-provider.c
@@ -32,11 +32,11 @@
 #include <libxfce4util/libxfce4util.h>
 #include <xfconf/xfconf.h>
 
-#include "frap-shortcuts-provider.h"
+#include "xfce-shortcuts-provider.h"
 
 
 
-#define FRAP_SHORTCUTS_PROVIDER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), FRAP_TYPE_SHORTCUTS_PROVIDER, FrapShortcutsProviderPrivate))
+#define XFCE_SHORTCUTS_PROVIDER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), XFCE_TYPE_SHORTCUTS_PROVIDER, XfceShortcutsProviderPrivate))
 
 
 
@@ -49,31 +49,31 @@ enum
 
 
 
-typedef struct _FrapShortcutsProviderContext FrapShortcutsProviderContext;
+typedef struct _XfceShortcutsProviderContext XfceShortcutsProviderContext;
 
 
 
-static void frap_shortcuts_provider_class_init       (FrapShortcutsProviderClass *klass);
-static void frap_shortcuts_provider_init             (FrapShortcutsProvider      *provider);
-static void frap_shortcuts_provider_constructed      (GObject                    *object);
-static void frap_shortcuts_provider_finalize         (GObject                    *object);
-static void frap_shortcuts_provider_get_property     (GObject                    *object,
+static void xfce_shortcuts_provider_class_init       (XfceShortcutsProviderClass *klass);
+static void xfce_shortcuts_provider_init             (XfceShortcutsProvider      *provider);
+static void xfce_shortcuts_provider_constructed      (GObject                    *object);
+static void xfce_shortcuts_provider_finalize         (GObject                    *object);
+static void xfce_shortcuts_provider_get_property     (GObject                    *object,
                                                       guint                       prop_id,
                                                       GValue                     *value,
                                                       GParamSpec                 *pspec);
-static void frap_shortcuts_provider_set_property     (GObject                    *object,
+static void xfce_shortcuts_provider_set_property     (GObject                    *object,
                                                       guint                       prop_id,
                                                       const GValue               *value,
                                                       GParamSpec                 *pspec);
-static void frap_shortcuts_provider_register         (FrapShortcutsProvider      *provider);
-static void frap_shortcuts_provider_property_changed (XfconfChannel              *channel,
+static void xfce_shortcuts_provider_register         (XfceShortcutsProvider      *provider);
+static void xfce_shortcuts_provider_property_changed (XfconfChannel              *channel,
                                                       gchar                      *property,
                                                       GValue                     *value,
-                                                      FrapShortcutsProvider      *provider);
+                                                      XfceShortcutsProvider      *provider);
 
 
 
-struct _FrapShortcutsProviderPrivate
+struct _XfceShortcutsProviderPrivate
 {
   XfconfChannel *channel;
   gchar         *name;
@@ -81,21 +81,21 @@ struct _FrapShortcutsProviderPrivate
   gchar         *custom_base_property;
 };
 
-struct _FrapShortcutsProviderContext
+struct _XfceShortcutsProviderContext
 {
-  FrapShortcutsProvider *provider;
+  XfceShortcutsProvider *provider;
   GList                 *list;
   const gchar           *base_property;
 };
 
 
 
-static GObjectClass *frap_shortcuts_provider_parent_class = NULL;
+static GObjectClass *xfce_shortcuts_provider_parent_class = NULL;
 
 
 
 GType
-frap_shortcuts_provider_get_type (void)
+xfce_shortcuts_provider_get_type (void)
 {
   static GType type = G_TYPE_INVALID;
 
@@ -103,19 +103,19 @@ frap_shortcuts_provider_get_type (void)
     {
       static const GTypeInfo info =
       {
-        sizeof (FrapShortcutsProviderClass),
+        sizeof (XfceShortcutsProviderClass),
         NULL,
         NULL,
-        (GClassInitFunc) frap_shortcuts_provider_class_init,
+        (GClassInitFunc) xfce_shortcuts_provider_class_init,
         NULL,
         NULL,
-        sizeof (FrapShortcutsProvider),
+        sizeof (XfceShortcutsProvider),
         0,
-        (GInstanceInitFunc) frap_shortcuts_provider_init,
+        (GInstanceInitFunc) xfce_shortcuts_provider_init,
         NULL,
       };
 
-      type = g_type_register_static (G_TYPE_OBJECT, "FrapShortcutsProvider", &info, 0);
+      type = g_type_register_static (G_TYPE_OBJECT, "XfceShortcutsProvider", &info, 0);
     }
 
   return type;
@@ -124,22 +124,22 @@ frap_shortcuts_provider_get_type (void)
 
 
 static void
-frap_shortcuts_provider_class_init (FrapShortcutsProviderClass *klass)
+xfce_shortcuts_provider_class_init (XfceShortcutsProviderClass *klass)
 {
   GObjectClass *gobject_class;
 
-  g_type_class_add_private (klass, sizeof (FrapShortcutsProviderPrivate));
+  g_type_class_add_private (klass, sizeof (XfceShortcutsProviderPrivate));
 
   /* Determine the parent type class */
-  frap_shortcuts_provider_parent_class = g_type_class_peek_parent (klass);
+  xfce_shortcuts_provider_parent_class = g_type_class_peek_parent (klass);
 
   gobject_class = G_OBJECT_CLASS (klass);
 #if GLIB_CHECK_VERSION (2,14,0)
-  gobject_class->constructed = frap_shortcuts_provider_constructed;
+  gobject_class->constructed = xfce_shortcuts_provider_constructed;
 #endif
-  gobject_class->finalize = frap_shortcuts_provider_finalize; 
-  gobject_class->get_property = frap_shortcuts_provider_get_property;
-  gobject_class->set_property = frap_shortcuts_provider_set_property;
+  gobject_class->finalize = xfce_shortcuts_provider_finalize; 
+  gobject_class->get_property = xfce_shortcuts_provider_get_property;
+  gobject_class->set_property = xfce_shortcuts_provider_set_property;
 
   g_object_class_install_property (gobject_class, 
                                    PROP_NAME,
@@ -151,7 +151,7 @@ frap_shortcuts_provider_class_init (FrapShortcutsProviderClass *klass)
                                                         G_PARAM_CONSTRUCT_ONLY));
 
   g_signal_new ("shortcut-removed", 
-                FRAP_TYPE_SHORTCUTS_PROVIDER,
+                XFCE_TYPE_SHORTCUTS_PROVIDER,
                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                 0,
                 NULL,
@@ -162,7 +162,7 @@ frap_shortcuts_provider_class_init (FrapShortcutsProviderClass *klass)
                 G_TYPE_STRING);
 
   g_signal_new ("shortcut-added", 
-                FRAP_TYPE_SHORTCUTS_PROVIDER,
+                XFCE_TYPE_SHORTCUTS_PROVIDER,
                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                 0,
                 NULL,
@@ -176,38 +176,38 @@ frap_shortcuts_provider_class_init (FrapShortcutsProviderClass *klass)
 
 
 static void
-frap_shortcuts_provider_init (FrapShortcutsProvider *provider)
+xfce_shortcuts_provider_init (XfceShortcutsProvider *provider)
 {
-  provider->priv = FRAP_SHORTCUTS_PROVIDER_GET_PRIVATE (provider);
+  provider->priv = XFCE_SHORTCUTS_PROVIDER_GET_PRIVATE (provider);
 
   provider->priv->channel = xfconf_channel_new ("xfce4-keyboard-shortcuts");
 
   g_signal_connect (provider->priv->channel, "property-changed", 
-                    G_CALLBACK (frap_shortcuts_provider_property_changed), provider);
+                    G_CALLBACK (xfce_shortcuts_provider_property_changed), provider);
 }
 
 
 
 static void
-frap_shortcuts_provider_constructed (GObject *object)
+xfce_shortcuts_provider_constructed (GObject *object)
 {
-  FrapShortcutsProvider *provider = FRAP_SHORTCUTS_PROVIDER (object);
+  XfceShortcutsProvider *provider = XFCE_SHORTCUTS_PROVIDER (object);
 
-  frap_shortcuts_provider_register (provider);
+  xfce_shortcuts_provider_register (provider);
 
   provider->priv->default_base_property = g_strdup_printf ("/%s/default", provider->priv->name);
   provider->priv->custom_base_property = g_strdup_printf ("/%s/custom", provider->priv->name);
 
-  if (!frap_shortcuts_provider_is_custom (provider))
-    frap_shortcuts_provider_reset_to_defaults (provider);
+  if (!xfce_shortcuts_provider_is_custom (provider))
+    xfce_shortcuts_provider_reset_to_defaults (provider);
 }
 
 
 
 static void
-frap_shortcuts_provider_finalize (GObject *object)
+xfce_shortcuts_provider_finalize (GObject *object)
 {
-  FrapShortcutsProvider *provider = FRAP_SHORTCUTS_PROVIDER (object);
+  XfceShortcutsProvider *provider = XFCE_SHORTCUTS_PROVIDER (object);
 
   g_free (provider->priv->name);
   g_free (provider->priv->custom_base_property);
@@ -215,18 +215,18 @@ frap_shortcuts_provider_finalize (GObject *object)
 
   g_object_unref (provider->priv->channel);
 
-  (*G_OBJECT_CLASS (frap_shortcuts_provider_parent_class)->finalize) (object);
+  (*G_OBJECT_CLASS (xfce_shortcuts_provider_parent_class)->finalize) (object);
 }
 
 
 
 static void
-frap_shortcuts_provider_get_property (GObject    *object,
+xfce_shortcuts_provider_get_property (GObject    *object,
                                       guint       prop_id,
                                       GValue     *value,
                                       GParamSpec *pspec)
 {
-  FrapShortcutsProvider *provider = FRAP_SHORTCUTS_PROVIDER (object);
+  XfceShortcutsProvider *provider = XFCE_SHORTCUTS_PROVIDER (object);
 
   switch (prop_id)
     {
@@ -242,12 +242,12 @@ frap_shortcuts_provider_get_property (GObject    *object,
 
 
 static void
-frap_shortcuts_provider_set_property (GObject      *object,
+xfce_shortcuts_provider_set_property (GObject      *object,
                                       guint         prop_id,
                                       const GValue *value,
                                       GParamSpec   *pspec)
 {
-  FrapShortcutsProvider *provider = FRAP_SHORTCUTS_PROVIDER (object);
+  XfceShortcutsProvider *provider = XFCE_SHORTCUTS_PROVIDER (object);
 
   switch (prop_id)
     {
@@ -265,7 +265,7 @@ frap_shortcuts_provider_set_property (GObject      *object,
 
 
 static void
-frap_shortcuts_provider_register (FrapShortcutsProvider *provider)
+xfce_shortcuts_provider_register (XfceShortcutsProvider *provider)
 {
   gchar       **provider_names;
   const gchar **names;
@@ -273,12 +273,12 @@ frap_shortcuts_provider_register (FrapShortcutsProvider *provider)
   gint          length;
   gint          i;
 
-  g_return_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (provider));
+  g_return_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (provider));
 
   provider_names = xfconf_channel_get_string_list (provider->priv->channel, "/providers");
 
   for (i = 0; provider_names != NULL && provider_names[i] != NULL; ++i)
-    if (G_UNLIKELY (g_str_equal (provider_names[i], frap_shortcuts_provider_get_name (provider))))
+    if (G_UNLIKELY (g_str_equal (provider_names[i], xfce_shortcuts_provider_get_name (provider))))
       {
         already_registered = TRUE;
         break;
@@ -291,7 +291,7 @@ frap_shortcuts_provider_register (FrapShortcutsProvider *provider)
       names = g_new0 (const gchar *, length + 1);
       for (i = 0; provider_names != NULL && provider_names[i] != NULL; ++i)
         names[i] = provider_names[i];
-      names[i++] = frap_shortcuts_provider_get_name (provider);
+      names[i++] = xfce_shortcuts_provider_get_name (provider);
       names[i] = NULL;
 
       xfconf_channel_set_string_list (provider->priv->channel, "/providers", names);
@@ -305,15 +305,15 @@ frap_shortcuts_provider_register (FrapShortcutsProvider *provider)
 
 
 static void 
-frap_shortcuts_provider_property_changed (XfconfChannel         *channel,
+xfce_shortcuts_provider_property_changed (XfconfChannel         *channel,
                                           gchar                 *property,
                                           GValue                *value,
-                                          FrapShortcutsProvider *provider)
+                                          XfceShortcutsProvider *provider)
 {
   const gchar *shortcut;
   gchar       *override_property;
 
-  g_return_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (provider));
+  g_return_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (provider));
 
   DBG ("property = %s", property);
 
@@ -339,22 +339,22 @@ frap_shortcuts_provider_property_changed (XfconfChannel         *channel,
 
 
 
-FrapShortcutsProvider *
-frap_shortcuts_provider_new (const gchar *name)
+XfceShortcutsProvider *
+xfce_shortcuts_provider_new (const gchar *name)
 {
-  GObject *object = g_object_new (FRAP_TYPE_SHORTCUTS_PROVIDER, "name", name, NULL);
+  GObject *object = g_object_new (XFCE_TYPE_SHORTCUTS_PROVIDER, "name", name, NULL);
 
 #if !GLIB_CHECK_VERSION (2,14,0)
-  frap_shortcuts_provider_constructed (object);
+  xfce_shortcuts_provider_constructed (object);  
 #endif
 
-  return FRAP_SHORTCUTS_PROVIDER (object);
+  return XFCE_SHORTCUTS_PROVIDER (object);
 }
 
 
 
 GList *
-frap_shortcuts_provider_get_providers (void)
+xfce_shortcuts_provider_get_providers (void)
 {
   GList         *providers = NULL;
   XfconfChannel *channel;
@@ -367,7 +367,7 @@ frap_shortcuts_provider_get_providers (void)
   if (G_LIKELY (names != NULL))
     {
       for (i = 0; names[i] != NULL; ++i)
-        providers = g_list_append (providers, frap_shortcuts_provider_new (names[i]));
+        providers = g_list_append (providers, xfce_shortcuts_provider_new (names[i]));
       g_strfreev (names);
     }
     
@@ -377,7 +377,7 @@ frap_shortcuts_provider_get_providers (void)
 
 
 void
-frap_shortcuts_provider_free_providers (GList *providers)
+xfce_shortcuts_provider_free_providers (GList *providers)
 {
   GList *iter;
 
@@ -390,21 +390,21 @@ frap_shortcuts_provider_free_providers (GList *providers)
 
 
 const gchar *
-frap_shortcuts_provider_get_name (FrapShortcutsProvider *provider)
+xfce_shortcuts_provider_get_name (XfceShortcutsProvider *provider)
 {
-  g_return_val_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (provider), NULL);
+  g_return_val_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (provider), NULL);
   return provider->priv->name;
 }
 
 
 
 gboolean
-frap_shortcuts_provider_is_custom (FrapShortcutsProvider *provider)
+xfce_shortcuts_provider_is_custom (XfceShortcutsProvider *provider)
 {
   gchar   *property;
   gboolean override;
 
-  g_return_val_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (provider), FALSE);
+  g_return_val_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (provider), FALSE);
   g_return_val_if_fail (XFCONF_IS_CHANNEL (provider->priv->channel), FALSE);
 
   property = g_strconcat (provider->priv->custom_base_property, "/override", NULL);
@@ -417,29 +417,29 @@ frap_shortcuts_provider_is_custom (FrapShortcutsProvider *provider)
 
 
 void
-frap_shortcuts_provider_reset_to_defaults (FrapShortcutsProvider *provider)
+xfce_shortcuts_provider_reset_to_defaults (XfceShortcutsProvider *provider)
 {
-  g_return_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (provider));
+  g_return_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (provider));
   g_return_if_fail (XFCONF_IS_CHANNEL (provider->priv->channel));
 
   DBG ("property = %s", provider->priv->custom_base_property);
 
   xfconf_channel_reset_property (provider->priv->channel, provider->priv->custom_base_property, TRUE);
-  frap_shortcuts_provider_clone_defaults (provider);
+  xfce_shortcuts_provider_clone_defaults (provider);
 }
 
 
 
 static gboolean
-_frap_shortcuts_provider_clone_default (const gchar           *property,
+_xfce_shortcuts_provider_clone_default (const gchar           *property,
                                         const GValue          *value,
-                                        FrapShortcutsProvider *provider)
+                                        XfceShortcutsProvider *provider)
 {
   const gchar *shortcut;
   const gchar *command;
   gchar       *custom_property;
 
-  g_return_val_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (provider), TRUE);
+  g_return_val_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (provider), TRUE);
   g_return_val_if_fail (XFCONF_IS_CHANNEL (provider->priv->channel), TRUE);
 
   if (G_UNLIKELY (!G_IS_VALUE (value) || G_VALUE_TYPE (value) != G_TYPE_STRING))
@@ -460,12 +460,12 @@ _frap_shortcuts_provider_clone_default (const gchar           *property,
 
 
 void
-frap_shortcuts_provider_clone_defaults (FrapShortcutsProvider *provider)
+xfce_shortcuts_provider_clone_defaults (XfceShortcutsProvider *provider)
 {
   GHashTable *properties;
   gchar      *property;
 
-  g_return_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (provider));
+  g_return_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (provider));
   g_return_if_fail (XFCONF_IS_CHANNEL (provider->priv->channel));
 
   /* Get default command shortcuts */
@@ -474,7 +474,7 @@ frap_shortcuts_provider_clone_defaults (FrapShortcutsProvider *provider)
   if (G_LIKELY (properties != NULL))
     {
       /* Copy from /commands/default to /commands/custom property by property */
-      g_hash_table_foreach (properties, (GHFunc) _frap_shortcuts_provider_clone_default, provider);
+      g_hash_table_foreach (properties, (GHFunc) _xfce_shortcuts_provider_clone_default, provider);
 
       g_hash_table_destroy (properties);
     }
@@ -490,16 +490,16 @@ frap_shortcuts_provider_clone_defaults (FrapShortcutsProvider *provider)
 
 
 static gboolean
-_frap_shortcuts_provider_get_shortcut (const gchar                  *property,
+_xfce_shortcuts_provider_get_shortcut (const gchar                  *property,
                                        const GValue                 *value,
-                                       FrapShortcutsProviderContext *context)
+                                       XfceShortcutsProviderContext *context)
 {
-  FrapShortcut *sc;
+  XfceShortcut *sc;
   const gchar  *shortcut;
   const gchar  *command;
 
   g_return_val_if_fail (context != NULL, TRUE);
-  g_return_val_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (context->provider), TRUE);
+  g_return_val_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (context->provider), TRUE);
 
   if (G_VALUE_TYPE (value) != G_TYPE_STRING)
     return FALSE;
@@ -512,7 +512,7 @@ _frap_shortcuts_provider_get_shortcut (const gchar                  *property,
 
   if (G_LIKELY (shortcut != NULL && command != NULL && g_utf8_strlen (shortcut, -1) > 0 && g_utf8_strlen (command, -1) > 0))
     {
-      sc = g_new0 (FrapShortcut, 1);
+      sc = g_new0 (XfceShortcut, 1);
 
       sc->property_name = g_strdup (property);
       sc->shortcut = g_strdup (shortcut);
@@ -527,12 +527,12 @@ _frap_shortcuts_provider_get_shortcut (const gchar                  *property,
 
 
 GList *
-frap_shortcuts_provider_get_shortcuts (FrapShortcutsProvider *provider)
+xfce_shortcuts_provider_get_shortcuts (XfceShortcutsProvider *provider)
 {
-  FrapShortcutsProviderContext context;
+  XfceShortcutsProviderContext context;
   GHashTable                  *properties;
 
-  g_return_val_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (provider), NULL);
+  g_return_val_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (provider), NULL);
   g_return_val_if_fail (XFCONF_IS_CHANNEL (provider->priv->channel), NULL);
 
   properties = xfconf_channel_get_properties (provider->priv->channel, provider->priv->custom_base_property);
@@ -541,26 +541,26 @@ frap_shortcuts_provider_get_shortcuts (FrapShortcutsProvider *provider)
   context.list = NULL;
 
   if (G_LIKELY (properties != NULL))
-    g_hash_table_foreach (properties, (GHFunc) _frap_shortcuts_provider_get_shortcut, &context);
+    g_hash_table_foreach (properties, (GHFunc) _xfce_shortcuts_provider_get_shortcut, &context);
 
   return context.list;
 }
 
 
 
-FrapShortcut *
-frap_shortcuts_provider_get_shortcut (FrapShortcutsProvider *provider,
+XfceShortcut *
+xfce_shortcuts_provider_get_shortcut (XfceShortcutsProvider *provider,
                                       const gchar           *shortcut)
 {
-  FrapShortcut *sc = NULL;
+  XfceShortcut *sc = NULL;
   gchar        *base_property;
   gchar        *property;
   gchar        *command;
 
-  g_return_val_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (provider), NULL);
+  g_return_val_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (provider), NULL);
   g_return_val_if_fail (XFCONF_IS_CHANNEL (provider->priv->channel), NULL);
 
-  if (G_LIKELY (frap_shortcuts_provider_is_custom (provider)))
+  if (G_LIKELY (xfce_shortcuts_provider_is_custom (provider)))
     base_property = provider->priv->custom_base_property;
   else
     base_property = provider->priv->default_base_property;
@@ -570,7 +570,7 @@ frap_shortcuts_provider_get_shortcut (FrapShortcutsProvider *provider,
 
   if (G_LIKELY (command != NULL))
     {
-      sc = g_new0 (FrapShortcut, 1);
+      sc = g_new0 (XfceShortcut, 1);
       sc->command = command;
       sc->property_name = g_strdup (property);
       sc->shortcut = g_strdup (shortcut);
@@ -584,17 +584,17 @@ frap_shortcuts_provider_get_shortcut (FrapShortcutsProvider *provider,
 
 
 gboolean
-frap_shortcuts_provider_has_shortcut (FrapShortcutsProvider *provider,
+xfce_shortcuts_provider_has_shortcut (XfceShortcutsProvider *provider,
                                       const gchar           *shortcut)
 {
   gchar   *base_property;
   gchar   *property;
   gboolean has_property;
 
-  g_return_val_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (provider), FALSE);
+  g_return_val_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (provider), FALSE);
   g_return_val_if_fail (XFCONF_IS_CHANNEL (provider->priv->channel), FALSE);
   
-  if (G_LIKELY (frap_shortcuts_provider_is_custom (provider)))
+  if (G_LIKELY (xfce_shortcuts_provider_is_custom (provider)))
     base_property = provider->priv->custom_base_property;
   else
     base_property = provider->priv->default_base_property;
@@ -609,18 +609,18 @@ frap_shortcuts_provider_has_shortcut (FrapShortcutsProvider *provider,
 
 
 void
-frap_shortcuts_provider_set_shortcut (FrapShortcutsProvider *provider,
+xfce_shortcuts_provider_set_shortcut (XfceShortcutsProvider *provider,
                                       const gchar           *shortcut,
                                       const gchar           *command)
 {
   gchar *property;
 
-  g_return_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (provider));
+  g_return_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (provider));
   g_return_if_fail (XFCONF_IS_CHANNEL (provider->priv->channel));
   g_return_if_fail (shortcut != NULL && command != NULL);
 
   /* Only allow custom shortcuts to be changed */
-  if (G_UNLIKELY (!frap_shortcuts_provider_is_custom (provider)))
+  if (G_UNLIKELY (!xfce_shortcuts_provider_is_custom (provider)))
     return;
     
   property = g_strconcat (provider->priv->custom_base_property, "/", shortcut, NULL);
@@ -636,12 +636,12 @@ frap_shortcuts_provider_set_shortcut (FrapShortcutsProvider *provider,
 
 
 void
-frap_shortcuts_provider_reset_shortcut (FrapShortcutsProvider *provider,
+xfce_shortcuts_provider_reset_shortcut (XfceShortcutsProvider *provider,
                                         const gchar           *shortcut)
 {
   gchar *property;
 
-  g_return_if_fail (FRAP_IS_SHORTCUTS_PROVIDER (provider));
+  g_return_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (provider));
   g_return_if_fail (XFCONF_IS_CHANNEL (provider->priv->channel));
   g_return_if_fail (shortcut != NULL);
 
@@ -656,15 +656,15 @@ frap_shortcuts_provider_reset_shortcut (FrapShortcutsProvider *provider,
 
 
 void
-frap_shortcuts_free_shortcuts (GList *shortcuts)
+xfce_shortcuts_free (GList *shortcuts)
 {
-  g_list_foreach (shortcuts, (GFunc) frap_shortcuts_free_shortcut, NULL);
+  g_list_foreach (shortcuts, (GFunc) xfce_shortcut_free, NULL);
 }
 
 
 
 void
-frap_shortcuts_free_shortcut (FrapShortcut *shortcut)
+xfce_shortcut_free (XfceShortcut *shortcut)
 {
   if (G_UNLIKELY (shortcut == NULL))
     return;
diff --git a/settings-dialogs/xfce-shortcuts-provider.h b/settings-dialogs/xfce-shortcuts-provider.h
new file mode 100644
index 000000000..5f1d7c7dc
--- /dev/null
+++ b/settings-dialogs/xfce-shortcuts-provider.h
@@ -0,0 +1,87 @@
+/* vi:set sw=2 sts=2 ts=2 et ai: */
+/*-
+ * Copyright (c) 2008 Jannis Pohlmann <jannis@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_SHORTCUTS_PROVIDER_H__
+#define __XFCE_SHORTCUTS_PROVIDER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS;
+
+typedef struct _XfceShortcut                 XfceShortcut;
+
+typedef struct _XfceShortcutsProviderPrivate XfceShortcutsProviderPrivate;
+typedef struct _XfceShortcutsProviderClass   XfceShortcutsProviderClass;
+typedef struct _XfceShortcutsProvider        XfceShortcutsProvider;
+
+#define XFCE_TYPE_SHORTCUTS_PROVIDER            (xfce_shortcuts_provider_get_type ())
+#define XFCE_SHORTCUTS_PROVIDER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_SHORTCUTS_PROVIDER, XfceShortcutsProvider))
+#define XFCE_SHORTCUTS_PROVIDER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_SHORTCUTS_PROVIDER, XfceShortcutsProviderClass))
+#define XFCE_IS_SHORTCUTS_PROVIDER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_SHORTCUTS_PROVIDER))
+#define XFCE_IS_SHORTCUTS_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_SHORTCUTS_PROVIDER)
+#define XFCE_SHORTCUTS_PROVIDER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_SHORTCUTS_PROVIDER, XfceShortcutsProviderClass))
+
+GType xfce_shortcuts_provider_get_type (void) G_GNUC_CONST;
+
+XfceShortcutsProvider  *xfce_shortcuts_provider_new               (const gchar           *name) G_GNUC_MALLOC;
+GList                  *xfce_shortcuts_provider_get_providers     (void) G_GNUC_MALLOC;
+void                    xfce_shortcuts_provider_free_providers    (GList                 *providers);
+const gchar            *xfce_shortcuts_provider_get_name          (XfceShortcutsProvider *provider);
+gboolean                xfce_shortcuts_provider_is_custom         (XfceShortcutsProvider *provider);
+void                    xfce_shortcuts_provider_reset_to_defaults (XfceShortcutsProvider *provider);
+void                    xfce_shortcuts_provider_clone_defaults    (XfceShortcutsProvider *provider);
+GList                  *xfce_shortcuts_provider_get_shortcuts     (XfceShortcutsProvider *provider);
+XfceShortcut           *xfce_shortcuts_provider_get_shortcut      (XfceShortcutsProvider *provider,
+                                                                   const gchar           *shortcut);
+gboolean                xfce_shortcuts_provider_has_shortcut      (XfceShortcutsProvider *provider,
+                                                                   const gchar           *shortcut);
+void                    xfce_shortcuts_provider_set_shortcut      (XfceShortcutsProvider *provider,
+                                                                   const gchar           *shortcut,
+                                                                   const gchar           *command);
+void                    xfce_shortcuts_provider_reset_shortcut    (XfceShortcutsProvider *provider,
+                                                                   const gchar           *shortcut);
+
+void                    xfce_shortcuts_free                       (GList                 *shortcuts);
+void                    xfce_shortcut_free                        (XfceShortcut          *shortcut);
+
+
+
+struct _XfceShortcutsProviderClass
+{
+  GObjectClass __parent__;
+};
+
+struct _XfceShortcutsProvider
+{
+  GObject __parent__;
+
+  XfceShortcutsProviderPrivate *priv;
+};
+
+struct _XfceShortcut
+{
+  gchar *property_name;
+  gchar *shortcut;
+  gchar *command;
+};
+
+G_END_DECLS;
+
+#endif /* !__XFCE_SHORTCUTS_PROVIDER_H__ */
diff --git a/settings-dialogs/xfwm4-dialog.glade b/settings-dialogs/xfwm4-dialog.glade
index 0a16e1e59..5ec11bd88 100644
--- a/settings-dialogs/xfwm4-dialog.glade
+++ b/settings-dialogs/xfwm4-dialog.glade
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.4.5 on Mon Oct 13 16:46:30 2008 -->
+<!--Generated with glade3 3.4.5 on Mon Oct 20 17:26:23 2008 -->
 <glade-interface>
   <requires lib="xfce4"/>
   <widget class="XfceTitledDialog" id="main-dialog">
@@ -24,24 +24,46 @@
                 <property name="border_width">12</property>
                 <property name="spacing">12</property>
                 <child>
-                  <widget class="GtkScrolledWindow" id="scrolledwindow3">
-                    <property name="width_request">120</property>
+                  <widget class="GtkFrame" id="frame13">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                    <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                    <property name="shadow_type">GTK_SHADOW_IN</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">GTK_SHADOW_NONE</property>
                     <child>
-                      <widget class="GtkTreeView" id="theme_name_treeview">
+                      <widget class="GtkAlignment" id="alignment11">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
+                        <property name="top_padding">6</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <widget class="GtkScrolledWindow" id="scrolledwindow3">
+                            <property name="width_request">200</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                            <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                            <property name="shadow_type">GTK_SHADOW_IN</property>
+                            <child>
+                              <widget class="GtkTreeView" id="theme_name_treeview">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="headers_visible">False</property>
+                              </widget>
+                            </child>
+                          </widget>
+                        </child>
                       </widget>
                     </child>
+                    <child>
+                      <widget class="GtkLabel" id="label32">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;b&gt;_Theme&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                        <property name="use_underline">True</property>
+                      </widget>
+                      <packing>
+                        <property name="type">label_item</property>
+                      </packing>
+                    </child>
                   </widget>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                  </packing>
                 </child>
                 <child>
                   <widget class="GtkVBox" id="vbox12">
@@ -419,16 +441,6 @@
                             <property name="visible">True</property>
                             <property name="spacing">12</property>
                             <property name="layout_style">GTK_BUTTONBOX_CENTER</property>
-                            <child>
-                              <widget class="GtkButton" id="shortcuts_select_button">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">True</property>
-                                <property name="label" translatable="yes">gtk-select-all</property>
-                                <property name="use_stock">True</property>
-                                <property name="response_id">0</property>
-                              </widget>
-                            </child>
                             <child>
                               <widget class="GtkButton" id="shortcuts_clear_button">
                                 <property name="visible">True</property>
@@ -438,9 +450,6 @@
                                 <property name="use_stock">True</property>
                                 <property name="response_id">0</property>
                               </widget>
-                              <packing>
-                                <property name="position">1</property>
-                              </packing>
                             </child>
                             <child>
                               <widget class="GtkButton" id="shortcuts_reset_button">
@@ -455,7 +464,7 @@
                                 <property name="expand">False</property>
                                 <property name="fill">False</property>
                                 <property name="pack_type">GTK_PACK_END</property>
-                                <property name="position">2</property>
+                                <property name="position">1</property>
                               </packing>
                             </child>
                           </widget>
@@ -619,7 +628,7 @@
                     <child>
                       <widget class="GtkLabel" id="label15">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Focus model&lt;/b&gt;</property>
+                        <property name="label" translatable="yes" context="yes">&lt;b&gt;Focus model&lt;/b&gt;</property>
                         <property name="use_markup">True</property>
                       </widget>
                       <packing>
@@ -647,7 +656,7 @@
                           <widget class="GtkCheckButton" id="focus_new_check">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
-                            <property name="label" translatable="yes">Automatically give focus to _newly created windows</property>
+                            <property name="label" translatable="yes" context="yes">Automatically give focus to _newly created windows</property>
                             <property name="use_underline">True</property>
                             <property name="response_id">0</property>
                             <property name="draw_indicator">True</property>
@@ -658,7 +667,7 @@
                     <child>
                       <widget class="GtkLabel" id="label16">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;New window focus&lt;/b&gt;</property>
+                        <property name="label" translatable="yes" context="yes">&lt;b&gt;New window focus&lt;/b&gt;</property>
                         <property name="use_markup">True</property>
                       </widget>
                       <packing>
@@ -691,7 +700,7 @@
                               <widget class="GtkCheckButton" id="raise_on_focus_check">
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Automatically _raise windows when they receive focus</property>
+                                <property name="label" translatable="yes" context="yes">Automatically _raise windows when they receive focus</property>
                                 <property name="use_underline">True</property>
                                 <property name="response_id">0</property>
                                 <property name="draw_indicator">True</property>
@@ -705,7 +714,7 @@
                                   <widget class="GtkLabel" id="label19">
                                     <property name="visible">True</property>
                                     <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">Delay _before raising focused window:</property>
+                                    <property name="label" translatable="yes" context="yes">Delay _before raising focused window:</property>
                                     <property name="use_underline">True</property>
                                     <property name="mnemonic_widget">focus_raise_delay_scale</property>
                                   </widget>
@@ -776,7 +785,7 @@
                     <child>
                       <widget class="GtkLabel" id="label17">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Raise on focus&lt;/b&gt;</property>
+                        <property name="label" translatable="yes" context="yes">&lt;b&gt;Raise on focus&lt;/b&gt;</property>
                         <property name="use_markup">True</property>
                       </widget>
                       <packing>
@@ -805,7 +814,7 @@
                           <widget class="GtkCheckButton" id="raise_on_click_check">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
-                            <property name="label" translatable="yes">Raise window when clicking _inside application window</property>
+                            <property name="label" translatable="yes" context="yes">Raise window when clicking _inside application window</property>
                             <property name="use_underline">True</property>
                             <property name="response_id">0</property>
                             <property name="draw_indicator">True</property>
@@ -816,7 +825,7 @@
                     <child>
                       <widget class="GtkLabel" id="label18">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Raise on click&lt;/b&gt;</property>
+                        <property name="label" translatable="yes" context="yes">&lt;b&gt;Raise on click&lt;/b&gt;</property>
                         <property name="use_markup">True</property>
                       </widget>
                       <packing>
@@ -838,7 +847,7 @@
             <child>
               <widget class="GtkLabel" id="label3">
                 <property name="visible">True</property>
-                <property name="label" translatable="yes">_Focus</property>
+                <property name="label" translatable="yes" context="yes">_Focus</property>
                 <property name="use_underline">True</property>
               </widget>
               <packing>
@@ -871,7 +880,7 @@
                               <widget class="GtkCheckButton" id="snap_to_border_check">
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Snap windows to screen _border</property>
+                                <property name="label" translatable="yes" context="yes">Snap windows to screen _border</property>
                                 <property name="use_underline">True</property>
                                 <property name="response_id">0</property>
                                 <property name="draw_indicator">True</property>
@@ -885,7 +894,7 @@
                               <widget class="GtkCheckButton" id="snap_to_window_check">
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Snap windows to other _windows</property>
+                                <property name="label" translatable="yes" context="yes">Snap windows to other _windows</property>
                                 <property name="use_underline">True</property>
                                 <property name="response_id">0</property>
                                 <property name="draw_indicator">True</property>
@@ -904,7 +913,7 @@
                                   <widget class="GtkLabel" id="label9">
                                     <property name="visible">True</property>
                                     <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">Dis_tance:</property>
+                                    <property name="label" translatable="yes" context="yes">Dis_tance:</property>
                                     <property name="use_underline">True</property>
                                     <property name="mnemonic_widget">snap_width_scale</property>
                                   </widget>
@@ -972,7 +981,7 @@
                     <child>
                       <widget class="GtkLabel" id="label5">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Windows snapping&lt;/b&gt;</property>
+                        <property name="label" translatable="yes" context="yes">&lt;b&gt;Windows snapping&lt;/b&gt;</property>
                         <property name="use_markup">True</property>
                       </widget>
                       <packing>
@@ -1003,7 +1012,7 @@
                               <widget class="GtkCheckButton" id="wrap_workspaces_check">
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Wrap workspaces when the _pointer reaches the screen edge</property>
+                                <property name="label" translatable="yes" context="yes">Wrap workspaces when the _pointer reaches the screen edge</property>
                                 <property name="use_underline">True</property>
                                 <property name="response_id">0</property>
                                 <property name="draw_indicator">True</property>
@@ -1013,7 +1022,7 @@
                               <widget class="GtkCheckButton" id="wrap_windows_check">
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Wrap workspaces when _dragging a window off the screen</property>
+                                <property name="label" translatable="yes" context="yes">Wrap workspaces when _dragging a window off the screen</property>
                                 <property name="use_underline">True</property>
                                 <property name="response_id">0</property>
                                 <property name="draw_indicator">True</property>
@@ -1030,7 +1039,7 @@
                                   <widget class="GtkLabel" id="label10">
                                     <property name="visible">True</property>
                                     <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">_Edge resistance:</property>
+                                    <property name="label" translatable="yes" context="yes">_Edge resistance:</property>
                                     <property name="use_underline">True</property>
                                     <property name="selectable">True</property>
                                     <property name="mnemonic_widget">wrap_resistance_scale</property>
@@ -1103,7 +1112,7 @@
                     <child>
                       <widget class="GtkLabel" id="label6">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Wrap workspaces&lt;/b&gt;</property>
+                        <property name="label" translatable="yes" context="yes">&lt;b&gt;Wrap workspaces&lt;/b&gt;</property>
                         <property name="use_markup">True</property>
                       </widget>
                       <packing>
@@ -1135,7 +1144,7 @@
                               <widget class="GtkCheckButton" id="box_resize_check">
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Hide content of windows when _resizing</property>
+                                <property name="label" translatable="yes" context="yes">Hide content of windows when _resizing</property>
                                 <property name="use_underline">True</property>
                                 <property name="response_id">0</property>
                                 <property name="draw_indicator">True</property>
@@ -1149,7 +1158,7 @@
                               <widget class="GtkCheckButton" id="box_move_check">
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Hide content of windows when _moving</property>
+                                <property name="label" translatable="yes" context="yes">Hide content of windows when _moving</property>
                                 <property name="use_underline">True</property>
                                 <property name="response_id">0</property>
                                 <property name="draw_indicator">True</property>
@@ -1167,7 +1176,7 @@
                     <child>
                       <widget class="GtkLabel" id="label7">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Box move and resize&lt;/b&gt;</property>
+                        <property name="label" translatable="yes" context="yes">&lt;b&gt;Box move and resize&lt;/b&gt;</property>
                         <property name="use_markup">True</property>
                       </widget>
                       <packing>
@@ -1193,8 +1202,8 @@
                         <child>
                           <widget class="GtkComboBox" id="double_click_action_combo">
                             <property name="visible">True</property>
-                            <property name="tooltip" translatable="yes">The action to perform when the title-bar is double-clicked</property>
-                            <property name="items" translatable="yes">  </property>
+                            <property name="tooltip" translatable="yes" context="yes">The action to perform when the title-bar is double-clicked</property>
+                            <property name="items" translatable="yes" context="yes">  </property>
                           </widget>
                         </child>
                       </widget>
@@ -1202,7 +1211,7 @@
                     <child>
                       <widget class="GtkLabel" id="label8">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Double click _action&lt;/b&gt;</property>
+                        <property name="label" translatable="yes" context="yes">&lt;b&gt;Double click _action&lt;/b&gt;</property>
                         <property name="use_markup">True</property>
                         <property name="use_underline">True</property>
                         <property name="mnemonic_widget">double_click_action_combo</property>
@@ -1225,7 +1234,7 @@
             <child>
               <widget class="GtkLabel" id="label4">
                 <property name="visible">True</property>
-                <property name="label" translatable="yes">Ad_vanced</property>
+                <property name="label" translatable="yes" context="yes">Ad_vanced</property>
                 <property name="use_underline">True</property>
               </widget>
               <packing>
@@ -1248,7 +1257,7 @@
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
-                <property name="label" translatable="yes">gtk-help</property>
+                <property name="label" translatable="yes" context="yes">gtk-help</property>
                 <property name="use_stock">True</property>
                 <property name="response_id">0</property>
               </widget>
@@ -1258,7 +1267,7 @@
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
-                <property name="label" translatable="yes">gtk-close</property>
+                <property name="label" translatable="yes" context="yes">gtk-close</property>
                 <property name="use_stock">True</property>
                 <property name="response_id">0</property>
               </widget>
diff --git a/settings-dialogs/xfwm4-settings.c b/settings-dialogs/xfwm4-settings.c
index 182f9e80d..062efcea9 100644
--- a/settings-dialogs/xfwm4-settings.c
+++ b/settings-dialogs/xfwm4-settings.c
@@ -44,13 +44,18 @@
 #include "xfwm4-dialog_glade.h"
 #include "xfwm4-settings.h"
 
-#include "frap-shortcuts-provider.h"
+#include "frap-shortcuts-dialog.h"
+#include "xfce-shortcuts-provider.h"
 
 
 
-#define DEFAULT_THEME  "Default"
+#define DEFAULT_THEME             "Default"
 
-#define INDICATOR_SIZE 9
+#define INDICATOR_SIZE            9
+
+#define SHORTCUTS_NAME_COLUMN     0
+#define SHORTCUTS_FEATURE_COLUMN  1
+#define SHORTCUTS_SHORTCUT_COLUMN 2
 
 
 
@@ -60,7 +65,8 @@
 
 
 
-typedef struct _MenuTemplate MenuTemplate;
+typedef struct _MenuTemplate     MenuTemplate;
+typedef struct _ShortcutTemplate ShortcutTemplate;
 
 
 
@@ -73,98 +79,114 @@ enum
 
 
 
-static void       xfwm_settings_class_init                           (XfwmSettingsClass *klass);
-static void       xfwm_settings_init                                 (XfwmSettings      *settings);
-static void       xfwm_settings_constructed                          (GObject           *object);
-static void       xfwm_settings_finalize                             (GObject           *object);
-static void       xfwm_settings_get_property                         (GObject           *object,
-                                                                      guint              prop_id,
-                                                                      GValue            *value,
-                                                                      GParamSpec        *pspec);
-static void       xfwm_settings_set_property                         (GObject           *object,
-                                                                      guint              prop_id,
-                                                                      const GValue      *value,
-                                                                      GParamSpec        *pspec);
-static gint       xfwm_settings_theme_sort_func                      (GtkTreeModel      *model,
-                                                                      GtkTreeIter       *iter1,
-                                                                      GtkTreeIter       *iter2);
-static void       xfwm_settings_load_themes                          (XfwmSettings      *settings);
-static void       xfwm_settings_theme_selection_changed              (GtkTreeSelection  *selection,
-                                                                      XfwmSettings      *settings);
-static void       xfwm_settings_title_alignment_changed              (GtkComboBox       *combo,
-                                                                      XfwmSettings      *settings);
-static void       xfwm_settings_active_frame_drag_data               (GtkWidget         *widget,
-                                                                      GdkDragContext    *drag_context,
-                                                                      gint               x,
-                                                                      gint               y,
-                                                                      GtkSelectionData  *data,
-                                                                      guint              info,
-                                                                      guint              time,
-                                                                      XfwmSettings      *settings);
-static gboolean   xfwm_settings_active_frame_drag_motion             (GtkWidget         *widget, 
-                                                                      GdkDragContext    *drag_context, 
-                                                                      gint               x,
-                                                                      gint               y, 
-                                                                      guint              time,
-                                                                      XfwmSettings      *settings);
-static void       xfwm_settings_active_frame_drag_leave              (GtkWidget         *widget,
-                                                                      GdkDragContext    *drag_context,
-                                                                      guint              time,
-                                                                      XfwmSettings      *settings);
-static void       xfwm_settings_hidden_frame_drag_data               (GtkWidget         *widget,
-                                                                      GdkDragContext    *drag_context,
-                                                                      gint               x,
-                                                                      gint               y,
-                                                                      GtkSelectionData  *data,
-                                                                      guint              info,
-                                                                      guint              time,
-                                                                      XfwmSettings      *settings);
-static void       xfwm_settings_delete_indicator                     (GtkWidget         *widget);
-static void       xfwm_settings_create_indicator                     (GtkWidget         *widget,
-                                                                      gint               x,
-                                                                      gint               y,
-                                                                      gint               width,
-                                                                      gint               height);
-static void       xfwm_settings_title_button_drag_data               (GtkWidget        *widget,
-                                                                      GdkDragContext   *drag_context,
-                                                                      GtkSelectionData *data,
-                                                                      guint             info,
-                                                                      guint             time,
-                                                                      const gchar      *atom_name,
-                                                                      XfwmSettings     *settings);
-static void       xfwm_settings_title_button_drag_begin              (GtkWidget        *widget,
-                                                                      GdkDragContext   *drag_context);
-static void       xfwm_settings_title_button_drag_end                (GtkWidget        *widget,
-                                                                      GdkDragContext   *drag_context);
-static gboolean   xfwm_settings_signal_blocker                       (GtkWidget        *widget);
-static GdkPixbuf *xfwm_settings_create_icon_from_widget              (GtkWidget        *widget);
-
-static void       xfwm_settings_save_button_layout                   (XfwmSettings      *settings,
-                                                                      GtkContainer      *container);
-static void       xfwm_settings_double_click_action_changed          (GtkComboBox       *combo,
-                                                                      XfwmSettings      *settings);
-static void       xfwm_settings_title_button_alignment_changed       (GtkComboBox       *combo,
-                                                                      GtkWidget         *button);
-
-static void       xfwm_settings_button_layout_property_changed       (XfconfChannel     *channel,
-                                                                      const gchar       *property,
-                                                                      const GValue      *value,
-                                                                      XfwmSettings      *settings);
-static void       xfwm_settings_title_alignment_property_changed     (XfconfChannel     *channel,
-                                                                      const gchar       *property,
-                                                                      const GValue      *value,
-                                                                      XfwmSettings      *settings);
-static void       xfwm_settings_double_click_action_property_changed (XfconfChannel     *channel,
-                                                                      const gchar       *property,
-                                                                      const GValue      *value,
-                                                                      XfwmSettings      *settings);
+static void       xfwm_settings_class_init                           (XfwmSettingsClass    *klass);
+static void       xfwm_settings_init                                 (XfwmSettings         *settings);
+static void       xfwm_settings_constructed                          (GObject              *object);
+static void       xfwm_settings_finalize                             (GObject              *object);
+static void       xfwm_settings_get_property                         (GObject              *object,
+                                                                      guint                 prop_id,
+                                                                      GValue               *value,
+                                                                      GParamSpec           *pspec);
+static void       xfwm_settings_set_property                         (GObject              *object,
+                                                                      guint                 prop_id,
+                                                                      const GValue         *value,
+                                                                      GParamSpec           *pspec);
+static gint       xfwm_settings_theme_sort_func                      (GtkTreeModel         *model,
+                                                                      GtkTreeIter          *iter1,
+                                                                      GtkTreeIter          *iter2);
+static void       xfwm_settings_load_themes                          (XfwmSettings         *settings);
+static void       xfwm_settings_theme_selection_changed              (GtkTreeSelection     *selection,
+                                                                      XfwmSettings         *settings);
+static void       xfwm_settings_title_alignment_changed              (GtkComboBox          *combo,
+                                                                      XfwmSettings         *settings);
+static void       xfwm_settings_active_frame_drag_data               (GtkWidget            *widget,
+                                                                      GdkDragContext       *drag_context,
+                                                                      gint                  x,
+                                                                      gint                  y,
+                                                                      GtkSelectionData     *data,
+                                                                      guint                 info,
+                                                                      guint                 time,
+                                                                      XfwmSettings         *settings);
+static gboolean   xfwm_settings_active_frame_drag_motion             (GtkWidget            *widget, 
+                                                                      GdkDragContext       *drag_context, 
+                                                                      gint                  x,
+                                                                      gint                  y, 
+                                                                      guint                 time,
+                                                                      XfwmSettings         *settings);
+static void       xfwm_settings_active_frame_drag_leave              (GtkWidget            *widget,
+                                                                      GdkDragContext       *drag_context,
+                                                                      guint                 time,
+                                                                      XfwmSettings         *settings);
+static void       xfwm_settings_hidden_frame_drag_data               (GtkWidget            *widget,
+                                                                      GdkDragContext       *drag_context,
+                                                                      gint                  x,
+                                                                      gint                  y,
+                                                                      GtkSelectionData     *data,
+                                                                      guint                 info,
+                                                                      guint                 time,
+                                                                      XfwmSettings         *settings);
+static void       xfwm_settings_delete_indicator                     (GtkWidget            *widget);
+static void       xfwm_settings_create_indicator                     (GtkWidget            *widget,
+                                                                      gint                  x,
+                                                                      gint                  y,
+                                                                      gint                  width,
+                                                                      gint                  height);
+static void       xfwm_settings_title_button_drag_data               (GtkWidget            *widget,
+                                                                      GdkDragContext       *drag_context,
+                                                                      GtkSelectionData     *data,
+                                                                      guint                 info,
+                                                                      guint                 time,
+                                                                      const gchar          *atom_name,
+                                                                      XfwmSettings         *settings);
+static void       xfwm_settings_title_button_drag_begin              (GtkWidget            *widget,
+                                                                      GdkDragContext       *drag_context);
+static void       xfwm_settings_title_button_drag_end                (GtkWidget            *widget,
+                                                                      GdkDragContext       *drag_context);
+static gboolean   xfwm_settings_signal_blocker                       (GtkWidget            *widget);
+static GdkPixbuf *xfwm_settings_create_icon_from_widget              (GtkWidget            *widget);
+
+static void       xfwm_settings_save_button_layout                   (XfwmSettings          *settings,
+                                                                      GtkContainer          *container);
+static void       xfwm_settings_double_click_action_changed          (GtkComboBox           *combo,
+                                                                      XfwmSettings          *settings);
+static void       xfwm_settings_title_button_alignment_changed       (GtkComboBox           *combo,
+                                                                      GtkWidget             *button);
+
+static void       xfwm_settings_button_layout_property_changed       (XfconfChannel         *channel,
+                                                                      const gchar           *property,
+                                                                      const GValue          *value,
+                                                                      XfwmSettings          *settings);
+static void       xfwm_settings_title_alignment_property_changed     (XfconfChannel         *channel,
+                                                                      const gchar           *property,
+                                                                      const GValue          *value,
+                                                                      XfwmSettings          *settings);
+static void       xfwm_settings_double_click_action_property_changed (XfconfChannel         *channel,
+                                                                      const gchar           *property,
+                                                                      const GValue          *value,
+                                                                      XfwmSettings          *settings);
+static void       xfwm_settings_initialize_shortcuts                 (XfwmSettings          *settings);
+static void       xfwm_settings_reload_shortcuts                     (XfwmSettings          *settings);
+static void       xfwm_settings_shortcut_added                       (XfceShortcutsProvider *provider,
+                                                                      const gchar           *shortcut,
+                                                                      XfwmSettings          *settings);
+static void       xfwm_settings_shortcut_removed                     (XfceShortcutsProvider *provider,
+                                                                      const gchar           *shortcut,
+                                                                      XfwmSettings          *settings);
+static void       xfwm_settings_shortcut_clear_clicked               (GtkButton             *button,
+                                                                      XfwmSettings          *settings);
+static void       xfwm_settings_shortcut_reset_clicked               (GtkButton             *button,
+                                                                      XfwmSettings          *settings);
+static void       xfwm_settings_shortcut_row_activated               (GtkTreeView           *tree_view,
+                                                                      GtkTreePath           *path,
+                                                                      GtkTreeViewColumn     *column,
+                                                                      XfwmSettings          *settings);
 
 
 
 struct _XfwmSettingsPrivate
 {
   GladeXML              *glade_xml;
-  FrapShortcutsProvider *provider;
+  XfceShortcutsProvider *provider;
   XfconfChannel         *wm_channel;
 };
 
@@ -174,6 +196,13 @@ struct _MenuTemplate
   const gchar *value;
 };
 
+struct _ShortcutTemplate
+{
+  const gchar *name;
+  const gchar *feature;
+  const gchar *shortcut;
+};
+
 
 
 static GObjectClass      *xfwm_settings_parent_class = NULL;
@@ -194,6 +223,50 @@ static const MenuTemplate title_align_values[] = {
   { NULL, NULL },
 };
 
+static const ShortcutTemplate shortcut_values[] = {
+  { N_("Window operations menu"), "popup_menu_key", NULL },
+  { N_("Up"), "up_key", NULL },
+  { N_("Down"), "down_key", NULL },
+  { N_("Left"), "left_key", NULL },
+  { N_("Right"), "right_key", NULL },
+  { N_("Cancel"), "cancel_key", NULL },
+  { N_("Cycle windows"), "cycle_windows_key", NULL },
+  { N_("Close window"), "close_window_key", NULL },
+  { N_("Maximize window horizontally"), "maximize_horiz_key", NULL },
+  { N_("Maximize window vertically"), "maximize_vert_key", NULL },
+  { N_("Maximize window"), "maximize_window_key", NULL },
+  { N_("Hide window"), "hide_window_key", NULL },
+  { N_("Move window"), "move_window_key", NULL },
+  { N_("Resize window"), "resize_window_key", NULL },
+  { N_("Shade window"), "shade_window_key", NULL },
+  { N_("Stick window"), "stick_window_key", NULL },
+  { N_("Raise window"), "raise_window_key", NULL },
+  { N_("Lower window"), "lower_window_key", NULL },
+  { N_("Fill window"), "fill_window_key", NULL },
+  { N_("Fill window horizontally"), "fill_horiz_key", NULL },
+  { N_("Fill window vertically"), "fill_vert_key", NULL },
+  { N_("Toggle above"), "above_key", NULL },
+  { N_("Toggle fullscreen"), "fullscreen_key", NULL },
+  { N_("Move window to upper workspace"), "move_window_up_workspace_key", NULL },
+  { N_("Move window to bottom workspace"), "move_window_down_workspace_key", NULL },
+  { N_("Move window to left workspace"), "move_window_left_workspace_key", NULL },
+  { N_("Move window to right workspace"), "move_window_right_workspace_key", NULL },
+  { N_("Move window to previous workspace"), "move_window_prev_workspace_key", NULL },
+  { N_("Move window to next workspace"), "move_window_next_workspace_key", NULL },
+  { N_("Show desktop"), "show_desktop_key", NULL },
+  { N_("Upper workspace"), "up_workspace_key", NULL },
+  { N_("Bottom workspace"), "down_workspace_key", NULL },
+  { N_("Left workspace"), "left_workspace_key", NULL },
+  { N_("Right workspace"), "right_workspace_key", NULL },
+  { N_("Previous workspace"), "prev_workspace_key", NULL },
+  { N_("Next workspace"), "next_workspace_key", NULL },
+  { N_("Add workspace"), "add_workspace_key", NULL },
+  { N_("Add adjacent workspace"), "add_adjacent_workspace_key", NULL },
+  { N_("Delete last workspace"), "del_workspace_key", NULL },
+  { N_("Delete active workspace"), "del_active_workspace_key", NULL },
+  { NULL, NULL, NULL }
+};
+
 static gboolean           opt_version = FALSE;
 static GdkNativeWindow    opt_socket_id = 0;
 static GOptionEntry       opt_entries[] = {
@@ -289,7 +362,7 @@ xfwm_settings_init (XfwmSettings *settings)
   settings->priv = XFWM_SETTINGS_GET_PRIVATE (settings);
 
   settings->priv->glade_xml = NULL;
-  settings->priv->provider = frap_shortcuts_provider_new ("xfwm4");
+  settings->priv->provider = xfce_shortcuts_provider_new ("xfwm4");
   settings->priv->wm_channel = xfconf_channel_new ("xfwm4");
 }
 
@@ -312,6 +385,9 @@ xfwm_settings_constructed (GObject *object)
   GtkWidget          *active_box;
   GtkWidget          *hidden_frame;
   GtkWidget          *hidden_box;
+  GtkWidget          *shortcuts_treeview;
+  GtkWidget          *shortcuts_clear_button;
+  GtkWidget          *shortcuts_reset_button;
   GtkWidget          *focus_delay_scale;
   GtkWidget          *click_to_focus_mode;
   GtkWidget          *raise_on_click_check;
@@ -480,6 +556,41 @@ xfwm_settings_constructed (GObject *object)
                                                 "/general/button_layout", &value, settings);
   g_value_unset (&value);
 
+  /* Keyboard tab widgets */
+  shortcuts_treeview = glade_xml_get_widget (settings->priv->glade_xml, "shortcuts_treeview");
+  shortcuts_clear_button = glade_xml_get_widget (settings->priv->glade_xml, 
+                                                 "shortcuts_clear_button");
+  shortcuts_reset_button = glade_xml_get_widget (settings->priv->glade_xml, 
+                                                 "shortcuts_reset_button");
+
+  /* Keyboard tab: Shortcuts tree view */
+  {
+    gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (shortcuts_treeview)),
+                                 GTK_SELECTION_MULTIPLE);
+
+    list_store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    gtk_tree_view_set_model (GTK_TREE_VIEW (shortcuts_treeview), GTK_TREE_MODEL (list_store));
+
+    renderer = gtk_cell_renderer_text_new ();
+    gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (shortcuts_treeview), 
+                                                 0, _("Action"), renderer, 
+                                                 "text", SHORTCUTS_NAME_COLUMN, NULL);
+
+    renderer = gtk_cell_renderer_text_new ();
+    gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (shortcuts_treeview),
+                                                 1, _("Shortcut"), renderer, 
+                                                 "text", SHORTCUTS_SHORTCUT_COLUMN, NULL);
+
+    g_signal_connect (shortcuts_treeview, "row-activated", 
+                      G_CALLBACK (xfwm_settings_shortcut_row_activated), settings);
+  }
+
+  /* Connect to shortcut buttons */
+  g_signal_connect (shortcuts_clear_button, "clicked", 
+                    G_CALLBACK (xfwm_settings_shortcut_clear_clicked), settings);
+  g_signal_connect (shortcuts_reset_button, "clicked", 
+                    G_CALLBACK (xfwm_settings_shortcut_reset_clicked), settings);
+
   /* Focus tab widgets */
   focus_delay_scale = glade_xml_get_widget (settings->priv->glade_xml, "focus_delay_scale");
   focus_new_check = glade_xml_get_widget (settings->priv->glade_xml, "focus_new_check");
@@ -563,6 +674,16 @@ xfwm_settings_constructed (GObject *object)
                           snap_to_border_check, "active");
   xfconf_g_property_bind (settings->priv->wm_channel, "/general/snap_to_windows", G_TYPE_BOOLEAN, 
                           snap_to_window_check, "active");
+
+  /* Load shortcuts */
+  xfwm_settings_initialize_shortcuts (settings);
+  xfwm_settings_reload_shortcuts (settings);
+
+  /* Connect to shortcuts provider */
+  g_signal_connect (settings->priv->provider, "shortcut-added", 
+                    G_CALLBACK (xfwm_settings_shortcut_added), settings);
+  g_signal_connect (settings->priv->provider, "shortcut-removed",
+                    G_CALLBACK (xfwm_settings_shortcut_removed), settings);
 }
 
 
@@ -636,6 +757,7 @@ xfwm_settings_new (void)
 
   if (G_LIKELY (glade_xml != NULL))
     settings = g_object_new (XFWM_TYPE_SETTINGS, "glade-xml", glade_xml, NULL);
+
 #if !GLIB_CHECK_VERSION (2,14,0)
   xfwm_settings_constructed (G_OBJECT(settings));
 #endif
@@ -1416,3 +1538,366 @@ xfwm_settings_double_click_action_property_changed (XfconfChannel *channel,
       while (gtk_tree_model_iter_next (model, &iter));
     }
 }
+
+
+
+static void
+xfwm_settings_initialize_shortcuts (XfwmSettings *settings)
+{
+  GtkTreeModel *model;
+  GtkTreeIter   iter;
+  GtkWidget    *view;
+  gint          i;
+
+  g_return_if_fail (XFWM_IS_SETTINGS (settings));
+  g_return_if_fail (GLADE_IS_XML (settings->priv->glade_xml));
+
+  view = glade_xml_get_widget (settings->priv->glade_xml, "shortcuts_treeview");
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+
+  gtk_list_store_clear (GTK_LIST_STORE (model));
+
+  for (i = 0; shortcut_values[i].name != NULL; ++i)
+    {
+      gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+      gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+                          SHORTCUTS_NAME_COLUMN, shortcut_values[i].name,
+                          SHORTCUTS_FEATURE_COLUMN, shortcut_values[i].feature,
+                          -1);
+    }
+}
+
+
+
+static void
+xfwm_settings_clear_shortcuts_view (XfwmSettings *settings)
+{
+  GtkTreeModel *model;
+  GtkTreeIter   iter;
+  GtkWidget    *view;
+
+  g_return_if_fail (XFWM_IS_SETTINGS (settings));
+  g_return_if_fail (GLADE_IS_XML (settings->priv->glade_xml));
+
+  view = glade_xml_get_widget (settings->priv->glade_xml, "shortcuts_treeview");
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+
+  if (G_LIKELY (gtk_tree_model_get_iter_first (model, &iter)))
+    {
+      do
+        {
+          gtk_list_store_set (GTK_LIST_STORE (model), &iter, 
+                              SHORTCUTS_SHORTCUT_COLUMN, NULL, -1);
+        }
+      while (gtk_tree_model_iter_next (model, &iter));
+    }
+}
+
+
+
+static void
+xfwm_settings_reload_shortcut (XfceShortcut *shortcut,
+                               GtkTreeModel *model)
+{
+  GtkTreeIter iter;
+  gchar      *feature;
+
+  g_return_if_fail (GTK_IS_TREE_MODEL (model));
+  g_return_if_fail (shortcut != NULL);
+
+  if (G_LIKELY (gtk_tree_model_get_iter_first (model, &iter)))
+    {
+      do 
+        {
+          gtk_tree_model_get (model, &iter, SHORTCUTS_FEATURE_COLUMN, &feature, -1);
+
+          if (G_UNLIKELY (g_str_equal (feature, shortcut->command)))
+            {
+              gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+                                  SHORTCUTS_SHORTCUT_COLUMN, shortcut->shortcut, -1);
+            }
+
+          g_free (feature);
+        }
+      while (gtk_tree_model_iter_next (model, &iter));
+    }
+}
+
+
+
+static void
+xfwm_settings_reload_shortcuts (XfwmSettings *settings)
+{
+  GtkTreeModel *model;
+  GtkWidget    *view;
+  GList        *shortcuts;
+
+  g_return_if_fail (XFWM_IS_SETTINGS (settings));
+  g_return_if_fail (GLADE_IS_XML (settings->priv->glade_xml));
+  g_return_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (settings->priv->provider));
+
+  view = glade_xml_get_widget (settings->priv->glade_xml, "shortcuts_treeview");
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+
+  xfwm_settings_clear_shortcuts_view (settings);
+
+  shortcuts = xfce_shortcuts_provider_get_shortcuts (settings->priv->provider);
+  g_list_foreach (shortcuts, (GFunc) xfwm_settings_reload_shortcut, model);
+  xfce_shortcuts_free (shortcuts);
+}
+
+
+
+static void
+xfwm_settings_shortcut_added (XfceShortcutsProvider *provider,
+                              const gchar           *shortcut,
+                              XfwmSettings          *settings)
+{
+  g_return_if_fail (XFWM_IS_SETTINGS (settings));
+  xfwm_settings_reload_shortcuts (settings);
+}
+
+
+
+static void
+xfwm_settings_shortcut_removed (XfceShortcutsProvider *provider,
+                                const gchar           *shortcut,
+                                XfwmSettings          *settings)
+{
+  g_return_if_fail (XFWM_IS_SETTINGS (settings));
+  xfwm_settings_reload_shortcuts (settings);
+}
+
+
+
+static void
+xfwm_settings_shortcut_clear_clicked (GtkButton    *button,
+                                      XfwmSettings *settings)
+{
+  GtkTreeSelection *selection;
+  GtkTreeModel     *model;
+  GtkTreePath      *path;
+  GtkTreeIter       tree_iter;
+  GtkWidget        *view;
+  GList            *rows;
+  GList            *iter;
+  GList            *row_references = NULL;
+  gchar            *shortcut;
+
+  g_return_if_fail (XFWM_IS_SETTINGS (settings));
+  g_return_if_fail (GLADE_IS_XML (settings->priv->glade_xml));
+  g_return_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (settings->priv->provider));
+
+  view = glade_xml_get_widget (settings->priv->glade_xml, "shortcuts_treeview");
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
+  rows = gtk_tree_selection_get_selected_rows (selection, &model);
+
+  for (iter = g_list_first (rows); iter != NULL; iter = g_list_next (iter))
+    {
+      row_references = g_list_append (row_references, 
+                                      gtk_tree_row_reference_new (model, iter->data));
+    }
+
+  for (iter = g_list_first (row_references); iter != NULL; iter = g_list_next (iter))
+    {
+      path = gtk_tree_row_reference_get_path (iter->data);
+
+      /* Convert tree path to tree iter */
+      if (G_LIKELY (gtk_tree_model_get_iter (model, &tree_iter, path)))
+        {
+          /* Read shortcut */
+          gtk_tree_model_get (model, &tree_iter, SHORTCUTS_SHORTCUT_COLUMN, &shortcut, -1);
+
+          if (G_LIKELY (shortcut != NULL))
+            {
+              DBG ("clear shortcut %s", shortcut);
+
+              /* Remove keyboard shortcut via xfconf */
+              xfce_shortcuts_provider_reset_shortcut (settings->priv->provider, shortcut);
+
+              /* Free shortcut string */
+              g_free (shortcut);
+            }
+        }
+
+      gtk_tree_path_free (path);
+    }
+
+  /* Free row reference list */
+  g_list_foreach (row_references, (GFunc) gtk_tree_row_reference_free, NULL);
+  g_list_free (row_references);
+
+  /* Free row list */
+  g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
+  g_list_free (rows);
+}
+
+
+
+static void
+xfwm_settings_shortcut_reset_clicked (GtkButton    *button,
+                                      XfwmSettings *settings)
+{
+  gint response;
+
+  g_return_if_fail (XFWM_IS_SETTINGS (settings));
+  g_return_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (settings->priv->provider));
+
+  response = xfce_message_dialog (NULL, _("Reset to Defaults"), GTK_STOCK_DIALOG_QUESTION,
+                                  _("Reset to Defaults"),
+                                  _("This will reset <b>all</b> shortcuts to their default "
+                                    "values. Do you really want to do this?"),
+                                  GTK_STOCK_NO, GTK_RESPONSE_NO,
+                                  GTK_STOCK_YES, GTK_RESPONSE_YES,
+                                  NULL);
+
+  if (G_LIKELY (response == GTK_RESPONSE_YES))
+    xfce_shortcuts_provider_reset_to_defaults (settings->priv->provider);
+}
+
+
+
+static const gchar *
+xfwm_settings_shortcut_feature_name (const gchar *feature)
+{
+  const gchar *result = feature;
+  gint         i;
+
+  for (i = 0; shortcut_values[i].name != NULL; ++i)
+    if (G_UNLIKELY (g_str_equal (shortcut_values[i].feature, feature)))
+      {
+        result = shortcut_values[i].name;
+        break;
+      }
+
+  return result;
+}
+
+
+
+static gboolean
+xfwm_settings_validate_shortcut (FrapShortcutsDialog *dialog,
+                                 const gchar         *shortcut,
+                                 XfwmSettings        *settings)
+{
+  XfceShortcutsProvider *other_provider = NULL;
+  XfceShortcut          *other_shortcut = NULL;
+  GList                 *providers;
+  GList                 *iter;
+  gchar                 *property;
+  gboolean               accepted = TRUE;
+  gint                   response;
+
+  g_return_val_if_fail (FRAP_IS_SHORTCUTS_DIALOG (dialog), FALSE);
+  g_return_val_if_fail (XFWM_IS_SETTINGS (settings), FALSE);
+  g_return_val_if_fail (shortcut != NULL, FALSE);
+
+  /* Ignore empty shortcuts */
+  if (G_UNLIKELY (g_utf8_strlen (shortcut, -1) == 0))
+    return FALSE;
+
+  /* Ignore raw 'Return' and 'space' since that may have been used to activate the shortcut row */
+  if (G_UNLIKELY (g_utf8_collate (shortcut, "Return") == 0 || 
+                  g_utf8_collate (shortcut, "space") == 0))
+    {
+      return FALSE;
+    }
+
+  providers = xfce_shortcuts_provider_get_providers ();
+
+  if (G_UNLIKELY (providers == NULL))
+    return TRUE;
+
+  for (iter = providers; iter != NULL && other_shortcut == NULL; iter = g_list_next (iter))
+    {
+      if (G_UNLIKELY (xfce_shortcuts_provider_has_shortcut (iter->data, shortcut)))
+        {
+          other_provider = g_object_ref (iter->data);
+          other_shortcut = xfce_shortcuts_provider_get_shortcut (iter->data, shortcut);
+        }
+    }
+
+  xfce_shortcuts_provider_free_providers (providers);
+
+  if (G_UNLIKELY (other_shortcut != NULL))
+    {
+      response = frap_shortcuts_conflict_dialog (xfce_shortcuts_provider_get_name (settings->priv->provider),
+                                                 xfce_shortcuts_provider_get_name (other_provider),
+                                                 shortcut,
+                                                 frap_shortcuts_dialog_get_action_name (dialog),
+                                                 xfwm_settings_shortcut_feature_name (other_shortcut->command),
+                                                 FALSE);
+
+      accepted = response == GTK_RESPONSE_ACCEPT;
+
+      xfce_shortcut_free (other_shortcut);
+      g_object_unref (other_provider);
+    }
+
+  return accepted;
+}
+
+
+
+static void
+xfwm_settings_shortcut_row_activated (GtkTreeView       *tree_view,
+                                      GtkTreePath       *path,
+                                      GtkTreeViewColumn *column,
+                                      XfwmSettings      *settings)
+{
+  GtkTreeModel *model;
+  GtkTreeIter   iter;
+  GtkWidget    *dialog;
+  const gchar  *new_shortcut;
+  gchar        *shortcut;
+  gchar        *feature;
+  gchar        *name;
+  gint          response;
+
+  g_return_if_fail (XFWM_IS_SETTINGS (settings));
+  g_return_if_fail (XFCE_IS_SHORTCUTS_PROVIDER (settings->priv->provider));
+
+  model = gtk_tree_view_get_model (tree_view);
+
+  if (G_LIKELY (gtk_tree_model_get_iter (model, &iter, path)))
+    {
+      /* Read shortcut from the activated row */
+      gtk_tree_model_get (model, &iter, 
+                          SHORTCUTS_NAME_COLUMN, &name, 
+                          SHORTCUTS_FEATURE_COLUMN, &feature, 
+                          SHORTCUTS_SHORTCUT_COLUMN, &shortcut, -1);
+  
+      /* Request a new shortcut from the user */
+      dialog = frap_shortcuts_dialog_new ("xfwm4", name, feature);
+      g_signal_connect (dialog, "validate-shortcut", 
+                        G_CALLBACK (xfwm_settings_validate_shortcut), settings);
+      response = frap_shortcuts_dialog_run (FRAP_SHORTCUTS_DIALOG (dialog));
+
+      if (G_LIKELY (response == GTK_RESPONSE_OK))
+        {
+          /* Remove old shortcut from the settings */
+          if (G_LIKELY (shortcut != NULL))
+            xfce_shortcuts_provider_reset_shortcut (settings->priv->provider, shortcut);
+
+          /* Get new shortcut entered by the user */
+          new_shortcut = frap_shortcuts_dialog_get_shortcut (FRAP_SHORTCUTS_DIALOG (dialog));
+
+          /* Save new shortcut */
+          xfce_shortcuts_provider_set_shortcut (settings->priv->provider, new_shortcut, feature);
+        }
+      else if (G_UNLIKELY (response == GTK_RESPONSE_REJECT))
+        {
+          /* Remove old shortcut from the settings */
+          if (G_LIKELY (shortcut != NULL))
+            xfce_shortcuts_provider_reset_shortcut (settings->priv->provider, shortcut);
+        }
+
+      /* Destroy the shortcut dialog */
+      gtk_widget_destroy (dialog);
+
+      /* Free strings */
+      g_free (feature);
+      g_free (name);
+      g_free (shortcut);
+    }
+}
-- 
GitLab