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 <xkbcommon/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,
104 struct xkb_desc *xkb;
106 xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
107 keycode = xkb->min_key_code;
109 retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
111 for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++)
113 gint max_shift_levels = XkbKeyGroupsWidth (xkb, keycode);
117 gint total_syms = XkbKeyNumSyms (xkb, keycode);
121 /* entry is an array with all syms for group 0, all
122 * syms for group 1, etc. and for each group the
123 * shift level syms are in order
125 entry = XkbKeySymsPtr (xkb, keycode);
127 for (i = 0; i < total_syms; i++)
129 /* check out our cool loop invariant */
130 g_assert (i == (group * max_shift_levels + level));
132 if (entry[i] == keyval)
137 key.keycode = keycode;
141 g_array_append_val (retval, key);
143 g_assert (XkbKeySymEntry (xkb, keycode, level, group) ==
149 if (level == max_shift_levels)
157 *n_keys = retval->len;
158 *keys = (GdkKeymapKey *) g_array_free (retval, FALSE);
166 gdk_wayland_keymap_get_entries_for_keycode (GdkKeymap *keymap,
167 guint hardware_keycode,
174 GArray *keyval_array;
175 struct xkb_desc *xkb;
176 gint max_shift_levels;
183 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
184 g_return_val_if_fail (n_entries != NULL, FALSE);
186 xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
188 if (hardware_keycode < xkb->min_key_code ||
189 hardware_keycode > xkb->max_key_code)
201 key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
206 keyval_array = g_array_new (FALSE, FALSE, sizeof (guint));
210 /* See sec 15.3.4 in XKB docs */
211 max_shift_levels = XkbKeyGroupsWidth (xkb, hardware_keycode);
212 total_syms = XkbKeyNumSyms (xkb, hardware_keycode);
214 /* entry is an array with all syms for group 0, all
215 * syms for group 1, etc. and for each group the
216 * shift level syms are in order
218 entry = XkbKeySymsPtr (xkb, hardware_keycode);
220 for (i = 0; i < total_syms; i++)
222 /* check out our cool loop invariant */
223 g_assert (i == (group * max_shift_levels + level));
229 key.keycode = hardware_keycode;
233 g_array_append_val (key_array, key);
237 g_array_append_val (keyval_array, entry[i]);
241 if (level == max_shift_levels)
252 *n_entries = key_array->len;
253 *keys = (GdkKeymapKey*) g_array_free (key_array, FALSE);
258 *n_entries = keyval_array->len;
259 *keyvals = (guint*) g_array_free (keyval_array, FALSE);
262 return *n_entries > 0;
268 gdk_wayland_keymap_lookup_key (GdkKeymap *keymap,
269 const GdkKeymapKey *key)
272 struct xkb_desc *xkb;
274 xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
276 return XkbKeySymEntry (xkb, key->keycode, key->level, key->group);
282 /* This is copied straight from XFree86 Xlib, to:
283 * - add the group and level return.
284 * - change the interpretation of mods_rtrn as described
285 * in the docs for gdk_keymap_translate_keyboard_state()
286 * It's unchanged for ease of diff against the Xlib sources; don't
290 MyEnhancedXkbTranslateKeyCode(struct xkb_desc * xkb,
293 unsigned int * mods_rtrn,
294 uint32_t * keysym_rtrn,
298 struct xkb_key_type *type;
300 unsigned preserve,effectiveGroup;
306 nKeyGroups= XkbKeyNumGroups(xkb,key);
307 if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
308 if (keysym_rtrn!=NULL)
313 syms = XkbKeySymsPtr(xkb,key);
315 /* find the offset of the effective group */
317 effectiveGroup= XkbGroupForCoreState(mods);
318 if ( effectiveGroup>=nKeyGroups ) {
319 unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
320 switch (XkbOutOfRangeGroupAction(groupInfo)) {
322 effectiveGroup %= nKeyGroups;
324 case XkbClampIntoRange:
325 effectiveGroup = nKeyGroups-1;
327 case XkbRedirectIntoRange:
328 effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
329 if (effectiveGroup>=nKeyGroups)
334 col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
335 type = XkbKeyKeyType(xkb,key,effectiveGroup);
338 if (type->map) { /* find the column (shift level) within the group */
340 struct xkb_kt_map_entry *entry;
341 /* ---- Begin section modified for GDK ---- */
344 for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
347 unsigned long tmp = entry->mods.mask;
353 /* We always add one-modifiers levels to mods_rtrn since
354 * they can't wipe out bits in the state unless the
355 * level would be triggered. But return other modifiers
358 if (bits == 1 || (mods&type->mods.mask)==entry->mods.mask)
359 *mods_rtrn |= entry->mods.mask;
362 if (!found&&entry->active&&((mods&type->mods.mask)==entry->mods.mask)) {
365 preserve= type->preserve[i].mask;
368 *level_rtrn = entry->level;
373 /* ---- End section modified for GDK ---- */
376 if (keysym_rtrn!=NULL)
377 *keysym_rtrn= syms[col];
379 /* ---- Begin section modified for GDK ---- */
380 *mods_rtrn &= ~preserve;
381 /* ---- End section modified for GDK ---- */
383 /* ---- Begin stuff GDK comments out of the original Xlib version ---- */
384 /* This is commented out because xkb_info is a private struct */
387 /* The Motif VTS doesn't get the help callback called if help
388 * is bound to Shift+<whatever>, and it appears as though it
389 * is XkbTranslateKeyCode that is causing the problem. The
390 * core X version of XTranslateKey always OR's in ShiftMask
391 * and LockMask for mods_rtrn, so this "fix" keeps this behavior
392 * and solves the VTS problem.
394 if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
395 (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) { *mods_rtrn|= (ShiftMask|LockMask);
399 /* ---- End stuff GDK comments out of the original Xlib version ---- */
402 /* ---- Begin stuff GDK adds to the original Xlib version ---- */
405 *group_rtrn = effectiveGroup;
407 /* ---- End stuff GDK adds to the original Xlib version ---- */
409 return (syms[col] != 0);
414 gdk_wayland_keymap_translate_keyboard_state (GdkKeymap *keymap,
415 guint hardware_keycode,
416 GdkModifierType state,
419 gint *effective_group,
421 GdkModifierType *consumed_modifiers)
424 GdkWaylandKeymap *wayland_keymap;
425 uint32_t tmp_keyval = 0;
427 struct xkb_desc *xkb;
429 g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
430 g_return_val_if_fail (group < 4, FALSE);
432 wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
433 xkb = wayland_keymap->xkb;
438 *effective_group = 0;
441 if (consumed_modifiers)
442 *consumed_modifiers = 0;
444 if (hardware_keycode < xkb->min_key_code ||
445 hardware_keycode > xkb->max_key_code)
449 /* replace bits 13 and 14 with the provided group */
450 state &= ~(1 << 13 | 1 << 14);
451 state |= group << 13;
453 MyEnhancedXkbTranslateKeyCode (xkb,
461 if (state & ~tmp_modifiers & XKB_COMMON_LOCK_MASK)
462 tmp_keyval = gdk_keyval_to_upper (tmp_keyval);
464 /* We need to augment the consumed modifiers with LockMask, since
465 * we handle that ourselves, and also with the group bits
467 tmp_modifiers |= XKB_COMMON_LOCK_MASK | 1 << 13 | 1 << 14;
470 if (consumed_modifiers)
471 *consumed_modifiers = tmp_modifiers;
474 *keyval = tmp_keyval;
476 return tmp_keyval != 0;
483 update_modmap (GdkWaylandKeymap *wayland_keymap)
488 GdkModifierType mask;
490 { "Meta", 0, GDK_META_MASK },
491 { "Super", 0, GDK_SUPER_MASK },
492 { "Hyper", 0, GDK_HYPER_MASK },
499 for (i = 0; vmods[i].name; i++)
500 vmods[i].atom = xkb_atom(vmods[i].name);
502 for (i = 0; i < 8; i++)
503 wayland_keymap->modmap[i] = 1 << i;
505 for (i = 0; i < XkbNumVirtualMods; i++)
507 for (j = 0; vmods[j].atom; j++)
509 if (wayland_keymap->xkb->names->vmods[i] == vmods[j].atom)
511 for (k = 0; k < 8; k++)
513 if (wayland_keymap->xkb->server->vmods[i] & (1 << k))
514 wayland_keymap->modmap[k] |= vmods[j].mask;
523 gdk_wayland_keymap_add_virtual_modifiers (GdkKeymap *keymap,
524 GdkModifierType *state)
526 GdkWaylandKeymap *wayland_keymap;
529 wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
531 for (i = 4; i < 8; i++)
533 if ((1 << i) & *state)
535 if (wayland_keymap->modmap[i] & GDK_SUPER_MASK)
536 *state |= GDK_SUPER_MASK;
537 if (wayland_keymap->modmap[i] & GDK_HYPER_MASK)
538 *state |= GDK_HYPER_MASK;
539 if (wayland_keymap->modmap[i] & GDK_META_MASK)
540 *state |= GDK_META_MASK;
546 gdk_wayland_keymap_map_virtual_modifiers (GdkKeymap *keymap,
547 GdkModifierType *state)
549 const guint vmods[] = {
550 GDK_SUPER_MASK, GDK_HYPER_MASK, GDK_META_MASK
553 GdkWaylandKeymap *wayland_keymap;
554 gboolean retval = TRUE;
556 wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
558 for (j = 0; j < 3; j++)
560 if (*state & vmods[j])
562 for (i = 4; i < 8; i++)
564 if (wayland_keymap->modmap[i] & vmods[j])
566 if (*state & (1 << i))
579 _gdk_wayland_keymap_class_init (GdkWaylandKeymapClass *klass)
581 GObjectClass *object_class = G_OBJECT_CLASS (klass);
582 GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
584 object_class->finalize = gdk_wayland_keymap_finalize;
586 keymap_class->get_direction = gdk_wayland_keymap_get_direction;
587 keymap_class->have_bidi_layouts = gdk_wayland_keymap_have_bidi_layouts;
588 keymap_class->get_caps_lock_state = gdk_wayland_keymap_get_caps_lock_state;
589 keymap_class->get_num_lock_state = gdk_wayland_keymap_get_num_lock_state;
590 keymap_class->get_entries_for_keyval = gdk_wayland_keymap_get_entries_for_keyval;
591 keymap_class->get_entries_for_keycode = gdk_wayland_keymap_get_entries_for_keycode;
592 keymap_class->lookup_key = gdk_wayland_keymap_lookup_key;
593 keymap_class->translate_keyboard_state = gdk_wayland_keymap_translate_keyboard_state;
594 keymap_class->add_virtual_modifiers = gdk_wayland_keymap_add_virtual_modifiers;
595 keymap_class->map_virtual_modifiers = gdk_wayland_keymap_map_virtual_modifiers;
599 _gdk_wayland_keymap_init (GdkWaylandKeymap *keymap)
605 update_keymaps (GdkWaylandKeymap *keymap)
607 struct xkb_desc *xkb = keymap->xkb;
608 gint keycode, total_syms, i, modifier;
612 for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++)
614 total_syms = XkbKeyNumSyms (xkb, keycode);
616 entry = XkbKeySymsPtr (xkb, keycode);
618 for (i = 0; i < total_syms; i++)
623 mask |= GDK_META_MASK;
625 case GDK_KEY_Hyper_L:
626 case GDK_KEY_Hyper_R:
627 mask |= GDK_HYPER_MASK;
629 case GDK_KEY_Super_L:
630 case GDK_KEY_Super_R:
631 mask |= GDK_SUPER_MASK;
636 modifier = g_bit_nth_lsf(xkb->map->modmap[keycode], -1);
637 keymap->modmap[modifier] |= mask;
643 _gdk_wayland_keymap_new (GdkDisplay *display)
645 GdkWaylandKeymap *keymap;
646 struct xkb_rule_names names;
648 keymap = g_object_new (_gdk_wayland_keymap_get_type(), NULL);
649 GDK_KEYMAP (keymap)->display = display;
652 names.rules = "evdev";
653 names.model = "pc105";
657 keymap->xkb = xkb_compile_keymap_from_rules(&names);
658 update_modmap (keymap);
659 update_keymaps (keymap);
661 return GDK_KEYMAP (keymap);
664 struct xkb_desc *_gdk_wayland_keymap_get_xkb_desc (GdkKeymap *keymap)
666 return GDK_WAYLAND_KEYMAP (keymap)->xkb;