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