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