]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkkeys-x11.c
Make PLT-reduction work with gcc4, and don't include everything in
[~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 <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <limits.h>
34 #include <errno.h>
35
36 #include "gdk.h"
37 #include "gdkx.h"
38
39 #include "gdkprivate-x11.h"
40 #include "gdkinternals.h"
41 #include "gdkdisplay-x11.h"
42 #include "gdkkeysyms.h"
43 #include "gdkalias.h"
44
45 #ifdef HAVE_XKB
46 #include <X11/XKBlib.h>
47
48 /* OSF-4.0 is apparently missing this macro
49  */
50 #  ifndef XkbKeySymEntry
51 #    define XkbKeySymEntry(d,k,sl,g) \
52         (XkbKeySym(d,k,((XkbKeyGroupsWidth(d,k)*(g))+(sl))))
53 #  endif
54 #endif /* HAVE_XKB */
55
56 typedef struct _GdkKeymapX11 GdkKeymapX11;
57
58 #define GDK_TYPE_KEYMAP_X11          (gdk_keymap_x11_get_type ())
59 #define GDK_KEYMAP_X11(object)       (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_KEYMAP_X11, GdkKeymapX11))
60 #define GDK_IS_KEYMAP_X11(object)    (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_KEYMAP_X11))
61
62 typedef struct _DirectionCacheEntry DirectionCacheEntry;
63
64 struct _DirectionCacheEntry
65 {
66   guint serial;
67   Atom group_atom;
68   PangoDirection direction;
69 };
70
71 struct _GdkKeymapX11
72 {
73   GdkKeymap     parent_instance;
74
75   gint min_keycode;
76   gint max_keycode;
77   KeySym* keymap;
78   gint keysyms_per_keycode;
79   XModifierKeymap* mod_keymap;
80   guint lock_keysym;
81   GdkModifierType group_switch_mask;
82   GdkModifierType num_lock_mask;
83   gboolean sun_keypad;
84   PangoDirection current_direction;
85   gboolean have_direction;
86   guint current_serial;
87
88 #ifdef HAVE_XKB
89   XkbDescPtr xkb_desc;
90   /* We cache the directions */
91   Atom current_group_atom;
92   guint current_cache_serial;
93   /* A cache of size four should be more than enough, people usually
94    * have two groups around, and the xkb limit is four.  It still
95    * works correct for more than four groups.  It's just the
96    * cache.
97    */
98   DirectionCacheEntry group_direction_cache[4];
99 #endif
100 };
101
102 #define KEYMAP_USE_XKB(keymap) GDK_DISPLAY_X11 ((keymap)->display)->use_xkb
103 #define KEYMAP_XDISPLAY(keymap) GDK_DISPLAY_XDISPLAY ((keymap)->display)
104
105 static GType gdk_keymap_x11_get_type (void);
106 static void  gdk_keymap_x11_init     (GdkKeymapX11 *keymap);
107
108 static GType
109 gdk_keymap_x11_get_type (void)
110 {
111   static GType object_type = 0;
112
113   if (!object_type)
114     {
115       static const GTypeInfo object_info =
116         {
117           sizeof (GdkKeymapClass),
118           (GBaseInitFunc) NULL,
119           (GBaseFinalizeFunc) NULL,
120           (GClassInitFunc) NULL,
121           NULL,           /* class_finalize */
122           NULL,           /* class_data */
123           sizeof (GdkKeymapX11),
124           0,              /* n_preallocs */
125           (GInstanceInitFunc) gdk_keymap_x11_init,
126         };
127       
128       object_type = g_type_register_static (GDK_TYPE_KEYMAP,
129                                             "GdkKeymapX11",
130                                             &object_info, 0);
131     }
132   
133   return object_type;
134 }
135
136 static void
137 gdk_keymap_x11_init (GdkKeymapX11 *keymap)
138 {
139   keymap->min_keycode = 0;
140   keymap->max_keycode = 0;
141
142   keymap->keymap = NULL;
143   keymap->keysyms_per_keycode = 0;
144   keymap->mod_keymap = NULL;
145   
146   keymap->num_lock_mask = 0;
147   keymap->sun_keypad = FALSE;
148   keymap->group_switch_mask = 0;
149   keymap->lock_keysym = GDK_Caps_Lock;
150   keymap->have_direction = FALSE;
151   keymap->current_serial = 0;
152
153 #ifdef HAVE_XKB
154   keymap->xkb_desc = NULL;
155   keymap->current_group_atom = 0;
156   keymap->current_cache_serial = 0;
157 #endif
158
159 }
160
161 static inline void
162 update_keyrange (GdkKeymapX11 *keymap_x11)
163 {
164   if (keymap_x11->max_keycode == 0)
165     XDisplayKeycodes (KEYMAP_XDISPLAY (GDK_KEYMAP (keymap_x11)),
166                       &keymap_x11->min_keycode, &keymap_x11->max_keycode);
167 }
168
169 #ifdef HAVE_XKB
170
171 static XkbDescPtr
172 get_xkb (GdkKeymapX11 *keymap_x11)
173 {
174   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_KEYMAP (keymap_x11)->display);
175   Display *xdisplay = display_x11->xdisplay;
176   
177   update_keyrange (keymap_x11);
178   
179   if (keymap_x11->xkb_desc == NULL)
180     {
181       keymap_x11->xkb_desc = XkbGetMap (xdisplay, XkbKeySymsMask | XkbKeyTypesMask, XkbUseCoreKbd);
182       if (keymap_x11->xkb_desc == NULL)
183         g_error ("Failed to get keymap");
184
185       XkbGetNames (xdisplay, XkbGroupNamesMask, keymap_x11->xkb_desc);
186     }
187   else if (keymap_x11->current_serial != display_x11->keymap_serial)
188     {
189       XkbGetUpdatedMap (xdisplay, XkbKeySymsMask | XkbKeyTypesMask,
190                         keymap_x11->xkb_desc);
191       XkbGetNames (xdisplay, XkbGroupNamesMask, keymap_x11->xkb_desc);
192     }
193
194   keymap_x11->current_serial = display_x11->keymap_serial;
195
196   return keymap_x11->xkb_desc;
197 }
198 #endif /* HAVE_XKB */
199
200 /* Whether we were able to turn on detectable-autorepeat using
201  * XkbSetDetectableAutorepeat. If FALSE, we'll fall back
202  * to checking the next event with XPending().
203  */
204
205 /** 
206  * gdk_keymap_get_for_display:
207  * @display: the #GdkDisplay.
208  * @returns: the #GdkKeymap attached to @display.
209  *
210  * Returns the #GdkKeymap attached to @display.
211  *
212  * Since: 2.2
213  **/
214 GdkKeymap*
215 gdk_keymap_get_for_display (GdkDisplay *display)
216 {
217   GdkDisplayX11 *display_x11;
218   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
219   display_x11 = GDK_DISPLAY_X11 (display);
220   
221   if (!display_x11->keymap)
222     display_x11->keymap = g_object_new (gdk_keymap_x11_get_type (), NULL);
223
224   display_x11->keymap->display = display;
225
226   return display_x11->keymap;
227 }
228
229 /* Find the index of the group/level pair within the keysyms for a key.
230  * We round up the number of keysyms per keycode to the next even number,
231  * otherwise we lose a whole group of keys
232  */
233 #define KEYSYM_INDEX(keymap_impl, group, level) \
234   (2 * ((group) % (gint)((keymap_impl->keysyms_per_keycode + 1) / 2)) + (level))
235 #define KEYSYM_IS_KEYPAD(s) (((s) >= 0xff80 && (s) <= 0xffbd) || \
236                              ((s) >= 0x11000000 && (s) <= 0x1100ffff))
237
238 static gint
239 get_symbol (const KeySym *syms,
240             GdkKeymapX11 *keymap_x11,
241             gint group,
242             gint level)
243 {
244   gint index;
245
246   index = KEYSYM_INDEX(keymap_x11, group, level);
247   if (index > keymap_x11->keysyms_per_keycode)
248       return NoSymbol;
249
250   return syms[index];
251 }
252
253 static void
254 update_keymaps (GdkKeymapX11 *keymap_x11)
255 {
256   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_KEYMAP (keymap_x11)->display);
257   Display *xdisplay = display_x11->xdisplay;
258   
259 #ifdef HAVE_XKB
260   g_assert (!KEYMAP_USE_XKB (GDK_KEYMAP (keymap_x11)));
261 #endif
262   
263   if (keymap_x11->keymap == NULL ||
264       keymap_x11->current_serial != display_x11->keymap_serial)
265     {
266       gint i;
267       gint map_size;
268       gint keycode;
269
270       keymap_x11->current_serial = display_x11->keymap_serial;
271       
272       update_keyrange (keymap_x11);
273       
274       if (keymap_x11->keymap)
275         XFree (keymap_x11->keymap);
276
277       if (keymap_x11->mod_keymap)
278         XFreeModifiermap (keymap_x11->mod_keymap);
279       
280       keymap_x11->keymap = XGetKeyboardMapping (xdisplay, keymap_x11->min_keycode,
281                                                 keymap_x11->max_keycode - keymap_x11->min_keycode + 1,
282                                                 &keymap_x11->keysyms_per_keycode);
283
284
285       /* GDK_ISO_Left_Tab, as usually configured through XKB, really messes
286        * up the whole idea of "consumed modifiers" because shift is consumed.
287        * However, <shift>Tab is not usually GDK_ISO_Left_Tab without XKB,
288        * we we fudge the map here.
289        */
290       keycode = keymap_x11->min_keycode;
291       while (keycode <= keymap_x11->max_keycode)
292         {
293           KeySym *syms = keymap_x11->keymap + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
294           /* Check both groups */
295           for (i = 0 ; i < 2 ; i++)
296             {
297               if (get_symbol (syms, keymap_x11, i, 0) == GDK_Tab)
298                 syms[KEYSYM_INDEX (keymap_x11, i, 1)] = GDK_ISO_Left_Tab;
299             }
300
301           /*
302            * If there is one keysym and the key symbol has upper and lower
303            * case variants fudge the keymap
304            */
305           if (get_symbol (syms, keymap_x11, 0, 1) == 0)
306             {
307               guint lower;
308               guint upper;
309
310               gdk_keyval_convert_case (get_symbol (syms, keymap_x11, 0, 0), &lower, &upper);
311               if (lower != upper)
312                 {
313                   syms[KEYSYM_INDEX (keymap_x11, 0, 0)] = lower;
314                   syms[KEYSYM_INDEX (keymap_x11, 0, 1)] = upper;
315                 }
316             }
317       
318           
319           ++keycode;
320         }
321
322       keymap_x11->mod_keymap = XGetModifierMapping (xdisplay);
323
324       keymap_x11->lock_keysym = GDK_VoidSymbol;
325       keymap_x11->group_switch_mask = 0;
326       keymap_x11->num_lock_mask = 0;
327
328       /* There are 8 sets of modifiers, with each set containing
329        * max_keypermod keycodes.
330        */
331       map_size = 8 * keymap_x11->mod_keymap->max_keypermod;
332       for (i = 0; i < map_size; i++)
333         {
334           /* Get the key code at this point in the map. */
335           gint keycode = keymap_x11->mod_keymap->modifiermap[i];
336           gint j;
337           KeySym *syms;
338           guint mask;
339
340           /* Ignore invalid keycodes. */
341           if (keycode < keymap_x11->min_keycode ||
342               keycode > keymap_x11->max_keycode)
343             continue;
344
345           syms = keymap_x11->keymap + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
346
347           /* The fourth modifier, GDK_MOD1_MASK is 1 << 3.
348            * Each group of max_keypermod entries refers to the same modifier.
349            */
350           mask = 1 << (i / keymap_x11->mod_keymap->max_keypermod);
351
352           switch (mask)
353             {
354             case GDK_LOCK_MASK:
355               /* Get the Lock keysym.  If any keysym bound to the Lock modifier
356                * is Caps_Lock, we will interpret the modifier as Caps_Lock;
357                * otherwise, if any is bound to Shift_Lock, we will interpret
358                * the modifier as Shift_Lock. Otherwise, the lock modifier
359                * has no effect.
360                */
361               for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
362                 {
363                   if (syms[j] == GDK_Caps_Lock)
364                     keymap_x11->lock_keysym = GDK_Caps_Lock;
365                   else if (syms[j] == GDK_Shift_Lock &&
366                            keymap_x11->lock_keysym == GDK_VoidSymbol)
367                     keymap_x11->lock_keysym = GDK_Shift_Lock;
368                 }
369               break;
370
371             case GDK_CONTROL_MASK:
372             case GDK_SHIFT_MASK:
373             case GDK_MOD1_MASK:
374               /* Some keyboard maps are known to map Mode_Switch as an
375                * extra Mod1 key. In circumstances like that, it won't be
376                * used to switch groups.
377                */
378               break;
379
380             default:
381               /* Find the Mode_Switch and Num_Lock modifiers. */
382               for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
383                 {
384                   if (syms[j] == GDK_Mode_switch)
385                     {
386                       /* This modifier swaps groups */
387                       keymap_x11->group_switch_mask |= mask;
388                     }
389                   else if (syms[j] == GDK_Num_Lock)
390                     {
391                       /* This modifier is used for Num_Lock */
392                       keymap_x11->num_lock_mask |= mask;
393                     }
394                 }
395               break;
396             }
397         }
398
399       /* Hack: The Sun X server puts the keysym to use when the Num Lock
400        * modifier is on in the third element of the keysym array, instead
401        * of the second.
402        */
403       if ((strcmp (ServerVendor (xdisplay), "Sun Microsystems, Inc.") == 0) &&
404           (keymap_x11->keysyms_per_keycode > 2))
405         keymap_x11->sun_keypad = TRUE;
406       else
407         keymap_x11->sun_keypad = FALSE;
408     }
409 }
410
411 static const KeySym*
412 get_keymap (GdkKeymapX11 *keymap_x11)
413 {
414   update_keymaps (keymap_x11);
415   
416   return keymap_x11->keymap;
417 }
418
419 #define GET_EFFECTIVE_KEYMAP(keymap) get_effective_keymap ((keymap), G_STRFUNC)
420
421 static GdkKeymap *
422 get_effective_keymap (GdkKeymap  *keymap,
423                       const char *function)
424 {
425   if (!keymap)
426     {
427       GDK_NOTE (MULTIHEAD,
428                 g_message ("reverting to default display keymap in %s",
429                            function));
430       return gdk_keymap_get_default ();
431     }
432
433   return keymap;
434 }
435
436 #if HAVE_XKB
437 static PangoDirection
438 get_direction (XkbDescRec *xkb, 
439                gint group)
440 {
441   gint code;
442
443   gint rtl_minus_ltr = 0; /* total number of RTL keysyms minus LTR ones */
444
445   for (code = xkb->min_key_code; code <= xkb->max_key_code; code++)
446     {
447       gint width = XkbKeyGroupWidth (xkb, code, group);
448       gint level;
449       for (level = 0; level < width; level++)
450         {
451           KeySym sym = XkbKeySymEntry (xkb, code, level, group);
452           PangoDirection dir = pango_unichar_direction (gdk_keyval_to_unicode (sym));
453
454           switch (dir)
455             {
456             case PANGO_DIRECTION_RTL:
457               rtl_minus_ltr++;
458               break;
459             case PANGO_DIRECTION_LTR:
460               rtl_minus_ltr--;
461               break;
462             default:
463               break;
464             }
465         }
466     }
467     
468   if (rtl_minus_ltr > 0)
469     return PANGO_DIRECTION_RTL;
470   else
471     return PANGO_DIRECTION_LTR;
472 }
473
474 static void
475 update_direction (GdkKeymapX11 *keymap_x11)
476 {
477   XkbDescRec *xkb = get_xkb (keymap_x11);
478   XkbStateRec state_rec;
479   GdkDisplay *display = GDK_KEYMAP (keymap_x11)->display;
480   gint group;
481   Atom group_atom;
482
483   XkbGetState (GDK_DISPLAY_XDISPLAY (display), XkbUseCoreKbd, &state_rec);
484   group = XkbGroupLock (&state_rec);
485   group_atom = xkb->names->groups[group];
486
487   /* a group change? */
488   if (!keymap_x11->have_direction || keymap_x11->current_group_atom != group_atom)
489     {
490       gboolean cache_hit = FALSE;
491       DirectionCacheEntry *cache = keymap_x11->group_direction_cache;
492
493       PangoDirection direction = PANGO_DIRECTION_NEUTRAL;
494       gint i;
495
496       if (keymap_x11->have_direction)
497         {
498           /* lookup in cache */
499           for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
500           {
501             if (cache[i].group_atom == group_atom)
502               {
503                 cache_hit = TRUE;
504                 cache[i].serial = keymap_x11->current_cache_serial++; /* freshen */
505                 direction = cache[i].direction;
506                 group_atom = cache[i].group_atom;
507                 break;
508               }
509           }
510         }
511       else
512         {
513           /* initialize cache */
514           for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
515             {
516               cache[i].group_atom = 0;
517               cache[i].serial = keymap_x11->current_cache_serial;
518             }
519           keymap_x11->current_cache_serial++;
520         }
521
522       /* insert in cache */
523       if (!cache_hit)
524         {
525           gint oldest = 0;
526
527           direction = get_direction (xkb, group);
528
529           /* remove the oldest entry */
530           for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
531             {
532               if (cache[i].serial < cache[oldest].serial)
533                 oldest = i;
534             }
535           
536           cache[oldest].group_atom = group_atom;
537           cache[oldest].direction = direction;
538           cache[oldest].serial = keymap_x11->current_cache_serial++;
539         }
540
541       keymap_x11->current_group_atom = group_atom;
542
543       keymap_x11->have_direction = TRUE;
544       keymap_x11->current_direction = direction;
545     }
546 }
547
548 static void
549 _gdk_keymap_direction_changed (GdkKeymapX11 *keymap_x11)
550 {
551   gboolean had_direction;
552   PangoDirection direction;
553
554   had_direction = keymap_x11->have_direction;
555   direction = keymap_x11->current_direction;
556
557   update_direction (keymap_x11);
558   
559   if (!had_direction || direction != keymap_x11->current_direction)
560     g_signal_emit_by_name (keymap_x11, "direction_changed");
561 }
562
563
564 void
565 _gdk_keymap_state_changed (GdkDisplay *display)
566 {
567   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
568   
569   if (display_x11->keymap)
570     {
571       GdkKeymapX11 *keymap_x11 = GDK_KEYMAP_X11 (display_x11->keymap);
572       
573       _gdk_keymap_direction_changed (keymap_x11);
574     }
575 }
576
577 #endif /* HAVE_XKB */
578
579 void
580 _gdk_keymap_keys_changed (GdkDisplay *display)
581 {
582   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
583   
584   ++display_x11->keymap_serial;
585   
586   if (display_x11->keymap)
587     g_signal_emit_by_name (display_x11->keymap, "keys_changed", 0);
588 }
589
590 PangoDirection
591 gdk_keymap_get_direction (GdkKeymap *keymap)
592 {
593   keymap = GET_EFFECTIVE_KEYMAP (keymap);
594   
595 #if HAVE_XKB
596   if (KEYMAP_USE_XKB (keymap))
597     {
598       GdkKeymapX11 *keymap_x11 = GDK_KEYMAP_X11 (keymap);
599       
600       if (!keymap_x11->have_direction)
601         update_direction (keymap_x11);
602   
603       return keymap_x11->current_direction;
604     }
605   else
606 #endif /* HAVE_XKB */
607     return PANGO_DIRECTION_NEUTRAL;
608 }
609
610 /**
611  * gdk_keymap_get_entries_for_keyval:
612  * @keymap: a #GdkKeymap, or %NULL to use the default keymap
613  * @keyval: a keyval, such as %GDK_a, %GDK_Up, %GDK_Return, etc.
614  * @keys: return location for an array of #GdkKeymapKey
615  * @n_keys: return location for number of elements in returned array
616  * 
617  * Obtains a list of keycode/group/level combinations that will
618  * generate @keyval. Groups and levels are two kinds of keyboard mode;
619  * in general, the level determines whether the top or bottom symbol
620  * on a key is used, and the group determines whether the left or
621  * right symbol is used. On US keyboards, the shift key changes the
622  * keyboard level, and there are no groups. A group switch key might
623  * convert a keyboard between Hebrew to English modes, for example.
624  * #GdkEventKey contains a %group field that indicates the active
625  * keyboard group. The level is computed from the modifier mask.
626  * The returned array should be freed
627  * with g_free().
628  *
629  * Return value: %TRUE if keys were found and returned
630  **/
631 gboolean
632 gdk_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
633                                    guint          keyval,
634                                    GdkKeymapKey **keys,
635                                    gint          *n_keys)
636 {
637   GArray *retval;
638   GdkKeymapX11 *keymap_x11;
639
640   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
641   g_return_val_if_fail (keys != NULL, FALSE);
642   g_return_val_if_fail (n_keys != NULL, FALSE);
643   g_return_val_if_fail (keyval != 0, FALSE);
644
645   keymap = GET_EFFECTIVE_KEYMAP (keymap);
646   keymap_x11 = GDK_KEYMAP_X11 (keymap);
647   
648   retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
649
650 #ifdef HAVE_XKB
651   if (KEYMAP_USE_XKB (keymap))
652     {
653       /* See sec 15.3.4 in XKB docs */
654
655       XkbDescRec *xkb = get_xkb (keymap_x11);
656       gint keycode;
657       
658       keycode = keymap_x11->min_keycode;
659
660       while (keycode <= keymap_x11->max_keycode)
661         {
662           gint max_shift_levels = XkbKeyGroupsWidth (xkb, keycode); /* "key width" */
663           gint group = 0;
664           gint level = 0;
665           gint total_syms = XkbKeyNumSyms (xkb, keycode);
666           gint i = 0;
667           KeySym *entry;
668
669           /* entry is an array with all syms for group 0, all
670            * syms for group 1, etc. and for each group the
671            * shift level syms are in order
672            */
673           entry = XkbKeySymsPtr (xkb, keycode);
674
675           while (i < total_syms)
676             {
677               /* check out our cool loop invariant */
678               g_assert (i == (group * max_shift_levels + level));
679
680               if (entry[i] == keyval)
681                 {
682                   /* Found a match */
683                   GdkKeymapKey key;
684
685                   key.keycode = keycode;
686                   key.group = group;
687                   key.level = level;
688
689                   g_array_append_val (retval, key);
690
691                   g_assert (XkbKeySymEntry (xkb, keycode, level, group) == 
692                             keyval);
693                 }
694
695               ++level;
696
697               if (level == max_shift_levels)
698                 {
699                   level = 0;
700                   ++group;
701                 }
702
703               ++i;
704             }
705
706           ++keycode;
707         }
708     }
709   else
710 #endif
711     {
712       const KeySym *map = get_keymap (keymap_x11);
713       gint keycode;
714       
715       keycode = keymap_x11->min_keycode;
716       while (keycode <= keymap_x11->max_keycode)
717         {
718           const KeySym *syms = map + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
719           gint i = 0;
720
721           while (i < keymap_x11->keysyms_per_keycode)
722             {
723               if (syms[i] == keyval)
724                 {
725                   /* found a match */
726                   GdkKeymapKey key;
727
728                   key.keycode = keycode;
729
730                   /* The "classic" non-XKB keymap has 2 levels per group */
731                   key.group = i / 2;
732                   key.level = i % 2;
733
734                   g_array_append_val (retval, key);
735                 }
736               
737               ++i;
738             }
739           
740           ++keycode;
741         }
742     }
743
744   if (retval->len > 0)
745     {
746       *keys = (GdkKeymapKey*) retval->data;
747       *n_keys = retval->len;
748     }
749   else
750     {
751       *keys = NULL;
752       *n_keys = 0;
753     }
754       
755   g_array_free (retval, retval->len > 0 ? FALSE : TRUE);
756
757   return *n_keys > 0;
758 }
759
760 /**
761  * gdk_keymap_get_entries_for_keycode:
762  * @keymap: a #GdkKeymap or %NULL to use the default keymap
763  * @hardware_keycode: a keycode
764  * @keys: return location for array of #GdkKeymapKey, or NULL
765  * @keyvals: return location for array of keyvals, or NULL
766  * @n_entries: length of @keys and @keyvals
767  *
768  * Returns the keyvals bound to @hardware_keycode.
769  * The Nth #GdkKeymapKey in @keys is bound to the Nth
770  * keyval in @keyvals. Free the returned arrays with g_free().
771  * When a keycode is pressed by the user, the keyval from
772  * this list of entries is selected by considering the effective
773  * keyboard group and level. See gdk_keymap_translate_keyboard_state().
774  *
775  * Returns: %TRUE if there were any entries
776  **/
777 gboolean
778 gdk_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
779                                     guint          hardware_keycode,
780                                     GdkKeymapKey **keys,
781                                     guint        **keyvals,
782                                     gint          *n_entries)
783 {
784   GdkKeymapX11 *keymap_x11;
785   
786   GArray *key_array;
787   GArray *keyval_array;
788
789   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
790   g_return_val_if_fail (n_entries != NULL, FALSE);
791
792   keymap = GET_EFFECTIVE_KEYMAP (keymap);
793   keymap_x11 = GDK_KEYMAP_X11 (keymap);
794
795   update_keyrange (keymap_x11);
796
797   if (hardware_keycode < keymap_x11->min_keycode ||
798       hardware_keycode > keymap_x11->max_keycode)
799     {
800       if (keys)
801         *keys = NULL;
802       if (keyvals)
803         *keyvals = NULL;
804
805       *n_entries = 0;
806       return FALSE;
807     }
808   
809   if (keys)
810     key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
811   else
812     key_array = NULL;
813   
814   if (keyvals)
815     keyval_array = g_array_new (FALSE, FALSE, sizeof (guint));
816   else
817     keyval_array = NULL;
818   
819 #ifdef HAVE_XKB
820   if (KEYMAP_USE_XKB (keymap))
821     {
822       /* See sec 15.3.4 in XKB docs */
823
824       XkbDescRec *xkb = get_xkb (keymap_x11);
825       gint max_shift_levels;
826       gint group = 0;
827       gint level = 0;
828       gint total_syms;
829       gint i = 0;
830       KeySym *entry;
831       
832       max_shift_levels = XkbKeyGroupsWidth (xkb, hardware_keycode); /* "key width" */
833       total_syms = XkbKeyNumSyms (xkb, hardware_keycode);
834
835       /* entry is an array with all syms for group 0, all
836        * syms for group 1, etc. and for each group the
837        * shift level syms are in order
838        */
839       entry = XkbKeySymsPtr (xkb, hardware_keycode);
840
841       while (i < total_syms)
842         {          
843           /* check out our cool loop invariant */          
844           g_assert (i == (group * max_shift_levels + level));
845
846           if (key_array)
847             {
848               GdkKeymapKey key;
849               
850               key.keycode = hardware_keycode;
851               key.group = group;
852               key.level = level;
853               
854               g_array_append_val (key_array, key);
855             }
856
857           if (keyval_array)
858             g_array_append_val (keyval_array, entry[i]);
859           
860           ++level;
861           
862           if (level == max_shift_levels)
863             {
864               level = 0;
865               ++group;
866             }
867           
868           ++i;
869         }
870     }
871   else
872 #endif
873     {
874       const KeySym *map = get_keymap (keymap_x11);
875       const KeySym *syms;
876       gint i = 0;
877
878       syms = map + (hardware_keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
879
880       while (i < keymap_x11->keysyms_per_keycode)
881         {
882           if (key_array)
883             {
884               GdkKeymapKey key;
885           
886               key.keycode = hardware_keycode;
887               
888               /* The "classic" non-XKB keymap has 2 levels per group */
889               key.group = i / 2;
890               key.level = i % 2;
891               
892               g_array_append_val (key_array, key);
893             }
894
895           if (keyval_array)
896             g_array_append_val (keyval_array, syms[i]);
897           
898           ++i;
899         }
900     }
901   
902   if ((key_array && key_array->len > 0) ||
903       (keyval_array && keyval_array->len > 0))
904     {
905       if (keys)
906         *keys = (GdkKeymapKey*) key_array->data;
907
908       if (keyvals)
909         *keyvals = (guint*) keyval_array->data;
910
911       if (key_array)
912         *n_entries = key_array->len;
913       else
914         *n_entries = keyval_array->len;
915     }
916   else
917     {
918       if (keys)
919         *keys = NULL;
920
921       if (keyvals)
922         *keyvals = NULL;
923       
924       *n_entries = 0;
925     }
926
927   if (key_array)
928     g_array_free (key_array, key_array->len > 0 ? FALSE : TRUE);
929   if (keyval_array)
930     g_array_free (keyval_array, keyval_array->len > 0 ? FALSE : TRUE);
931
932   return *n_entries > 0;
933 }
934
935
936 /**
937  * gdk_keymap_lookup_key:
938  * @keymap: a #GdkKeymap or %NULL to use the default keymap
939  * @key: a #GdkKeymapKey with keycode, group, and level initialized
940  * 
941  * Looks up the keyval mapped to a keycode/group/level triplet.
942  * If no keyval is bound to @key, returns 0. For normal user input,
943  * you want to use gdk_keymap_translate_keyboard_state() instead of
944  * this function, since the effective group/level may not be
945  * the same as the current keyboard state.
946  * 
947  * Return value: a keyval, or 0 if none was mapped to the given @key
948  **/
949 guint
950 gdk_keymap_lookup_key (GdkKeymap          *keymap,
951                        const GdkKeymapKey *key)
952 {
953   GdkKeymapX11 *keymap_x11;
954   
955   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
956   g_return_val_if_fail (key != NULL, 0);
957   g_return_val_if_fail (key->group < 4, 0);
958
959   keymap = GET_EFFECTIVE_KEYMAP (keymap);
960   keymap_x11 = GDK_KEYMAP_X11 (keymap);
961   
962 #ifdef HAVE_XKB
963   if (KEYMAP_USE_XKB (keymap))
964     {
965       XkbDescRec *xkb = get_xkb (keymap_x11);
966       
967       return XkbKeySymEntry (xkb, key->keycode, key->level, key->group);
968     }
969   else
970 #endif
971     {
972       const KeySym *map = get_keymap (keymap_x11);
973       const KeySym *syms = map + (key->keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
974       return get_symbol (syms, keymap_x11, key->group, key->level);
975     }
976 }
977
978 #ifdef HAVE_XKB
979 /* This is copied straight from XFree86 Xlib, to:
980  *  - add the group and level return.
981  *  - change the interpretation of mods_rtrn as described
982  *    in the docs for gdk_keymap_translate_keyboard_state()
983  * It's unchanged for ease of diff against the Xlib sources; don't
984  * reformat it.
985  */
986 static Bool
987 MyEnhancedXkbTranslateKeyCode(register XkbDescPtr     xkb,
988                               KeyCode                 key,
989                               register unsigned int   mods,
990                               unsigned int *          mods_rtrn,
991                               KeySym *                keysym_rtrn,
992                               unsigned int *          group_rtrn,
993                               unsigned int *          level_rtrn)
994 {
995     XkbKeyTypeRec *type;
996     int col,nKeyGroups;
997     unsigned preserve,effectiveGroup;
998     KeySym *syms;
999
1000     if (mods_rtrn!=NULL)
1001         *mods_rtrn = 0;
1002
1003     nKeyGroups= XkbKeyNumGroups(xkb,key);
1004     if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
1005         if (keysym_rtrn!=NULL)
1006             *keysym_rtrn = NoSymbol;
1007         return False;
1008     }
1009
1010     syms = XkbKeySymsPtr(xkb,key);
1011
1012     /* find the offset of the effective group */
1013     col = 0;
1014     effectiveGroup= XkbGroupForCoreState(mods);
1015     if ( effectiveGroup>=nKeyGroups ) {
1016         unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
1017         switch (XkbOutOfRangeGroupAction(groupInfo)) {
1018             default:
1019                 effectiveGroup %= nKeyGroups;
1020                 break;
1021             case XkbClampIntoRange:
1022                 effectiveGroup = nKeyGroups-1;
1023                 break;
1024             case XkbRedirectIntoRange:
1025                 effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
1026                 if (effectiveGroup>=nKeyGroups)
1027                     effectiveGroup= 0;
1028                 break;
1029         }
1030     }
1031     col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
1032     type = XkbKeyKeyType(xkb,key,effectiveGroup);
1033
1034     preserve= 0;
1035     if (type->map) { /* find the column (shift level) within the group */
1036         register int i;
1037         register XkbKTMapEntryPtr entry;
1038         /* ---- Begin section modified for GDK  ---- */
1039         int found = 0;
1040         
1041         for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
1042             if (mods_rtrn) {
1043                 int bits = 0;
1044                 unsigned long tmp = entry->mods.mask;
1045                 while (tmp) {
1046                     if ((tmp & 1) == 1)
1047                         bits++;
1048                     tmp >>= 1;
1049                 }
1050                 /* We always add one-modifiers levels to mods_rtrn since
1051                  * they can't wipe out bits in the state unless the
1052                  * level would be triggered. But return other modifiers
1053                  * 
1054                  */
1055                 if (bits == 1 || (mods&type->mods.mask)==entry->mods.mask)
1056                     *mods_rtrn |= entry->mods.mask;
1057             }
1058             
1059             if (!found&&entry->active&&((mods&type->mods.mask)==entry->mods.mask)) {
1060                 col+= entry->level;
1061                 if (type->preserve)
1062                     preserve= type->preserve[i].mask;
1063
1064                 if (level_rtrn)
1065                   *level_rtrn = entry->level;
1066                 
1067                 found = 1;
1068             }
1069         }
1070         /* ---- End section modified for GDK ---- */
1071     }
1072
1073     if (keysym_rtrn!=NULL)
1074         *keysym_rtrn= syms[col];
1075     if (mods_rtrn) {
1076         /* ---- Begin section modified for GDK  ---- */
1077         *mods_rtrn &= ~preserve;
1078         /* ---- End section modified for GDK ---- */
1079         
1080         /* ---- Begin stuff GDK comments out of the original Xlib version ---- */
1081         /* This is commented out because xkb_info is a private struct */
1082
1083 #if 0
1084         /* The Motif VTS doesn't get the help callback called if help
1085          * is bound to Shift+<whatever>, and it appears as though it 
1086          * is XkbTranslateKeyCode that is causing the problem.  The 
1087          * core X version of XTranslateKey always OR's in ShiftMask 
1088          * and LockMask for mods_rtrn, so this "fix" keeps this behavior 
1089          * and solves the VTS problem.
1090          */
1091         if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
1092             (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) {            *mods_rtrn|= (ShiftMask|LockMask);
1093         }
1094 #endif
1095         
1096         /* ---- End stuff GDK comments out of the original Xlib version ---- */
1097     }
1098
1099     /* ---- Begin stuff GDK adds to the original Xlib version ---- */
1100
1101     if (group_rtrn)
1102       *group_rtrn = effectiveGroup;
1103     
1104     /* ---- End stuff GDK adds to the original Xlib version ---- */
1105     
1106     return (syms[col]!=NoSymbol);
1107 }
1108 #endif /* HAVE_XKB */
1109
1110 /* Translates from keycode/state to keysymbol using the traditional interpretation
1111  * of the keyboard map. See section 12.7 of the Xlib reference manual
1112  */
1113 static guint
1114 translate_keysym (GdkKeymapX11   *keymap_x11,
1115                   guint           hardware_keycode,
1116                   gint            group,
1117                   GdkModifierType state,
1118                   guint          *effective_group,
1119                   guint          *effective_level)
1120 {
1121   const KeySym *map = get_keymap (keymap_x11);
1122   const KeySym *syms = map + (hardware_keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
1123
1124 #define SYM(k,g,l) get_symbol (syms, k,g,l)
1125
1126   GdkModifierType shift_modifiers;
1127   gint shift_level;
1128   guint tmp_keyval;
1129   gint num_lock_index;
1130
1131   shift_modifiers = GDK_SHIFT_MASK;
1132   if (keymap_x11->lock_keysym == GDK_Shift_Lock)
1133     shift_modifiers |= GDK_LOCK_MASK;
1134
1135   /* Fall back to the first group if the passed in group is empty
1136    */
1137   if (!(SYM (keymap_x11, group, 0) || SYM (keymap_x11, group, 1)) &&
1138       (SYM (keymap_x11, 0, 0) || SYM (keymap_x11, 0, 1)))
1139     group = 0;
1140
1141   /* Hack: On Sun, the Num Lock modifier uses the third element in the
1142    * keysym array, and Mode_Switch does not apply for a keypad key.
1143    */
1144   if (keymap_x11->sun_keypad)
1145     {
1146       num_lock_index = 2;
1147       
1148       if (group != 0)
1149         {
1150           gint i;
1151           
1152           for (i = 0; i < keymap_x11->keysyms_per_keycode; i++)
1153             if (KEYSYM_IS_KEYPAD (SYM (keymap_x11, 0, i)))
1154               group = 0;
1155         }
1156     }
1157   else
1158     num_lock_index = 1;
1159
1160   if ((state & keymap_x11->num_lock_mask) &&
1161       KEYSYM_IS_KEYPAD (SYM (keymap_x11, group, num_lock_index)))
1162     {
1163       /* Shift, Shift_Lock cancel Num_Lock
1164        */
1165       shift_level = (state & shift_modifiers) ? 0 : num_lock_index;
1166       if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, group, 0))
1167         shift_level = 0;
1168
1169        tmp_keyval = SYM (keymap_x11, group, shift_level);
1170     }
1171   else
1172     {
1173       /* Fall back to the first level if no symbol for the level
1174        * we were passed.
1175        */
1176       shift_level = (state & shift_modifiers) ? 1 : 0;
1177       if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, group, 0))
1178         shift_level = 0;
1179   
1180       tmp_keyval = SYM (keymap_x11, group, shift_level);
1181       
1182       if (keymap_x11->lock_keysym == GDK_Caps_Lock && (state & GDK_LOCK_MASK) != 0)
1183         {
1184           guint upper = gdk_keyval_to_upper (tmp_keyval);
1185           if (upper != tmp_keyval)
1186             tmp_keyval = upper;
1187         }
1188     }
1189
1190   if (effective_group)
1191     *effective_group = group;
1192       
1193   if (effective_level)
1194     *effective_level = shift_level;
1195
1196   return tmp_keyval;
1197   
1198 #undef SYM
1199 }
1200
1201 /**
1202  * gdk_keymap_translate_keyboard_state:
1203  * @keymap: a #GdkKeymap, or %NULL to use the default
1204  * @hardware_keycode: a keycode
1205  * @state: a modifier state 
1206  * @group: active keyboard group
1207  * @keyval: return location for keyval
1208  * @effective_group: return location for effective group
1209  * @level: return location for level
1210  * @consumed_modifiers: return location for modifiers that were used to determine the group or level
1211  * 
1212  *
1213  * Translates the contents of a #GdkEventKey into a keyval, effective
1214  * group, and level. Modifiers that affected the translation and
1215  * are thus unavailable for application use are returned in
1216  * @consumed_modifiers.  See gdk_keyval_get_keys() for an explanation of
1217  * groups and levels.  The @effective_group is the group that was
1218  * actually used for the translation; some keys such as Enter are not
1219  * affected by the active keyboard group. The @level is derived from
1220  * @state. For convenience, #GdkEventKey already contains the translated
1221  * keyval, so this function isn't as useful as you might think.
1222  *
1223  * <note><para>
1224  * @consumed_modifiers gives modifiers that should be masked out
1225  * from @state when comparing this key press to a hot key. For
1226  * instance, on a US keyboard, the <literal>plus</literal>
1227  * symbol is shifted, so when comparing a key press to a
1228  * <literal>&lt;Control&gt;plus</literal> accelerator &lt;Shift&gt; should
1229  * be masked out.
1230  * </para>
1231  * <informalexample><programlisting>
1232  * &sol;* We want to ignore irrelevant modifiers like ScrollLock *&sol;
1233  * &num;define ALL_ACCELS_MASK (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK)
1234  * gdk_keymap_translate_keyboard_state (keymap, event->hardware_keycode,
1235  *                                      event->state, event->group,
1236  *                                      &amp;keyval, NULL, NULL, &amp;consumed);
1237  * if (keyval == GDK_PLUS &&
1238  *     (event->state &amp; ~consumed &amp; ALL_ACCELS_MASK) == GDK_CONTROL_MASK)
1239  *   &sol;* Control was pressed *&sol;
1240  * </programlisting></informalexample>
1241  * <para>
1242  * An older interpretation @consumed_modifiers was that it contained
1243  * all modifiers that might affect the translation of the key;
1244  * this allowed accelerators to be stored with irrelevant consumed
1245  * modifiers, by doing:</para>
1246  * <informalexample><programlisting>
1247  * &sol;* XXX Don't do this XXX *&sol;
1248  * if (keyval == accel_keyval &&
1249  *     (event->state &amp; ~consumed &amp; ALL_ACCELS_MASK) == (accel_mods &amp; ~consumed))
1250  *   &sol;* Accelerator was pressed *&sol;
1251  * </programlisting></informalexample>
1252  * <para>
1253  * However, this did not work if multi-modifier combinations were
1254  * used in the keymap, since, for instance, <literal>&lt;Control&gt;</literal>
1255  * would be masked out even if only <literal>&lt;Control&gt;&lt;Alt&gt;</literal>
1256  * was used in the keymap. To support this usage as well as well as
1257  * possible, all <emphasis>single modifier</emphasis> combinations
1258  * that could affect the key for any combination of modifiers will
1259  * be returned in @consumed_modifiers; multi-modifier combinations
1260  * are returned only when actually found in @state. When you store
1261  * accelerators, you should always store them with consumed modifiers
1262  * removed. Store <literal>&lt;Control&gt;plus</literal>,
1263  * not <literal>&lt;Control&gt;&lt;Shift&gt;plus</literal>,
1264  * </para></note>
1265  * 
1266  * Return value: %TRUE if there was a keyval bound to the keycode/state/group
1267  **/
1268 gboolean
1269 gdk_keymap_translate_keyboard_state (GdkKeymap       *keymap,
1270                                      guint            hardware_keycode,
1271                                      GdkModifierType  state,
1272                                      gint             group,
1273                                      guint           *keyval,
1274                                      gint            *effective_group,
1275                                      gint            *level,
1276                                      GdkModifierType *consumed_modifiers)
1277 {
1278   GdkKeymapX11 *keymap_x11;
1279   KeySym tmp_keyval = NoSymbol;
1280   guint tmp_modifiers;
1281
1282   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
1283   g_return_val_if_fail (group < 4, FALSE);
1284
1285   keymap = GET_EFFECTIVE_KEYMAP (keymap);  
1286   keymap_x11 = GDK_KEYMAP_X11 (keymap);
1287
1288   if (keyval)
1289     *keyval = NoSymbol;
1290   if (effective_group)
1291     *effective_group = 0;
1292   if (level)
1293     *level = 0;
1294   if (consumed_modifiers)
1295     *consumed_modifiers = 0;
1296
1297   update_keyrange (keymap_x11);
1298   
1299   if (hardware_keycode < keymap_x11->min_keycode ||
1300       hardware_keycode > keymap_x11->max_keycode)
1301     return FALSE;
1302   
1303 #ifdef HAVE_XKB
1304   if (KEYMAP_USE_XKB (keymap))
1305     {
1306       XkbDescRec *xkb = get_xkb (keymap_x11);
1307
1308       /* replace bits 13 and 14 with the provided group */
1309       state &= ~(1 << 13 | 1 << 14);
1310       state |= group << 13;
1311       
1312       MyEnhancedXkbTranslateKeyCode (xkb,
1313                                      hardware_keycode,
1314                                      state,
1315                                      &tmp_modifiers,
1316                                      &tmp_keyval,
1317                                      effective_group,
1318                                      level);
1319
1320       if (state & ~tmp_modifiers & LockMask)
1321         tmp_keyval = gdk_keyval_to_upper (tmp_keyval);
1322
1323       /* We need to augment the consumed modifiers with LockMask, since
1324        * we handle that ourselves, and also with the group bits
1325        */
1326       tmp_modifiers |= LockMask | 1 << 13 | 1 << 14;
1327     }
1328   else
1329 #endif
1330     {
1331       GdkModifierType bit;
1332       
1333       tmp_modifiers = 0;
1334
1335       /* We see what modifiers matter by trying the translation with
1336        * and without each possible modifier
1337        */
1338       for (bit = GDK_SHIFT_MASK; bit < GDK_BUTTON1_MASK; bit <<= 1)
1339         {
1340           /* Handling of the group here is a bit funky; a traditional
1341            * X keyboard map can have more than two groups, but no way
1342            * of accessing the extra groups is defined. We allow a
1343            * caller to pass in any group to this function, but we 
1344            * only can represent switching between group 0 and 1 in
1345            * consumed modifiers.
1346            */
1347           if (translate_keysym (keymap_x11, hardware_keycode,
1348                                 (bit == keymap_x11->group_switch_mask) ? 0 : group,
1349                                 state & ~bit,
1350                                 NULL, NULL) !=
1351               translate_keysym (keymap_x11, hardware_keycode,
1352                                 (bit == keymap_x11->group_switch_mask) ? 1 : group,
1353                                 state | bit,
1354                                 NULL, NULL))
1355             tmp_modifiers |= bit;
1356         }
1357       
1358       tmp_keyval = translate_keysym (keymap_x11, hardware_keycode,
1359                                      group, state,
1360                                      level, effective_group);
1361     }
1362
1363   if (consumed_modifiers)
1364     *consumed_modifiers = tmp_modifiers;
1365                                 
1366   if (keyval)
1367     *keyval = tmp_keyval;
1368
1369   return tmp_keyval != NoSymbol;
1370 }
1371
1372
1373 /* Key handling not part of the keymap */
1374
1375 gchar*
1376 gdk_keyval_name (guint        keyval)
1377 {
1378   switch (keyval)
1379     {
1380     case GDK_Page_Up:
1381       return "Page_Up";
1382     case GDK_Page_Down:
1383       return "Page_Down";
1384     case GDK_KP_Page_Up:
1385       return "KP_Page_Up";
1386     case GDK_KP_Page_Down:
1387       return "KP_Page_Down";
1388     }
1389   
1390   return XKeysymToString (keyval);
1391 }
1392
1393 guint
1394 gdk_keyval_from_name (const gchar *keyval_name)
1395 {
1396   g_return_val_if_fail (keyval_name != NULL, 0);
1397   
1398   return XStringToKeysym (keyval_name);
1399 }
1400
1401 #ifdef HAVE_XCONVERTCASE
1402 void
1403 gdk_keyval_convert_case (guint symbol,
1404                          guint *lower,
1405                          guint *upper)
1406 {
1407   KeySym xlower = 0;
1408   KeySym xupper = 0;
1409
1410   /* Check for directly encoded 24-bit UCS characters: */
1411   if ((symbol & 0xff000000) == 0x01000000)
1412     {
1413       if (lower)
1414         *lower = gdk_unicode_to_keyval (g_unichar_tolower (symbol & 0x00ffffff));
1415       if (upper)
1416         *upper = gdk_unicode_to_keyval (g_unichar_toupper (symbol & 0x00ffffff));
1417       return;
1418     }
1419   
1420   if (symbol)
1421     XConvertCase (symbol, &xlower, &xupper);
1422
1423   if (lower)
1424     *lower = xlower;
1425   if (upper)
1426     *upper = xupper;
1427 }  
1428 #endif /* HAVE_XCONVERTCASE */
1429
1430 gint
1431 _gdk_x11_get_group_for_state (GdkDisplay      *display,
1432                               GdkModifierType  state)
1433 {
1434   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1435   
1436 #ifdef HAVE_XKB
1437   if (display_x11->use_xkb)
1438     {
1439       return XkbGroupForCoreState (state);
1440     }
1441   else
1442 #endif
1443     {
1444       GdkKeymapX11 *keymap_impl = GDK_KEYMAP_X11 (gdk_keymap_get_for_display (display));
1445       update_keymaps (keymap_impl);
1446       return (state & keymap_impl->group_switch_mask) ? 1 : 0;
1447     }
1448 }
1449
1450 #define __GDK_KEYS_X11_C__
1451 #include "gdkaliasdef.c"