1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 2000 Red Hat, Inc.
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.
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.
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.
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/.
37 #include "gdkwayland.h"
39 #include "gdkprivate-wayland.h"
40 #include "gdkinternals.h"
41 #include "gdkdisplay-wayland.h"
42 #include "gdkkeysprivate.h"
44 #include <X11/extensions/XKBcommon.h>
46 typedef struct _GdkWaylandKeymap GdkWaylandKeymap;
47 typedef struct _GdkWaylandKeymapClass GdkWaylandKeymapClass;
49 struct _GdkWaylandKeymap
51 GdkKeymap parent_instance;
52 GdkModifierType modmap[8];
56 struct _GdkWaylandKeymapClass
58 GdkKeymapClass parent_class;
61 #define GDK_TYPE_WAYLAND_KEYMAP (_gdk_wayland_keymap_get_type ())
62 #define GDK_WAYLAND_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_KEYMAP, GdkWaylandKeymap))
63 #define GDK_IS_WAYLAND_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_KEYMAP))
65 G_DEFINE_TYPE (GdkWaylandKeymap, _gdk_wayland_keymap, GDK_TYPE_KEYMAP)
68 gdk_wayland_keymap_finalize (GObject *object)
70 G_OBJECT_CLASS (_gdk_wayland_keymap_parent_class)->finalize (object);
74 gdk_wayland_keymap_get_direction (GdkKeymap *keymap)
76 return PANGO_DIRECTION_NEUTRAL;
80 gdk_wayland_keymap_have_bidi_layouts (GdkKeymap *keymap)
86 gdk_wayland_keymap_get_caps_lock_state (GdkKeymap *keymap)
92 gdk_wayland_keymap_get_num_lock_state (GdkKeymap *keymap)
98 gdk_wayland_keymap_get_entries_for_keyval (GdkKeymap *keymap,
105 struct xkb_desc *xkb;
107 xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
108 keycode = xkb->min_key_code;
110 retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
112 for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++)
114 gint max_shift_levels = XkbKeyGroupsWidth (xkb, keycode);
118 gint total_syms = XkbKeyNumSyms (xkb, keycode);
122 /* entry is an array with all syms for group 0, all
123 * syms for group 1, etc. and for each group the
124 * shift level syms are in order
126 entry = XkbKeySymsPtr (xkb, keycode);
128 for (i = 0; i < total_syms; i++)
130 /* check out our cool loop invariant */
131 g_assert (i == (group * max_shift_levels + level));
133 if (entry[i] == keyval)
138 key.keycode = keycode;
142 g_array_append_val (retval, key);
144 g_assert (XkbKeySymEntry (xkb, keycode, level, group) ==
150 if (level == max_shift_levels)
158 *n_keys = retval->len;
159 *keys = (GdkKeymapKey *) g_array_free (retval, FALSE);
165 gdk_wayland_keymap_get_entries_for_keycode (GdkKeymap *keymap,
166 guint hardware_keycode,
172 GArray *keyval_array;
173 struct xkb_desc *xkb;
174 gint max_shift_levels;
181 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
182 g_return_val_if_fail (n_entries != NULL, FALSE);
184 xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
186 if (hardware_keycode < xkb->min_key_code ||
187 hardware_keycode > xkb->max_key_code)
199 key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
204 keyval_array = g_array_new (FALSE, FALSE, sizeof (guint));
208 /* See sec 15.3.4 in XKB docs */
209 max_shift_levels = XkbKeyGroupsWidth (xkb, hardware_keycode);
210 total_syms = XkbKeyNumSyms (xkb, hardware_keycode);
212 /* entry is an array with all syms for group 0, all
213 * syms for group 1, etc. and for each group the
214 * shift level syms are in order
216 entry = XkbKeySymsPtr (xkb, hardware_keycode);
218 for (i = 0; i < total_syms; i++)
220 /* check out our cool loop invariant */
221 g_assert (i == (group * max_shift_levels + level));
227 key.keycode = hardware_keycode;
231 g_array_append_val (key_array, key);
235 g_array_append_val (keyval_array, entry[i]);
239 if (level == max_shift_levels)
250 *n_entries = key_array->len;
251 *keys = (GdkKeymapKey*) g_array_free (key_array, FALSE);
256 *n_entries = keyval_array->len;
257 *keyvals = (guint*) g_array_free (keyval_array, FALSE);
260 return *n_entries > 0;
264 gdk_wayland_keymap_lookup_key (GdkKeymap *keymap,
265 const GdkKeymapKey *key)
267 struct xkb_desc *xkb;
269 xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
271 return XkbKeySymEntry (xkb, key->keycode, key->level, key->group);
274 /* This is copied straight from XFree86 Xlib, to:
275 * - add the group and level return.
276 * - change the interpretation of mods_rtrn as described
277 * in the docs for gdk_keymap_translate_keyboard_state()
278 * It's unchanged for ease of diff against the Xlib sources; don't
282 MyEnhancedXkbTranslateKeyCode(struct xkb_desc * xkb,
285 unsigned int * mods_rtrn,
286 uint32_t * keysym_rtrn,
290 struct xkb_key_type *type;
292 unsigned preserve,effectiveGroup;
298 nKeyGroups= XkbKeyNumGroups(xkb,key);
299 if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
300 if (keysym_rtrn!=NULL)
305 syms = XkbKeySymsPtr(xkb,key);
307 /* find the offset of the effective group */
309 effectiveGroup= XkbGroupForCoreState(mods);
310 if ( effectiveGroup>=nKeyGroups ) {
311 unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
312 switch (XkbOutOfRangeGroupAction(groupInfo)) {
314 effectiveGroup %= nKeyGroups;
316 case XkbClampIntoRange:
317 effectiveGroup = nKeyGroups-1;
319 case XkbRedirectIntoRange:
320 effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
321 if (effectiveGroup>=nKeyGroups)
326 col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
327 type = XkbKeyKeyType(xkb,key,effectiveGroup);
330 if (type->map) { /* find the column (shift level) within the group */
332 struct xkb_kt_map_entry *entry;
333 /* ---- Begin section modified for GDK ---- */
336 for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
339 unsigned long tmp = entry->mods.mask;
345 /* We always add one-modifiers levels to mods_rtrn since
346 * they can't wipe out bits in the state unless the
347 * level would be triggered. But return other modifiers
350 if (bits == 1 || (mods&type->mods.mask)==entry->mods.mask)
351 *mods_rtrn |= entry->mods.mask;
354 if (!found&&entry->active&&((mods&type->mods.mask)==entry->mods.mask)) {
357 preserve= type->preserve[i].mask;
360 *level_rtrn = entry->level;
365 /* ---- End section modified for GDK ---- */
368 if (keysym_rtrn!=NULL)
369 *keysym_rtrn= syms[col];
371 /* ---- Begin section modified for GDK ---- */
372 *mods_rtrn &= ~preserve;
373 /* ---- End section modified for GDK ---- */
375 /* ---- Begin stuff GDK comments out of the original Xlib version ---- */
376 /* This is commented out because xkb_info is a private struct */
379 /* The Motif VTS doesn't get the help callback called if help
380 * is bound to Shift+<whatever>, and it appears as though it
381 * is XkbTranslateKeyCode that is causing the problem. The
382 * core X version of XTranslateKey always OR's in ShiftMask
383 * and LockMask for mods_rtrn, so this "fix" keeps this behavior
384 * and solves the VTS problem.
386 if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
387 (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) { *mods_rtrn|= (ShiftMask|LockMask);
391 /* ---- End stuff GDK comments out of the original Xlib version ---- */
394 /* ---- Begin stuff GDK adds to the original Xlib version ---- */
397 *group_rtrn = effectiveGroup;
399 /* ---- End stuff GDK adds to the original Xlib version ---- */
401 return (syms[col] != 0);
405 gdk_wayland_keymap_translate_keyboard_state (GdkKeymap *keymap,
406 guint hardware_keycode,
407 GdkModifierType state,
410 gint *effective_group,
412 GdkModifierType *consumed_modifiers)
414 GdkWaylandKeymap *wayland_keymap;
415 uint32_t tmp_keyval = 0;
417 struct xkb_desc *xkb;
419 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
420 g_return_val_if_fail (group < 4, FALSE);
422 wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
423 xkb = wayland_keymap->xkb;
428 *effective_group = 0;
431 if (consumed_modifiers)
432 *consumed_modifiers = 0;
434 if (hardware_keycode < xkb->min_key_code ||
435 hardware_keycode > xkb->max_key_code)
439 /* replace bits 13 and 14 with the provided group */
440 state &= ~(1 << 13 | 1 << 14);
441 state |= group << 13;
443 MyEnhancedXkbTranslateKeyCode (xkb,
451 if (state & ~tmp_modifiers & XKB_COMMON_LOCK_MASK)
452 tmp_keyval = gdk_keyval_to_upper (tmp_keyval);
454 /* We need to augment the consumed modifiers with LockMask, since
455 * we handle that ourselves, and also with the group bits
457 tmp_modifiers |= XKB_COMMON_LOCK_MASK | 1 << 13 | 1 << 14;
460 if (consumed_modifiers)
461 *consumed_modifiers = tmp_modifiers;
464 *keyval = tmp_keyval;
466 return tmp_keyval != 0;
471 update_modmap (GdkWaylandKeymap *wayland_keymap)
476 GdkModifierType mask;
478 { "Meta", 0, GDK_META_MASK },
479 { "Super", 0, GDK_SUPER_MASK },
480 { "Hyper", 0, GDK_HYPER_MASK },
487 for (i = 0; vmods[i].name; i++)
488 vmods[i].atom = xkb_intern_atom(vmods[i].name);
490 for (i = 0; i < 8; i++)
491 wayland_keymap->modmap[i] = 1 << i;
493 for (i = 0; i < XkbNumVirtualMods; i++)
495 for (j = 0; vmods[j].atom; j++)
497 if (wayland_keymap->xkb->names->vmods[i] == vmods[j].atom)
499 for (k = 0; k < 8; k++)
501 if (wayland_keymap->xkb->server->vmods[i] & (1 << k))
502 wayland_keymap->modmap[k] |= vmods[j].mask;
510 gdk_wayland_keymap_add_virtual_modifiers (GdkKeymap *keymap,
511 GdkModifierType *state)
513 GdkWaylandKeymap *wayland_keymap;
516 wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
518 for (i = 4; i < 8; i++)
520 if ((1 << i) & *state)
522 if (wayland_keymap->modmap[i] & GDK_SUPER_MASK)
523 *state |= GDK_SUPER_MASK;
524 if (wayland_keymap->modmap[i] & GDK_HYPER_MASK)
525 *state |= GDK_HYPER_MASK;
526 if (wayland_keymap->modmap[i] & GDK_META_MASK)
527 *state |= GDK_META_MASK;
533 gdk_wayland_keymap_map_virtual_modifiers (GdkKeymap *keymap,
534 GdkModifierType *state)
536 const guint vmods[] = {
537 GDK_SUPER_MASK, GDK_HYPER_MASK, GDK_META_MASK
540 GdkWaylandKeymap *wayland_keymap;
541 gboolean retval = TRUE;
543 wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
545 for (j = 0; j < 3; j++)
547 if (*state & vmods[j])
549 for (i = 4; i < 8; i++)
551 if (wayland_keymap->modmap[i] & vmods[j])
553 if (*state & (1 << i))
566 _gdk_wayland_keymap_class_init (GdkWaylandKeymapClass *klass)
568 GObjectClass *object_class = G_OBJECT_CLASS (klass);
569 GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
571 object_class->finalize = gdk_wayland_keymap_finalize;
573 keymap_class->get_direction = gdk_wayland_keymap_get_direction;
574 keymap_class->have_bidi_layouts = gdk_wayland_keymap_have_bidi_layouts;
575 keymap_class->get_caps_lock_state = gdk_wayland_keymap_get_caps_lock_state;
576 keymap_class->get_num_lock_state = gdk_wayland_keymap_get_num_lock_state;
577 keymap_class->get_entries_for_keyval = gdk_wayland_keymap_get_entries_for_keyval;
578 keymap_class->get_entries_for_keycode = gdk_wayland_keymap_get_entries_for_keycode;
579 keymap_class->lookup_key = gdk_wayland_keymap_lookup_key;
580 keymap_class->translate_keyboard_state = gdk_wayland_keymap_translate_keyboard_state;
581 keymap_class->add_virtual_modifiers = gdk_wayland_keymap_add_virtual_modifiers;
582 keymap_class->map_virtual_modifiers = gdk_wayland_keymap_map_virtual_modifiers;
586 _gdk_wayland_keymap_init (GdkWaylandKeymap *keymap)
591 update_keymaps (GdkWaylandKeymap *keymap)
593 struct xkb_desc *xkb = keymap->xkb;
594 gint keycode, total_syms, i, modifier;
598 for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++)
600 total_syms = XkbKeyNumSyms (xkb, keycode);
602 entry = XkbKeySymsPtr (xkb, keycode);
604 for (i = 0; i < total_syms; i++)
609 mask |= GDK_META_MASK;
611 case GDK_KEY_Hyper_L:
612 case GDK_KEY_Hyper_R:
613 mask |= GDK_HYPER_MASK;
615 case GDK_KEY_Super_L:
616 case GDK_KEY_Super_R:
617 mask |= GDK_SUPER_MASK;
622 modifier = g_bit_nth_lsf(xkb->map->modmap[keycode], -1);
623 keymap->modmap[modifier] |= mask;
628 _gdk_wayland_keymap_new (GdkDisplay *display)
630 GdkWaylandKeymap *keymap;
631 struct xkb_rule_names names;
633 keymap = g_object_new (_gdk_wayland_keymap_get_type(), NULL);
634 GDK_KEYMAP (keymap)->display = display;
636 names.rules = "evdev";
637 names.model = "pc105";
641 keymap->xkb = xkb_compile_keymap_from_rules(&names);
643 update_modmap (keymap);
644 update_keymaps (keymap);
646 return GDK_KEYMAP (keymap);
649 struct xkb_desc *_gdk_wayland_keymap_get_xkb_desc (GdkKeymap *keymap)
651 return GDK_WAYLAND_KEYMAP (keymap)->xkb;