]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkkeys-x11.c
ef2fefc733bf8b461eaff48c6f7a1c2a0c3a6d6c
[~andy/gtk] / gdk / x11 / gdkkeys-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2000 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25  */
26
27 #include "config.h"
28
29 #include "gdkx11keys.h"
30 #include "gdkkeysprivate.h"
31 #include "gdkkeysyms.h"
32 #include "gdkprivate-x11.h"
33 #include "gdkdisplay-x11.h"
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <limits.h>
40 #include <errno.h>
41
42 #ifdef HAVE_XKB
43 #include <X11/XKBlib.h>
44
45 /* OSF-4.0 is apparently missing this macro
46  */
47 #  ifndef XkbKeySymEntry
48 #    define XkbKeySymEntry(d,k,sl,g) \
49         (XkbKeySym(d,k,((XkbKeyGroupsWidth(d,k)*(g))+(sl))))
50 #  endif
51 #endif /* HAVE_XKB */
52
53 typedef struct _DirectionCacheEntry DirectionCacheEntry;
54
55 struct _DirectionCacheEntry
56 {
57   guint serial;
58   Atom group_atom;
59   PangoDirection direction;
60 };
61
62 struct _GdkX11Keymap
63 {
64   GdkKeymap     parent_instance;
65
66   gint min_keycode;
67   gint max_keycode;
68   KeySym* keymap;
69   gint keysyms_per_keycode;
70   XModifierKeymap* mod_keymap;
71   guint lock_keysym;
72   GdkModifierType group_switch_mask;
73   GdkModifierType num_lock_mask;
74   GdkModifierType modmap[8];
75   PangoDirection current_direction;
76   guint sun_keypad      : 1;
77   guint have_direction  : 1;
78   guint have_lock_state : 1;
79   guint caps_lock_state : 1;
80   guint num_lock_state : 1;
81   guint current_serial;
82
83 #ifdef HAVE_XKB
84   XkbDescPtr xkb_desc;
85   /* We cache the directions */
86   Atom current_group_atom;
87   guint current_cache_serial;
88   /* A cache of size four should be more than enough, people usually
89    * have two groups around, and the xkb limit is four.  It still
90    * works correct for more than four groups.  It's just the
91    * cache.
92    */
93   DirectionCacheEntry group_direction_cache[4];
94 #endif
95 };
96
97 struct _GdkX11KeymapClass
98 {
99   GdkKeymapClass parent_class;
100 };
101
102 #define KEYMAP_USE_XKB(keymap) GDK_X11_DISPLAY ((keymap)->display)->use_xkb
103 #define KEYMAP_XDISPLAY(keymap) GDK_DISPLAY_XDISPLAY ((keymap)->display)
104
105 G_DEFINE_TYPE (GdkX11Keymap, gdk_x11_keymap, GDK_TYPE_KEYMAP)
106
107 static void
108 gdk_x11_keymap_init (GdkX11Keymap *keymap)
109 {
110   keymap->min_keycode = 0;
111   keymap->max_keycode = 0;
112
113   keymap->keymap = NULL;
114   keymap->keysyms_per_keycode = 0;
115   keymap->mod_keymap = NULL;
116
117   keymap->num_lock_mask = 0;
118   keymap->sun_keypad = FALSE;
119   keymap->group_switch_mask = 0;
120   keymap->lock_keysym = GDK_KEY_Caps_Lock;
121   keymap->have_direction = FALSE;
122   keymap->have_lock_state = FALSE;
123   keymap->current_serial = 0;
124
125 #ifdef HAVE_XKB
126   keymap->xkb_desc = NULL;
127   keymap->current_group_atom = 0;
128   keymap->current_cache_serial = 0;
129 #endif
130
131 }
132
133 static void
134 gdk_x11_keymap_finalize (GObject *object)
135 {
136   GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (object);
137
138   if (keymap_x11->keymap)
139     XFree (keymap_x11->keymap);
140
141   if (keymap_x11->mod_keymap)
142     XFreeModifiermap (keymap_x11->mod_keymap);
143
144 #ifdef HAVE_XKB
145   if (keymap_x11->xkb_desc)
146     XkbFreeKeyboard (keymap_x11->xkb_desc, XkbAllComponentsMask, True);
147 #endif
148
149   G_OBJECT_CLASS (gdk_x11_keymap_parent_class)->finalize (object);
150 }
151
152 static inline void
153 update_keyrange (GdkX11Keymap *keymap_x11)
154 {
155   if (keymap_x11->max_keycode == 0)
156     XDisplayKeycodes (KEYMAP_XDISPLAY (GDK_KEYMAP (keymap_x11)),
157                       &keymap_x11->min_keycode, &keymap_x11->max_keycode);
158 }
159
160 #ifdef HAVE_XKB
161
162 static void
163 update_modmap (Display      *display,
164                GdkX11Keymap *keymap_x11)
165 {
166   static struct {
167     const gchar *name;
168     Atom atom;
169     GdkModifierType mask;
170   } vmods[] = {
171     { "Meta", 0, GDK_META_MASK },
172     { "Super", 0, GDK_SUPER_MASK },
173     { "Hyper", 0, GDK_HYPER_MASK },
174     { NULL, 0, 0 }
175   };
176
177   gint i, j, k;
178
179   if (!vmods[0].atom)
180     for (i = 0; vmods[i].name; i++)
181       vmods[i].atom = XInternAtom (display, vmods[i].name, FALSE);
182
183   for (i = 0; i < 8; i++)
184     keymap_x11->modmap[i] = 1 << i;
185
186   for (i = 0; i < XkbNumVirtualMods; i++)
187     {
188       for (j = 0; vmods[j].atom; j++)
189         {
190           if (keymap_x11->xkb_desc->names->vmods[i] == vmods[j].atom)
191             {
192               for (k = 0; k < 8; k++)
193                 {
194                   if (keymap_x11->xkb_desc->server->vmods[i] & (1 << k))
195                     keymap_x11->modmap[k] |= vmods[j].mask;
196                 }
197             }
198         }
199     }
200 }
201
202 static XkbDescPtr
203 get_xkb (GdkX11Keymap *keymap_x11)
204 {
205   GdkX11Display *display_x11 = GDK_X11_DISPLAY (GDK_KEYMAP (keymap_x11)->display);
206   Display *xdisplay = display_x11->xdisplay;
207
208   update_keyrange (keymap_x11);
209
210   if (keymap_x11->xkb_desc == NULL)
211     {
212       keymap_x11->xkb_desc = XkbGetMap (xdisplay, XkbKeySymsMask | XkbKeyTypesMask | XkbModifierMapMask | XkbVirtualModsMask, XkbUseCoreKbd);
213       if (keymap_x11->xkb_desc == NULL)
214         {
215           g_error ("Failed to get keymap");
216           return NULL;
217         }
218
219       XkbGetNames (xdisplay, XkbGroupNamesMask | XkbVirtualModNamesMask, keymap_x11->xkb_desc);
220
221       update_modmap (xdisplay, keymap_x11);
222     }
223   else if (keymap_x11->current_serial != display_x11->keymap_serial)
224     {
225       XkbGetUpdatedMap (xdisplay, XkbKeySymsMask | XkbKeyTypesMask | XkbModifierMapMask | XkbVirtualModsMask,
226                         keymap_x11->xkb_desc);
227       XkbGetNames (xdisplay, XkbGroupNamesMask | XkbVirtualModNamesMask, keymap_x11->xkb_desc);
228
229       update_modmap (xdisplay, keymap_x11);
230     }
231
232   keymap_x11->current_serial = display_x11->keymap_serial;
233
234   if (keymap_x11->num_lock_mask == 0)
235     keymap_x11->num_lock_mask = XkbKeysymToModifiers (KEYMAP_XDISPLAY (GDK_KEYMAP (keymap_x11)), GDK_KEY_Num_Lock);
236
237   return keymap_x11->xkb_desc;
238 }
239 #endif /* HAVE_XKB */
240
241 /* Whether we were able to turn on detectable-autorepeat using
242  * XkbSetDetectableAutorepeat. If FALSE, we'll fall back
243  * to checking the next event with XPending().
244  */
245
246 /* Find the index of the group/level pair within the keysyms for a key.
247  * We round up the number of keysyms per keycode to the next even number,
248  * otherwise we lose a whole group of keys
249  */
250 #define KEYSYM_INDEX(keymap_impl, group, level) \
251   (2 * ((group) % (gint)((keymap_impl->keysyms_per_keycode + 1) / 2)) + (level))
252 #define KEYSYM_IS_KEYPAD(s) (((s) >= 0xff80 && (s) <= 0xffbd) || \
253                              ((s) >= 0x11000000 && (s) <= 0x1100ffff))
254
255 static gint
256 get_symbol (const KeySym *syms,
257             GdkX11Keymap *keymap_x11,
258             gint          group,
259             gint          level)
260 {
261   gint index;
262
263   index = KEYSYM_INDEX(keymap_x11, group, level);
264   if (index >= keymap_x11->keysyms_per_keycode)
265       return NoSymbol;
266
267   return syms[index];
268 }
269
270 static void
271 set_symbol (KeySym       *syms,
272             GdkX11Keymap *keymap_x11,
273             gint          group,
274             gint          level,
275             KeySym        sym)
276 {
277   gint index;
278
279   index = KEYSYM_INDEX(keymap_x11, group, level);
280   if (index >= keymap_x11->keysyms_per_keycode)
281       return;
282
283   syms[index] = sym;
284 }
285
286 static void
287 update_keymaps (GdkX11Keymap *keymap_x11)
288 {
289   GdkX11Display *display_x11 = GDK_X11_DISPLAY (GDK_KEYMAP (keymap_x11)->display);
290   Display *xdisplay = display_x11->xdisplay;
291
292 #ifdef HAVE_XKB
293   g_assert (!KEYMAP_USE_XKB (GDK_KEYMAP (keymap_x11)));
294 #endif
295
296   if (keymap_x11->keymap == NULL ||
297       keymap_x11->current_serial != display_x11->keymap_serial)
298     {
299       gint i;
300       gint map_size;
301       gint keycode;
302
303       keymap_x11->current_serial = display_x11->keymap_serial;
304
305       update_keyrange (keymap_x11);
306
307       if (keymap_x11->keymap)
308         XFree (keymap_x11->keymap);
309
310       if (keymap_x11->mod_keymap)
311         XFreeModifiermap (keymap_x11->mod_keymap);
312
313       keymap_x11->keymap = XGetKeyboardMapping (xdisplay, keymap_x11->min_keycode,
314                                                 keymap_x11->max_keycode - keymap_x11->min_keycode + 1,
315                                                 &keymap_x11->keysyms_per_keycode);
316
317
318       /* GDK_KEY_ISO_Left_Tab, as usually configured through XKB, really messes
319        * up the whole idea of "consumed modifiers" because shift is consumed.
320        * However, <shift>Tab is not usually GDK_KEY_ISO_Left_Tab without XKB,
321        * we we fudge the map here.
322        */
323       keycode = keymap_x11->min_keycode;
324       while (keycode <= keymap_x11->max_keycode)
325         {
326           KeySym *syms = keymap_x11->keymap + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
327           /* Check both groups */
328           for (i = 0 ; i < 2 ; i++)
329             {
330               if (get_symbol (syms, keymap_x11, i, 0) == GDK_KEY_Tab)
331                 set_symbol (syms, keymap_x11, i, 1, GDK_KEY_ISO_Left_Tab);
332             }
333
334           /*
335            * If there is one keysym and the key symbol has upper and lower
336            * case variants fudge the keymap
337            */
338           if (get_symbol (syms, keymap_x11, 0, 1) == 0)
339             {
340               guint lower;
341               guint upper;
342
343               gdk_keyval_convert_case (get_symbol (syms, keymap_x11, 0, 0), &lower, &upper);
344               if (lower != upper)
345                 {
346                   set_symbol (syms, keymap_x11, 0, 0, lower);
347                   set_symbol (syms, keymap_x11, 0, 1, upper);
348                 }
349             }
350
351           ++keycode;
352         }
353
354       keymap_x11->mod_keymap = XGetModifierMapping (xdisplay);
355
356       keymap_x11->lock_keysym = GDK_KEY_VoidSymbol;
357       keymap_x11->group_switch_mask = 0;
358       keymap_x11->num_lock_mask = 0;
359
360       for (i = 0; i < 8; i++)
361         keymap_x11->modmap[i] = 1 << i;
362
363       /* There are 8 sets of modifiers, with each set containing
364        * max_keypermod keycodes.
365        */
366       map_size = 8 * keymap_x11->mod_keymap->max_keypermod;
367       for (i = 0; i < map_size; i++)
368         {
369           /* Get the key code at this point in the map. */
370           gint keycode = keymap_x11->mod_keymap->modifiermap[i];
371           gint j;
372           KeySym *syms;
373           guint mask;
374
375           /* Ignore invalid keycodes. */
376           if (keycode < keymap_x11->min_keycode ||
377               keycode > keymap_x11->max_keycode)
378             continue;
379
380           syms = keymap_x11->keymap + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
381
382           mask = 0;
383           for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
384             {
385               if (syms[j] == GDK_KEY_Meta_L ||
386                   syms[j] == GDK_KEY_Meta_R)
387                 mask |= GDK_META_MASK;
388               else if (syms[j] == GDK_KEY_Hyper_L ||
389                        syms[j] == GDK_KEY_Hyper_R)
390                 mask |= GDK_HYPER_MASK;
391               else if (syms[j] == GDK_KEY_Super_L ||
392                        syms[j] == GDK_KEY_Super_R)
393                 mask |= GDK_SUPER_MASK;
394             }
395
396           keymap_x11->modmap[i/keymap_x11->mod_keymap->max_keypermod] |= mask;
397
398           /* The fourth modifier, GDK_MOD1_MASK is 1 << 3.
399            * Each group of max_keypermod entries refers to the same modifier.
400            */
401           mask = 1 << (i / keymap_x11->mod_keymap->max_keypermod);
402
403           switch (mask)
404             {
405             case GDK_LOCK_MASK:
406               /* Get the Lock keysym.  If any keysym bound to the Lock modifier
407                * is Caps_Lock, we will interpret the modifier as Caps_Lock;
408                * otherwise, if any is bound to Shift_Lock, we will interpret
409                * the modifier as Shift_Lock. Otherwise, the lock modifier
410                * has no effect.
411                */
412               for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
413                 {
414                   if (syms[j] == GDK_KEY_Caps_Lock)
415                     keymap_x11->lock_keysym = GDK_KEY_Caps_Lock;
416                   else if (syms[j] == GDK_KEY_Shift_Lock &&
417                            keymap_x11->lock_keysym == GDK_KEY_VoidSymbol)
418                     keymap_x11->lock_keysym = GDK_KEY_Shift_Lock;
419                 }
420               break;
421
422             case GDK_CONTROL_MASK:
423             case GDK_SHIFT_MASK:
424             case GDK_MOD1_MASK:
425               /* Some keyboard maps are known to map Mode_Switch as an
426                * extra Mod1 key. In circumstances like that, it won't be
427                * used to switch groups.
428                */
429               break;
430
431             default:
432               /* Find the Mode_Switch and Num_Lock modifiers. */
433               for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
434                 {
435                   if (syms[j] == GDK_KEY_Mode_switch)
436                     {
437                       /* This modifier swaps groups */
438                       keymap_x11->group_switch_mask |= mask;
439                     }
440                   else if (syms[j] == GDK_KEY_Num_Lock)
441                     {
442                       /* This modifier is used for Num_Lock */
443                       keymap_x11->num_lock_mask |= mask;
444                     }
445                 }
446               break;
447             }
448         }
449
450       /* Hack: The Sun X server puts the keysym to use when the Num Lock
451        * modifier is on in the third element of the keysym array, instead
452        * of the second.
453        */
454       if ((strcmp (ServerVendor (xdisplay), "Sun Microsystems, Inc.") == 0) &&
455           (keymap_x11->keysyms_per_keycode > 2))
456         keymap_x11->sun_keypad = TRUE;
457       else
458         keymap_x11->sun_keypad = FALSE;
459     }
460 }
461
462 static const KeySym*
463 get_keymap (GdkX11Keymap *keymap_x11)
464 {
465   update_keymaps (keymap_x11);
466
467   return keymap_x11->keymap;
468 }
469
470 #define GET_EFFECTIVE_KEYMAP(keymap) get_effective_keymap ((keymap), G_STRFUNC)
471
472 static GdkKeymap *
473 get_effective_keymap (GdkKeymap  *keymap,
474                       const char *function)
475 {
476   if (!keymap)
477     {
478       GDK_NOTE (MULTIHEAD,
479                 g_message ("reverting to default display keymap in %s",
480                            function));
481       return gdk_keymap_get_default ();
482     }
483
484   return keymap;
485 }
486
487 #ifdef HAVE_XKB
488 static PangoDirection
489 get_direction (XkbDescRec *xkb,
490                gint        group)
491 {
492   gint code;
493
494   gint rtl_minus_ltr = 0; /* total number of RTL keysyms minus LTR ones */
495
496   for (code = xkb->min_key_code; code <= xkb->max_key_code; code++)
497     {
498       gint level = 0;
499       KeySym sym = XkbKeySymEntry (xkb, code, level, group);
500       PangoDirection dir = pango_unichar_direction (gdk_keyval_to_unicode (sym));
501
502       switch (dir)
503         {
504         case PANGO_DIRECTION_RTL:
505           rtl_minus_ltr++;
506           break;
507         case PANGO_DIRECTION_LTR:
508           rtl_minus_ltr--;
509           break;
510         default:
511           break;
512         }
513     }
514
515   if (rtl_minus_ltr > 0)
516     return PANGO_DIRECTION_RTL;
517   else
518     return PANGO_DIRECTION_LTR;
519 }
520
521 static PangoDirection
522 get_direction_from_cache (GdkX11Keymap *keymap_x11,
523                           XkbDescPtr    xkb,
524                           gint          group)
525 {
526   Atom group_atom = xkb->names->groups[group];
527
528   gboolean cache_hit = FALSE;
529   DirectionCacheEntry *cache = keymap_x11->group_direction_cache;
530
531   PangoDirection direction = PANGO_DIRECTION_NEUTRAL;
532   gint i;
533
534   if (keymap_x11->have_direction)
535     {
536       /* lookup in cache */
537       for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
538       {
539         if (cache[i].group_atom == group_atom)
540           {
541             cache_hit = TRUE;
542             cache[i].serial = keymap_x11->current_cache_serial++; /* freshen */
543             direction = cache[i].direction;
544             group_atom = cache[i].group_atom;
545             break;
546           }
547       }
548     }
549   else
550     {
551       /* initialize cache */
552       for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
553         {
554           cache[i].group_atom = 0;
555           cache[i].serial = keymap_x11->current_cache_serial;
556         }
557       keymap_x11->current_cache_serial++;
558     }
559
560   /* insert in cache */
561   if (!cache_hit)
562     {
563       gint oldest = 0;
564
565       direction = get_direction (xkb, group);
566
567       /* remove the oldest entry */
568       for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
569         {
570           if (cache[i].serial < cache[oldest].serial)
571             oldest = i;
572         }
573
574       cache[oldest].group_atom = group_atom;
575       cache[oldest].direction = direction;
576       cache[oldest].serial = keymap_x11->current_cache_serial++;
577     }
578
579   return direction;
580 }
581
582 static int
583 get_num_groups (GdkKeymap *keymap,
584                 XkbDescPtr xkb)
585 {
586       Display *display = KEYMAP_XDISPLAY (keymap);
587       XkbGetControls(display, XkbSlowKeysMask, xkb);
588       XkbGetUpdatedMap (display, XkbKeySymsMask | XkbKeyTypesMask |
589                         XkbModifierMapMask | XkbVirtualModsMask, xkb);
590       return xkb->ctrls->num_groups;
591 }
592
593 static gboolean
594 update_direction (GdkX11Keymap *keymap_x11,
595                   gint          group)
596 {
597   XkbDescPtr xkb = get_xkb (keymap_x11);
598   Atom group_atom;
599   gboolean had_direction;
600   PangoDirection old_direction;
601
602   had_direction = keymap_x11->have_direction;
603   old_direction = keymap_x11->current_direction;
604
605   group_atom = xkb->names->groups[group];
606
607   /* a group change? */
608   if (!keymap_x11->have_direction || keymap_x11->current_group_atom != group_atom)
609     {
610       keymap_x11->current_direction = get_direction_from_cache (keymap_x11, xkb, group);
611       keymap_x11->current_group_atom = group_atom;
612       keymap_x11->have_direction = TRUE;
613     }
614
615   return !had_direction || old_direction != keymap_x11->current_direction;
616 }
617
618 static gboolean
619 update_lock_state (GdkX11Keymap *keymap_x11,
620                    gint          locked_mods)
621 {
622   XkbDescPtr xkb G_GNUC_UNUSED;
623   gboolean have_lock_state;
624   gboolean caps_lock_state;
625   gboolean num_lock_state;
626
627   /* ensure keymap_x11->num_lock_mask is initialized */
628   xkb = get_xkb (keymap_x11);
629
630   have_lock_state = keymap_x11->have_lock_state;
631   caps_lock_state = keymap_x11->caps_lock_state;
632   num_lock_state = keymap_x11->num_lock_state;
633
634   keymap_x11->have_lock_state = TRUE;
635   keymap_x11->caps_lock_state = (locked_mods & GDK_LOCK_MASK) != 0;
636   keymap_x11->num_lock_state = (locked_mods & keymap_x11->num_lock_mask) != 0;
637
638   return !have_lock_state
639          || (caps_lock_state != keymap_x11->caps_lock_state)
640          || (num_lock_state != keymap_x11->num_lock_state);
641 }
642
643 /* keep this in sync with the XkbSelectEventDetails()
644  * call in gdk_display_open()
645  */
646 void
647 _gdk_x11_keymap_state_changed (GdkDisplay *display,
648                                XEvent     *xevent)
649 {
650   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
651   XkbEvent *xkb_event = (XkbEvent *)xevent;
652
653   if (display_x11->keymap)
654     {
655       GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (display_x11->keymap);
656
657       if (update_direction (keymap_x11, XkbStateGroup (&xkb_event->state)))
658         g_signal_emit_by_name (keymap_x11, "direction-changed");
659
660       if (update_lock_state (keymap_x11, xkb_event->state.locked_mods))
661         g_signal_emit_by_name (keymap_x11, "state-changed");
662     }
663 }
664
665 #endif /* HAVE_XKB */
666
667 static void
668 ensure_lock_state (GdkKeymap *keymap)
669 {
670 #ifdef HAVE_XKB
671   if (KEYMAP_USE_XKB (keymap))
672     {
673       GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
674
675       if (!keymap_x11->have_lock_state)
676         {
677           GdkDisplay *display = keymap->display;
678           XkbStateRec state_rec;
679
680           XkbGetState (GDK_DISPLAY_XDISPLAY (display), XkbUseCoreKbd, &state_rec);
681           update_lock_state (keymap_x11, state_rec.locked_mods);
682         }
683     }
684 #endif /* HAVE_XKB */
685 }
686
687 void
688 _gdk_x11_keymap_keys_changed (GdkDisplay *display)
689 {
690   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
691
692   ++display_x11->keymap_serial;
693
694   if (display_x11->keymap)
695     g_signal_emit_by_name (display_x11->keymap, "keys_changed", 0);
696 }
697
698 static PangoDirection
699 gdk_x11_keymap_get_direction (GdkKeymap *keymap)
700 {
701   keymap = GET_EFFECTIVE_KEYMAP (keymap);
702
703 #ifdef HAVE_XKB
704   if (KEYMAP_USE_XKB (keymap))
705     {
706       GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
707
708       if (!keymap_x11->have_direction)
709         {
710           GdkDisplay *display = keymap->display;
711           XkbStateRec state_rec;
712
713           XkbGetState (GDK_DISPLAY_XDISPLAY (display), XkbUseCoreKbd,
714                        &state_rec);
715           update_direction (keymap_x11, XkbStateGroup (&state_rec));
716         }
717
718       return keymap_x11->current_direction;
719     }
720   else
721 #endif /* HAVE_XKB */
722     return PANGO_DIRECTION_NEUTRAL;
723 }
724
725 static gboolean
726 gdk_x11_keymap_have_bidi_layouts (GdkKeymap *keymap)
727 {
728   keymap = GET_EFFECTIVE_KEYMAP (keymap);
729
730 #ifdef HAVE_XKB
731   if (KEYMAP_USE_XKB (keymap))
732     {
733       GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
734       XkbDescPtr xkb = get_xkb (keymap_x11);
735       int num_groups = get_num_groups (keymap, xkb);
736
737       int i;
738       gboolean have_ltr_keyboard = FALSE;
739       gboolean have_rtl_keyboard = FALSE;
740
741       for (i = 0; i < num_groups; i++)
742       {
743         if (get_direction_from_cache (keymap_x11, xkb, i) == PANGO_DIRECTION_RTL)
744           have_rtl_keyboard = TRUE;
745         else
746           have_ltr_keyboard = TRUE;
747       }
748
749       return have_ltr_keyboard && have_rtl_keyboard;
750     }
751   else
752 #endif /* HAVE_XKB */
753     return FALSE;
754 }
755
756 static gboolean
757 gdk_x11_keymap_get_caps_lock_state (GdkKeymap *keymap)
758 {
759   keymap = GET_EFFECTIVE_KEYMAP (keymap);
760
761   ensure_lock_state (keymap);
762
763   return GDK_X11_KEYMAP (keymap)->caps_lock_state;
764 }
765
766 static gboolean
767 gdk_x11_keymap_get_num_lock_state (GdkKeymap *keymap)
768 {
769   keymap = GET_EFFECTIVE_KEYMAP (keymap);
770
771   ensure_lock_state (keymap);
772
773   return GDK_X11_KEYMAP (keymap)->num_lock_state;
774 }
775
776 static gboolean
777 gdk_x11_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
778                                        guint          keyval,
779                                        GdkKeymapKey **keys,
780                                        gint          *n_keys)
781 {
782   GArray *retval;
783   GdkX11Keymap *keymap_x11;
784
785   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
786   g_return_val_if_fail (keys != NULL, FALSE);
787   g_return_val_if_fail (n_keys != NULL, FALSE);
788   g_return_val_if_fail (keyval != 0, FALSE);
789
790   keymap = GET_EFFECTIVE_KEYMAP (keymap);
791   keymap_x11 = GDK_X11_KEYMAP (keymap);
792
793   retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
794
795 #ifdef HAVE_XKB
796   if (KEYMAP_USE_XKB (keymap))
797     {
798       /* See sec 15.3.4 in XKB docs */
799
800       XkbDescRec *xkb = get_xkb (keymap_x11);
801       gint keycode;
802
803       keycode = keymap_x11->min_keycode;
804
805       while (keycode <= keymap_x11->max_keycode)
806         {
807           gint max_shift_levels = XkbKeyGroupsWidth (xkb, keycode); /* "key width" */
808           gint group = 0;
809           gint level = 0;
810           gint total_syms = XkbKeyNumSyms (xkb, keycode);
811           gint i = 0;
812           KeySym *entry;
813
814           /* entry is an array with all syms for group 0, all
815            * syms for group 1, etc. and for each group the
816            * shift level syms are in order
817            */
818           entry = XkbKeySymsPtr (xkb, keycode);
819
820           while (i < total_syms)
821             {
822               /* check out our cool loop invariant */
823               g_assert (i == (group * max_shift_levels + level));
824
825               if (entry[i] == keyval)
826                 {
827                   /* Found a match */
828                   GdkKeymapKey key;
829
830                   key.keycode = keycode;
831                   key.group = group;
832                   key.level = level;
833
834                   g_array_append_val (retval, key);
835
836                   g_assert (XkbKeySymEntry (xkb, keycode, level, group) ==
837                             keyval);
838                 }
839
840               ++level;
841
842               if (level == max_shift_levels)
843                 {
844                   level = 0;
845                   ++group;
846                 }
847
848               ++i;
849             }
850
851           ++keycode;
852         }
853     }
854   else
855 #endif
856     {
857       const KeySym *map = get_keymap (keymap_x11);
858       gint keycode;
859
860       keycode = keymap_x11->min_keycode;
861       while (keycode <= keymap_x11->max_keycode)
862         {
863           const KeySym *syms = map + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
864           gint i = 0;
865
866           while (i < keymap_x11->keysyms_per_keycode)
867             {
868               if (syms[i] == keyval)
869                 {
870                   /* found a match */
871                   GdkKeymapKey key;
872
873                   key.keycode = keycode;
874
875                   /* The "classic" non-XKB keymap has 2 levels per group */
876                   key.group = i / 2;
877                   key.level = i % 2;
878
879                   g_array_append_val (retval, key);
880                 }
881
882               ++i;
883             }
884
885           ++keycode;
886         }
887     }
888
889   if (retval->len > 0)
890     {
891       *keys = (GdkKeymapKey*) retval->data;
892       *n_keys = retval->len;
893     }
894   else
895     {
896       *keys = NULL;
897       *n_keys = 0;
898     }
899
900   g_array_free (retval, retval->len > 0 ? FALSE : TRUE);
901
902   return *n_keys > 0;
903 }
904
905 static gboolean
906 gdk_x11_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
907                                         guint          hardware_keycode,
908                                         GdkKeymapKey **keys,
909                                         guint        **keyvals,
910                                         gint          *n_entries)
911 {
912   GdkX11Keymap *keymap_x11;
913
914   GArray *key_array;
915   GArray *keyval_array;
916
917   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
918   g_return_val_if_fail (n_entries != NULL, FALSE);
919
920   keymap = GET_EFFECTIVE_KEYMAP (keymap);
921   keymap_x11 = GDK_X11_KEYMAP (keymap);
922
923   update_keyrange (keymap_x11);
924
925   if (hardware_keycode < keymap_x11->min_keycode ||
926       hardware_keycode > keymap_x11->max_keycode)
927     {
928       if (keys)
929         *keys = NULL;
930       if (keyvals)
931         *keyvals = NULL;
932
933       *n_entries = 0;
934       return FALSE;
935     }
936
937   if (keys)
938     key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
939   else
940     key_array = NULL;
941
942   if (keyvals)
943     keyval_array = g_array_new (FALSE, FALSE, sizeof (guint));
944   else
945     keyval_array = NULL;
946
947 #ifdef HAVE_XKB
948   if (KEYMAP_USE_XKB (keymap))
949     {
950       /* See sec 15.3.4 in XKB docs */
951
952       XkbDescRec *xkb = get_xkb (keymap_x11);
953       gint max_shift_levels;
954       gint group = 0;
955       gint level = 0;
956       gint total_syms;
957       gint i = 0;
958       KeySym *entry;
959
960       max_shift_levels = XkbKeyGroupsWidth (xkb, hardware_keycode); /* "key width" */
961       total_syms = XkbKeyNumSyms (xkb, hardware_keycode);
962
963       /* entry is an array with all syms for group 0, all
964        * syms for group 1, etc. and for each group the
965        * shift level syms are in order
966        */
967       entry = XkbKeySymsPtr (xkb, hardware_keycode);
968
969       while (i < total_syms)
970         {
971           /* check out our cool loop invariant */
972           g_assert (i == (group * max_shift_levels + level));
973
974           if (key_array)
975             {
976               GdkKeymapKey key;
977
978               key.keycode = hardware_keycode;
979               key.group = group;
980               key.level = level;
981
982               g_array_append_val (key_array, key);
983             }
984
985           if (keyval_array)
986             g_array_append_val (keyval_array, entry[i]);
987
988           ++level;
989
990           if (level == max_shift_levels)
991             {
992               level = 0;
993               ++group;
994             }
995
996           ++i;
997         }
998     }
999   else
1000 #endif
1001     {
1002       const KeySym *map = get_keymap (keymap_x11);
1003       const KeySym *syms;
1004       gint i = 0;
1005
1006       syms = map + (hardware_keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
1007
1008       while (i < keymap_x11->keysyms_per_keycode)
1009         {
1010           if (key_array)
1011             {
1012               GdkKeymapKey key;
1013
1014               key.keycode = hardware_keycode;
1015
1016               /* The "classic" non-XKB keymap has 2 levels per group */
1017               key.group = i / 2;
1018               key.level = i % 2;
1019
1020               g_array_append_val (key_array, key);
1021             }
1022
1023           if (keyval_array)
1024             g_array_append_val (keyval_array, syms[i]);
1025
1026           ++i;
1027         }
1028     }
1029
1030   *n_entries = 0;
1031
1032   if (keys)
1033     {
1034       *n_entries = key_array->len;
1035       *keys = (GdkKeymapKey*) g_array_free (key_array, FALSE);
1036     }
1037
1038   if (keyvals)
1039     {
1040       *n_entries = keyval_array->len;
1041       *keyvals = (guint*) g_array_free (keyval_array, FALSE);
1042     }
1043
1044   return *n_entries > 0;
1045 }
1046
1047 static guint
1048 gdk_x11_keymap_lookup_key (GdkKeymap          *keymap,
1049                            const GdkKeymapKey *key)
1050 {
1051   GdkX11Keymap *keymap_x11;
1052
1053   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
1054   g_return_val_if_fail (key != NULL, 0);
1055   g_return_val_if_fail (key->group < 4, 0);
1056
1057   keymap = GET_EFFECTIVE_KEYMAP (keymap);
1058   keymap_x11 = GDK_X11_KEYMAP (keymap);
1059
1060 #ifdef HAVE_XKB
1061   if (KEYMAP_USE_XKB (keymap))
1062     {
1063       XkbDescRec *xkb = get_xkb (keymap_x11);
1064
1065       return XkbKeySymEntry (xkb, key->keycode, key->level, key->group);
1066     }
1067   else
1068 #endif
1069     {
1070       const KeySym *map = get_keymap (keymap_x11);
1071       const KeySym *syms = map + (key->keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
1072       return get_symbol (syms, keymap_x11, key->group, key->level);
1073     }
1074 }
1075
1076 #ifdef HAVE_XKB
1077 /* This is copied straight from XFree86 Xlib, to:
1078  *  - add the group and level return.
1079  *  - change the interpretation of mods_rtrn as described
1080  *    in the docs for gdk_keymap_translate_keyboard_state()
1081  * It's unchanged for ease of diff against the Xlib sources; don't
1082  * reformat it.
1083  */
1084 static Bool
1085 MyEnhancedXkbTranslateKeyCode(register XkbDescPtr     xkb,
1086                               KeyCode                 key,
1087                               register unsigned int   mods,
1088                               unsigned int *          mods_rtrn,
1089                               KeySym *                keysym_rtrn,
1090                               int *                   group_rtrn,
1091                               int *                   level_rtrn)
1092 {
1093     XkbKeyTypeRec *type;
1094     int col,nKeyGroups;
1095     unsigned preserve,effectiveGroup;
1096     KeySym *syms;
1097
1098     if (mods_rtrn!=NULL)
1099         *mods_rtrn = 0;
1100
1101     nKeyGroups= XkbKeyNumGroups(xkb,key);
1102     if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
1103         if (keysym_rtrn!=NULL)
1104             *keysym_rtrn = NoSymbol;
1105         return False;
1106     }
1107
1108     syms = XkbKeySymsPtr(xkb,key);
1109
1110     /* find the offset of the effective group */
1111     col = 0;
1112     effectiveGroup= XkbGroupForCoreState(mods);
1113     if ( effectiveGroup>=nKeyGroups ) {
1114         unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
1115         switch (XkbOutOfRangeGroupAction(groupInfo)) {
1116             default:
1117                 effectiveGroup %= nKeyGroups;
1118                 break;
1119             case XkbClampIntoRange:
1120                 effectiveGroup = nKeyGroups-1;
1121                 break;
1122             case XkbRedirectIntoRange:
1123                 effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
1124                 if (effectiveGroup>=nKeyGroups)
1125                     effectiveGroup= 0;
1126                 break;
1127         }
1128     }
1129     col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
1130     type = XkbKeyKeyType(xkb,key,effectiveGroup);
1131
1132     preserve= 0;
1133     if (type->map) { /* find the column (shift level) within the group */
1134         register int i;
1135         register XkbKTMapEntryPtr entry;
1136         /* ---- Begin section modified for GDK  ---- */
1137         int found = 0;
1138
1139         for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
1140             if (mods_rtrn) {
1141                 int bits = 0;
1142                 unsigned long tmp = entry->mods.mask;
1143                 while (tmp) {
1144                     if ((tmp & 1) == 1)
1145                         bits++;
1146                     tmp >>= 1;
1147                 }
1148                 /* We always add one-modifiers levels to mods_rtrn since
1149                  * they can't wipe out bits in the state unless the
1150                  * level would be triggered. But return other modifiers
1151                  *
1152                  */
1153                 if (bits == 1 || (mods&type->mods.mask)==entry->mods.mask)
1154                     *mods_rtrn |= entry->mods.mask;
1155             }
1156
1157             if (!found&&entry->active&&((mods&type->mods.mask)==entry->mods.mask)) {
1158                 col+= entry->level;
1159                 if (type->preserve)
1160                     preserve= type->preserve[i].mask;
1161
1162                 if (level_rtrn)
1163                   *level_rtrn = entry->level;
1164
1165                 found = 1;
1166             }
1167         }
1168         /* ---- End section modified for GDK ---- */
1169     }
1170
1171     if (keysym_rtrn!=NULL)
1172         *keysym_rtrn= syms[col];
1173     if (mods_rtrn) {
1174         /* ---- Begin section modified for GDK  ---- */
1175         *mods_rtrn &= ~preserve;
1176         /* ---- End section modified for GDK ---- */
1177
1178         /* ---- Begin stuff GDK comments out of the original Xlib version ---- */
1179         /* This is commented out because xkb_info is a private struct */
1180
1181 #if 0
1182         /* The Motif VTS doesn't get the help callback called if help
1183          * is bound to Shift+<whatever>, and it appears as though it
1184          * is XkbTranslateKeyCode that is causing the problem.  The
1185          * core X version of XTranslateKey always OR's in ShiftMask
1186          * and LockMask for mods_rtrn, so this "fix" keeps this behavior
1187          * and solves the VTS problem.
1188          */
1189         if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
1190             (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) {            *mods_rtrn|= (ShiftMask|LockMask);
1191         }
1192 #endif
1193
1194         /* ---- End stuff GDK comments out of the original Xlib version ---- */
1195     }
1196
1197     /* ---- Begin stuff GDK adds to the original Xlib version ---- */
1198
1199     if (group_rtrn)
1200       *group_rtrn = effectiveGroup;
1201
1202     /* ---- End stuff GDK adds to the original Xlib version ---- */
1203
1204     return (syms[col] != NoSymbol);
1205 }
1206 #endif /* HAVE_XKB */
1207
1208 /* Translates from keycode/state to keysymbol using the traditional interpretation
1209  * of the keyboard map. See section 12.7 of the Xlib reference manual
1210  */
1211 static guint
1212 translate_keysym (GdkX11Keymap   *keymap_x11,
1213                   guint           hardware_keycode,
1214                   gint            group,
1215                   GdkModifierType state,
1216                   gint           *effective_group,
1217                   gint           *effective_level)
1218 {
1219   const KeySym *map = get_keymap (keymap_x11);
1220   const KeySym *syms = map + (hardware_keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
1221
1222 #define SYM(k,g,l) get_symbol (syms, k,g,l)
1223
1224   GdkModifierType shift_modifiers;
1225   gint shift_level;
1226   guint tmp_keyval;
1227   gint num_lock_index;
1228
1229   shift_modifiers = GDK_SHIFT_MASK;
1230   if (keymap_x11->lock_keysym == GDK_KEY_Shift_Lock)
1231     shift_modifiers |= GDK_LOCK_MASK;
1232
1233   /* Fall back to the first group if the passed in group is empty
1234    */
1235   if (!(SYM (keymap_x11, group, 0) || SYM (keymap_x11, group, 1)) &&
1236       (SYM (keymap_x11, 0, 0) || SYM (keymap_x11, 0, 1)))
1237     group = 0;
1238
1239   /* Hack: On Sun, the Num Lock modifier uses the third element in the
1240    * keysym array, and Mode_Switch does not apply for a keypad key.
1241    */
1242   if (keymap_x11->sun_keypad)
1243     {
1244       num_lock_index = 2;
1245
1246       if (group != 0)
1247         {
1248           gint i;
1249
1250           for (i = 0; i < keymap_x11->keysyms_per_keycode; i++)
1251             if (KEYSYM_IS_KEYPAD (SYM (keymap_x11, 0, i)))
1252               group = 0;
1253         }
1254     }
1255   else
1256     num_lock_index = 1;
1257
1258   if ((state & keymap_x11->num_lock_mask) &&
1259       KEYSYM_IS_KEYPAD (SYM (keymap_x11, group, num_lock_index)))
1260     {
1261       /* Shift, Shift_Lock cancel Num_Lock
1262        */
1263       shift_level = (state & shift_modifiers) ? 0 : num_lock_index;
1264       if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, group, 0))
1265         shift_level = 0;
1266
1267        tmp_keyval = SYM (keymap_x11, group, shift_level);
1268     }
1269   else
1270     {
1271       /* Fall back to the first level if no symbol for the level
1272        * we were passed.
1273        */
1274       shift_level = (state & shift_modifiers) ? 1 : 0;
1275       if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, group, 0))
1276         shift_level = 0;
1277
1278       tmp_keyval = SYM (keymap_x11, group, shift_level);
1279
1280       if (keymap_x11->lock_keysym == GDK_KEY_Caps_Lock && (state & GDK_LOCK_MASK) != 0)
1281         {
1282           guint upper = gdk_keyval_to_upper (tmp_keyval);
1283           if (upper != tmp_keyval)
1284             tmp_keyval = upper;
1285         }
1286     }
1287
1288   if (effective_group)
1289     *effective_group = group;
1290
1291   if (effective_level)
1292     *effective_level = shift_level;
1293
1294   return tmp_keyval;
1295
1296 #undef SYM
1297 }
1298
1299 static gboolean
1300 gdk_x11_keymap_translate_keyboard_state (GdkKeymap       *keymap,
1301                                          guint            hardware_keycode,
1302                                          GdkModifierType  state,
1303                                          gint             group,
1304                                          guint           *keyval,
1305                                          gint            *effective_group,
1306                                          gint            *level,
1307                                          GdkModifierType *consumed_modifiers)
1308 {
1309   GdkX11Keymap *keymap_x11;
1310   KeySym tmp_keyval = NoSymbol;
1311   guint tmp_modifiers;
1312
1313   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
1314   g_return_val_if_fail (group < 4, FALSE);
1315
1316   keymap = GET_EFFECTIVE_KEYMAP (keymap);
1317   keymap_x11 = GDK_X11_KEYMAP (keymap);
1318
1319   if (keyval)
1320     *keyval = NoSymbol;
1321   if (effective_group)
1322     *effective_group = 0;
1323   if (level)
1324     *level = 0;
1325   if (consumed_modifiers)
1326     *consumed_modifiers = 0;
1327
1328   update_keyrange (keymap_x11);
1329
1330   if (hardware_keycode < keymap_x11->min_keycode ||
1331       hardware_keycode > keymap_x11->max_keycode)
1332     return FALSE;
1333
1334 #ifdef HAVE_XKB
1335   if (KEYMAP_USE_XKB (keymap))
1336     {
1337       XkbDescRec *xkb = get_xkb (keymap_x11);
1338
1339       /* replace bits 13 and 14 with the provided group */
1340       state &= ~(1 << 13 | 1 << 14);
1341       state |= group << 13;
1342
1343       MyEnhancedXkbTranslateKeyCode (xkb,
1344                                      hardware_keycode,
1345                                      state,
1346                                      &tmp_modifiers,
1347                                      &tmp_keyval,
1348                                      effective_group,
1349                                      level);
1350
1351       if (state & ~tmp_modifiers & LockMask)
1352         tmp_keyval = gdk_keyval_to_upper (tmp_keyval);
1353
1354       /* We need to augment the consumed modifiers with LockMask, since
1355        * we handle that ourselves, and also with the group bits
1356        */
1357       tmp_modifiers |= LockMask | 1 << 13 | 1 << 14;
1358     }
1359   else
1360 #endif
1361     {
1362       GdkModifierType bit;
1363
1364       tmp_modifiers = 0;
1365
1366       /* We see what modifiers matter by trying the translation with
1367        * and without each possible modifier
1368        */
1369       for (bit = GDK_SHIFT_MASK; bit < GDK_BUTTON1_MASK; bit <<= 1)
1370         {
1371           /* Handling of the group here is a bit funky; a traditional
1372            * X keyboard map can have more than two groups, but no way
1373            * of accessing the extra groups is defined. We allow a
1374            * caller to pass in any group to this function, but we
1375            * only can represent switching between group 0 and 1 in
1376            * consumed modifiers.
1377            */
1378           if (translate_keysym (keymap_x11, hardware_keycode,
1379                                 (bit == keymap_x11->group_switch_mask) ? 0 : group,
1380                                 state & ~bit,
1381                                 NULL, NULL) !=
1382               translate_keysym (keymap_x11, hardware_keycode,
1383                                 (bit == keymap_x11->group_switch_mask) ? 1 : group,
1384                                 state | bit,
1385                                 NULL, NULL))
1386             tmp_modifiers |= bit;
1387         }
1388
1389       tmp_keyval = translate_keysym (keymap_x11, hardware_keycode,
1390                                      group, state,
1391                                      level, effective_group);
1392     }
1393
1394   if (consumed_modifiers)
1395     *consumed_modifiers = tmp_modifiers;
1396
1397   if (keyval)
1398     *keyval = tmp_keyval;
1399
1400   return tmp_keyval != NoSymbol;
1401 }
1402
1403 /* Key handling not part of the keymap */
1404 gchar*
1405 _gdk_x11_display_manager_get_keyval_name (GdkDisplayManager *manager,
1406                                           guint              keyval)
1407 {
1408   switch (keyval)
1409     {
1410     case GDK_KEY_Page_Up:
1411       return "Page_Up";
1412     case GDK_KEY_Page_Down:
1413       return "Page_Down";
1414     case GDK_KEY_KP_Page_Up:
1415       return "KP_Page_Up";
1416     case GDK_KEY_KP_Page_Down:
1417       return "KP_Page_Down";
1418     }
1419
1420   return XKeysymToString (keyval);
1421 }
1422
1423 guint
1424 _gdk_x11_display_manager_lookup_keyval (GdkDisplayManager *manager,
1425                                         const gchar       *keyval_name)
1426 {
1427   g_return_val_if_fail (keyval_name != NULL, 0);
1428
1429   return XStringToKeysym (keyval_name);
1430 }
1431
1432 #ifdef HAVE_XCONVERTCASE
1433 void
1434 _gdk_x11_display_manager_keyval_convert_case (GdkDisplayManager *manager,
1435                                               guint              symbol,
1436                                               guint             *lower,
1437                                               guint             *upper)
1438 {
1439   KeySym xlower = 0;
1440   KeySym xupper = 0;
1441
1442   /* Check for directly encoded 24-bit UCS characters: */
1443   if ((symbol & 0xff000000) == 0x01000000)
1444     {
1445       if (lower)
1446         *lower = gdk_unicode_to_keyval (g_unichar_tolower (symbol & 0x00ffffff));
1447       if (upper)
1448         *upper = gdk_unicode_to_keyval (g_unichar_toupper (symbol & 0x00ffffff));
1449       return;
1450     }
1451
1452   if (symbol)
1453     XConvertCase (symbol, &xlower, &xupper);
1454
1455   if (lower)
1456     *lower = xlower;
1457   if (upper)
1458     *upper = xupper;
1459 }
1460 #endif /* HAVE_XCONVERTCASE */
1461
1462 gint
1463 _gdk_x11_get_group_for_state (GdkDisplay      *display,
1464                               GdkModifierType  state)
1465 {
1466   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
1467
1468 #ifdef HAVE_XKB
1469   if (display_x11->use_xkb)
1470     {
1471       return XkbGroupForCoreState (state);
1472     }
1473   else
1474 #endif
1475     {
1476       GdkX11Keymap *keymap_impl = GDK_X11_KEYMAP (gdk_keymap_get_for_display (display));
1477       update_keymaps (keymap_impl);
1478       return (state & keymap_impl->group_switch_mask) ? 1 : 0;
1479     }
1480 }
1481
1482 void
1483 _gdk_x11_keymap_add_virt_mods (GdkKeymap       *keymap,
1484                                GdkModifierType *modifiers)
1485 {
1486   GdkX11Keymap *keymap_x11;
1487   int i;
1488
1489   keymap = GET_EFFECTIVE_KEYMAP (keymap);
1490   keymap_x11 = GDK_X11_KEYMAP (keymap);
1491
1492   /* See comment in add_virtual_modifiers() */
1493   for (i = 4; i < 8; i++)
1494     {
1495       if ((1 << i) & *modifiers)
1496         {
1497           if (keymap_x11->modmap[i] & GDK_SUPER_MASK)
1498             *modifiers |= GDK_SUPER_MASK;
1499           else if (keymap_x11->modmap[i] & GDK_HYPER_MASK)
1500             *modifiers |= GDK_HYPER_MASK;
1501           else if (keymap_x11->modmap[i] & GDK_META_MASK)
1502             *modifiers |= GDK_META_MASK;
1503         }
1504     }
1505 }
1506
1507 static void
1508 gdk_x11_keymap_add_virtual_modifiers (GdkKeymap       *keymap,
1509                                       GdkModifierType *state)
1510 {
1511   GdkX11Keymap *keymap_x11;
1512   int i;
1513
1514   keymap = GET_EFFECTIVE_KEYMAP (keymap);
1515   keymap_x11 = GDK_X11_KEYMAP (keymap);
1516
1517   /*  This loop used to start at 3, which included MOD1 in the
1518    *  virtual mapping. However, all of GTK+ treats MOD1 as a
1519    *  synonym for Alt, and does not expect it to be mapped around,
1520    *  therefore it's more sane to simply treat MOD1 like SHIFT and
1521    *  CONTROL, which are not mappable either.
1522    */
1523   for (i = 4; i < 8; i++)
1524     {
1525       if ((1 << i) & *state)
1526         {
1527           if (keymap_x11->modmap[i] & GDK_SUPER_MASK)
1528             *state |= GDK_SUPER_MASK;
1529           if (keymap_x11->modmap[i] & GDK_HYPER_MASK)
1530             *state |= GDK_HYPER_MASK;
1531           if (keymap_x11->modmap[i] & GDK_META_MASK)
1532             *state |= GDK_META_MASK;
1533         }
1534     }
1535 }
1536
1537 gboolean
1538 _gdk_x11_keymap_key_is_modifier (GdkKeymap *keymap,
1539                                  guint      keycode)
1540 {
1541   GdkX11Keymap *keymap_x11;
1542   gint i;
1543
1544   keymap = GET_EFFECTIVE_KEYMAP (keymap);
1545   keymap_x11 = GDK_X11_KEYMAP (keymap);
1546
1547   if (keycode < keymap_x11->min_keycode ||
1548       keycode > keymap_x11->max_keycode)
1549     return FALSE;
1550
1551 #ifdef HAVE_XKB
1552   if (KEYMAP_USE_XKB (keymap))
1553     {
1554       XkbDescRec *xkb = get_xkb (keymap_x11);
1555
1556       if (xkb->map->modmap && xkb->map->modmap[keycode] != 0)
1557         return TRUE;
1558     }
1559   else
1560 #endif
1561     {
1562       for (i = 0; i < 8 * keymap_x11->mod_keymap->max_keypermod; i++)
1563         {
1564           if (keycode == keymap_x11->mod_keymap->modifiermap[i])
1565             return TRUE;
1566         }
1567     }
1568
1569   return FALSE;
1570 }
1571
1572 static gboolean
1573 gdk_x11_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
1574                                       GdkModifierType *state)
1575 {
1576   GdkX11Keymap *keymap_x11;
1577   const guint vmods[] = {
1578     GDK_SUPER_MASK, GDK_HYPER_MASK, GDK_META_MASK
1579   };
1580   int i, j;
1581   gboolean retval;
1582
1583   keymap = GET_EFFECTIVE_KEYMAP (keymap);
1584   keymap_x11 = GDK_X11_KEYMAP (keymap);
1585
1586   if (KEYMAP_USE_XKB (keymap))
1587     get_xkb (keymap_x11);
1588
1589   retval = TRUE;
1590
1591   for (j = 0; j < 3; j++)
1592     {
1593       if (*state & vmods[j])
1594         {
1595           /* See comment in add_virtual_modifiers() */
1596           for (i = 4; i < 8; i++)
1597             {
1598               if (keymap_x11->modmap[i] & vmods[j])
1599                 {
1600                   if (*state & (1 << i))
1601                     retval = FALSE;
1602                   else
1603                     *state |= 1 << i;
1604                 }
1605             }
1606         }
1607     }
1608
1609   return retval;
1610 }
1611
1612 static GdkModifierType
1613 gdk_x11_keymap_get_modifier_mask (GdkKeymap         *keymap,
1614                                   GdkModifierIntent  intent)
1615 {
1616   GdkX11Keymap *keymap_x11 = GDK_X11_KEYMAP (keymap);
1617
1618   switch (intent)
1619     {
1620     case GDK_MODIFIER_INTENT_SHIFT_GROUP:
1621       return keymap_x11->group_switch_mask;
1622
1623     default:
1624       return GDK_KEYMAP_CLASS (gdk_x11_keymap_parent_class)->get_modifier_mask (keymap,
1625                                                                                 intent);
1626     }
1627 }
1628
1629 static void
1630 gdk_x11_keymap_class_init (GdkX11KeymapClass *klass)
1631 {
1632   GObjectClass *object_class = G_OBJECT_CLASS (klass);
1633   GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
1634
1635   object_class->finalize = gdk_x11_keymap_finalize;
1636
1637   keymap_class->get_direction = gdk_x11_keymap_get_direction;
1638   keymap_class->have_bidi_layouts = gdk_x11_keymap_have_bidi_layouts;
1639   keymap_class->get_caps_lock_state = gdk_x11_keymap_get_caps_lock_state;
1640   keymap_class->get_num_lock_state = gdk_x11_keymap_get_num_lock_state;
1641   keymap_class->get_entries_for_keyval = gdk_x11_keymap_get_entries_for_keyval;
1642   keymap_class->get_entries_for_keycode = gdk_x11_keymap_get_entries_for_keycode;
1643   keymap_class->lookup_key = gdk_x11_keymap_lookup_key;
1644   keymap_class->translate_keyboard_state = gdk_x11_keymap_translate_keyboard_state;
1645   keymap_class->add_virtual_modifiers = gdk_x11_keymap_add_virtual_modifiers;
1646   keymap_class->map_virtual_modifiers = gdk_x11_keymap_map_virtual_modifiers;
1647   keymap_class->get_modifier_mask = gdk_x11_keymap_get_modifier_mask;
1648 }