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