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