diff --git a/src/xfpm-button.c b/src/xfpm-button.c
index 62d001bc26ca59fd9210282a053c811ada68a0f2..cdc2e56ef18384aa561b002eb1627c5d6a06fa81 100644
--- a/src/xfpm-button.c
+++ b/src/xfpm-button.c
@@ -41,6 +41,7 @@
 #ifdef ENABLE_X11
 #include <X11/X.h>
 #include <X11/XF86keysym.h>
+#include <X11/XKBlib.h>
 #include <gdk/gdkx.h>
 #endif
 
@@ -52,13 +53,18 @@ static struct
 {
   XfpmButtonKey key;
   guint key_code;
-} xfpm_key_map[N_XFPM_BUTTON_KEYS] = { 0 };
+  guint key_modifiers;
+} xfpm_key_map[N_XFPM_BUTTON_KEYS] = { { 0, 0 } };
 #endif
 
 struct XfpmButtonPrivate
 {
   GdkScreen *screen;
   GdkWindow *window;
+#ifdef ENABLE_X11
+  Display *xdisplay;
+#endif
+  GdkDisplay *gdisplay;
   gboolean handle_brightness_keys;
   guint16 mapped_buttons;
 };
@@ -78,20 +84,83 @@ G_DEFINE_TYPE_WITH_PRIVATE (XfpmButton, xfpm_button, G_TYPE_OBJECT)
 #ifdef ENABLE_X11
 
 static guint
-xfpm_button_get_key (unsigned int keycode)
+xfpm_button_get_key (unsigned int keycode,
+                     unsigned int keymodifiers)
 {
   XfpmButtonKey key = BUTTON_UNKNOWN;
   guint i;
 
   for (i = 0; i < G_N_ELEMENTS (xfpm_key_map); i++)
   {
-    if (xfpm_key_map[i].key_code == keycode)
+    /* Match keycode and modifiers, but ignore CapsLock state */
+    if (xfpm_key_map[i].key_code == keycode
+        && xfpm_key_map[i].key_modifiers == (keymodifiers & ~LockMask))
       key = xfpm_key_map[i].key;
   }
 
   return key;
 }
 
+static gboolean
+xfpm_button_keysym_to_code_mask (XfpmButton *button,
+                                 guint keysym,
+                                 guint *keycode,
+                                 guint *modmask)
+{
+  GdkKeymap *keymap = gdk_keymap_get_for_display (button->priv->gdisplay);
+  GdkKeymapKey *keys;
+  gint nkeys;
+  gboolean retval = FALSE;
+  *keycode = 0;
+  *modmask = 0;
+
+  /*
+   * Try to figure out the keysym modifier mask.
+   * If there is more than 1 keycode for the keysym, the first keycode is used.
+   * Defaults to previously used 'AllModifiers'. Code taken from keybinder library.
+   */
+  /* Force keymap sync */
+  gdk_keymap_have_bidi_layouts (keymap);
+  if (gdk_keymap_get_entries_for_keyval (keymap, keysym, &keys, &nkeys))
+  {
+    XFPM_DEBUG ("%i Keymap entries found", nkeys);
+    XkbDescPtr xkbmap = XkbGetMap (button->priv->xdisplay, XkbAllClientInfoMask, XkbUseCoreKbd);
+    if (xkbmap)
+    {
+      XkbKeyTypeRec *type = XkbKeyKeyType (xkbmap, keys[0].keycode, keys[0].group);
+      if (type)
+      {
+        *keycode = keys[0].keycode;
+        for (int k = 0; k < type->map_count; k++)
+        {
+          if (type->map[k].active && type->map[k].level == keys[0].level)
+          {
+            if (type->preserve)
+            {
+              *modmask = type->map[k].mods.mask & ~type->preserve[k].mask;
+            }
+            else
+            {
+              *modmask = type->map[k].mods.mask;
+            }
+          }
+        }
+        retval = TRUE;
+      }
+    }
+    else
+    {
+      *modmask = AnyModifier;
+    }
+    g_free (keys);
+  }
+  else
+  {
+    XFPM_DEBUG ("No keymap entry found for keysym %i", keysym);
+  }
+  return retval;
+}
+
 static GdkFilterReturn
 xfpm_button_filter_x_events (GdkXEvent *xevent,
                              GdkEvent *ev,
@@ -105,7 +174,8 @@ xfpm_button_filter_x_events (GdkXEvent *xevent,
   if (xev->type != KeyPress)
     return GDK_FILTER_CONTINUE;
 
-  key = xfpm_button_get_key (xev->xkey.keycode);
+  XFPM_DEBUG ("keycode:%u, state:%u", xev->xkey.keycode, xev->xkey.state);
+  key = xfpm_button_get_key (xev->xkey.keycode, xev->xkey.state);
 
   if (key != BUTTON_UNKNOWN)
   {
@@ -122,42 +192,38 @@ xfpm_button_filter_x_events (GdkXEvent *xevent,
 
 static gboolean
 xfpm_button_grab_keystring (XfpmButton *button,
-                            guint keycode)
+                            guint keycode,
+                            guint modmask)
 {
-  Display *display;
-  GdkDisplay *gdisplay;
   guint ret;
-  guint modmask = AnyModifier;
+  guint retval = 0;
 
-  display = gdk_x11_get_default_xdisplay ();
-  gdisplay = gdk_display_get_default ();
+  gdk_x11_display_error_trap_push (button->priv->gdisplay);
 
-  gdk_x11_display_error_trap_push (gdisplay);
-
-  ret = XGrabKey (display, keycode, modmask,
+  ret = XGrabKey (button->priv->xdisplay, keycode, modmask,
                   GDK_WINDOW_XID (button->priv->window), True,
                   GrabModeAsync, GrabModeAsync);
 
-  if (ret == BadAccess)
+  if (ret == BadAccess || ret == BadValue || ret == BadWindow)
   {
-    g_warning ("Failed to grab modmask=%u, keycode=%li", modmask, (long int) keycode);
-    return FALSE;
+    g_warning ("ReturnCode=%u - Failed to grab modmask=%u, keycode=%li", ret, modmask, (long int) keycode);
+    retval++;
   }
 
-  ret = XGrabKey (display, keycode, LockMask | modmask,
+  ret = XGrabKey (button->priv->xdisplay, keycode, LockMask | modmask,
                   GDK_WINDOW_XID (button->priv->window), True,
                   GrabModeAsync, GrabModeAsync);
 
-  if (ret == BadAccess)
+  if (ret == BadAccess || ret == BadValue || ret == BadWindow)
   {
-    g_warning ("Failed to grab modmask=%u, keycode=%li", LockMask | modmask, (long int) keycode);
-    return FALSE;
+    g_warning ("ReturnCode=%u - Failed to grab modmask=%u, keycode=%li", ret, LockMask | modmask, (long int) keycode);
+    retval++;
   }
 
-  gdk_display_flush (gdisplay);
-  gdk_x11_display_error_trap_pop_ignored (gdisplay);
+  gdk_display_flush (button->priv->gdisplay);
+  gdk_x11_display_error_trap_pop_ignored (button->priv->gdisplay);
 
-  return TRUE;
+  return retval == 0;
 }
 
 
@@ -166,23 +232,28 @@ xfpm_button_xevent_key (XfpmButton *button,
                         guint keysym,
                         XfpmButtonKey key)
 {
-  guint keycode = XKeysymToKeycode (gdk_x11_get_default_xdisplay (), keysym);
-
-  if (keycode == 0)
+  XFPM_DEBUG ("keysym:%x", keysym);
+  guint keycode;
+  guint keymodifiers;
+  if (xfpm_button_keysym_to_code_mask (button, keysym, &keycode, &keymodifiers))
   {
-    XFPM_DEBUG ("could not map keysym %x to keycode\n", keysym);
-    return FALSE;
-  }
-
-  if (!xfpm_button_grab_keystring (button, keycode))
-    return FALSE;
+    XFPM_DEBUG ("keycode:%u, keymodifiers:%u", keycode, keymodifiers);
+    if (!xfpm_button_grab_keystring (button, keycode, keymodifiers))
+      return FALSE;
 
-  XFPM_DEBUG_ENUM (key, XFPM_TYPE_BUTTON_KEY, "Grabbed key %li ", (long int) keycode);
+    XFPM_DEBUG_ENUM (key, XFPM_TYPE_BUTTON_KEY, "Grabbed key:%li, mod:%u ", (long int) keycode, keymodifiers);
 
-  xfpm_key_map[key].key_code = keycode;
-  xfpm_key_map[key].key = key;
+    xfpm_key_map[key].key_code = keycode;
+    xfpm_key_map[key].key_modifiers = keymodifiers;
+    xfpm_key_map[key].key = key;
 
-  return TRUE;
+    return TRUE;
+  }
+  else
+  {
+    XFPM_DEBUG ("could not map keysym %x to keycode and modifiers", keysym);
+    return FALSE;
+  }
 }
 
 static void
@@ -190,34 +261,28 @@ xfpm_button_ungrab (XfpmButton *button,
                     guint keysym,
                     XfpmButtonKey key)
 {
-  Display *display;
-  GdkDisplay *gdisplay;
-  guint modmask = AnyModifier;
-  guint keycode = XKeysymToKeycode (gdk_x11_get_default_xdisplay (), keysym);
+  guint keycode;
+  guint modmask;
 
-  if (keycode == 0)
+  if (xfpm_button_keysym_to_code_mask (button, keysym, &keycode, &modmask))
   {
-    XFPM_DEBUG ("could not map keysym %x to keycode\n", keysym);
-    return;
+    gdk_x11_display_error_trap_push (button->priv->gdisplay);
+    XUngrabKey (button->priv->xdisplay, keycode, modmask,
+                GDK_WINDOW_XID (button->priv->window));
+    XUngrabKey (button->priv->xdisplay, keycode, LockMask | modmask,
+                GDK_WINDOW_XID (button->priv->window));
+    gdk_display_flush (button->priv->gdisplay);
+    gdk_x11_display_error_trap_pop_ignored (button->priv->gdisplay);
+    XFPM_DEBUG_ENUM (key, XFPM_TYPE_BUTTON_KEY, "Ungrabbed key %li ", (long int) keycode);
+
+    xfpm_key_map[key].key_code = 0;
+    xfpm_key_map[key].key_modifiers = 0;
+    xfpm_key_map[key].key = 0;
+  }
+  else
+  {
+    XFPM_DEBUG ("could not map keysym %x to keycode and modifiers", keysym);
   }
-
-  display = gdk_x11_get_default_xdisplay ();
-  gdisplay = gdk_display_get_default ();
-
-  gdk_x11_display_error_trap_push (gdisplay);
-
-  XUngrabKey (display, keycode, modmask,
-              GDK_WINDOW_XID (button->priv->window));
-  XUngrabKey (display, keycode, LockMask | modmask,
-              GDK_WINDOW_XID (button->priv->window));
-
-  gdk_display_flush (gdisplay);
-  gdk_x11_display_error_trap_pop_ignored (gdisplay);
-
-  XFPM_DEBUG_ENUM (key, XFPM_TYPE_BUTTON_KEY, "Ungrabbed key %li ", (long int) keycode);
-
-  xfpm_key_map[key].key_code = 0;
-  xfpm_key_map[key].key = 0;
 }
 
 static void
@@ -225,6 +290,9 @@ xfpm_button_setup (XfpmButton *button)
 {
   button->priv->screen = gdk_screen_get_default ();
   button->priv->window = gdk_screen_get_root_window (button->priv->screen);
+  button->priv->gdisplay = gdk_display_get_default ();
+  if (GDK_IS_X11_DISPLAY (button->priv->gdisplay))
+    button->priv->xdisplay = gdk_x11_get_default_xdisplay ();
 
   if (xfpm_button_xevent_key (button, XF86XK_PowerOff, BUTTON_POWER_OFF))
     button->priv->mapped_buttons |= POWER_KEY;
@@ -293,6 +361,10 @@ xfpm_button_init (XfpmButton *button)
   button->priv->mapped_buttons = 0;
   button->priv->screen = NULL;
   button->priv->window = NULL;
+#ifdef ENABLE_X11
+  button->priv->xdisplay = NULL;
+#endif
+  button->priv->gdisplay = NULL;
 
 #ifdef ENABLE_X11
   if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))