]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkkeys-x11.c
Fix build with XI2.x for x < 2
[~andy/gtk] / gdk / x11 / gdkkeys-x11.c
index 1b1e9427a433bbc43f0a27a42aacaf9db160cff3..c5153bdcc2a668d5fc2359508e8f8119b91f0d1b 100644 (file)
@@ -12,9 +12,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
@@ -26,6 +24,7 @@
 
 #include "config.h"
 
+#include "gdkx11keys.h"
 #include "gdkkeysprivate.h"
 #include "gdkkeysyms.h"
 #include "gdkprivate-x11.h"
 #  endif
 #endif /* HAVE_XKB */
 
-typedef struct _GdkKeymapX11   GdkKeymapX11;
-typedef struct _GdkKeymapClass GdkKeymapX11Class;
-
-#define GDK_TYPE_KEYMAP_X11          (_gdk_keymap_x11_get_type ())
-#define GDK_KEYMAP_X11(object)       (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_KEYMAP_X11, GdkKeymapX11))
-#define GDK_IS_KEYMAP_X11(object)    (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_KEYMAP_X11))
-
 typedef struct _DirectionCacheEntry DirectionCacheEntry;
 
 struct _DirectionCacheEntry
@@ -65,7 +57,7 @@ struct _DirectionCacheEntry
   PangoDirection direction;
 };
 
-struct _GdkKeymapX11
+struct _GdkX11Keymap
 {
   GdkKeymap     parent_instance;
 
@@ -81,8 +73,10 @@ struct _GdkKeymapX11
   PangoDirection current_direction;
   guint sun_keypad      : 1;
   guint have_direction  : 1;
+  guint have_lock_state : 1;
   guint caps_lock_state : 1;
-  guint num_lock_state : 1;
+  guint num_lock_state  : 1;
+  guint modifier_state;
   guint current_serial;
 
 #ifdef HAVE_XKB
@@ -99,46 +93,18 @@ struct _GdkKeymapX11
 #endif
 };
 
-#define KEYMAP_USE_XKB(keymap) GDK_DISPLAY_X11 ((keymap)->display)->use_xkb
-#define KEYMAP_XDISPLAY(keymap) GDK_DISPLAY_XDISPLAY ((keymap)->display)
-
-GType _gdk_keymap_x11_get_type   (void);
-static void  gdk_keymap_x11_class_init (GdkKeymapX11Class *klass);
-static void  gdk_keymap_x11_init       (GdkKeymapX11      *keymap);
-static void  gdk_keymap_x11_finalize   (GObject           *object);
-
-static GdkKeymapClass *parent_class = NULL;
-
-GType
-_gdk_keymap_x11_get_type (void)
+struct _GdkX11KeymapClass
 {
-  static GType object_type = 0;
+  GdkKeymapClass parent_class;
+};
 
-  if (!object_type)
-    {
-      const GTypeInfo object_info =
-        {
-          sizeof (GdkKeymapClass),
-          (GBaseInitFunc) NULL,
-          (GBaseFinalizeFunc) NULL,
-          (GClassInitFunc) gdk_keymap_x11_class_init,
-          NULL,           /* class_finalize */
-          NULL,           /* class_data */
-          sizeof (GdkKeymapX11),
-          0,              /* n_preallocs */
-          (GInstanceInitFunc) gdk_keymap_x11_init,
-        };
-
-      object_type = g_type_register_static (GDK_TYPE_KEYMAP,
-                                            g_intern_static_string ("GdkKeymapX11"),
-                                            &object_info, 0);
-    }
+#define KEYMAP_USE_XKB(keymap) GDK_X11_DISPLAY ((keymap)->display)->use_xkb
+#define KEYMAP_XDISPLAY(keymap) GDK_DISPLAY_XDISPLAY ((keymap)->display)
 
-  return object_type;
-}
+G_DEFINE_TYPE (GdkX11Keymap, gdk_x11_keymap, GDK_TYPE_KEYMAP)
 
 static void
-gdk_keymap_x11_init (GdkKeymapX11 *keymap)
+gdk_x11_keymap_init (GdkX11Keymap *keymap)
 {
   keymap->min_keycode = 0;
   keymap->max_keycode = 0;
@@ -152,6 +118,7 @@ gdk_keymap_x11_init (GdkKeymapX11 *keymap)
   keymap->group_switch_mask = 0;
   keymap->lock_keysym = GDK_KEY_Caps_Lock;
   keymap->have_direction = FALSE;
+  keymap->have_lock_state = FALSE;
   keymap->current_serial = 0;
 
 #ifdef HAVE_XKB
@@ -163,9 +130,9 @@ gdk_keymap_x11_init (GdkKeymapX11 *keymap)
 }
 
 static void
-gdk_keymap_x11_finalize (GObject *object)
+gdk_x11_keymap_finalize (GObject *object)
 {
-  GdkKeymapX11 *keymap_x11 = GDK_KEYMAP_X11 (object);
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (object);
 
   if (keymap_x11->keymap)
     XFree (keymap_x11->keymap);
@@ -178,11 +145,11 @@ gdk_keymap_x11_finalize (GObject *object)
     XkbFreeKeyboard (keymap_x11->xkb_desc, XkbAllComponentsMask, True);
 #endif
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (gdk_x11_keymap_parent_class)->finalize (object);
 }
 
 static inline void
-update_keyrange (GdkKeymapX11 *keymap_x11)
+update_keyrange (GdkX11Keymap *keymap_x11)
 {
   if (keymap_x11->max_keycode == 0)
     XDisplayKeycodes (KEYMAP_XDISPLAY (GDK_KEYMAP (keymap_x11)),
@@ -193,7 +160,7 @@ update_keyrange (GdkKeymapX11 *keymap_x11)
 
 static void
 update_modmap (Display      *display,
-               GdkKeymapX11 *keymap_x11)
+               GdkX11Keymap *keymap_x11)
 {
   static struct {
     const gchar *name;
@@ -232,9 +199,9 @@ update_modmap (Display      *display,
 }
 
 static XkbDescPtr
-get_xkb (GdkKeymapX11 *keymap_x11)
+get_xkb (GdkX11Keymap *keymap_x11)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_KEYMAP (keymap_x11)->display);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (GDK_KEYMAP (keymap_x11)->display);
   Display *xdisplay = display_x11->xdisplay;
 
   update_keyrange (keymap_x11);
@@ -264,7 +231,7 @@ get_xkb (GdkKeymapX11 *keymap_x11)
   keymap_x11->current_serial = display_x11->keymap_serial;
 
   if (keymap_x11->num_lock_mask == 0)
-    keymap_x11->num_lock_mask = XkbKeysymToModifiers (KEYMAP_XDISPLAY (GDK_KEYMAP (keymap_x11)), XK_Num_Lock);
+    keymap_x11->num_lock_mask = XkbKeysymToModifiers (KEYMAP_XDISPLAY (GDK_KEYMAP (keymap_x11)), GDK_KEY_Num_Lock);
 
   return keymap_x11->xkb_desc;
 }
@@ -286,9 +253,9 @@ get_xkb (GdkKeymapX11 *keymap_x11)
 
 static gint
 get_symbol (const KeySym *syms,
-            GdkKeymapX11 *keymap_x11,
-            gint group,
-            gint level)
+            GdkX11Keymap *keymap_x11,
+            gint          group,
+            gint          level)
 {
   gint index;
 
@@ -301,7 +268,7 @@ get_symbol (const KeySym *syms,
 
 static void
 set_symbol (KeySym       *syms,
-            GdkKeymapX11 *keymap_x11,
+            GdkX11Keymap *keymap_x11,
             gint          group,
             gint          level,
             KeySym        sym)
@@ -316,9 +283,9 @@ set_symbol (KeySym       *syms,
 }
 
 static void
-update_keymaps (GdkKeymapX11 *keymap_x11)
+update_keymaps (GdkX11Keymap *keymap_x11)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_KEYMAP (keymap_x11)->display);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (GDK_KEYMAP (keymap_x11)->display);
   Display *xdisplay = display_x11->xdisplay;
 
 #ifdef HAVE_XKB
@@ -492,34 +459,17 @@ update_keymaps (GdkKeymapX11 *keymap_x11)
 }
 
 static const KeySym*
-get_keymap (GdkKeymapX11 *keymap_x11)
+get_keymap (GdkX11Keymap *keymap_x11)
 {
   update_keymaps (keymap_x11);
 
   return keymap_x11->keymap;
 }
 
-#define GET_EFFECTIVE_KEYMAP(keymap) get_effective_keymap ((keymap), G_STRFUNC)
-
-static GdkKeymap *
-get_effective_keymap (GdkKeymap  *keymap,
-                      const char *function)
-{
-  if (!keymap)
-    {
-      GDK_NOTE (MULTIHEAD,
-                g_message ("reverting to default display keymap in %s",
-                           function));
-      return gdk_keymap_get_default ();
-    }
-
-  return keymap;
-}
-
-#if HAVE_XKB
+#ifdef HAVE_XKB
 static PangoDirection
 get_direction (XkbDescRec *xkb,
-               gint group)
+               gint        group)
 {
   gint code;
 
@@ -551,9 +501,9 @@ get_direction (XkbDescRec *xkb,
 }
 
 static PangoDirection
-get_direction_from_cache (GdkKeymapX11 *keymap_x11,
-                          XkbDescPtr xkb,
-                          gint group)
+get_direction_from_cache (GdkX11Keymap *keymap_x11,
+                          XkbDescPtr    xkb,
+                          gint          group)
 {
   Atom group_atom = xkb->names->groups[group];
 
@@ -623,7 +573,7 @@ get_num_groups (GdkKeymap *keymap,
 }
 
 static gboolean
-update_direction (GdkKeymapX11 *keymap_x11,
+update_direction (GdkX11Keymap *keymap_x11,
                   gint          group)
 {
   XkbDescPtr xkb = get_xkb (keymap_x11);
@@ -648,20 +598,34 @@ update_direction (GdkKeymapX11 *keymap_x11,
 }
 
 static gboolean
-update_lock_state (GdkKeymapX11 *keymap_x11,
-                   gint          locked_mods)
+update_lock_state (GdkX11Keymap *keymap_x11,
+                   gint          locked_mods,
+                   gint          effective_mods)
 {
+  XkbDescPtr xkb G_GNUC_UNUSED;
+  gboolean have_lock_state;
   gboolean caps_lock_state;
   gboolean num_lock_state;
+  guint modifier_state;
+
+  /* ensure keymap_x11->num_lock_mask is initialized */
+  xkb = get_xkb (keymap_x11);
 
+  have_lock_state = keymap_x11->have_lock_state;
   caps_lock_state = keymap_x11->caps_lock_state;
   num_lock_state = keymap_x11->num_lock_state;
+  modifier_state = keymap_x11->modifier_state;
 
+  keymap_x11->have_lock_state = TRUE;
   keymap_x11->caps_lock_state = (locked_mods & GDK_LOCK_MASK) != 0;
   keymap_x11->num_lock_state = (locked_mods & keymap_x11->num_lock_mask) != 0;
+  /* FIXME: sanitize this */
+  keymap_x11->modifier_state = (guint)effective_mods;
 
-  return (caps_lock_state != keymap_x11->caps_lock_state)
-    || (num_lock_state != keymap_x11->num_lock_state);
+  return !have_lock_state
+         || (caps_lock_state != keymap_x11->caps_lock_state)
+         || (num_lock_state != keymap_x11->num_lock_state)
+         || (modifier_state != keymap_x11->modifier_state);
 }
 
 /* keep this in sync with the XkbSelectEventDetails()
@@ -671,27 +635,49 @@ void
 _gdk_x11_keymap_state_changed (GdkDisplay *display,
                                XEvent     *xevent)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
   XkbEvent *xkb_event = (XkbEvent *)xevent;
 
   if (display_x11->keymap)
     {
-      GdkKeymapX11 *keymap_x11 = GDK_KEYMAP_X11 (display_x11->keymap);
+      GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (display_x11->keymap);
 
       if (update_direction (keymap_x11, XkbStateGroup (&xkb_event->state)))
         g_signal_emit_by_name (keymap_x11, "direction-changed");
 
-      if (update_lock_state (keymap_x11, xkb_event->state.locked_mods))
+      if (update_lock_state (keymap_x11,
+                             xkb_event->state.locked_mods,
+                             xkb_event->state.mods))
         g_signal_emit_by_name (keymap_x11, "state-changed");
     }
 }
 
 #endif /* HAVE_XKB */
 
+static void
+ensure_lock_state (GdkKeymap *keymap)
+{
+#ifdef HAVE_XKB
+  if (KEYMAP_USE_XKB (keymap))
+    {
+      GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
+
+      if (!keymap_x11->have_lock_state)
+        {
+          GdkDisplay *display = keymap->display;
+          XkbStateRec state_rec;
+
+          XkbGetState (GDK_DISPLAY_XDISPLAY (display), XkbUseCoreKbd, &state_rec);
+          update_lock_state (keymap_x11, state_rec.locked_mods, state_rec.mods);
+        }
+    }
+#endif /* HAVE_XKB */
+}
+
 void
 _gdk_x11_keymap_keys_changed (GdkDisplay *display)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
 
   ++display_x11->keymap_serial;
 
@@ -702,16 +688,14 @@ _gdk_x11_keymap_keys_changed (GdkDisplay *display)
 static PangoDirection
 gdk_x11_keymap_get_direction (GdkKeymap *keymap)
 {
-  keymap = GET_EFFECTIVE_KEYMAP (keymap);
-
-#if HAVE_XKB
+#ifdef HAVE_XKB
   if (KEYMAP_USE_XKB (keymap))
     {
-      GdkKeymapX11 *keymap_x11 = GDK_KEYMAP_X11 (keymap);
+      GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
 
       if (!keymap_x11->have_direction)
         {
-          GdkDisplay *display = GDK_KEYMAP (keymap_x11)->display;
+          GdkDisplay *display = keymap->display;
           XkbStateRec state_rec;
 
           XkbGetState (GDK_DISPLAY_XDISPLAY (display), XkbUseCoreKbd,
@@ -729,12 +713,10 @@ gdk_x11_keymap_get_direction (GdkKeymap *keymap)
 static gboolean
 gdk_x11_keymap_have_bidi_layouts (GdkKeymap *keymap)
 {
-  keymap = GET_EFFECTIVE_KEYMAP (keymap);
-
-#if HAVE_XKB
+#ifdef HAVE_XKB
   if (KEYMAP_USE_XKB (keymap))
     {
-      GdkKeymapX11 *keymap_x11 = GDK_KEYMAP_X11 (keymap);
+      GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
       XkbDescPtr xkb = get_xkb (keymap_x11);
       int num_groups = get_num_groups (keymap, xkb);
 
@@ -760,11 +742,9 @@ gdk_x11_keymap_have_bidi_layouts (GdkKeymap *keymap)
 static gboolean
 gdk_x11_keymap_get_caps_lock_state (GdkKeymap *keymap)
 {
-  GdkKeymapX11 *keymap_x11;
-
-  keymap = GET_EFFECTIVE_KEYMAP (keymap);
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
 
-  keymap_x11 = GDK_KEYMAP_X11 (keymap);
+  ensure_lock_state (keymap);
 
   return keymap_x11->caps_lock_state;
 }
@@ -772,31 +752,31 @@ gdk_x11_keymap_get_caps_lock_state (GdkKeymap *keymap)
 static gboolean
 gdk_x11_keymap_get_num_lock_state (GdkKeymap *keymap)
 {
-  GdkKeymapX11 *keymap_x11;
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
 
-  keymap = GET_EFFECTIVE_KEYMAP (keymap);
-
-  keymap_x11 = GDK_KEYMAP_X11 (keymap);
+  ensure_lock_state (keymap);
 
   return keymap_x11->num_lock_state;
 }
 
+static guint
+gdk_x11_keymap_get_modifier_state (GdkKeymap *keymap)
+{
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
+
+  ensure_lock_state (keymap);
+
+  return keymap_x11->modifier_state;
+}
+
 static gboolean
 gdk_x11_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
                                        guint          keyval,
                                        GdkKeymapKey **keys,
                                        gint          *n_keys)
 {
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
   GArray *retval;
-  GdkKeymapX11 *keymap_x11;
-
-  g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
-  g_return_val_if_fail (keys != NULL, FALSE);
-  g_return_val_if_fail (n_keys != NULL, FALSE);
-  g_return_val_if_fail (keyval != 0, FALSE);
-
-  keymap = GET_EFFECTIVE_KEYMAP (keymap);
-  keymap_x11 = GDK_KEYMAP_X11 (keymap);
 
   retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
 
@@ -889,6 +869,8 @@ gdk_x11_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
 
               ++i;
             }
+
+          ++keycode;
         }
     }
 
@@ -915,17 +897,10 @@ gdk_x11_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
                                         guint        **keyvals,
                                         gint          *n_entries)
 {
-  GdkKeymapX11 *keymap_x11;
-
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
   GArray *key_array;
   GArray *keyval_array;
 
-  g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
-  g_return_val_if_fail (n_entries != NULL, FALSE);
-
-  keymap = GET_EFFECTIVE_KEYMAP (keymap);
-  keymap_x11 = GDK_KEYMAP_X11 (keymap);
-
   update_keyrange (keymap_x11);
 
   if (hardware_keycode < keymap_x11->min_keycode ||
@@ -1054,15 +1029,10 @@ static guint
 gdk_x11_keymap_lookup_key (GdkKeymap          *keymap,
                            const GdkKeymapKey *key)
 {
-  GdkKeymapX11 *keymap_x11;
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
 
-  g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
-  g_return_val_if_fail (key != NULL, 0);
   g_return_val_if_fail (key->group < 4, 0);
 
-  keymap = GET_EFFECTIVE_KEYMAP (keymap);
-  keymap_x11 = GDK_KEYMAP_X11 (keymap);
-
 #ifdef HAVE_XKB
   if (KEYMAP_USE_XKB (keymap))
     {
@@ -1215,7 +1185,7 @@ MyEnhancedXkbTranslateKeyCode(register XkbDescPtr     xkb,
  * of the keyboard map. See section 12.7 of the Xlib reference manual
  */
 static guint
-translate_keysym (GdkKeymapX11   *keymap_x11,
+translate_keysym (GdkX11Keymap   *keymap_x11,
                   guint           hardware_keycode,
                   gint            group,
                   GdkModifierType state,
@@ -1312,16 +1282,12 @@ gdk_x11_keymap_translate_keyboard_state (GdkKeymap       *keymap,
                                          gint            *level,
                                          GdkModifierType *consumed_modifiers)
 {
-  GdkKeymapX11 *keymap_x11;
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
   KeySym tmp_keyval = NoSymbol;
   guint tmp_modifiers;
 
-  g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
   g_return_val_if_fail (group < 4, FALSE);
 
-  keymap = GET_EFFECTIVE_KEYMAP (keymap);
-  keymap_x11 = GDK_KEYMAP_X11 (keymap);
-
   if (keyval)
     *keyval = NoSymbol;
   if (effective_group)
@@ -1463,139 +1429,13 @@ _gdk_x11_display_manager_keyval_convert_case (GdkDisplayManager *manager,
   if (upper)
     *upper = xupper;
 }
-#else /* !HAVE_XCONVERTCASE */
-void
-_gdk_x11_display_manager_keyval_convert_case (GdkDisplayManager *manager,
-                                              guint              symbol,
-                                              guint             *lower,
-                                              guint             *upper)
-{
-  guint xlower = symbol;
-  guint xupper = symbol;
-
-  /* Check for directly encoded 24-bit UCS characters: */
-  if ((symbol & 0xff000000) == 0x01000000)
-    {
-      if (lower)
-        *lower = gdk_unicode_to_keyval (g_unichar_tolower (symbol & 0x00ffffff));
-      if (upper)
-        *upper = gdk_unicode_to_keyval (g_unichar_toupper (symbol & 0x00ffffff));
-      return;
-    }
-
-  switch (symbol >> 8)
-    {
-    case 0: /* Latin 1 */
-      if ((symbol >= GDK_KEY_A) && (symbol <= GDK_KEY_Z))
-        xlower += (GDK_KEY_a - GDK_KEY_A);
-      else if ((symbol >= GDK_KEY_a) && (symbol <= GDK_KEY_z))
-        xupper -= (GDK_KEY_a - GDK_KEY_A);
-      else if ((symbol >= GDK_KEY_Agrave) && (symbol <= GDK_KEY_Odiaeresis))
-        xlower += (GDK_KEY_agrave - GDK_KEY_Agrave);
-      else if ((symbol >= GDK_KEY_agrave) && (symbol <= GDK_KEY_odiaeresis))
-        xupper -= (GDK_KEY_agrave - GDK_KEY_Agrave);
-      else if ((symbol >= GDK_KEY_Ooblique) && (symbol <= GDK_KEY_Thorn))
-        xlower += (GDK_KEY_oslash - GDK_KEY_Ooblique);
-      else if ((symbol >= GDK_KEY_oslash) && (symbol <= GDK_KEY_thorn))
-        xupper -= (GDK_KEY_oslash - GDK_KEY_Ooblique);
-      break;
-
-    case 1: /* Latin 2 */
-      /* Assume the KeySym is a legal value (ignore discontinuities) */
-      if (symbol == GDK_KEY_Aogonek)
-        xlower = GDK_KEY_aogonek;
-      else if (symbol >= GDK_KEY_Lstroke && symbol <= GDK_KEY_Sacute)
-        xlower += (GDK_KEY_lstroke - GDK_KEY_Lstroke);
-      else if (symbol >= GDK_KEY_Scaron && symbol <= GDK_KEY_Zacute)
-        xlower += (GDK_KEY_scaron - GDK_KEY_Scaron);
-      else if (symbol >= GDK_KEY_Zcaron && symbol <= GDK_KEY_Zabovedot)
-        xlower += (GDK_KEY_zcaron - GDK_KEY_Zcaron);
-      else if (symbol == GDK_KEY_aogonek)
-        xupper = GDK_KEY_Aogonek;
-      else if (symbol >= GDK_KEY_lstroke && symbol <= GDK_KEY_sacute)
-        xupper -= (GDK_KEY_lstroke - GDK_KEY_Lstroke);
-      else if (symbol >= GDK_KEY_scaron && symbol <= GDK_KEY_zacute)
-        xupper -= (GDK_KEY_scaron - GDK_KEY_Scaron);
-      else if (symbol >= GDK_KEY_zcaron && symbol <= GDK_KEY_zabovedot)
-        xupper -= (GDK_KEY_zcaron - GDK_KEY_Zcaron);
-      else if (symbol >= GDK_KEY_Racute && symbol <= GDK_KEY_Tcedilla)
-        xlower += (GDK_KEY_racute - GDK_KEY_Racute);
-      else if (symbol >= GDK_KEY_racute && symbol <= GDK_KEY_tcedilla)
-        xupper -= (GDK_KEY_racute - GDK_KEY_Racute);
-      break;
-
-    case 2: /* Latin 3 */
-      /* Assume the KeySym is a legal value (ignore discontinuities) */
-      if (symbol >= GDK_KEY_Hstroke && symbol <= GDK_KEY_Hcircumflex)
-        xlower += (GDK_KEY_hstroke - GDK_KEY_Hstroke);
-      else if (symbol >= GDK_KEY_Gbreve && symbol <= GDK_KEY_Jcircumflex)
-        xlower += (GDK_KEY_gbreve - GDK_KEY_Gbreve);
-      else if (symbol >= GDK_KEY_hstroke && symbol <= GDK_KEY_hcircumflex)
-        xupper -= (GDK_KEY_hstroke - GDK_KEY_Hstroke);
-      else if (symbol >= GDK_KEY_gbreve && symbol <= GDK_KEY_jcircumflex)
-        xupper -= (GDK_KEY_gbreve - GDK_KEY_Gbreve);
-      else if (symbol >= GDK_KEY_Cabovedot && symbol <= GDK_KEY_Scircumflex)
-        xlower += (GDK_KEY_cabovedot - GDK_KEY_Cabovedot);
-      else if (symbol >= GDK_KEY_cabovedot && symbol <= GDK_KEY_scircumflex)
-        xupper -= (GDK_KEY_cabovedot - GDK_KEY_Cabovedot);
-      break;
-
-    case 3: /* Latin 4 */
-      /* Assume the KeySym is a legal value (ignore discontinuities) */
-      if (symbol >= GDK_KEY_Rcedilla && symbol <= GDK_KEY_Tslash)
-        xlower += (GDK_KEY_rcedilla - GDK_KEY_Rcedilla);
-      else if (symbol >= GDK_KEY_rcedilla && symbol <= GDK_KEY_tslash)
-        xupper -= (GDK_KEY_rcedilla - GDK_KEY_Rcedilla);
-      else if (symbol == GDK_KEY_ENG)
-        xlower = GDK_KEY_eng;
-      else if (symbol == GDK_KEY_eng)
-        xupper = GDK_KEY_ENG;
-      else if (symbol >= GDK_KEY_Amacron && symbol <= GDK_KEY_Umacron)
-        xlower += (GDK_KEY_amacron - GDK_KEY_Amacron);
-      else if (symbol >= GDK_KEY_amacron && symbol <= GDK_KEY_umacron)
-        xupper -= (GDK_KEY_amacron - GDK_KEY_Amacron);
-      break;
-
-    case 6: /* Cyrillic */
-      /* Assume the KeySym is a legal value (ignore discontinuities) */
-      if (symbol >= GDK_KEY_Serbian_DJE && symbol <= GDK_KEY_Serbian_DZE)
-        xlower -= (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje);
-      else if (symbol >= GDK_KEY_Serbian_dje && symbol <= GDK_KEY_Serbian_dze)
-        xupper += (GDK_KEY_Serbian_DJE - GDK_KEY_Serbian_dje);
-      else if (symbol >= GDK_KEY_Cyrillic_YU && symbol <= GDK_KEY_Cyrillic_HARDSIGN)
-        xlower -= (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu);
-      else if (symbol >= GDK_KEY_Cyrillic_yu && symbol <= GDK_KEY_Cyrillic_hardsign)
-        xupper += (GDK_KEY_Cyrillic_YU - GDK_KEY_Cyrillic_yu);
-      break;
-
-    case 7: /* Greek */
-      /* Assume the KeySym is a legal value (ignore discontinuities) */
-      if (symbol >= GDK_KEY_Greek_ALPHAaccent && symbol <= GDK_KEY_Greek_OMEGAaccent)
-        xlower += (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent);
-      else if (symbol >= GDK_KEY_Greek_alphaaccent && symbol <= GDK_KEY_Greek_omegaaccent &&
-               symbol != GDK_KEY_Greek_iotaaccentdieresis &&
-               symbol != GDK_KEY_Greek_upsilonaccentdieresis)
-        xupper -= (GDK_KEY_Greek_alphaaccent - GDK_KEY_Greek_ALPHAaccent);
-      else if (symbol >= GDK_KEY_Greek_ALPHA && symbol <= GDK_KEY_Greek_OMEGA)
-        xlower += (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA);
-      else if (symbol >= GDK_KEY_Greek_alpha && symbol <= GDK_KEY_Greek_omega &&
-               symbol != GDK_KEY_Greek_finalsmallsigma)
-        xupper -= (GDK_KEY_Greek_alpha - GDK_KEY_Greek_ALPHA);
-      break;
-    }
-
-  if (lower)
-    *lower = xlower;
-  if (upper)
-    *upper = xupper;
-}
-#endif
+#endif /* HAVE_XCONVERTCASE */
 
 gint
 _gdk_x11_get_group_for_state (GdkDisplay      *display,
                               GdkModifierType  state)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
 
 #ifdef HAVE_XKB
   if (display_x11->use_xkb)
@@ -1605,7 +1445,7 @@ _gdk_x11_get_group_for_state (GdkDisplay      *display,
   else
 #endif
     {
-      GdkKeymapX11 *keymap_impl = GDK_KEYMAP_X11 (gdk_keymap_get_for_display (display));
+      GdkX11Keymap *keymap_impl = GDK_X11_KEYMAP (gdk_keymap_get_for_display (display));
       update_keymaps (keymap_impl);
       return (state & keymap_impl->group_switch_mask) ? 1 : 0;
     }
@@ -1615,19 +1455,15 @@ void
 _gdk_x11_keymap_add_virt_mods (GdkKeymap       *keymap,
                                GdkModifierType *modifiers)
 {
-  GdkKeymapX11 *keymap_x11;
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
   int i;
 
-  keymap = GET_EFFECTIVE_KEYMAP (keymap);
-  keymap_x11 = GDK_KEYMAP_X11 (keymap);
-
-  for (i = 3; i < 8; i++)
+  /* See comment in add_virtual_modifiers() */
+  for (i = 4; i < 8; i++)
     {
       if ((1 << i) & *modifiers)
         {
-          if (keymap_x11->modmap[i] & GDK_MOD1_MASK)
-            *modifiers |= GDK_MOD1_MASK;
-          else if (keymap_x11->modmap[i] & GDK_SUPER_MASK)
+          if (keymap_x11->modmap[i] & GDK_SUPER_MASK)
             *modifiers |= GDK_SUPER_MASK;
           else if (keymap_x11->modmap[i] & GDK_HYPER_MASK)
             *modifiers |= GDK_HYPER_MASK;
@@ -1641,18 +1477,19 @@ static void
 gdk_x11_keymap_add_virtual_modifiers (GdkKeymap       *keymap,
                                       GdkModifierType *state)
 {
-  GdkKeymapX11 *keymap_x11;
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
   int i;
 
-  keymap = GET_EFFECTIVE_KEYMAP (keymap);
-  keymap_x11 = GDK_KEYMAP_X11 (keymap);
-
-  for (i = 3; i < 8; i++)
+  /*  This loop used to start at 3, which included MOD1 in the
+   *  virtual mapping. However, all of GTK+ treats MOD1 as a
+   *  synonym for Alt, and does not expect it to be mapped around,
+   *  therefore it's more sane to simply treat MOD1 like SHIFT and
+   *  CONTROL, which are not mappable either.
+   */
+  for (i = 4; i < 8; i++)
     {
       if ((1 << i) & *state)
         {
-          if (keymap_x11->modmap[i] & GDK_MOD1_MASK)
-            *state |= GDK_MOD1_MASK;
           if (keymap_x11->modmap[i] & GDK_SUPER_MASK)
             *state |= GDK_SUPER_MASK;
           if (keymap_x11->modmap[i] & GDK_HYPER_MASK)
@@ -1667,12 +1504,10 @@ gboolean
 _gdk_x11_keymap_key_is_modifier (GdkKeymap *keymap,
                                  guint      keycode)
 {
-  GdkKeymapX11 *keymap_x11;
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
   gint i;
 
-  keymap = GET_EFFECTIVE_KEYMAP (keymap);
-  keymap_x11 = GDK_KEYMAP_X11 (keymap);
-
+  update_keyrange (keymap_x11);
   if (keycode < keymap_x11->min_keycode ||
       keycode > keymap_x11->max_keycode)
     return FALSE;
@@ -1702,16 +1537,11 @@ static gboolean
 gdk_x11_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
                                       GdkModifierType *state)
 {
-  GdkKeymapX11 *keymap_x11;
-  const guint vmods[] = {
-    GDK_SUPER_MASK, GDK_HYPER_MASK, GDK_META_MASK
-  };
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
+  const guint vmods[] = { GDK_SUPER_MASK, GDK_HYPER_MASK, GDK_META_MASK };
   int i, j;
   gboolean retval;
 
-  keymap = GET_EFFECTIVE_KEYMAP (keymap);
-  keymap_x11 = GDK_KEYMAP_X11 (keymap);
-
   if (KEYMAP_USE_XKB (keymap))
     get_xkb (keymap_x11);
 
@@ -1721,7 +1551,8 @@ gdk_x11_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
     {
       if (*state & vmods[j])
         {
-          for (i = 3; i < 8; i++)
+          /* See comment in add_virtual_modifiers() */
+          for (i = 4; i < 8; i++)
             {
               if (keymap_x11->modmap[i] & vmods[j])
                 {
@@ -1737,24 +1568,41 @@ gdk_x11_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
   return retval;
 }
 
+static GdkModifierType
+gdk_x11_keymap_get_modifier_mask (GdkKeymap         *keymap,
+                                  GdkModifierIntent  intent)
+{
+  GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
+
+  switch (intent)
+    {
+    case GDK_MODIFIER_INTENT_SHIFT_GROUP:
+      return keymap_x11->group_switch_mask;
+
+    default:
+      return GDK_KEYMAP_CLASS (gdk_x11_keymap_parent_class)->get_modifier_mask (keymap,
+                                                                                intent);
+    }
+}
+
 static void
-gdk_keymap_x11_class_init (GdkKeymapX11Class *klass)
+gdk_x11_keymap_class_init (GdkX11KeymapClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
 
-  parent_class = g_type_class_peek_parent (klass);
-
-  object_class->finalize = gdk_keymap_x11_finalize;
+  object_class->finalize = gdk_x11_keymap_finalize;
 
   keymap_class->get_direction = gdk_x11_keymap_get_direction;
   keymap_class->have_bidi_layouts = gdk_x11_keymap_have_bidi_layouts;
   keymap_class->get_caps_lock_state = gdk_x11_keymap_get_caps_lock_state;
   keymap_class->get_num_lock_state = gdk_x11_keymap_get_num_lock_state;
+  keymap_class->get_modifier_state = gdk_x11_keymap_get_modifier_state;
   keymap_class->get_entries_for_keyval = gdk_x11_keymap_get_entries_for_keyval;
   keymap_class->get_entries_for_keycode = gdk_x11_keymap_get_entries_for_keycode;
   keymap_class->lookup_key = gdk_x11_keymap_lookup_key;
   keymap_class->translate_keyboard_state = gdk_x11_keymap_translate_keyboard_state;
   keymap_class->add_virtual_modifiers = gdk_x11_keymap_add_virtual_modifiers;
   keymap_class->map_virtual_modifiers = gdk_x11_keymap_map_virtual_modifiers;
+  keymap_class->get_modifier_mask = gdk_x11_keymap_get_modifier_mask;
 }