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