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, see <http://www.gnu.org/licenses/>.
19 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
36 #include "gdkwayland.h"
38 #include "gdkprivate-wayland.h"
39 #include "gdkinternals.h"
40 #include "gdkkeysprivate.h"
42 #include <xkbcommon/xkbcommon.h>
44 typedef struct _GdkWaylandKeymap GdkWaylandKeymap;
45 typedef struct _GdkWaylandKeymapClass GdkWaylandKeymapClass;
47 struct _GdkWaylandKeymap
49 GdkKeymap parent_instance;
51 struct xkb_keymap *xkb_keymap;
52 struct xkb_state *xkb_state;
55 struct _GdkWaylandKeymapClass
57 GdkKeymapClass parent_class;
60 #define GDK_TYPE_WAYLAND_KEYMAP (_gdk_wayland_keymap_get_type ())
61 #define GDK_WAYLAND_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_KEYMAP, GdkWaylandKeymap))
62 #define GDK_IS_WAYLAND_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_KEYMAP))
64 G_DEFINE_TYPE (GdkWaylandKeymap, _gdk_wayland_keymap, GDK_TYPE_KEYMAP)
67 gdk_wayland_keymap_finalize (GObject *object)
69 G_OBJECT_CLASS (_gdk_wayland_keymap_parent_class)->finalize (object);
73 gdk_wayland_keymap_get_direction (GdkKeymap *keymap)
75 return PANGO_DIRECTION_NEUTRAL;
79 gdk_wayland_keymap_have_bidi_layouts (GdkKeymap *keymap)
85 gdk_wayland_keymap_get_caps_lock_state (GdkKeymap *keymap)
91 gdk_wayland_keymap_get_num_lock_state (GdkKeymap *keymap)
97 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);
167 gdk_wayland_keymap_get_entries_for_keycode (GdkKeymap *keymap,
168 guint hardware_keycode,
175 GArray *keyval_array;
176 struct xkb_desc *xkb;
177 gint max_shift_levels;
184 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
185 g_return_val_if_fail (n_entries != NULL, FALSE);
187 xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
189 if (hardware_keycode < xkb->min_key_code ||
190 hardware_keycode > xkb->max_key_code)
202 key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
207 keyval_array = g_array_new (FALSE, FALSE, sizeof (guint));
211 /* See sec 15.3.4 in XKB docs */
212 max_shift_levels = XkbKeyGroupsWidth (xkb, hardware_keycode);
213 total_syms = XkbKeyNumSyms (xkb, hardware_keycode);
215 /* entry is an array with all syms for group 0, all
216 * syms for group 1, etc. and for each group the
217 * shift level syms are in order
219 entry = XkbKeySymsPtr (xkb, hardware_keycode);
221 for (i = 0; i < total_syms; i++)
223 /* check out our cool loop invariant */
224 g_assert (i == (group * max_shift_levels + level));
230 key.keycode = hardware_keycode;
234 g_array_append_val (key_array, key);
238 g_array_append_val (keyval_array, entry[i]);
242 if (level == max_shift_levels)
253 *n_entries = key_array->len;
254 *keys = (GdkKeymapKey*) g_array_free (key_array, FALSE);
259 *n_entries = keyval_array->len;
260 *keyvals = (guint*) g_array_free (keyval_array, FALSE);
263 return *n_entries > 0;
269 gdk_wayland_keymap_lookup_key (GdkKeymap *keymap,
270 const GdkKeymapKey *key)
273 struct xkb_desc *xkb;
275 xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
277 return XkbKeySymEntry (xkb, key->keycode, key->level, key->group);
283 /* This is copied straight from XFree86 Xlib, to:
284 * - add the group and level return.
285 * - change the interpretation of mods_rtrn as described
286 * in the docs for gdk_keymap_translate_keyboard_state()
287 * It's unchanged for ease of diff against the Xlib sources; don't
291 MyEnhancedXkbTranslateKeyCode(struct xkb_desc * xkb,
294 unsigned int * mods_rtrn,
295 uint32_t * keysym_rtrn,
299 struct xkb_key_type *type;
301 unsigned preserve,effectiveGroup;
307 nKeyGroups= XkbKeyNumGroups(xkb,key);
308 if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
309 if (keysym_rtrn!=NULL)
314 syms = XkbKeySymsPtr(xkb,key);
316 /* find the offset of the effective group */
318 effectiveGroup= XkbGroupForCoreState(mods);
319 if ( effectiveGroup>=nKeyGroups ) {
320 unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
321 switch (XkbOutOfRangeGroupAction(groupInfo)) {
323 effectiveGroup %= nKeyGroups;
325 case XkbClampIntoRange:
326 effectiveGroup = nKeyGroups-1;
328 case XkbRedirectIntoRange:
329 effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
330 if (effectiveGroup>=nKeyGroups)
335 col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
336 type = XkbKeyKeyType(xkb,key,effectiveGroup);
339 if (type->map) { /* find the column (shift level) within the group */
341 struct xkb_kt_map_entry *entry;
342 /* ---- Begin section modified for GDK ---- */
345 for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
348 unsigned long tmp = entry->mods.mask;
354 /* We always add one-modifiers levels to mods_rtrn since
355 * they can't wipe out bits in the state unless the
356 * level would be triggered. But return other modifiers
359 if (bits == 1 || (mods&type->mods.mask)==entry->mods.mask)
360 *mods_rtrn |= entry->mods.mask;
363 if (!found&&entry->active&&((mods&type->mods.mask)==entry->mods.mask)) {
366 preserve= type->preserve[i].mask;
369 *level_rtrn = entry->level;
374 /* ---- End section modified for GDK ---- */
377 if (keysym_rtrn!=NULL)
378 *keysym_rtrn= syms[col];
380 /* ---- Begin section modified for GDK ---- */
381 *mods_rtrn &= ~preserve;
382 /* ---- End section modified for GDK ---- */
384 /* ---- Begin stuff GDK comments out of the original Xlib version ---- */
385 /* This is commented out because xkb_info is a private struct */
388 /* The Motif VTS doesn't get the help callback called if help
389 * is bound to Shift+<whatever>, and it appears as though it
390 * is XkbTranslateKeyCode that is causing the problem. The
391 * core X version of XTranslateKey always OR's in ShiftMask
392 * and LockMask for mods_rtrn, so this "fix" keeps this behavior
393 * and solves the VTS problem.
395 if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
396 (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) { *mods_rtrn|= (ShiftMask|LockMask);
400 /* ---- End stuff GDK comments out of the original Xlib version ---- */
403 /* ---- Begin stuff GDK adds to the original Xlib version ---- */
406 *group_rtrn = effectiveGroup;
408 /* ---- End stuff GDK adds to the original Xlib version ---- */
410 return (syms[col] != 0);
415 gdk_wayland_keymap_translate_keyboard_state (GdkKeymap *keymap,
416 guint hardware_keycode,
417 GdkModifierType state,
420 gint *effective_group,
422 GdkModifierType *consumed_modifiers)
425 GdkWaylandKeymap *wayland_keymap;
426 uint32_t tmp_keyval = 0;
428 struct xkb_desc *xkb;
430 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
431 g_return_val_if_fail (group < 4, FALSE);
433 wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
434 xkb = wayland_keymap->xkb;
439 *effective_group = 0;
442 if (consumed_modifiers)
443 *consumed_modifiers = 0;
445 if (hardware_keycode < xkb->min_key_code ||
446 hardware_keycode > xkb->max_key_code)
450 /* replace bits 13 and 14 with the provided group */
451 state &= ~(1 << 13 | 1 << 14);
452 state |= group << 13;
454 MyEnhancedXkbTranslateKeyCode (xkb,
462 if (state & ~tmp_modifiers & XKB_COMMON_LOCK_MASK)
463 tmp_keyval = gdk_keyval_to_upper (tmp_keyval);
465 /* We need to augment the consumed modifiers with LockMask, since
466 * we handle that ourselves, and also with the group bits
468 tmp_modifiers |= XKB_COMMON_LOCK_MASK | 1 << 13 | 1 << 14;
471 if (consumed_modifiers)
472 *consumed_modifiers = tmp_modifiers;
475 *keyval = tmp_keyval;
477 return tmp_keyval != 0;
484 update_modmap (GdkWaylandKeymap *wayland_keymap)
489 GdkModifierType mask;
491 { "Meta", 0, GDK_META_MASK },
492 { "Super", 0, GDK_SUPER_MASK },
493 { "Hyper", 0, GDK_HYPER_MASK },
500 for (i = 0; vmods[i].name; i++)
501 vmods[i].atom = xkb_atom(vmods[i].name);
503 for (i = 0; i < 8; i++)
504 wayland_keymap->modmap[i] = 1 << i;
506 for (i = 0; i < XkbNumVirtualMods; i++)
508 for (j = 0; vmods[j].atom; j++)
510 if (wayland_keymap->xkb->names->vmods[i] == vmods[j].atom)
512 for (k = 0; k < 8; k++)
514 if (wayland_keymap->xkb->server->vmods[i] & (1 << k))
515 wayland_keymap->modmap[k] |= vmods[j].mask;
524 gdk_wayland_keymap_add_virtual_modifiers (GdkKeymap *keymap,
525 GdkModifierType *state)
527 GdkWaylandKeymap *wayland_keymap;
530 wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
532 for (i = 4; i < 8; i++)
534 if ((1 << i) & *state)
536 if (wayland_keymap->modmap[i] & GDK_SUPER_MASK)
537 *state |= GDK_SUPER_MASK;
538 if (wayland_keymap->modmap[i] & GDK_HYPER_MASK)
539 *state |= GDK_HYPER_MASK;
540 if (wayland_keymap->modmap[i] & GDK_META_MASK)
541 *state |= GDK_META_MASK;
547 gdk_wayland_keymap_map_virtual_modifiers (GdkKeymap *keymap,
548 GdkModifierType *state)
550 const guint vmods[] = {
551 GDK_SUPER_MASK, GDK_HYPER_MASK, GDK_META_MASK
554 GdkWaylandKeymap *wayland_keymap;
555 gboolean retval = TRUE;
557 wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
559 for (j = 0; j < 3; j++)
561 if (*state & vmods[j])
563 for (i = 4; i < 8; i++)
565 if (wayland_keymap->modmap[i] & vmods[j])
567 if (*state & (1 << i))
580 _gdk_wayland_keymap_class_init (GdkWaylandKeymapClass *klass)
582 GObjectClass *object_class = G_OBJECT_CLASS (klass);
583 GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
585 object_class->finalize = gdk_wayland_keymap_finalize;
587 keymap_class->get_direction = gdk_wayland_keymap_get_direction;
588 keymap_class->have_bidi_layouts = gdk_wayland_keymap_have_bidi_layouts;
589 keymap_class->get_caps_lock_state = gdk_wayland_keymap_get_caps_lock_state;
590 keymap_class->get_num_lock_state = gdk_wayland_keymap_get_num_lock_state;
591 keymap_class->get_entries_for_keyval = gdk_wayland_keymap_get_entries_for_keyval;
592 keymap_class->get_entries_for_keycode = gdk_wayland_keymap_get_entries_for_keycode;
593 keymap_class->lookup_key = gdk_wayland_keymap_lookup_key;
594 keymap_class->translate_keyboard_state = gdk_wayland_keymap_translate_keyboard_state;
595 keymap_class->add_virtual_modifiers = gdk_wayland_keymap_add_virtual_modifiers;
596 keymap_class->map_virtual_modifiers = gdk_wayland_keymap_map_virtual_modifiers;
600 _gdk_wayland_keymap_init (GdkWaylandKeymap *keymap)
606 update_keymaps (GdkWaylandKeymap *keymap)
608 struct xkb_desc *xkb = keymap->xkb;
609 gint keycode, total_syms, i, modifier;
613 for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++)
615 total_syms = XkbKeyNumSyms (xkb, keycode);
617 entry = XkbKeySymsPtr (xkb, keycode);
619 for (i = 0; i < total_syms; i++)
624 mask |= GDK_META_MASK;
626 case GDK_KEY_Hyper_L:
627 case GDK_KEY_Hyper_R:
628 mask |= GDK_HYPER_MASK;
630 case GDK_KEY_Super_L:
631 case GDK_KEY_Super_R:
632 mask |= GDK_SUPER_MASK;
637 modifier = g_bit_nth_lsf(xkb->map->modmap[keycode], -1);
638 keymap->modmap[modifier] |= mask;
644 _gdk_wayland_keymap_new ()
646 GdkWaylandKeymap *keymap;
647 struct xkb_context *context;
648 struct xkb_rule_names names;
650 keymap = g_object_new (_gdk_wayland_keymap_get_type(), NULL);
652 context = xkb_context_new (0);
654 names.rules = "evdev";
655 names.model = "pc105";
659 keymap->xkb_keymap = xkb_map_new_from_names(context, &names, XKB_MAP_COMPILE_PLACEHOLDER);
660 keymap->xkb_state = xkb_state_new (keymap->xkb_keymap);
661 xkb_context_unref (context);
663 return GDK_KEYMAP (keymap);
667 _gdk_wayland_keymap_new_from_fd (uint32_t format,
668 uint32_t fd, uint32_t size)
670 GdkWaylandKeymap *keymap;
671 struct xkb_context *context;
674 keymap = g_object_new (_gdk_wayland_keymap_get_type(), NULL);
676 context = xkb_context_new (0);
678 map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
679 if (map_str == MAP_FAILED) {
684 keymap->xkb_keymap = xkb_map_new_from_string (context, map_str, format, XKB_MAP_COMPILE_PLACEHOLDER);
685 munmap (map_str, size);
687 keymap->xkb_state = xkb_state_new (keymap->xkb_keymap);
688 xkb_context_unref (context);
690 return GDK_KEYMAP (keymap);
693 struct xkb_keymap *_gdk_wayland_keymap_get_xkb_keymap (GdkKeymap *keymap)
695 return GDK_WAYLAND_KEYMAP (keymap)->xkb_keymap;
698 struct xkb_state *_gdk_wayland_keymap_get_xkb_state (GdkKeymap *keymap)
700 return GDK_WAYLAND_KEYMAP (keymap)->xkb_state;