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