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/.
35 #include "gdkwayland.h"
37 #include "gdkprivate-wayland.h"
38 #include "gdkinternals.h"
39 #include "gdkdisplay-wayland.h"
40 #include "gdkkeysprivate.h"
42 #include <X11/extensions/XKBcommon.h>
44 typedef struct _GdkWaylandKeymap GdkWaylandKeymap;
45 typedef struct _GdkWaylandKeymapClass GdkWaylandKeymapClass;
47 struct _GdkWaylandKeymap
49 GdkKeymap parent_instance;
50 GdkModifierType modmap[8];
54 struct _GdkWaylandKeymapClass
56 GdkKeymapClass parent_class;
59 #define GDK_TYPE_WAYLAND_KEYMAP (_gdk_wayland_keymap_get_type ())
60 #define GDK_WAYLAND_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_KEYMAP, GdkWaylandKeymap))
61 #define GDK_IS_WAYLAND_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_KEYMAP))
63 G_DEFINE_TYPE (GdkWaylandKeymap, _gdk_wayland_keymap, GDK_TYPE_KEYMAP)
66 gdk_wayland_keymap_finalize (GObject *object)
68 G_OBJECT_CLASS (_gdk_wayland_keymap_parent_class)->finalize (object);
72 gdk_wayland_keymap_get_direction (GdkKeymap *keymap)
74 return PANGO_DIRECTION_NEUTRAL;
78 gdk_wayland_keymap_have_bidi_layouts (GdkKeymap *keymap)
84 gdk_wayland_keymap_get_caps_lock_state (GdkKeymap *keymap)
90 gdk_wayland_keymap_get_num_lock_state (GdkKeymap *keymap)
96 gdk_wayland_keymap_get_entries_for_keyval (GdkKeymap *keymap,
103 struct xkb_desc *xkb;
105 xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
106 keycode = xkb->min_key_code;
108 retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
110 for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++)
112 gint max_shift_levels = XkbKeyGroupsWidth (xkb, keycode);
116 gint total_syms = XkbKeyNumSyms (xkb, keycode);
120 /* entry is an array with all syms for group 0, all
121 * syms for group 1, etc. and for each group the
122 * shift level syms are in order
124 entry = XkbKeySymsPtr (xkb, keycode);
126 for (i = 0; i < total_syms; i++)
128 /* check out our cool loop invariant */
129 g_assert (i == (group * max_shift_levels + level));
131 if (entry[i] == keyval)
136 key.keycode = keycode;
140 g_array_append_val (retval, key);
142 g_assert (XkbKeySymEntry (xkb, keycode, level, group) ==
148 if (level == max_shift_levels)
156 *n_keys = retval->len;
157 *keys = (GdkKeymapKey *) g_array_free (retval, FALSE);
163 gdk_wayland_keymap_get_entries_for_keycode (GdkKeymap *keymap,
164 guint hardware_keycode,
170 GArray *keyval_array;
171 struct xkb_desc *xkb;
172 gint max_shift_levels;
179 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
180 g_return_val_if_fail (n_entries != NULL, FALSE);
182 xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
184 if (hardware_keycode < xkb->min_key_code ||
185 hardware_keycode > xkb->max_key_code)
197 key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
202 keyval_array = g_array_new (FALSE, FALSE, sizeof (guint));
206 /* See sec 15.3.4 in XKB docs */
207 max_shift_levels = XkbKeyGroupsWidth (xkb, hardware_keycode);
208 total_syms = XkbKeyNumSyms (xkb, hardware_keycode);
210 /* entry is an array with all syms for group 0, all
211 * syms for group 1, etc. and for each group the
212 * shift level syms are in order
214 entry = XkbKeySymsPtr (xkb, hardware_keycode);
216 for (i = 0; i < total_syms; i++)
218 /* check out our cool loop invariant */
219 g_assert (i == (group * max_shift_levels + level));
225 key.keycode = hardware_keycode;
229 g_array_append_val (key_array, key);
233 g_array_append_val (keyval_array, entry[i]);
237 if (level == max_shift_levels)
248 *n_entries = key_array->len;
249 *keys = (GdkKeymapKey*) g_array_free (key_array, FALSE);
254 *n_entries = keyval_array->len;
255 *keyvals = (guint*) g_array_free (keyval_array, FALSE);
258 return *n_entries > 0;
262 gdk_wayland_keymap_lookup_key (GdkKeymap *keymap,
263 const GdkKeymapKey *key)
265 struct xkb_desc *xkb;
267 xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
269 return XkbKeySymEntry (xkb, key->keycode, key->level, key->group);
272 /* This is copied straight from XFree86 Xlib, to:
273 * - add the group and level return.
274 * - change the interpretation of mods_rtrn as described
275 * in the docs for gdk_keymap_translate_keyboard_state()
276 * It's unchanged for ease of diff against the Xlib sources; don't
280 MyEnhancedXkbTranslateKeyCode(struct xkb_desc * xkb,
283 unsigned int * mods_rtrn,
284 uint32_t * keysym_rtrn,
288 struct xkb_key_type *type;
290 unsigned preserve,effectiveGroup;
296 nKeyGroups= XkbKeyNumGroups(xkb,key);
297 if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
298 if (keysym_rtrn!=NULL)
303 syms = XkbKeySymsPtr(xkb,key);
305 /* find the offset of the effective group */
307 effectiveGroup= XkbGroupForCoreState(mods);
308 if ( effectiveGroup>=nKeyGroups ) {
309 unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
310 switch (XkbOutOfRangeGroupAction(groupInfo)) {
312 effectiveGroup %= nKeyGroups;
314 case XkbClampIntoRange:
315 effectiveGroup = nKeyGroups-1;
317 case XkbRedirectIntoRange:
318 effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
319 if (effectiveGroup>=nKeyGroups)
324 col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
325 type = XkbKeyKeyType(xkb,key,effectiveGroup);
328 if (type->map) { /* find the column (shift level) within the group */
330 struct xkb_kt_map_entry *entry;
331 /* ---- Begin section modified for GDK ---- */
334 for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
337 unsigned long tmp = entry->mods.mask;
343 /* We always add one-modifiers levels to mods_rtrn since
344 * they can't wipe out bits in the state unless the
345 * level would be triggered. But return other modifiers
348 if (bits == 1 || (mods&type->mods.mask)==entry->mods.mask)
349 *mods_rtrn |= entry->mods.mask;
352 if (!found&&entry->active&&((mods&type->mods.mask)==entry->mods.mask)) {
355 preserve= type->preserve[i].mask;
358 *level_rtrn = entry->level;
363 /* ---- End section modified for GDK ---- */
366 if (keysym_rtrn!=NULL)
367 *keysym_rtrn= syms[col];
369 /* ---- Begin section modified for GDK ---- */
370 *mods_rtrn &= ~preserve;
371 /* ---- End section modified for GDK ---- */
373 /* ---- Begin stuff GDK comments out of the original Xlib version ---- */
374 /* This is commented out because xkb_info is a private struct */
377 /* The Motif VTS doesn't get the help callback called if help
378 * is bound to Shift+<whatever>, and it appears as though it
379 * is XkbTranslateKeyCode that is causing the problem. The
380 * core X version of XTranslateKey always OR's in ShiftMask
381 * and LockMask for mods_rtrn, so this "fix" keeps this behavior
382 * and solves the VTS problem.
384 if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
385 (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) { *mods_rtrn|= (ShiftMask|LockMask);
389 /* ---- End stuff GDK comments out of the original Xlib version ---- */
392 /* ---- Begin stuff GDK adds to the original Xlib version ---- */
395 *group_rtrn = effectiveGroup;
397 /* ---- End stuff GDK adds to the original Xlib version ---- */
399 return (syms[col] != 0);
403 gdk_wayland_keymap_translate_keyboard_state (GdkKeymap *keymap,
404 guint hardware_keycode,
405 GdkModifierType state,
408 gint *effective_group,
410 GdkModifierType *consumed_modifiers)
412 GdkWaylandKeymap *wayland_keymap;
413 uint32_t tmp_keyval = 0;
415 struct xkb_desc *xkb;
417 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
418 g_return_val_if_fail (group < 4, FALSE);
420 wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
421 xkb = wayland_keymap->xkb;
426 *effective_group = 0;
429 if (consumed_modifiers)
430 *consumed_modifiers = 0;
432 if (hardware_keycode < xkb->min_key_code ||
433 hardware_keycode > xkb->max_key_code)
437 /* replace bits 13 and 14 with the provided group */
438 state &= ~(1 << 13 | 1 << 14);
439 state |= group << 13;
441 MyEnhancedXkbTranslateKeyCode (xkb,
449 if (state & ~tmp_modifiers & XKB_COMMON_LOCK_MASK)
450 tmp_keyval = gdk_keyval_to_upper (tmp_keyval);
452 /* We need to augment the consumed modifiers with LockMask, since
453 * we handle that ourselves, and also with the group bits
455 tmp_modifiers |= XKB_COMMON_LOCK_MASK | 1 << 13 | 1 << 14;
458 if (consumed_modifiers)
459 *consumed_modifiers = tmp_modifiers;
462 *keyval = tmp_keyval;
464 return tmp_keyval != 0;
469 update_modmap (GdkWaylandKeymap *wayland_keymap)
474 GdkModifierType mask;
476 { "Meta", 0, GDK_META_MASK },
477 { "Super", 0, GDK_SUPER_MASK },
478 { "Hyper", 0, GDK_HYPER_MASK },
485 for (i = 0; vmods[i].name; i++)
486 vmods[i].atom = xkb_intern_atom(vmods[i].name);
488 for (i = 0; i < 8; i++)
489 wayland_keymap->modmap[i] = 1 << i;
491 for (i = 0; i < XkbNumVirtualMods; i++)
493 for (j = 0; vmods[j].atom; j++)
495 if (wayland_keymap->xkb->names->vmods[i] == vmods[j].atom)
497 for (k = 0; k < 8; k++)
499 if (wayland_keymap->xkb->server->vmods[i] & (1 << k))
500 wayland_keymap->modmap[k] |= vmods[j].mask;
508 gdk_wayland_keymap_add_virtual_modifiers (GdkKeymap *keymap,
509 GdkModifierType *state)
511 GdkWaylandKeymap *wayland_keymap;
514 wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
516 for (i = 4; i < 8; i++)
518 if ((1 << i) & *state)
520 if (wayland_keymap->modmap[i] & GDK_SUPER_MASK)
521 *state |= GDK_SUPER_MASK;
522 if (wayland_keymap->modmap[i] & GDK_HYPER_MASK)
523 *state |= GDK_HYPER_MASK;
524 if (wayland_keymap->modmap[i] & GDK_META_MASK)
525 *state |= GDK_META_MASK;
531 gdk_wayland_keymap_map_virtual_modifiers (GdkKeymap *keymap,
532 GdkModifierType *state)
534 const guint vmods[] = {
535 GDK_SUPER_MASK, GDK_HYPER_MASK, GDK_META_MASK
538 GdkWaylandKeymap *wayland_keymap;
539 gboolean retval = TRUE;
541 wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
543 for (j = 0; j < 3; j++)
545 if (*state & vmods[j])
547 for (i = 4; i < 8; i++)
549 if (wayland_keymap->modmap[i] & vmods[j])
551 if (*state & (1 << i))
564 _gdk_wayland_keymap_class_init (GdkWaylandKeymapClass *klass)
566 GObjectClass *object_class = G_OBJECT_CLASS (klass);
567 GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
569 object_class->finalize = gdk_wayland_keymap_finalize;
571 keymap_class->get_direction = gdk_wayland_keymap_get_direction;
572 keymap_class->have_bidi_layouts = gdk_wayland_keymap_have_bidi_layouts;
573 keymap_class->get_caps_lock_state = gdk_wayland_keymap_get_caps_lock_state;
574 keymap_class->get_num_lock_state = gdk_wayland_keymap_get_num_lock_state;
575 keymap_class->get_entries_for_keyval = gdk_wayland_keymap_get_entries_for_keyval;
576 keymap_class->get_entries_for_keycode = gdk_wayland_keymap_get_entries_for_keycode;
577 keymap_class->lookup_key = gdk_wayland_keymap_lookup_key;
578 keymap_class->translate_keyboard_state = gdk_wayland_keymap_translate_keyboard_state;
579 keymap_class->add_virtual_modifiers = gdk_wayland_keymap_add_virtual_modifiers;
580 keymap_class->map_virtual_modifiers = gdk_wayland_keymap_map_virtual_modifiers;
584 _gdk_wayland_keymap_init (GdkWaylandKeymap *keymap)
589 update_keymaps (GdkWaylandKeymap *keymap)
591 struct xkb_desc *xkb = keymap->xkb;
592 gint keycode, total_syms, i, modifier;
596 for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++)
598 total_syms = XkbKeyNumSyms (xkb, keycode);
600 entry = XkbKeySymsPtr (xkb, keycode);
602 for (i = 0; i < total_syms; i++)
607 mask |= GDK_META_MASK;
609 case GDK_KEY_Hyper_L:
610 case GDK_KEY_Hyper_R:
611 mask |= GDK_HYPER_MASK;
613 case GDK_KEY_Super_L:
614 case GDK_KEY_Super_R:
615 mask |= GDK_SUPER_MASK;
620 modifier = g_bit_nth_lsf(xkb->map->modmap[keycode], -1);
621 keymap->modmap[modifier] |= mask;
626 _gdk_wayland_keymap_new (GdkDisplay *display)
628 GdkWaylandKeymap *keymap;
629 struct xkb_rule_names names;
631 keymap = g_object_new (_gdk_wayland_keymap_get_type(), NULL);
632 GDK_KEYMAP (keymap)->display = display;
634 names.rules = "evdev";
635 names.model = "pc105";
639 keymap->xkb = xkb_compile_keymap_from_rules(&names);
641 update_modmap (keymap);
642 update_keymaps (keymap);
644 return GDK_KEYMAP (keymap);
647 struct xkb_desc *_gdk_wayland_keymap_get_xkb_desc (GdkKeymap *keymap)
649 return GDK_WAYLAND_KEYMAP (keymap)->xkb;