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><Control>plus</literal> accelerator <Shift> should
1462 * be masked out.
1463 * </para>
1464 * <informalexample><programlisting>
1465 * /* We want to ignore irrelevant modifiers like ScrollLock */
1466 * #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 * &keyval, NULL, NULL, &consumed);
1470 * if (keyval == GDK_PLUS &&
1471 * (event->state & ~consumed & ALL_ACCELS_MASK) == GDK_CONTROL_MASK)
1472 * /* Control was pressed */
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 * /* XXX Don't do this XXX */
1481 * if (keyval == accel_keyval &&
1482 * (event->state & ~consumed & ALL_ACCELS_MASK) == (accel_mods & ~consumed))
1483 * /* Accelerator was pressed */
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><Control></literal>
1488 * would be masked out even if only <literal><Control><Alt></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><Control>plus</literal>,
1496 * not <literal><Control><Shift>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