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