]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkkeys-x11.c
Merge branch 'master' into treeview-refactor
[~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 "gdkx.h"
30 #include "gdkprivate-x11.h"
31 #include "gdkinternals.h"
32 #include "gdkdisplay-x11.h"
33 #include "gdkkeysyms.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 _GdkKeymapX11   GdkKeymapX11;
54 typedef struct _GdkKeymapClass GdkKeymapX11Class;
55
56 #define GDK_TYPE_KEYMAP_X11          (gdk_keymap_x11_get_type ())
57 #define GDK_KEYMAP_X11(object)       (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_KEYMAP_X11, GdkKeymapX11))
58 #define GDK_IS_KEYMAP_X11(object)    (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_KEYMAP_X11))
59
60 typedef struct _DirectionCacheEntry DirectionCacheEntry;
61
62 struct _DirectionCacheEntry
63 {
64   guint serial;
65   Atom group_atom;
66   PangoDirection direction;
67 };
68
69 struct _GdkKeymapX11
70 {
71   GdkKeymap     parent_instance;
72
73   gint min_keycode;
74   gint max_keycode;
75   KeySym* keymap;
76   gint keysyms_per_keycode;
77   XModifierKeymap* mod_keymap;
78   guint lock_keysym;
79   GdkModifierType group_switch_mask;
80   GdkModifierType num_lock_mask;
81   GdkModifierType modmap[8];
82   PangoDirection current_direction;
83   guint sun_keypad      : 1;
84   guint have_direction  : 1;
85   guint caps_lock_state : 1;
86   guint num_lock_state : 1;
87   guint current_serial;
88
89 #ifdef HAVE_XKB
90   XkbDescPtr xkb_desc;
91   /* We cache the directions */
92   Atom current_group_atom;
93   guint current_cache_serial;
94   /* A cache of size four should be more than enough, people usually
95    * have two groups around, and the xkb limit is four.  It still
96    * works correct for more than four groups.  It's just the
97    * cache.
98    */
99   DirectionCacheEntry group_direction_cache[4];
100 #endif
101 };
102
103 #define KEYMAP_USE_XKB(keymap) GDK_DISPLAY_X11 ((keymap)->display)->use_xkb
104 #define KEYMAP_XDISPLAY(keymap) GDK_DISPLAY_XDISPLAY ((keymap)->display)
105
106 static GType gdk_keymap_x11_get_type   (void);
107 static void  gdk_keymap_x11_class_init (GdkKeymapX11Class *klass);
108 static void  gdk_keymap_x11_init       (GdkKeymapX11      *keymap);
109 static void  gdk_keymap_x11_finalize   (GObject           *object);
110
111 static GdkKeymapClass *parent_class = NULL;
112
113 static GType
114 gdk_keymap_x11_get_type (void)
115 {
116   static GType object_type = 0;
117
118   if (!object_type)
119     {
120       const GTypeInfo object_info =
121         {
122           sizeof (GdkKeymapClass),
123           (GBaseInitFunc) NULL,
124           (GBaseFinalizeFunc) NULL,
125           (GClassInitFunc) gdk_keymap_x11_class_init,
126           NULL,           /* class_finalize */
127           NULL,           /* class_data */
128           sizeof (GdkKeymapX11),
129           0,              /* n_preallocs */
130           (GInstanceInitFunc) gdk_keymap_x11_init,
131         };
132       
133       object_type = g_type_register_static (GDK_TYPE_KEYMAP,
134                                             g_intern_static_string ("GdkKeymapX11"),
135                                             &object_info, 0);
136     }
137   
138   return object_type;
139 }
140
141 static void
142 gdk_keymap_x11_class_init (GdkKeymapX11Class *klass)
143 {
144   GObjectClass *object_class = G_OBJECT_CLASS (klass);
145
146   parent_class = g_type_class_peek_parent (klass);
147
148   object_class->finalize = gdk_keymap_x11_finalize;
149 }
150
151 static void
152 gdk_keymap_x11_init (GdkKeymapX11 *keymap)
153 {
154   keymap->min_keycode = 0;
155   keymap->max_keycode = 0;
156
157   keymap->keymap = NULL;
158   keymap->keysyms_per_keycode = 0;
159   keymap->mod_keymap = NULL;
160   
161   keymap->num_lock_mask = 0;
162   keymap->sun_keypad = FALSE;
163   keymap->group_switch_mask = 0;
164   keymap->lock_keysym = GDK_KEY_Caps_Lock;
165   keymap->have_direction = FALSE;
166   keymap->current_serial = 0;
167
168 #ifdef HAVE_XKB
169   keymap->xkb_desc = NULL;
170   keymap->current_group_atom = 0;
171   keymap->current_cache_serial = 0;
172 #endif
173
174 }
175
176 static void
177 gdk_keymap_x11_finalize (GObject *object)
178 {
179   GdkKeymapX11 *keymap_x11 = GDK_KEYMAP_X11 (object);
180
181   if (keymap_x11->keymap)
182     XFree (keymap_x11->keymap);
183
184   if (keymap_x11->mod_keymap)
185     XFreeModifiermap (keymap_x11->mod_keymap);
186
187 #ifdef HAVE_XKB
188   if (keymap_x11->xkb_desc)
189     XkbFreeKeyboard (keymap_x11->xkb_desc, XkbAllComponentsMask, True);
190 #endif
191
192   G_OBJECT_CLASS (parent_class)->finalize (object);
193 }
194
195 static inline void
196 update_keyrange (GdkKeymapX11 *keymap_x11)
197 {
198   if (keymap_x11->max_keycode == 0)
199     XDisplayKeycodes (KEYMAP_XDISPLAY (GDK_KEYMAP (keymap_x11)),
200                       &keymap_x11->min_keycode, &keymap_x11->max_keycode);
201 }
202
203 #ifdef HAVE_XKB
204
205 static void
206 update_modmap (Display      *display,
207                GdkKeymapX11 *keymap_x11)
208 {
209   static struct {
210     const gchar *name;
211     Atom atom;
212     GdkModifierType mask;
213   } vmods[] = {
214     { "Meta", 0, GDK_META_MASK },
215     { "Super", 0, GDK_SUPER_MASK },
216     { "Hyper", 0, GDK_HYPER_MASK },
217     { NULL, 0, 0 }
218   };
219
220   gint i, j, k;
221
222   if (!vmods[0].atom)
223     for (i = 0; vmods[i].name; i++)
224       vmods[i].atom = XInternAtom (display, vmods[i].name, FALSE);
225
226   for (i = 0; i < 8; i++)
227     keymap_x11->modmap[i] = 1 << i;
228
229   for (i = 0; i < XkbNumVirtualMods; i++)
230     {
231       for (j = 0; vmods[j].atom; j++)
232         {
233           if (keymap_x11->xkb_desc->names->vmods[i] == vmods[j].atom)
234             {
235               for (k = 0; k < 8; k++)
236                 {
237                   if (keymap_x11->xkb_desc->server->vmods[i] & (1 << k))
238                     keymap_x11->modmap[k] |= vmods[j].mask;
239                 }
240             }
241         }
242     }
243 }
244
245 static XkbDescPtr
246 get_xkb (GdkKeymapX11 *keymap_x11)
247 {
248   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_KEYMAP (keymap_x11)->display);
249   Display *xdisplay = display_x11->xdisplay;
250   
251   update_keyrange (keymap_x11);
252   
253   if (keymap_x11->xkb_desc == NULL)
254     {
255       keymap_x11->xkb_desc = XkbGetMap (xdisplay, XkbKeySymsMask | XkbKeyTypesMask | XkbModifierMapMask | XkbVirtualModsMask, XkbUseCoreKbd);
256       if (keymap_x11->xkb_desc == NULL)
257         {
258           g_error ("Failed to get keymap");
259           return NULL;
260         }
261
262       XkbGetNames (xdisplay, XkbGroupNamesMask | XkbVirtualModNamesMask, keymap_x11->xkb_desc);
263
264       update_modmap (xdisplay, keymap_x11);
265     }
266   else if (keymap_x11->current_serial != display_x11->keymap_serial)
267     {
268       XkbGetUpdatedMap (xdisplay, XkbKeySymsMask | XkbKeyTypesMask | XkbModifierMapMask | XkbVirtualModsMask,
269                         keymap_x11->xkb_desc);
270       XkbGetNames (xdisplay, XkbGroupNamesMask | XkbVirtualModNamesMask, keymap_x11->xkb_desc);
271
272       update_modmap (xdisplay, keymap_x11);
273     }
274
275   keymap_x11->current_serial = display_x11->keymap_serial;
276
277   if (keymap_x11->num_lock_mask == 0)
278     keymap_x11->num_lock_mask = XkbKeysymToModifiers (KEYMAP_XDISPLAY (GDK_KEYMAP (keymap_x11)), XK_Num_Lock);
279
280   return keymap_x11->xkb_desc;
281 }
282 #endif /* HAVE_XKB */
283
284 /* Whether we were able to turn on detectable-autorepeat using
285  * XkbSetDetectableAutorepeat. If FALSE, we'll fall back
286  * to checking the next event with XPending().
287  */
288
289 /** 
290  * gdk_keymap_get_for_display:
291  * @display: the #GdkDisplay.
292  *
293  * Returns the #GdkKeymap attached to @display.
294  *
295  * Return value: (transfer none): the #GdkKeymap attached to @display.
296  *
297  * Since: 2.2
298  **/
299 GdkKeymap*
300 gdk_keymap_get_for_display (GdkDisplay *display)
301 {
302   GdkDisplayX11 *display_x11;
303   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
304   display_x11 = GDK_DISPLAY_X11 (display);
305   
306   if (!display_x11->keymap)
307     display_x11->keymap = g_object_new (gdk_keymap_x11_get_type (), NULL);
308
309   display_x11->keymap->display = display;
310
311   return display_x11->keymap;
312 }
313
314 /* Find the index of the group/level pair within the keysyms for a key.
315  * We round up the number of keysyms per keycode to the next even number,
316  * otherwise we lose a whole group of keys
317  */
318 #define KEYSYM_INDEX(keymap_impl, group, level) \
319   (2 * ((group) % (gint)((keymap_impl->keysyms_per_keycode + 1) / 2)) + (level))
320 #define KEYSYM_IS_KEYPAD(s) (((s) >= 0xff80 && (s) <= 0xffbd) || \
321                              ((s) >= 0x11000000 && (s) <= 0x1100ffff))
322
323 static gint
324 get_symbol (const KeySym *syms,
325             GdkKeymapX11 *keymap_x11,
326             gint group,
327             gint level)
328 {
329   gint index;
330
331   index = KEYSYM_INDEX(keymap_x11, group, level);
332   if (index >= keymap_x11->keysyms_per_keycode)
333       return NoSymbol;
334
335   return syms[index];
336 }
337
338 static void
339 set_symbol (KeySym       *syms, 
340             GdkKeymapX11 *keymap_x11, 
341             gint          group, 
342             gint          level, 
343             KeySym        sym)
344 {
345   gint index;
346
347   index = KEYSYM_INDEX(keymap_x11, group, level);
348   if (index >= keymap_x11->keysyms_per_keycode)
349       return;
350
351   syms[index] = sym;
352 }
353
354 static void
355 update_keymaps (GdkKeymapX11 *keymap_x11)
356 {
357   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_KEYMAP (keymap_x11)->display);
358   Display *xdisplay = display_x11->xdisplay;
359   
360 #ifdef HAVE_XKB
361   g_assert (!KEYMAP_USE_XKB (GDK_KEYMAP (keymap_x11)));
362 #endif
363   
364   if (keymap_x11->keymap == NULL ||
365       keymap_x11->current_serial != display_x11->keymap_serial)
366     {
367       gint i;
368       gint map_size;
369       gint keycode;
370
371       keymap_x11->current_serial = display_x11->keymap_serial;
372       
373       update_keyrange (keymap_x11);
374       
375       if (keymap_x11->keymap)
376         XFree (keymap_x11->keymap);
377
378       if (keymap_x11->mod_keymap)
379         XFreeModifiermap (keymap_x11->mod_keymap);
380       
381       keymap_x11->keymap = XGetKeyboardMapping (xdisplay, keymap_x11->min_keycode,
382                                                 keymap_x11->max_keycode - keymap_x11->min_keycode + 1,
383                                                 &keymap_x11->keysyms_per_keycode);
384
385
386       /* GDK_KEY_ISO_Left_Tab, as usually configured through XKB, really messes
387        * up the whole idea of "consumed modifiers" because shift is consumed.
388        * However, <shift>Tab is not usually GDK_KEY_ISO_Left_Tab without XKB,
389        * we we fudge the map here.
390        */
391       keycode = keymap_x11->min_keycode;
392       while (keycode <= keymap_x11->max_keycode)
393         {
394           KeySym *syms = keymap_x11->keymap + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
395           /* Check both groups */
396           for (i = 0 ; i < 2 ; i++)
397             {
398               if (get_symbol (syms, keymap_x11, i, 0) == GDK_KEY_Tab)
399                 set_symbol (syms, keymap_x11, i, 1, GDK_KEY_ISO_Left_Tab);
400             }
401
402           /*
403            * If there is one keysym and the key symbol has upper and lower
404            * case variants fudge the keymap
405            */
406           if (get_symbol (syms, keymap_x11, 0, 1) == 0)
407             {
408               guint lower;
409               guint upper;
410
411               gdk_keyval_convert_case (get_symbol (syms, keymap_x11, 0, 0), &lower, &upper);
412               if (lower != upper)
413                 {
414                   set_symbol (syms, keymap_x11, 0, 0, lower);
415                   set_symbol (syms, keymap_x11, 0, 1, upper);
416                 }
417             }
418       
419           
420           ++keycode;
421         }
422
423       keymap_x11->mod_keymap = XGetModifierMapping (xdisplay);
424
425       keymap_x11->lock_keysym = GDK_KEY_VoidSymbol;
426       keymap_x11->group_switch_mask = 0;
427       keymap_x11->num_lock_mask = 0;
428
429       for (i = 0; i < 8; i++)
430         keymap_x11->modmap[i] = 1 << i;
431       
432       /* There are 8 sets of modifiers, with each set containing
433        * max_keypermod keycodes.
434        */
435       map_size = 8 * keymap_x11->mod_keymap->max_keypermod;
436       for (i = 0; i < map_size; i++)
437         {
438           /* Get the key code at this point in the map. */
439           gint keycode = keymap_x11->mod_keymap->modifiermap[i];
440           gint j;
441           KeySym *syms;
442           guint mask;
443
444           /* Ignore invalid keycodes. */
445           if (keycode < keymap_x11->min_keycode ||
446               keycode > keymap_x11->max_keycode)
447             continue;
448
449           syms = keymap_x11->keymap + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
450
451           mask = 0;
452           for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
453             {
454               if (syms[j] == GDK_KEY_Meta_L ||
455                   syms[j] == GDK_KEY_Meta_R)
456                 mask |= GDK_META_MASK;
457               else if (syms[j] == GDK_KEY_Hyper_L ||
458                        syms[j] == GDK_KEY_Hyper_R)
459                 mask |= GDK_HYPER_MASK;
460               else if (syms[j] == GDK_KEY_Super_L ||
461                        syms[j] == GDK_KEY_Super_R)
462                 mask |= GDK_SUPER_MASK;
463             }
464
465           keymap_x11->modmap[i/keymap_x11->mod_keymap->max_keypermod] |= mask;
466
467           /* The fourth modifier, GDK_MOD1_MASK is 1 << 3.
468            * Each group of max_keypermod entries refers to the same modifier.
469            */
470           mask = 1 << (i / keymap_x11->mod_keymap->max_keypermod);
471
472           switch (mask)
473             {
474             case GDK_LOCK_MASK:
475               /* Get the Lock keysym.  If any keysym bound to the Lock modifier
476                * is Caps_Lock, we will interpret the modifier as Caps_Lock;
477                * otherwise, if any is bound to Shift_Lock, we will interpret
478                * the modifier as Shift_Lock. Otherwise, the lock modifier
479                * has no effect.
480                */
481               for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
482                 {
483                   if (syms[j] == GDK_KEY_Caps_Lock)
484                     keymap_x11->lock_keysym = GDK_KEY_Caps_Lock;
485                   else if (syms[j] == GDK_KEY_Shift_Lock &&
486                            keymap_x11->lock_keysym == GDK_KEY_VoidSymbol)
487                     keymap_x11->lock_keysym = GDK_KEY_Shift_Lock;
488                 }
489               break;
490
491             case GDK_CONTROL_MASK:
492             case GDK_SHIFT_MASK:
493             case GDK_MOD1_MASK:
494               /* Some keyboard maps are known to map Mode_Switch as an
495                * extra Mod1 key. In circumstances like that, it won't be
496                * used to switch groups.
497                */
498               break;
499
500             default:
501               /* Find the Mode_Switch and Num_Lock modifiers. */
502               for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
503                 {
504                   if (syms[j] == GDK_KEY_Mode_switch)
505                     {
506                       /* This modifier swaps groups */
507                       keymap_x11->group_switch_mask |= mask;
508                     }
509                   else if (syms[j] == GDK_KEY_Num_Lock)
510                     {
511                       /* This modifier is used for Num_Lock */
512                       keymap_x11->num_lock_mask |= mask;
513                     }
514                 }
515               break;
516             }
517         }
518
519       /* Hack: The Sun X server puts the keysym to use when the Num Lock
520        * modifier is on in the third element of the keysym array, instead
521        * of the second.
522        */
523       if ((strcmp (ServerVendor (xdisplay), "Sun Microsystems, Inc.") == 0) &&
524           (keymap_x11->keysyms_per_keycode > 2))
525         keymap_x11->sun_keypad = TRUE;
526       else
527         keymap_x11->sun_keypad = FALSE;
528     }
529 }
530
531 static const KeySym*
532 get_keymap (GdkKeymapX11 *keymap_x11)
533 {
534   update_keymaps (keymap_x11);
535   
536   return keymap_x11->keymap;
537 }
538
539 #define GET_EFFECTIVE_KEYMAP(keymap) get_effective_keymap ((keymap), G_STRFUNC)
540
541 static GdkKeymap *
542 get_effective_keymap (GdkKeymap  *keymap,
543                       const char *function)
544 {
545   if (!keymap)
546     {
547       GDK_NOTE (MULTIHEAD,
548                 g_message ("reverting to default display keymap in %s",
549                            function));
550       return gdk_keymap_get_default ();
551     }
552
553   return keymap;
554 }
555
556 #if HAVE_XKB
557 static PangoDirection
558 get_direction (XkbDescRec *xkb, 
559                gint group)
560 {
561   gint code;
562
563   gint rtl_minus_ltr = 0; /* total number of RTL keysyms minus LTR ones */
564
565   for (code = xkb->min_key_code; code <= xkb->max_key_code; code++)
566     {
567       gint level = 0;
568       KeySym sym = XkbKeySymEntry (xkb, code, level, group);
569       PangoDirection dir = pango_unichar_direction (gdk_keyval_to_unicode (sym));
570
571       switch (dir)
572         {
573         case PANGO_DIRECTION_RTL:
574           rtl_minus_ltr++;
575           break;
576         case PANGO_DIRECTION_LTR:
577           rtl_minus_ltr--;
578           break;
579         default:
580           break;
581         }
582     }
583
584   if (rtl_minus_ltr > 0)
585     return PANGO_DIRECTION_RTL;
586   else
587     return PANGO_DIRECTION_LTR;
588 }
589
590 static PangoDirection
591 get_direction_from_cache (GdkKeymapX11 *keymap_x11,
592                           XkbDescPtr xkb,
593                           gint group)
594 {
595   Atom group_atom = xkb->names->groups[group];
596
597   gboolean cache_hit = FALSE;
598   DirectionCacheEntry *cache = keymap_x11->group_direction_cache;
599
600   PangoDirection direction = PANGO_DIRECTION_NEUTRAL;
601   gint i;
602
603   if (keymap_x11->have_direction)
604     {
605       /* lookup in cache */
606       for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
607       {
608         if (cache[i].group_atom == group_atom)
609           {
610             cache_hit = TRUE;
611             cache[i].serial = keymap_x11->current_cache_serial++; /* freshen */
612             direction = cache[i].direction;
613             group_atom = cache[i].group_atom;
614             break;
615           }
616       }
617     }
618   else
619     {
620       /* initialize cache */
621       for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
622         {
623           cache[i].group_atom = 0;
624           cache[i].serial = keymap_x11->current_cache_serial;
625         }
626       keymap_x11->current_cache_serial++;
627     }
628
629   /* insert in cache */
630   if (!cache_hit)
631     {
632       gint oldest = 0;
633
634       direction = get_direction (xkb, group);
635
636       /* remove the oldest entry */
637       for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
638         {
639           if (cache[i].serial < cache[oldest].serial)
640             oldest = i;
641         }
642       
643       cache[oldest].group_atom = group_atom;
644       cache[oldest].direction = direction;
645       cache[oldest].serial = keymap_x11->current_cache_serial++;
646     }
647
648   return direction;
649 }
650
651 static int
652 get_num_groups (GdkKeymap *keymap,
653                 XkbDescPtr xkb)
654 {
655       Display *display = KEYMAP_XDISPLAY (keymap);
656       XkbGetControls(display, XkbSlowKeysMask, xkb);
657       XkbGetUpdatedMap (display, XkbKeySymsMask | XkbKeyTypesMask |
658                         XkbModifierMapMask | XkbVirtualModsMask, xkb);
659       return xkb->ctrls->num_groups;
660 }
661
662 static gboolean
663 update_direction (GdkKeymapX11 *keymap_x11,
664                   gint          group)
665 {
666   XkbDescPtr xkb = get_xkb (keymap_x11);
667   Atom group_atom;
668   gboolean had_direction;
669   PangoDirection old_direction;
670       
671   had_direction = keymap_x11->have_direction;
672   old_direction = keymap_x11->current_direction;
673
674   group_atom = xkb->names->groups[group];
675
676   /* a group change? */
677   if (!keymap_x11->have_direction || keymap_x11->current_group_atom != group_atom)
678     {
679       keymap_x11->current_direction = get_direction_from_cache (keymap_x11, xkb, group);
680       keymap_x11->current_group_atom = group_atom;
681       keymap_x11->have_direction = TRUE;
682     }
683
684   return !had_direction || old_direction != keymap_x11->current_direction;
685 }
686
687 static gboolean
688 update_lock_state (GdkKeymapX11 *keymap_x11,
689                    gint          locked_mods)
690 {
691   gboolean caps_lock_state;
692   gboolean num_lock_state;
693
694   caps_lock_state = keymap_x11->caps_lock_state;
695   num_lock_state = keymap_x11->num_lock_state;
696
697   keymap_x11->caps_lock_state = (locked_mods & GDK_LOCK_MASK) != 0;
698   keymap_x11->num_lock_state = (locked_mods & keymap_x11->num_lock_mask) != 0;
699
700   return (caps_lock_state != keymap_x11->caps_lock_state)
701     || (num_lock_state != keymap_x11->num_lock_state);
702 }
703
704 /* keep this in sync with the XkbSelectEventDetails() call 
705  * in gdk_display_open()
706  */
707 void
708 _gdk_keymap_state_changed (GdkDisplay *display,
709                            XEvent     *xevent)
710 {
711   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
712   XkbEvent *xkb_event = (XkbEvent *)xevent;
713   
714   if (display_x11->keymap)
715     {
716       GdkKeymapX11 *keymap_x11 = GDK_KEYMAP_X11 (display_x11->keymap);
717       
718       if (update_direction (keymap_x11, XkbStateGroup (&xkb_event->state)))
719         g_signal_emit_by_name (keymap_x11, "direction-changed");      
720
721       if (update_lock_state (keymap_x11, xkb_event->state.locked_mods))
722         g_signal_emit_by_name (keymap_x11, "state-changed");
723     }
724 }
725
726 #endif /* HAVE_XKB */
727
728 void
729 _gdk_keymap_keys_changed (GdkDisplay *display)
730 {
731   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
732   
733   ++display_x11->keymap_serial;
734   
735   if (display_x11->keymap)
736     g_signal_emit_by_name (display_x11->keymap, "keys_changed", 0);
737 }
738
739 /** 
740  * gdk_keymap_get_direction:
741  * @keymap: a #GdkKeymap or %NULL to use the default keymap
742  *
743  * Returns the direction of effective layout of the keymap.
744  *
745  * Returns: %PANGO_DIRECTION_LTR or %PANGO_DIRECTION_RTL 
746  *   if it can determine the direction. %PANGO_DIRECTION_NEUTRAL 
747  *   otherwise.
748  **/
749 PangoDirection
750 gdk_keymap_get_direction (GdkKeymap *keymap)
751 {
752   keymap = GET_EFFECTIVE_KEYMAP (keymap);
753   
754 #if HAVE_XKB
755   if (KEYMAP_USE_XKB (keymap))
756     {
757       GdkKeymapX11 *keymap_x11 = GDK_KEYMAP_X11 (keymap);
758
759       if (!keymap_x11->have_direction)
760         {
761           GdkDisplay *display = GDK_KEYMAP (keymap_x11)->display;
762           XkbStateRec state_rec;
763
764           XkbGetState (GDK_DISPLAY_XDISPLAY (display), XkbUseCoreKbd, 
765                        &state_rec);
766           update_direction (keymap_x11, XkbStateGroup (&state_rec));
767         }
768   
769       return keymap_x11->current_direction;
770     }
771   else
772 #endif /* HAVE_XKB */
773     return PANGO_DIRECTION_NEUTRAL;
774 }
775
776 /** 
777  * gdk_keymap_have_bidi_layouts:
778  * @keymap: a #GdkKeymap or %NULL to use the default keymap
779  *
780  * Determines if keyboard layouts for both right-to-left and left-to-right
781  * languages are in use.
782  *
783  * Returns: %TRUE if there are layouts in both directions, %FALSE otherwise
784  *
785  * Since: 2.12
786  **/
787 gboolean
788 gdk_keymap_have_bidi_layouts (GdkKeymap *keymap)
789 {
790   keymap = GET_EFFECTIVE_KEYMAP (keymap);
791
792 #if HAVE_XKB
793   if (KEYMAP_USE_XKB (keymap))
794     {
795       GdkKeymapX11 *keymap_x11 = GDK_KEYMAP_X11 (keymap);
796       XkbDescPtr xkb = get_xkb (keymap_x11);
797       int num_groups = get_num_groups (keymap, xkb);
798
799       int i;
800       gboolean have_ltr_keyboard = FALSE;
801       gboolean have_rtl_keyboard = FALSE;
802
803       for (i = 0; i < num_groups; i++)
804       {
805         if (get_direction_from_cache (keymap_x11, xkb, i) == PANGO_DIRECTION_RTL)
806           have_rtl_keyboard = TRUE;
807         else
808           have_ltr_keyboard = TRUE;
809       }
810
811       return have_ltr_keyboard && have_rtl_keyboard;
812     }
813   else
814 #endif /* HAVE_XKB */
815     return FALSE;
816 }
817
818 /**
819  * gdk_keymap_get_caps_lock_state:
820  * @keymap: a #GdkKeymap
821  *
822  * Returns whether the Caps Lock modifer is locked. 
823  *
824  * Returns: %TRUE if Caps Lock is on
825  *
826  * Since: 2.16
827  */
828 gboolean
829 gdk_keymap_get_caps_lock_state (GdkKeymap *keymap)
830 {
831   GdkKeymapX11 *keymap_x11;
832   
833   keymap = GET_EFFECTIVE_KEYMAP (keymap);
834   
835   keymap_x11 = GDK_KEYMAP_X11 (keymap);
836   
837   return keymap_x11->caps_lock_state;
838 }
839
840 /**
841  * gdk_keymap_get_num_lock_state:
842  * @keymap: a #GdkKeymap
843  *
844  * Returns whether the Num Lock modifer is locked.
845  *
846  * Returns: %TRUE if Num Lock is on
847  *
848  * Since: 3.0
849  */
850 gboolean
851 gdk_keymap_get_num_lock_state (GdkKeymap *keymap)
852 {
853   GdkKeymapX11 *keymap_x11;
854
855   keymap = GET_EFFECTIVE_KEYMAP (keymap);
856
857   keymap_x11 = GDK_KEYMAP_X11 (keymap);
858
859   return keymap_x11->num_lock_state;
860 }
861
862 /**
863  * gdk_keymap_get_entries_for_keyval:
864  * @keymap: (allow-none): a #GdkKeymap, or %NULL to use the default keymap
865  * @keyval: a keyval, such as %GDK_a, %GDK_Up, %GDK_Return, etc.
866  * @keys: (out): return location for an array of #GdkKeymapKey
867  * @n_keys: (out): return location for number of elements in returned array
868  *
869  * Obtains a list of keycode/group/level combinations that will
870  * generate @keyval. Groups and levels are two kinds of keyboard mode;
871  * in general, the level determines whether the top or bottom symbol
872  * on a key is used, and the group determines whether the left or
873  * right symbol is used. On US keyboards, the shift key changes the
874  * keyboard level, and there are no groups. A group switch key might
875  * convert a keyboard between Hebrew to English modes, for example.
876  * #GdkEventKey contains a %group field that indicates the active
877  * keyboard group. The level is computed from the modifier mask.
878  * The returned array should be freed
879  * with g_free().
880  *
881  * Return value: %TRUE if keys were found and returned
882  **/
883 gboolean
884 gdk_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
885                                    guint          keyval,
886                                    GdkKeymapKey **keys,
887                                    gint          *n_keys)
888 {
889   GArray *retval;
890   GdkKeymapX11 *keymap_x11;
891
892   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
893   g_return_val_if_fail (keys != NULL, FALSE);
894   g_return_val_if_fail (n_keys != NULL, FALSE);
895   g_return_val_if_fail (keyval != 0, FALSE);
896
897   keymap = GET_EFFECTIVE_KEYMAP (keymap);
898   keymap_x11 = GDK_KEYMAP_X11 (keymap);
899   
900   retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
901
902 #ifdef HAVE_XKB
903   if (KEYMAP_USE_XKB (keymap))
904     {
905       /* See sec 15.3.4 in XKB docs */
906
907       XkbDescRec *xkb = get_xkb (keymap_x11);
908       gint keycode;
909       
910       keycode = keymap_x11->min_keycode;
911
912       while (keycode <= keymap_x11->max_keycode)
913         {
914           gint max_shift_levels = XkbKeyGroupsWidth (xkb, keycode); /* "key width" */
915           gint group = 0;
916           gint level = 0;
917           gint total_syms = XkbKeyNumSyms (xkb, keycode);
918           gint i = 0;
919           KeySym *entry;
920
921           /* entry is an array with all syms for group 0, all
922            * syms for group 1, etc. and for each group the
923            * shift level syms are in order
924            */
925           entry = XkbKeySymsPtr (xkb, keycode);
926
927           while (i < total_syms)
928             {
929               /* check out our cool loop invariant */
930               g_assert (i == (group * max_shift_levels + level));
931
932               if (entry[i] == keyval)
933                 {
934                   /* Found a match */
935                   GdkKeymapKey key;
936
937                   key.keycode = keycode;
938                   key.group = group;
939                   key.level = level;
940
941                   g_array_append_val (retval, key);
942
943                   g_assert (XkbKeySymEntry (xkb, keycode, level, group) == 
944                             keyval);
945                 }
946
947               ++level;
948
949               if (level == max_shift_levels)
950                 {
951                   level = 0;
952                   ++group;
953                 }
954
955               ++i;
956             }
957
958           ++keycode;
959         }
960     }
961   else
962 #endif
963     {
964       const KeySym *map = get_keymap (keymap_x11);
965       gint keycode;
966       
967       keycode = keymap_x11->min_keycode;
968       while (keycode <= keymap_x11->max_keycode)
969         {
970           const KeySym *syms = map + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
971           gint i = 0;
972
973           while (i < keymap_x11->keysyms_per_keycode)
974             {
975               if (syms[i] == keyval)
976                 {
977                   /* found a match */
978                   GdkKeymapKey key;
979
980                   key.keycode = keycode;
981
982                   /* The "classic" non-XKB keymap has 2 levels per group */
983                   key.group = i / 2;
984                   key.level = i % 2;
985
986                   g_array_append_val (retval, key);
987                 }
988               
989               ++i;
990             }
991           
992           ++keycode;
993         }
994     }
995
996   if (retval->len > 0)
997     {
998       *keys = (GdkKeymapKey*) retval->data;
999       *n_keys = retval->len;
1000     }
1001   else
1002     {
1003       *keys = NULL;
1004       *n_keys = 0;
1005     }
1006       
1007   g_array_free (retval, retval->len > 0 ? FALSE : TRUE);
1008
1009   return *n_keys > 0;
1010 }
1011
1012 /**
1013  * gdk_keymap_get_entries_for_keycode:
1014  * @keymap: (allow-none): a #GdkKeymap or %NULL to use the default keymap
1015  * @hardware_keycode: a keycode
1016  * @keys: (out): return location for array of #GdkKeymapKey, or %NULL
1017  * @keyvals: (out): return location for array of keyvals, or %NULL
1018  * @n_entries: length of @keys and @keyvals
1019  *
1020  * Returns the keyvals bound to @hardware_keycode.
1021  * The Nth #GdkKeymapKey in @keys is bound to the Nth
1022  * keyval in @keyvals. Free the returned arrays with g_free().
1023  * When a keycode is pressed by the user, the keyval from
1024  * this list of entries is selected by considering the effective
1025  * keyboard group and level. See gdk_keymap_translate_keyboard_state().
1026  *
1027  * Returns: %TRUE if there were any entries
1028  **/
1029 gboolean
1030 gdk_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
1031                                     guint          hardware_keycode,
1032                                     GdkKeymapKey **keys,
1033                                     guint        **keyvals,
1034                                     gint          *n_entries)
1035 {
1036   GdkKeymapX11 *keymap_x11;
1037   
1038   GArray *key_array;
1039   GArray *keyval_array;
1040
1041   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
1042   g_return_val_if_fail (n_entries != NULL, FALSE);
1043
1044   keymap = GET_EFFECTIVE_KEYMAP (keymap);
1045   keymap_x11 = GDK_KEYMAP_X11 (keymap);
1046
1047   update_keyrange (keymap_x11);
1048
1049   if (hardware_keycode < keymap_x11->min_keycode ||
1050       hardware_keycode > keymap_x11->max_keycode)
1051     {
1052       if (keys)
1053         *keys = NULL;
1054       if (keyvals)
1055         *keyvals = NULL;
1056
1057       *n_entries = 0;
1058       return FALSE;
1059     }
1060   
1061   if (keys)
1062     key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
1063   else
1064     key_array = NULL;
1065   
1066   if (keyvals)
1067     keyval_array = g_array_new (FALSE, FALSE, sizeof (guint));
1068   else
1069     keyval_array = NULL;
1070   
1071 #ifdef HAVE_XKB
1072   if (KEYMAP_USE_XKB (keymap))
1073     {
1074       /* See sec 15.3.4 in XKB docs */
1075
1076       XkbDescRec *xkb = get_xkb (keymap_x11);
1077       gint max_shift_levels;
1078       gint group = 0;
1079       gint level = 0;
1080       gint total_syms;
1081       gint i = 0;
1082       KeySym *entry;
1083       
1084       max_shift_levels = XkbKeyGroupsWidth (xkb, hardware_keycode); /* "key width" */
1085       total_syms = XkbKeyNumSyms (xkb, hardware_keycode);
1086
1087       /* entry is an array with all syms for group 0, all
1088        * syms for group 1, etc. and for each group the
1089        * shift level syms are in order
1090        */
1091       entry = XkbKeySymsPtr (xkb, hardware_keycode);
1092
1093       while (i < total_syms)
1094         {          
1095           /* check out our cool loop invariant */          
1096           g_assert (i == (group * max_shift_levels + level));
1097
1098           if (key_array)
1099             {
1100               GdkKeymapKey key;
1101               
1102               key.keycode = hardware_keycode;
1103               key.group = group;
1104               key.level = level;
1105               
1106               g_array_append_val (key_array, key);
1107             }
1108
1109           if (keyval_array)
1110             g_array_append_val (keyval_array, entry[i]);
1111           
1112           ++level;
1113           
1114           if (level == max_shift_levels)
1115             {
1116               level = 0;
1117               ++group;
1118             }
1119           
1120           ++i;
1121         }
1122     }
1123   else
1124 #endif
1125     {
1126       const KeySym *map = get_keymap (keymap_x11);
1127       const KeySym *syms;
1128       gint i = 0;
1129
1130       syms = map + (hardware_keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
1131
1132       while (i < keymap_x11->keysyms_per_keycode)
1133         {
1134           if (key_array)
1135             {
1136               GdkKeymapKey key;
1137           
1138               key.keycode = hardware_keycode;
1139               
1140               /* The "classic" non-XKB keymap has 2 levels per group */
1141               key.group = i / 2;
1142               key.level = i % 2;
1143               
1144               g_array_append_val (key_array, key);
1145             }
1146
1147           if (keyval_array)
1148             g_array_append_val (keyval_array, syms[i]);
1149           
1150           ++i;
1151         }
1152     }
1153
1154   *n_entries = 0;
1155
1156   if (keys)
1157     {
1158       *n_entries = key_array->len;
1159       *keys = (GdkKeymapKey*) g_array_free (key_array, FALSE);
1160     }
1161   
1162   if (keyvals)
1163     {
1164       *n_entries = keyval_array->len;
1165       *keyvals = (guint*) g_array_free (keyval_array, FALSE);
1166     }
1167
1168   return *n_entries > 0;
1169 }
1170
1171
1172 /**
1173  * gdk_keymap_lookup_key:
1174  * @keymap: a #GdkKeymap or %NULL to use the default keymap
1175  * @key: a #GdkKeymapKey with keycode, group, and level initialized
1176  * 
1177  * Looks up the keyval mapped to a keycode/group/level triplet.
1178  * If no keyval is bound to @key, returns 0. For normal user input,
1179  * you want to use gdk_keymap_translate_keyboard_state() instead of
1180  * this function, since the effective group/level may not be
1181  * the same as the current keyboard state.
1182  * 
1183  * Return value: a keyval, or 0 if none was mapped to the given @key
1184  **/
1185 guint
1186 gdk_keymap_lookup_key (GdkKeymap          *keymap,
1187                        const GdkKeymapKey *key)
1188 {
1189   GdkKeymapX11 *keymap_x11;
1190   
1191   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
1192   g_return_val_if_fail (key != NULL, 0);
1193   g_return_val_if_fail (key->group < 4, 0);
1194
1195   keymap = GET_EFFECTIVE_KEYMAP (keymap);
1196   keymap_x11 = GDK_KEYMAP_X11 (keymap);
1197   
1198 #ifdef HAVE_XKB
1199   if (KEYMAP_USE_XKB (keymap))
1200     {
1201       XkbDescRec *xkb = get_xkb (keymap_x11);
1202       
1203       return XkbKeySymEntry (xkb, key->keycode, key->level, key->group);
1204     }
1205   else
1206 #endif
1207     {
1208       const KeySym *map = get_keymap (keymap_x11);
1209       const KeySym *syms = map + (key->keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
1210       return get_symbol (syms, keymap_x11, key->group, key->level);
1211     }
1212 }
1213
1214 #ifdef HAVE_XKB
1215 /* This is copied straight from XFree86 Xlib, to:
1216  *  - add the group and level return.
1217  *  - change the interpretation of mods_rtrn as described
1218  *    in the docs for gdk_keymap_translate_keyboard_state()
1219  * It's unchanged for ease of diff against the Xlib sources; don't
1220  * reformat it.
1221  */
1222 static Bool
1223 MyEnhancedXkbTranslateKeyCode(register XkbDescPtr     xkb,
1224                               KeyCode                 key,
1225                               register unsigned int   mods,
1226                               unsigned int *          mods_rtrn,
1227                               KeySym *                keysym_rtrn,
1228                               int *                   group_rtrn,
1229                               int *                   level_rtrn)
1230 {
1231     XkbKeyTypeRec *type;
1232     int col,nKeyGroups;
1233     unsigned preserve,effectiveGroup;
1234     KeySym *syms;
1235
1236     if (mods_rtrn!=NULL)
1237         *mods_rtrn = 0;
1238
1239     nKeyGroups= XkbKeyNumGroups(xkb,key);
1240     if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
1241         if (keysym_rtrn!=NULL)
1242             *keysym_rtrn = NoSymbol;
1243         return False;
1244     }
1245
1246     syms = XkbKeySymsPtr(xkb,key);
1247
1248     /* find the offset of the effective group */
1249     col = 0;
1250     effectiveGroup= XkbGroupForCoreState(mods);
1251     if ( effectiveGroup>=nKeyGroups ) {
1252         unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
1253         switch (XkbOutOfRangeGroupAction(groupInfo)) {
1254             default:
1255                 effectiveGroup %= nKeyGroups;
1256                 break;
1257             case XkbClampIntoRange:
1258                 effectiveGroup = nKeyGroups-1;
1259                 break;
1260             case XkbRedirectIntoRange:
1261                 effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
1262                 if (effectiveGroup>=nKeyGroups)
1263                     effectiveGroup= 0;
1264                 break;
1265         }
1266     }
1267     col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
1268     type = XkbKeyKeyType(xkb,key,effectiveGroup);
1269
1270     preserve= 0;
1271     if (type->map) { /* find the column (shift level) within the group */
1272         register int i;
1273         register XkbKTMapEntryPtr entry;
1274         /* ---- Begin section modified for GDK  ---- */
1275         int found = 0;
1276         
1277         for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
1278             if (mods_rtrn) {
1279                 int bits = 0;
1280                 unsigned long tmp = entry->mods.mask;
1281                 while (tmp) {
1282                     if ((tmp & 1) == 1)
1283                         bits++;
1284                     tmp >>= 1;
1285                 }
1286                 /* We always add one-modifiers levels to mods_rtrn since
1287                  * they can't wipe out bits in the state unless the
1288                  * level would be triggered. But return other modifiers
1289                  * 
1290                  */
1291                 if (bits == 1 || (mods&type->mods.mask)==entry->mods.mask)
1292                     *mods_rtrn |= entry->mods.mask;
1293             }
1294             
1295             if (!found&&entry->active&&((mods&type->mods.mask)==entry->mods.mask)) {
1296                 col+= entry->level;
1297                 if (type->preserve)
1298                     preserve= type->preserve[i].mask;
1299
1300                 if (level_rtrn)
1301                   *level_rtrn = entry->level;
1302                 
1303                 found = 1;
1304             }
1305         }
1306         /* ---- End section modified for GDK ---- */
1307     }
1308
1309     if (keysym_rtrn!=NULL)
1310         *keysym_rtrn= syms[col];
1311     if (mods_rtrn) {
1312         /* ---- Begin section modified for GDK  ---- */
1313         *mods_rtrn &= ~preserve;
1314         /* ---- End section modified for GDK ---- */
1315         
1316         /* ---- Begin stuff GDK comments out of the original Xlib version ---- */
1317         /* This is commented out because xkb_info is a private struct */
1318
1319 #if 0
1320         /* The Motif VTS doesn't get the help callback called if help
1321          * is bound to Shift+<whatever>, and it appears as though it 
1322          * is XkbTranslateKeyCode that is causing the problem.  The 
1323          * core X version of XTranslateKey always OR's in ShiftMask 
1324          * and LockMask for mods_rtrn, so this "fix" keeps this behavior 
1325          * and solves the VTS problem.
1326          */
1327         if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
1328             (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) {            *mods_rtrn|= (ShiftMask|LockMask);
1329         }
1330 #endif
1331         
1332         /* ---- End stuff GDK comments out of the original Xlib version ---- */
1333     }
1334
1335     /* ---- Begin stuff GDK adds to the original Xlib version ---- */
1336
1337     if (group_rtrn)
1338       *group_rtrn = effectiveGroup;
1339     
1340     /* ---- End stuff GDK adds to the original Xlib version ---- */
1341     
1342     return (syms[col] != NoSymbol);
1343 }
1344 #endif /* HAVE_XKB */
1345
1346 /* Translates from keycode/state to keysymbol using the traditional interpretation
1347  * of the keyboard map. See section 12.7 of the Xlib reference manual
1348  */
1349 static guint
1350 translate_keysym (GdkKeymapX11   *keymap_x11,
1351                   guint           hardware_keycode,
1352                   gint            group,
1353                   GdkModifierType state,
1354                   gint           *effective_group,
1355                   gint           *effective_level)
1356 {
1357   const KeySym *map = get_keymap (keymap_x11);
1358   const KeySym *syms = map + (hardware_keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
1359
1360 #define SYM(k,g,l) get_symbol (syms, k,g,l)
1361
1362   GdkModifierType shift_modifiers;
1363   gint shift_level;
1364   guint tmp_keyval;
1365   gint num_lock_index;
1366
1367   shift_modifiers = GDK_SHIFT_MASK;
1368   if (keymap_x11->lock_keysym == GDK_KEY_Shift_Lock)
1369     shift_modifiers |= GDK_LOCK_MASK;
1370
1371   /* Fall back to the first group if the passed in group is empty
1372    */
1373   if (!(SYM (keymap_x11, group, 0) || SYM (keymap_x11, group, 1)) &&
1374       (SYM (keymap_x11, 0, 0) || SYM (keymap_x11, 0, 1)))
1375     group = 0;
1376
1377   /* Hack: On Sun, the Num Lock modifier uses the third element in the
1378    * keysym array, and Mode_Switch does not apply for a keypad key.
1379    */
1380   if (keymap_x11->sun_keypad)
1381     {
1382       num_lock_index = 2;
1383       
1384       if (group != 0)
1385         {
1386           gint i;
1387           
1388           for (i = 0; i < keymap_x11->keysyms_per_keycode; i++)
1389             if (KEYSYM_IS_KEYPAD (SYM (keymap_x11, 0, i)))
1390               group = 0;
1391         }
1392     }
1393   else
1394     num_lock_index = 1;
1395
1396   if ((state & keymap_x11->num_lock_mask) &&
1397       KEYSYM_IS_KEYPAD (SYM (keymap_x11, group, num_lock_index)))
1398     {
1399       /* Shift, Shift_Lock cancel Num_Lock
1400        */
1401       shift_level = (state & shift_modifiers) ? 0 : num_lock_index;
1402       if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, group, 0))
1403         shift_level = 0;
1404
1405        tmp_keyval = SYM (keymap_x11, group, shift_level);
1406     }
1407   else
1408     {
1409       /* Fall back to the first level if no symbol for the level
1410        * we were passed.
1411        */
1412       shift_level = (state & shift_modifiers) ? 1 : 0;
1413       if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, group, 0))
1414         shift_level = 0;
1415   
1416       tmp_keyval = SYM (keymap_x11, group, shift_level);
1417       
1418       if (keymap_x11->lock_keysym == GDK_KEY_Caps_Lock && (state & GDK_LOCK_MASK) != 0)
1419         {
1420           guint upper = gdk_keyval_to_upper (tmp_keyval);
1421           if (upper != tmp_keyval)
1422             tmp_keyval = upper;
1423         }
1424     }
1425
1426   if (effective_group)
1427     *effective_group = group;
1428       
1429   if (effective_level)
1430     *effective_level = shift_level;
1431
1432   return tmp_keyval;
1433   
1434 #undef SYM
1435 }
1436
1437 /**
1438  * gdk_keymap_translate_keyboard_state:
1439  * @keymap: (allow-none): a #GdkKeymap, or %NULL to use the default
1440  * @hardware_keycode: a keycode
1441  * @state: a modifier state
1442  * @group: active keyboard group
1443  * @keyval: (out) (allow-none): return location for keyval, or %NULL
1444  * @effective_group: (out) (allow-none): return location for effective group, or %NULL
1445  * @level: (out) (allow-none):  return location for level, or %NULL
1446  * @consumed_modifiers: (out) (allow-none):  return location for modifiers that were used to
1447  *     determine the group or level, or %NULL
1448  *
1449  * Translates the contents of a #GdkEventKey into a keyval, effective
1450  * group, and level. Modifiers that affected the translation and
1451  * are thus unavailable for application use are returned in
1452  * @consumed_modifiers.  See <xref linkend="key-group-explanation"/> for an explanation of
1453  * groups and levels.  The @effective_group is the group that was
1454  * actually used for the translation; some keys such as Enter are not
1455  * affected by the active keyboard group. The @level is derived from
1456  * @state. For convenience, #GdkEventKey already contains the translated
1457  * keyval, so this function isn't as useful as you might think.
1458  *
1459  * <note><para>
1460  * @consumed_modifiers gives modifiers that should be masked out
1461  * from @state when comparing this key press to a hot key. For
1462  * instance, on a US keyboard, the <literal>plus</literal>
1463  * symbol is shifted, so when comparing a key press to a
1464  * <literal>&lt;Control&gt;plus</literal> accelerator &lt;Shift&gt; should
1465  * be masked out.
1466  * </para>
1467  * <informalexample><programlisting>
1468  * &sol;* We want to ignore irrelevant modifiers like ScrollLock *&sol;
1469  * &num;define ALL_ACCELS_MASK (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK)
1470  * gdk_keymap_translate_keyboard_state (keymap, event->hardware_keycode,
1471  *                                      event->state, event->group,
1472  *                                      &amp;keyval, NULL, NULL, &amp;consumed);
1473  * if (keyval == GDK_PLUS &&
1474  *     (event->state &amp; ~consumed &amp; ALL_ACCELS_MASK) == GDK_CONTROL_MASK)
1475  *   &sol;* Control was pressed *&sol;
1476  * </programlisting></informalexample>
1477  * <para>
1478  * An older interpretation @consumed_modifiers was that it contained
1479  * all modifiers that might affect the translation of the key;
1480  * this allowed accelerators to be stored with irrelevant consumed
1481  * modifiers, by doing:</para>
1482  * <informalexample><programlisting>
1483  * &sol;* XXX Don't do this XXX *&sol;
1484  * if (keyval == accel_keyval &&
1485  *     (event->state &amp; ~consumed &amp; ALL_ACCELS_MASK) == (accel_mods &amp; ~consumed))
1486  *   &sol;* Accelerator was pressed *&sol;
1487  * </programlisting></informalexample>
1488  * <para>
1489  * However, this did not work if multi-modifier combinations were
1490  * used in the keymap, since, for instance, <literal>&lt;Control&gt;</literal>
1491  * would be masked out even if only <literal>&lt;Control&gt;&lt;Alt&gt;</literal>
1492  * was used in the keymap. To support this usage as well as well as
1493  * possible, all <emphasis>single modifier</emphasis> combinations
1494  * that could affect the key for any combination of modifiers will
1495  * be returned in @consumed_modifiers; multi-modifier combinations
1496  * are returned only when actually found in @state. When you store
1497  * accelerators, you should always store them with consumed modifiers
1498  * removed. Store <literal>&lt;Control&gt;plus</literal>,
1499  * not <literal>&lt;Control&gt;&lt;Shift&gt;plus</literal>,
1500  * </para></note>
1501  * 
1502  * Return value: %TRUE if there was a keyval bound to the keycode/state/group
1503  **/
1504 gboolean
1505 gdk_keymap_translate_keyboard_state (GdkKeymap       *keymap,
1506                                      guint            hardware_keycode,
1507                                      GdkModifierType  state,
1508                                      gint             group,
1509                                      guint           *keyval,
1510                                      gint            *effective_group,
1511                                      gint            *level,
1512                                      GdkModifierType *consumed_modifiers)
1513 {
1514   GdkKeymapX11 *keymap_x11;
1515   KeySym tmp_keyval = NoSymbol;
1516   guint tmp_modifiers;
1517
1518   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
1519   g_return_val_if_fail (group < 4, FALSE);
1520
1521   keymap = GET_EFFECTIVE_KEYMAP (keymap);  
1522   keymap_x11 = GDK_KEYMAP_X11 (keymap);
1523
1524   if (keyval)
1525     *keyval = NoSymbol;
1526   if (effective_group)
1527     *effective_group = 0;
1528   if (level)
1529     *level = 0;
1530   if (consumed_modifiers)
1531     *consumed_modifiers = 0;
1532
1533   update_keyrange (keymap_x11);
1534   
1535   if (hardware_keycode < keymap_x11->min_keycode ||
1536       hardware_keycode > keymap_x11->max_keycode)
1537     return FALSE;
1538
1539 #ifdef HAVE_XKB
1540   if (KEYMAP_USE_XKB (keymap))
1541     {
1542       XkbDescRec *xkb = get_xkb (keymap_x11);
1543
1544       /* replace bits 13 and 14 with the provided group */
1545       state &= ~(1 << 13 | 1 << 14);
1546       state |= group << 13;
1547       
1548       MyEnhancedXkbTranslateKeyCode (xkb,
1549                                      hardware_keycode,
1550                                      state,
1551                                      &tmp_modifiers,
1552                                      &tmp_keyval,
1553                                      effective_group,
1554                                      level);
1555
1556       if (state & ~tmp_modifiers & LockMask)
1557         tmp_keyval = gdk_keyval_to_upper (tmp_keyval);
1558
1559       /* We need to augment the consumed modifiers with LockMask, since
1560        * we handle that ourselves, and also with the group bits
1561        */
1562       tmp_modifiers |= LockMask | 1 << 13 | 1 << 14;
1563     }
1564   else
1565 #endif
1566     {
1567       GdkModifierType bit;
1568       
1569       tmp_modifiers = 0;
1570
1571       /* We see what modifiers matter by trying the translation with
1572        * and without each possible modifier
1573        */
1574       for (bit = GDK_SHIFT_MASK; bit < GDK_BUTTON1_MASK; bit <<= 1)
1575         {
1576           /* Handling of the group here is a bit funky; a traditional
1577            * X keyboard map can have more than two groups, but no way
1578            * of accessing the extra groups is defined. We allow a
1579            * caller to pass in any group to this function, but we 
1580            * only can represent switching between group 0 and 1 in
1581            * consumed modifiers.
1582            */
1583           if (translate_keysym (keymap_x11, hardware_keycode,
1584                                 (bit == keymap_x11->group_switch_mask) ? 0 : group,
1585                                 state & ~bit,
1586                                 NULL, NULL) !=
1587               translate_keysym (keymap_x11, hardware_keycode,
1588                                 (bit == keymap_x11->group_switch_mask) ? 1 : group,
1589                                 state | bit,
1590                                 NULL, NULL))
1591             tmp_modifiers |= bit;
1592         }
1593       
1594       tmp_keyval = translate_keysym (keymap_x11, hardware_keycode,
1595                                      group, state,
1596                                      level, effective_group);
1597     }
1598
1599   if (consumed_modifiers)
1600     *consumed_modifiers = tmp_modifiers;
1601                                 
1602   if (keyval)
1603     *keyval = tmp_keyval;
1604
1605   return tmp_keyval != NoSymbol;
1606 }
1607
1608
1609 /* Key handling not part of the keymap */
1610 /**
1611  * gdk_keyval_name:
1612  * @keyval: a key value.
1613  *
1614  * Converts a key value into a symbolic name.
1615  * The names are the same as those in the
1616  * <filename>&lt;gdk/gdkkeysyms.h&gt;</filename> header file
1617  * but without the leading "GDK_KEY_".
1618  *
1619  * Return value: (transfer none): a string containing the name of the key, or 
1620  * %NULL if @keyval is not a valid key. The string should not be modified.
1621  **/
1622 gchar*
1623 gdk_keyval_name (guint        keyval)
1624 {
1625   switch (keyval)
1626     {
1627     case GDK_KEY_Page_Up:
1628       return "Page_Up";
1629     case GDK_KEY_Page_Down:
1630       return "Page_Down";
1631     case GDK_KEY_KP_Page_Up:
1632       return "KP_Page_Up";
1633     case GDK_KEY_KP_Page_Down:
1634       return "KP_Page_Down";
1635     }
1636   
1637   return XKeysymToString (keyval);
1638 }
1639
1640 guint
1641 gdk_keyval_from_name (const gchar *keyval_name)
1642 {
1643   g_return_val_if_fail (keyval_name != NULL, 0);
1644   
1645   return XStringToKeysym (keyval_name);
1646 }
1647
1648 #ifdef HAVE_XCONVERTCASE
1649 void
1650 gdk_keyval_convert_case (guint symbol,
1651                          guint *lower,
1652                          guint *upper)
1653 {
1654   KeySym xlower = 0;
1655   KeySym xupper = 0;
1656
1657   /* Check for directly encoded 24-bit UCS characters: */
1658   if ((symbol & 0xff000000) == 0x01000000)
1659     {
1660       if (lower)
1661         *lower = gdk_unicode_to_keyval (g_unichar_tolower (symbol & 0x00ffffff));
1662       if (upper)
1663         *upper = gdk_unicode_to_keyval (g_unichar_toupper (symbol & 0x00ffffff));
1664       return;
1665     }
1666   
1667   if (symbol)
1668     XConvertCase (symbol, &xlower, &xupper);
1669
1670   if (lower)
1671     *lower = xlower;
1672   if (upper)
1673     *upper = xupper;
1674 }  
1675 #endif /* HAVE_XCONVERTCASE */
1676
1677 gint
1678 _gdk_x11_get_group_for_state (GdkDisplay      *display,
1679                               GdkModifierType  state)
1680 {
1681   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1682   
1683 #ifdef HAVE_XKB
1684   if (display_x11->use_xkb)
1685     {
1686       return XkbGroupForCoreState (state);
1687     }
1688   else
1689 #endif
1690     {
1691       GdkKeymapX11 *keymap_impl = GDK_KEYMAP_X11 (gdk_keymap_get_for_display (display));
1692       update_keymaps (keymap_impl);
1693       return (state & keymap_impl->group_switch_mask) ? 1 : 0;
1694     }
1695 }
1696
1697 void
1698 _gdk_keymap_add_virtual_modifiers_compat (GdkKeymap       *keymap,
1699                                           GdkModifierType *modifiers)
1700 {
1701   GdkKeymapX11 *keymap_x11;
1702   int i;
1703   
1704   keymap = GET_EFFECTIVE_KEYMAP (keymap);
1705   keymap_x11 = GDK_KEYMAP_X11 (keymap);
1706
1707   for (i = 3; i < 8; i++)
1708     {
1709       if ((1 << i) & *modifiers)
1710         {
1711           if (keymap_x11->modmap[i] & GDK_MOD1_MASK)
1712             *modifiers |= GDK_MOD1_MASK;
1713           else if (keymap_x11->modmap[i] & GDK_SUPER_MASK)
1714             *modifiers |= GDK_SUPER_MASK;
1715           else if (keymap_x11->modmap[i] & GDK_HYPER_MASK)
1716             *modifiers |= GDK_HYPER_MASK;
1717           else if (keymap_x11->modmap[i] & GDK_META_MASK)
1718             *modifiers |= GDK_META_MASK;
1719         }
1720     }
1721 }
1722
1723 /**
1724  * gdk_keymap_add_virtual_modifiers:
1725  * @keymap: a #GdkKeymap
1726  * @state: pointer to the modifier mask to change
1727  *
1728  * Adds virtual modifiers (i.e. Super, Hyper and Meta) which correspond
1729  * to the real modifiers (i.e Mod2, Mod3, ...) in @modifiers.
1730  * are set in @state to their non-virtual counterparts (i.e. Mod2,
1731  * Mod3,...) and set the corresponding bits in @state.
1732  *
1733  * GDK already does this before delivering key events, but for
1734  * compatibility reasons, it only sets the first virtual modifier
1735  * it finds, whereas this function sets all matching virtual modifiers.
1736  *
1737  * This function is useful when matching key events against
1738  * accelerators.
1739  *
1740  * Since: 2.20
1741  */
1742 void
1743 gdk_keymap_add_virtual_modifiers (GdkKeymap       *keymap,
1744                                   GdkModifierType *state)
1745 {
1746   GdkKeymapX11 *keymap_x11;
1747   int i;
1748
1749   keymap = GET_EFFECTIVE_KEYMAP (keymap);
1750   keymap_x11 = GDK_KEYMAP_X11 (keymap);
1751
1752   for (i = 3; i < 8; i++)
1753     {
1754       if ((1 << i) & *state)
1755         {
1756           if (keymap_x11->modmap[i] & GDK_MOD1_MASK)
1757             *state |= GDK_MOD1_MASK;
1758           if (keymap_x11->modmap[i] & GDK_SUPER_MASK)
1759             *state |= GDK_SUPER_MASK;
1760           if (keymap_x11->modmap[i] & GDK_HYPER_MASK)
1761             *state |= GDK_HYPER_MASK;
1762           if (keymap_x11->modmap[i] & GDK_META_MASK)
1763             *state |= GDK_META_MASK;
1764         }
1765     }
1766 }
1767
1768 gboolean
1769 _gdk_keymap_key_is_modifier (GdkKeymap *keymap,
1770                              guint      keycode)
1771 {
1772   GdkKeymapX11 *keymap_x11;
1773   gint i;
1774
1775   keymap = GET_EFFECTIVE_KEYMAP (keymap);  
1776   keymap_x11 = GDK_KEYMAP_X11 (keymap);
1777
1778   if (keycode < keymap_x11->min_keycode ||
1779       keycode > keymap_x11->max_keycode)
1780     return FALSE;
1781
1782 #ifdef HAVE_XKB
1783   if (KEYMAP_USE_XKB (keymap))
1784     {
1785       XkbDescRec *xkb = get_xkb (keymap_x11);
1786       
1787       if (xkb->map->modmap && xkb->map->modmap[keycode] != 0)
1788         return TRUE;
1789     }
1790   else
1791 #endif
1792     {
1793       for (i = 0; i < 8 * keymap_x11->mod_keymap->max_keypermod; i++)
1794         {
1795           if (keycode == keymap_x11->mod_keymap->modifiermap[i])
1796             return TRUE;
1797         }
1798     }
1799
1800   return FALSE;
1801 }
1802
1803 /**
1804  * gdk_keymap_map_virtual_modifiers:
1805  * @keymap: a #GdkKeymap
1806  * @state: pointer to the modifier state to map
1807  *
1808  * Maps the virtual modifiers (i.e. Super, Hyper and Meta) which
1809  * are set in @state to their non-virtual counterparts (i.e. Mod2,
1810  * Mod3,...) and set the corresponding bits in @state.
1811  *
1812  * This function is useful when matching key events against
1813  * accelerators.
1814  *
1815  * Returns: %TRUE if no virtual modifiers were mapped to the
1816  *     same non-virtual modifier. Note that %FALSE is also returned
1817  *     if a virtual modifier is mapped to a non-virtual modifier that
1818  *     was already set in @state.
1819  *
1820  * Since: 2.20
1821  */
1822 gboolean
1823 gdk_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
1824                                   GdkModifierType *state)
1825 {
1826   GdkKeymapX11 *keymap_x11;
1827   const guint vmods[] = {
1828     GDK_SUPER_MASK, GDK_HYPER_MASK, GDK_META_MASK
1829   };
1830   int i, j;
1831   gboolean retval;
1832
1833   keymap = GET_EFFECTIVE_KEYMAP (keymap);
1834   keymap_x11 = GDK_KEYMAP_X11 (keymap);
1835
1836   if (KEYMAP_USE_XKB (keymap))
1837     get_xkb (keymap_x11);
1838
1839   retval = TRUE;
1840
1841   for (j = 0; j < 3; j++)
1842     {
1843       if (*state & vmods[j])
1844         {
1845           for (i = 3; i < 8; i++)
1846             {
1847               if (keymap_x11->modmap[i] & vmods[j])
1848                 {
1849                   if (*state & (1 << i))
1850                     retval = FALSE;
1851                   else
1852                     *state |= 1 << i;
1853                 }
1854             }
1855         }
1856     }
1857
1858   return retval;
1859 }