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