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