]> Pileus Git - ~andy/gtk/blob - gdk/wayland/gdkkeys-wayland.c
Change FSF Address
[~andy/gtk] / gdk / wayland / gdkkeys-wayland.c
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, see <http://www.gnu.org/licenses/>.
16  */
17
18 /*
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/.
23  */
24
25 #include "config.h"
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <limits.h>
32 #include <errno.h>
33
34 #include "gdk.h"
35 #include "gdkwayland.h"
36
37 #include "gdkprivate-wayland.h"
38 #include "gdkinternals.h"
39 #include "gdkdisplay-wayland.h"
40 #include "gdkkeysprivate.h"
41
42 #include <X11/extensions/XKBcommon.h>
43
44 typedef struct _GdkWaylandKeymap          GdkWaylandKeymap;
45 typedef struct _GdkWaylandKeymapClass     GdkWaylandKeymapClass;
46
47 struct _GdkWaylandKeymap
48 {
49   GdkKeymap parent_instance;
50   GdkModifierType modmap[8];
51   struct xkb_desc *xkb;
52 };
53
54 struct _GdkWaylandKeymapClass
55 {
56   GdkKeymapClass parent_class;
57 };
58
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))
62
63 G_DEFINE_TYPE (GdkWaylandKeymap, _gdk_wayland_keymap, GDK_TYPE_KEYMAP)
64
65 static void
66 gdk_wayland_keymap_finalize (GObject *object)
67 {
68   G_OBJECT_CLASS (_gdk_wayland_keymap_parent_class)->finalize (object);
69 }
70
71 static PangoDirection
72 gdk_wayland_keymap_get_direction (GdkKeymap *keymap)
73 {
74     return PANGO_DIRECTION_NEUTRAL;
75 }
76
77 static gboolean
78 gdk_wayland_keymap_have_bidi_layouts (GdkKeymap *keymap)
79 {
80     return FALSE;
81 }
82
83 static gboolean
84 gdk_wayland_keymap_get_caps_lock_state (GdkKeymap *keymap)
85 {
86   return FALSE;
87 }
88
89 static gboolean
90 gdk_wayland_keymap_get_num_lock_state (GdkKeymap *keymap)
91 {
92   return FALSE;
93 }
94
95 static gboolean
96 gdk_wayland_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
97                                            guint          keyval,
98                                            GdkKeymapKey **keys,
99                                            gint          *n_keys)
100 {
101   GArray *retval;
102   uint32_t keycode;
103   struct xkb_desc *xkb;
104
105   xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
106   keycode = xkb->min_key_code;
107
108   retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
109
110   for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++)
111     {
112       gint max_shift_levels = XkbKeyGroupsWidth (xkb, keycode);
113
114       gint group = 0;
115       gint level = 0;
116       gint total_syms = XkbKeyNumSyms (xkb, keycode);
117       gint i = 0;
118       uint32_t *entry;
119
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
123        */
124       entry = XkbKeySymsPtr (xkb, keycode);
125
126       for (i = 0; i < total_syms; i++)
127         {
128           /* check out our cool loop invariant */
129           g_assert (i == (group * max_shift_levels + level));
130
131           if (entry[i] == keyval)
132             {
133               /* Found a match */
134               GdkKeymapKey key;
135
136               key.keycode = keycode;
137               key.group = group;
138               key.level = level;
139
140               g_array_append_val (retval, key);
141
142               g_assert (XkbKeySymEntry (xkb, keycode, level, group) ==
143                         keyval);
144             }
145
146           level++;
147
148           if (level == max_shift_levels)
149             {
150               level = 0;
151               group++;
152             }
153         }
154     }
155
156   *n_keys = retval->len;
157   *keys = (GdkKeymapKey *) g_array_free (retval, FALSE);
158
159   return *n_keys > 0;
160 }
161
162 static gboolean
163 gdk_wayland_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
164                                             guint          hardware_keycode,
165                                             GdkKeymapKey **keys,
166                                             guint        **keyvals,
167                                             gint          *n_entries)
168 {
169   GArray *key_array;
170   GArray *keyval_array;
171   struct xkb_desc *xkb;
172   gint max_shift_levels;
173   gint group = 0;
174   gint level = 0;
175   gint total_syms;
176   gint i;
177   uint32_t *entry;
178
179   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
180   g_return_val_if_fail (n_entries != NULL, FALSE);
181
182   xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
183
184   if (hardware_keycode < xkb->min_key_code ||
185       hardware_keycode > xkb->max_key_code)
186     {
187       if (keys)
188         *keys = NULL;
189       if (keyvals)
190         *keyvals = NULL;
191
192       *n_entries = 0;
193       return FALSE;
194     }
195
196   if (keys)
197     key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
198   else
199     key_array = NULL;
200
201   if (keyvals)
202     keyval_array = g_array_new (FALSE, FALSE, sizeof (guint));
203   else
204     keyval_array = NULL;
205
206   /* See sec 15.3.4 in XKB docs */
207   max_shift_levels = XkbKeyGroupsWidth (xkb, hardware_keycode);
208   total_syms = XkbKeyNumSyms (xkb, hardware_keycode);
209
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
213    */
214   entry = XkbKeySymsPtr (xkb, hardware_keycode);
215
216   for (i = 0; i < total_syms; i++)
217     {
218       /* check out our cool loop invariant */
219       g_assert (i == (group * max_shift_levels + level));
220
221       if (key_array)
222         {
223           GdkKeymapKey key;
224
225           key.keycode = hardware_keycode;
226           key.group = group;
227           key.level = level;
228
229           g_array_append_val (key_array, key);
230         }
231
232       if (keyval_array)
233         g_array_append_val (keyval_array, entry[i]);
234
235       ++level;
236
237       if (level == max_shift_levels)
238         {
239           level = 0;
240           ++group;
241         }
242     }
243
244   *n_entries = 0;
245
246   if (keys)
247     {
248       *n_entries = key_array->len;
249       *keys = (GdkKeymapKey*) g_array_free (key_array, FALSE);
250     }
251
252   if (keyvals)
253     {
254       *n_entries = keyval_array->len;
255       *keyvals = (guint*) g_array_free (keyval_array, FALSE);
256     }
257
258   return *n_entries > 0;
259 }
260
261 static guint
262 gdk_wayland_keymap_lookup_key (GdkKeymap          *keymap,
263                                const GdkKeymapKey *key)
264 {
265   struct xkb_desc *xkb;
266
267   xkb = GDK_WAYLAND_KEYMAP (keymap)->xkb;
268
269   return XkbKeySymEntry (xkb, key->keycode, key->level, key->group);
270 }
271
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
277  * reformat it.
278  */
279 static int
280 MyEnhancedXkbTranslateKeyCode(struct xkb_desc *       xkb,
281                               KeyCode                 key,
282                               unsigned int            mods,
283                               unsigned int *          mods_rtrn,
284                               uint32_t *              keysym_rtrn,
285                               int *                   group_rtrn,
286                               int *                   level_rtrn)
287 {
288     struct xkb_key_type *type;
289     int col,nKeyGroups;
290     unsigned preserve,effectiveGroup;
291     uint32_t *syms;
292
293     if (mods_rtrn!=NULL)
294         *mods_rtrn = 0;
295
296     nKeyGroups= XkbKeyNumGroups(xkb,key);
297     if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
298         if (keysym_rtrn!=NULL)
299             *keysym_rtrn = 0;
300         return 0;
301     }
302
303     syms = XkbKeySymsPtr(xkb,key);
304
305     /* find the offset of the effective group */
306     col = 0;
307     effectiveGroup= XkbGroupForCoreState(mods);
308     if ( effectiveGroup>=nKeyGroups ) {
309         unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
310         switch (XkbOutOfRangeGroupAction(groupInfo)) {
311             default:
312                 effectiveGroup %= nKeyGroups;
313                 break;
314             case XkbClampIntoRange:
315                 effectiveGroup = nKeyGroups-1;
316                 break;
317             case XkbRedirectIntoRange:
318                 effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
319                 if (effectiveGroup>=nKeyGroups)
320                     effectiveGroup= 0;
321                 break;
322         }
323     }
324     col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
325     type = XkbKeyKeyType(xkb,key,effectiveGroup);
326
327     preserve= 0;
328     if (type->map) { /* find the column (shift level) within the group */
329         register int i;
330         struct xkb_kt_map_entry *entry;
331         /* ---- Begin section modified for GDK  ---- */
332         int found = 0;
333
334         for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
335             if (mods_rtrn) {
336                 int bits = 0;
337                 unsigned long tmp = entry->mods.mask;
338                 while (tmp) {
339                     if ((tmp & 1) == 1)
340                         bits++;
341                     tmp >>= 1;
342                 }
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
346                  *
347                  */
348                 if (bits == 1 || (mods&type->mods.mask)==entry->mods.mask)
349                     *mods_rtrn |= entry->mods.mask;
350             }
351
352             if (!found&&entry->active&&((mods&type->mods.mask)==entry->mods.mask)) {
353                 col+= entry->level;
354                 if (type->preserve)
355                     preserve= type->preserve[i].mask;
356
357                 if (level_rtrn)
358                   *level_rtrn = entry->level;
359
360                 found = 1;
361             }
362         }
363         /* ---- End section modified for GDK ---- */
364     }
365
366     if (keysym_rtrn!=NULL)
367         *keysym_rtrn= syms[col];
368     if (mods_rtrn) {
369         /* ---- Begin section modified for GDK  ---- */
370         *mods_rtrn &= ~preserve;
371         /* ---- End section modified for GDK ---- */
372
373         /* ---- Begin stuff GDK comments out of the original Xlib version ---- */
374         /* This is commented out because xkb_info is a private struct */
375
376 #if 0
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.
383          */
384         if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
385             (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) {            *mods_rtrn|= (ShiftMask|LockMask);
386         }
387 #endif
388
389         /* ---- End stuff GDK comments out of the original Xlib version ---- */
390     }
391
392     /* ---- Begin stuff GDK adds to the original Xlib version ---- */
393
394     if (group_rtrn)
395       *group_rtrn = effectiveGroup;
396
397     /* ---- End stuff GDK adds to the original Xlib version ---- */
398
399     return (syms[col] != 0);
400 }
401
402 static gboolean
403 gdk_wayland_keymap_translate_keyboard_state (GdkKeymap       *keymap,
404                                              guint            hardware_keycode,
405                                              GdkModifierType  state,
406                                              gint             group,
407                                              guint           *keyval,
408                                              gint            *effective_group,
409                                              gint            *level,
410                                              GdkModifierType *consumed_modifiers)
411 {
412   GdkWaylandKeymap *wayland_keymap;
413   uint32_t tmp_keyval = 0;
414   guint tmp_modifiers;
415   struct xkb_desc *xkb;
416
417   g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
418   g_return_val_if_fail (group < 4, FALSE);
419
420   wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
421   xkb = wayland_keymap->xkb;
422
423   if (keyval)
424     *keyval = 0;
425   if (effective_group)
426     *effective_group = 0;
427   if (level)
428     *level = 0;
429   if (consumed_modifiers)
430     *consumed_modifiers = 0;
431
432   if (hardware_keycode < xkb->min_key_code ||
433       hardware_keycode > xkb->max_key_code)
434     return FALSE;
435
436
437   /* replace bits 13 and 14 with the provided group */
438   state &= ~(1 << 13 | 1 << 14);
439   state |= group << 13;
440
441   MyEnhancedXkbTranslateKeyCode (xkb,
442                                  hardware_keycode,
443                                  state,
444                                  &tmp_modifiers,
445                                  &tmp_keyval,
446                                  effective_group,
447                                  level);
448
449   if (state & ~tmp_modifiers & XKB_COMMON_LOCK_MASK)
450     tmp_keyval = gdk_keyval_to_upper (tmp_keyval);
451
452   /* We need to augment the consumed modifiers with LockMask, since
453    * we handle that ourselves, and also with the group bits
454    */
455   tmp_modifiers |= XKB_COMMON_LOCK_MASK | 1 << 13 | 1 << 14;
456
457
458   if (consumed_modifiers)
459     *consumed_modifiers = tmp_modifiers;
460
461   if (keyval)
462     *keyval = tmp_keyval;
463
464   return tmp_keyval != 0;
465 }
466
467
468 static void
469 update_modmap (GdkWaylandKeymap *wayland_keymap)
470 {
471   static struct {
472     const gchar *name;
473     uint32_t atom;
474     GdkModifierType mask;
475   } vmods[] = {
476     { "Meta", 0, GDK_META_MASK },
477     { "Super", 0, GDK_SUPER_MASK },
478     { "Hyper", 0, GDK_HYPER_MASK },
479     { NULL, 0, 0 }
480   };
481
482   gint i, j, k;
483
484   if (!vmods[0].atom)
485     for (i = 0; vmods[i].name; i++)
486       vmods[i].atom = xkb_intern_atom(vmods[i].name);
487
488   for (i = 0; i < 8; i++)
489     wayland_keymap->modmap[i] = 1 << i;
490
491   for (i = 0; i < XkbNumVirtualMods; i++)
492     {
493       for (j = 0; vmods[j].atom; j++)
494         {
495           if (wayland_keymap->xkb->names->vmods[i] == vmods[j].atom)
496             {
497               for (k = 0; k < 8; k++)
498                 {
499                   if (wayland_keymap->xkb->server->vmods[i] & (1 << k))
500                     wayland_keymap->modmap[k] |= vmods[j].mask;
501                 }
502             }
503         }
504     }
505 }
506
507 static void
508 gdk_wayland_keymap_add_virtual_modifiers (GdkKeymap       *keymap,
509                                           GdkModifierType *state)
510 {
511   GdkWaylandKeymap *wayland_keymap;
512   int i;
513
514   wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
515
516   for (i = 4; i < 8; i++)
517     {
518       if ((1 << i) & *state)
519         {
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;
526         }
527     }
528 }
529
530 static gboolean
531 gdk_wayland_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
532                                           GdkModifierType *state)
533 {
534   const guint vmods[] = {
535     GDK_SUPER_MASK, GDK_HYPER_MASK, GDK_META_MASK
536   };
537   int i, j;
538   GdkWaylandKeymap *wayland_keymap;
539   gboolean retval = TRUE;
540
541   wayland_keymap = GDK_WAYLAND_KEYMAP (keymap);
542
543   for (j = 0; j < 3; j++)
544     {
545       if (*state & vmods[j])
546         {
547           for (i = 4; i < 8; i++)
548             {
549               if (wayland_keymap->modmap[i] & vmods[j])
550                 {
551                   if (*state & (1 << i))
552                     retval = FALSE;
553                   else
554                     *state |= 1 << i;
555                 }
556             }
557         }
558     }
559
560   return retval;
561 }
562
563 static void
564 _gdk_wayland_keymap_class_init (GdkWaylandKeymapClass *klass)
565 {
566   GObjectClass *object_class = G_OBJECT_CLASS (klass);
567   GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
568
569   object_class->finalize = gdk_wayland_keymap_finalize;
570
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;
581 }
582
583 static void
584 _gdk_wayland_keymap_init (GdkWaylandKeymap *keymap)
585 {
586 }
587
588 static void
589 update_keymaps (GdkWaylandKeymap *keymap)
590 {
591   struct xkb_desc *xkb = keymap->xkb;
592   gint keycode, total_syms, i, modifier;
593   uint32_t *entry;
594   guint mask;
595
596   for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++)
597     {
598       total_syms = XkbKeyNumSyms (xkb, keycode);
599
600       entry = XkbKeySymsPtr (xkb, keycode);
601       mask = 0;
602       for (i = 0; i < total_syms; i++)
603         {
604           switch (entry[i]) {
605           case GDK_KEY_Meta_L:
606           case GDK_KEY_Meta_R:
607             mask |= GDK_META_MASK;
608             break;
609           case GDK_KEY_Hyper_L:
610           case GDK_KEY_Hyper_R:
611             mask |= GDK_HYPER_MASK;
612             break;
613           case GDK_KEY_Super_L:
614           case GDK_KEY_Super_R:
615             mask |= GDK_SUPER_MASK;
616             break;
617           }
618         }
619
620       modifier = g_bit_nth_lsf(xkb->map->modmap[keycode], -1);
621       keymap->modmap[modifier] |= mask;
622     }
623 }
624
625 GdkKeymap *
626 _gdk_wayland_keymap_new (GdkDisplay *display)
627 {
628   GdkWaylandKeymap *keymap;
629   struct xkb_rule_names names;
630
631   keymap = g_object_new (_gdk_wayland_keymap_get_type(), NULL);
632   GDK_KEYMAP (keymap)->display = display;
633
634   names.rules = "evdev";
635   names.model = "pc105";
636   names.layout = "us";
637   names.variant = "";
638   names.options = "";
639   keymap->xkb = xkb_compile_keymap_from_rules(&names);
640
641   update_modmap (keymap);
642   update_keymaps (keymap);
643
644   return GDK_KEYMAP (keymap);
645 }
646
647 struct xkb_desc *_gdk_wayland_keymap_get_xkb_desc (GdkKeymap *keymap)
648 {
649   return GDK_WAYLAND_KEYMAP (keymap)->xkb;
650 }