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