~kroq-gar78/ubuntu/precise/gnome-control-center/fix-885947

« back to all changes in this revision

Viewing changes to panels/common/eggaccelerators.c

  • Committer: Bazaar Package Importer
  • Author(s): Rodrigo Moya
  • Date: 2011-05-17 10:47:27 UTC
  • mfrom: (0.1.11 experimental) (1.1.45 upstream)
  • Revision ID: james.westby@ubuntu.com-20110517104727-lqel6m8vhfw5jby1
Tags: 1:3.0.1.1-1ubuntu1
* Rebase on Debian, remaining Ubuntu changes:
* debian/control:
  - Build-Depend on hardening-wrapper, dpkg-dev and dh-autoreconf
  - Add dependency on ubuntu-system-service
  - Remove dependency on gnome-icon-theme-symbolic
  - Move dependency on apg, gnome-icon-theme-symbolic and accountsservice to
    be a Recommends: until we get them in main
* debian/rules:
  - Use autoreconf
  - Add binary-post-install rule for gnome-control-center-data
  - Run dh-autoreconf
* debian/gnome-control-center.dirs:
* debian/gnome-control-center.links:
  - Add a link to the control center shell for indicators
* debian/patches/00_disable-nm.patch:
  - Temporary patch to disable building with NetworkManager until we get
    the new one in the archive
* debian/patches/01_git_remove_gettext_calls.patch:
  - Remove calls to AM_GNU_GETTEXT, IT_PROG_INTLTOOL should be enough
* debian/patches/01_git_kill_warning.patch:
  - Kill warning
* debian/patches/50_ubuntu_systemwide_prefs.patch:
  - Ubuntu specific proxy preferences
* debian/patches/51_ubuntu_system_keyboard.patch:
  - Implement the global keyboard spec at https://wiki.ubuntu.com/DefaultKeyboardSettings

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* eggaccelerators.c
 
2
 * Copyright (C) 2002  Red Hat, Inc.; Copyright 1998, 2001 Tim Janik
 
3
 * Developed by Havoc Pennington, Tim Janik
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Library General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Library General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Library General Public
 
16
 * License along with this library; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
#include "eggaccelerators.h"
 
22
 
 
23
#include <stdlib.h>
 
24
#include <string.h>
 
25
#include <gdk/gdkx.h>
 
26
#include <gdk/gdkkeysyms.h>
 
27
#include <gtk/gtk.h>
 
28
 
 
29
enum
 
30
{
 
31
  EGG_MODMAP_ENTRY_SHIFT   = 0,
 
32
  EGG_MODMAP_ENTRY_LOCK    = 1,
 
33
  EGG_MODMAP_ENTRY_CONTROL = 2,
 
34
  EGG_MODMAP_ENTRY_MOD1    = 3,
 
35
  EGG_MODMAP_ENTRY_MOD2    = 4,
 
36
  EGG_MODMAP_ENTRY_MOD3    = 5,
 
37
  EGG_MODMAP_ENTRY_MOD4    = 6,
 
38
  EGG_MODMAP_ENTRY_MOD5    = 7,
 
39
  EGG_MODMAP_ENTRY_LAST    = 8
 
40
};
 
41
 
 
42
#define MODMAP_ENTRY_TO_MODIFIER(x) (1 << (x))
 
43
 
 
44
typedef struct
 
45
{
 
46
  EggVirtualModifierType mapping[EGG_MODMAP_ENTRY_LAST];
 
47
 
 
48
} EggModmap;
 
49
 
 
50
const EggModmap* egg_keymap_get_modmap (GdkKeymap *keymap);
 
51
 
 
52
static inline gboolean
 
53
is_alt (const gchar *string)
 
54
{
 
55
  return ((string[0] == '<') &&
 
56
          (string[1] == 'a' || string[1] == 'A') &&
 
57
          (string[2] == 'l' || string[2] == 'L') &&
 
58
          (string[3] == 't' || string[3] == 'T') &&
 
59
          (string[4] == '>'));
 
60
}
 
61
 
 
62
static inline gboolean
 
63
is_ctl (const gchar *string)
 
64
{
 
65
  return ((string[0] == '<') &&
 
66
          (string[1] == 'c' || string[1] == 'C') &&
 
67
          (string[2] == 't' || string[2] == 'T') &&
 
68
          (string[3] == 'l' || string[3] == 'L') &&
 
69
          (string[4] == '>'));
 
70
}
 
71
 
 
72
static inline gboolean
 
73
is_modx (const gchar *string)
 
74
{
 
75
  return ((string[0] == '<') &&
 
76
          (string[1] == 'm' || string[1] == 'M') &&
 
77
          (string[2] == 'o' || string[2] == 'O') &&
 
78
          (string[3] == 'd' || string[3] == 'D') &&
 
79
          (string[4] >= '1' && string[4] <= '5') &&
 
80
          (string[5] == '>'));
 
81
}
 
82
 
 
83
static inline gboolean
 
84
is_ctrl (const gchar *string)
 
85
{
 
86
  return ((string[0] == '<') &&
 
87
          (string[1] == 'c' || string[1] == 'C') &&
 
88
          (string[2] == 't' || string[2] == 'T') &&
 
89
          (string[3] == 'r' || string[3] == 'R') &&
 
90
          (string[4] == 'l' || string[4] == 'L') &&
 
91
          (string[5] == '>'));
 
92
}
 
93
 
 
94
static inline gboolean
 
95
is_shft (const gchar *string)
 
96
{
 
97
  return ((string[0] == '<') &&
 
98
          (string[1] == 's' || string[1] == 'S') &&
 
99
          (string[2] == 'h' || string[2] == 'H') &&
 
100
          (string[3] == 'f' || string[3] == 'F') &&
 
101
          (string[4] == 't' || string[4] == 'T') &&
 
102
          (string[5] == '>'));
 
103
}
 
104
 
 
105
static inline gboolean
 
106
is_shift (const gchar *string)
 
107
{
 
108
  return ((string[0] == '<') &&
 
109
          (string[1] == 's' || string[1] == 'S') &&
 
110
          (string[2] == 'h' || string[2] == 'H') &&
 
111
          (string[3] == 'i' || string[3] == 'I') &&
 
112
          (string[4] == 'f' || string[4] == 'F') &&
 
113
          (string[5] == 't' || string[5] == 'T') &&
 
114
          (string[6] == '>'));
 
115
}
 
116
 
 
117
static inline gboolean
 
118
is_control (const gchar *string)
 
119
{
 
120
  return ((string[0] == '<') &&
 
121
          (string[1] == 'c' || string[1] == 'C') &&
 
122
          (string[2] == 'o' || string[2] == 'O') &&
 
123
          (string[3] == 'n' || string[3] == 'N') &&
 
124
          (string[4] == 't' || string[4] == 'T') &&
 
125
          (string[5] == 'r' || string[5] == 'R') &&
 
126
          (string[6] == 'o' || string[6] == 'O') &&
 
127
          (string[7] == 'l' || string[7] == 'L') &&
 
128
          (string[8] == '>'));
 
129
}
 
130
 
 
131
static inline gboolean
 
132
is_release (const gchar *string)
 
133
{
 
134
  return ((string[0] == '<') &&
 
135
          (string[1] == 'r' || string[1] == 'R') &&
 
136
          (string[2] == 'e' || string[2] == 'E') &&
 
137
          (string[3] == 'l' || string[3] == 'L') &&
 
138
          (string[4] == 'e' || string[4] == 'E') &&
 
139
          (string[5] == 'a' || string[5] == 'A') &&
 
140
          (string[6] == 's' || string[6] == 'S') &&
 
141
          (string[7] == 'e' || string[7] == 'E') &&
 
142
          (string[8] == '>'));
 
143
}
 
144
 
 
145
static inline gboolean
 
146
is_meta (const gchar *string)
 
147
{
 
148
  return ((string[0] == '<') &&
 
149
          (string[1] == 'm' || string[1] == 'M') &&
 
150
          (string[2] == 'e' || string[2] == 'E') &&
 
151
          (string[3] == 't' || string[3] == 'T') &&
 
152
          (string[4] == 'a' || string[4] == 'A') &&
 
153
          (string[5] == '>'));
 
154
}
 
155
 
 
156
static inline gboolean
 
157
is_super (const gchar *string)
 
158
{
 
159
  return ((string[0] == '<') &&
 
160
          (string[1] == 's' || string[1] == 'S') &&
 
161
          (string[2] == 'u' || string[2] == 'U') &&
 
162
          (string[3] == 'p' || string[3] == 'P') &&
 
163
          (string[4] == 'e' || string[4] == 'E') &&
 
164
          (string[5] == 'r' || string[5] == 'R') &&
 
165
          (string[6] == '>'));
 
166
}
 
167
 
 
168
static inline gboolean
 
169
is_hyper (const gchar *string)
 
170
{
 
171
  return ((string[0] == '<') &&
 
172
          (string[1] == 'h' || string[1] == 'H') &&
 
173
          (string[2] == 'y' || string[2] == 'Y') &&
 
174
          (string[3] == 'p' || string[3] == 'P') &&
 
175
          (string[4] == 'e' || string[4] == 'E') &&
 
176
          (string[5] == 'r' || string[5] == 'R') &&
 
177
          (string[6] == '>'));
 
178
}
 
179
 
 
180
static inline gboolean
 
181
is_keycode (const gchar *string)
 
182
{
 
183
  return ((string[0] == '0') &&
 
184
          (string[1] == 'x'));
 
185
}
 
186
 
 
187
/**
 
188
 * egg_accelerator_parse_virtual:
 
189
 * @accelerator:      string representing an accelerator
 
190
 * @accelerator_key:  return location for accelerator keyval
 
191
 * @accelerator_mods: return location for accelerator modifier mask
 
192
 *
 
193
 * Parses a string representing a virtual accelerator. The format
 
194
 * looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1" or
 
195
 * "&lt;Release&gt;z" (the last one is for key release).  The parser
 
196
 * is fairly liberal and allows lower or upper case, and also
 
197
 * abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;".
 
198
 *
 
199
 * If the parse fails, @accelerator_key and @accelerator_mods will
 
200
 * be set to 0 (zero) and %FALSE will be returned. If the string contains
 
201
 * only modifiers, @accelerator_key will be set to 0 but %TRUE will be
 
202
 * returned.
 
203
 *
 
204
 * The virtual vs. concrete accelerator distinction is a relic of
 
205
 * how the X Window System works; there are modifiers Mod2-Mod5 that
 
206
 * can represent various keyboard keys (numlock, meta, hyper, etc.),
 
207
 * the virtual modifier represents the keyboard key, the concrete
 
208
 * modifier the actual Mod2-Mod5 bits in the key press event.
 
209
 *
 
210
 * Returns: %TRUE on success.
 
211
 */
 
212
gboolean
 
213
egg_accelerator_parse_virtual (const gchar            *accelerator,
 
214
                               guint                  *accelerator_key,
 
215
                               guint                  *keycode,
 
216
                               EggVirtualModifierType *accelerator_mods)
 
217
{
 
218
  guint keyval;
 
219
  GdkModifierType mods;
 
220
  gint len;
 
221
  gboolean bad_keyval;
 
222
 
 
223
  if (accelerator_key)
 
224
    *accelerator_key = 0;
 
225
  if (accelerator_mods)
 
226
    *accelerator_mods = 0;
 
227
  if (keycode)
 
228
    *keycode = 0;
 
229
 
 
230
  g_return_val_if_fail (accelerator != NULL, FALSE);
 
231
 
 
232
  bad_keyval = FALSE;
 
233
 
 
234
  keyval = 0;
 
235
  mods = 0;
 
236
  len = strlen (accelerator);
 
237
  while (len)
 
238
    {
 
239
      if (*accelerator == '<')
 
240
        {
 
241
          if (len >= 9 && is_release (accelerator))
 
242
            {
 
243
              accelerator += 9;
 
244
              len -= 9;
 
245
              mods |= EGG_VIRTUAL_RELEASE_MASK;
 
246
            }
 
247
          else if (len >= 9 && is_control (accelerator))
 
248
            {
 
249
              accelerator += 9;
 
250
              len -= 9;
 
251
              mods |= EGG_VIRTUAL_CONTROL_MASK;
 
252
            }
 
253
          else if (len >= 7 && is_shift (accelerator))
 
254
            {
 
255
              accelerator += 7;
 
256
              len -= 7;
 
257
              mods |= EGG_VIRTUAL_SHIFT_MASK;
 
258
            }
 
259
          else if (len >= 6 && is_shft (accelerator))
 
260
            {
 
261
              accelerator += 6;
 
262
              len -= 6;
 
263
              mods |= EGG_VIRTUAL_SHIFT_MASK;
 
264
            }
 
265
          else if (len >= 6 && is_ctrl (accelerator))
 
266
            {
 
267
              accelerator += 6;
 
268
              len -= 6;
 
269
              mods |= EGG_VIRTUAL_CONTROL_MASK;
 
270
            }
 
271
          else if (len >= 6 && is_modx (accelerator))
 
272
            {
 
273
              static const guint mod_vals[] = {
 
274
                EGG_VIRTUAL_ALT_MASK, EGG_VIRTUAL_MOD2_MASK, EGG_VIRTUAL_MOD3_MASK,
 
275
                EGG_VIRTUAL_MOD4_MASK, EGG_VIRTUAL_MOD5_MASK
 
276
              };
 
277
 
 
278
              len -= 6;
 
279
              accelerator += 4;
 
280
              mods |= mod_vals[*accelerator - '1'];
 
281
              accelerator += 2;
 
282
            }
 
283
          else if (len >= 5 && is_ctl (accelerator))
 
284
            {
 
285
              accelerator += 5;
 
286
              len -= 5;
 
287
              mods |= EGG_VIRTUAL_CONTROL_MASK;
 
288
            }
 
289
          else if (len >= 5 && is_alt (accelerator))
 
290
            {
 
291
              accelerator += 5;
 
292
              len -= 5;
 
293
              mods |= EGG_VIRTUAL_ALT_MASK;
 
294
            }
 
295
          else if (len >= 6 && is_meta (accelerator))
 
296
            {
 
297
              accelerator += 6;
 
298
              len -= 6;
 
299
              mods |= EGG_VIRTUAL_META_MASK;
 
300
            }
 
301
          else if (len >= 7 && is_hyper (accelerator))
 
302
            {
 
303
              accelerator += 7;
 
304
              len -= 7;
 
305
              mods |= EGG_VIRTUAL_HYPER_MASK;
 
306
            }
 
307
          else if (len >= 7 && is_super (accelerator))
 
308
            {
 
309
              accelerator += 7;
 
310
              len -= 7;
 
311
              mods |= EGG_VIRTUAL_SUPER_MASK;
 
312
            }
 
313
          else
 
314
            {
 
315
              gchar last_ch;
 
316
 
 
317
              last_ch = *accelerator;
 
318
              while (last_ch && last_ch != '>')
 
319
                {
 
320
                  last_ch = *accelerator;
 
321
                  accelerator += 1;
 
322
                  len -= 1;
 
323
                }
 
324
            }
 
325
        }
 
326
      else
 
327
        {
 
328
          keyval = gdk_keyval_from_name (accelerator);
 
329
 
 
330
          if (keyval == 0)
 
331
            {
 
332
              /* If keyval is 0, then maybe it's a keycode.  Check for 0x## */
 
333
              if (len >= 4 && is_keycode (accelerator))
 
334
                {
 
335
                  char keystring[5];
 
336
                  gchar *endptr;
 
337
                  gint tmp_keycode;
 
338
 
 
339
                  memcpy (keystring, accelerator, 4);
 
340
                  keystring [4] = '\000';
 
341
 
 
342
                  tmp_keycode = strtol (keystring, &endptr, 16);
 
343
 
 
344
                  if (endptr == NULL || *endptr != '\000')
 
345
                    {
 
346
                      bad_keyval = TRUE;
 
347
                    }
 
348
                  else if (keycode != NULL)
 
349
                    {
 
350
                      *keycode = tmp_keycode;
 
351
                      /* 0x00 is an invalid keycode too. */
 
352
                      if (*keycode == 0)
 
353
                        bad_keyval = TRUE;
 
354
                    }
 
355
                }
 
356
            }
 
357
          else if (keycode != NULL)
 
358
            {
 
359
              *keycode = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), keyval);
 
360
              if (*keycode == 0)
 
361
                bad_keyval = TRUE;
 
362
            }
 
363
 
 
364
          accelerator += len;
 
365
          len -= len;
 
366
        }
 
367
    }
 
368
 
 
369
  if (accelerator_key)
 
370
    *accelerator_key = gdk_keyval_to_lower (keyval);
 
371
  if (accelerator_mods)
 
372
    *accelerator_mods = mods;
 
373
 
 
374
  return !bad_keyval;
 
375
}
 
376
 
 
377
/**
 
378
 * egg_virtual_accelerator_name:
 
379
 * @accelerator_key:  accelerator keyval
 
380
 * @accelerator_mods: accelerator modifier mask
 
381
 * @returns:          a newly-allocated accelerator name
 
382
 *
 
383
 * Converts an accelerator keyval and modifier mask
 
384
 * into a string parseable by egg_accelerator_parse_virtual().
 
385
 * For example, if you pass in #GDK_q and #EGG_VIRTUAL_CONTROL_MASK,
 
386
 * this function returns "&lt;Control&gt;q".
 
387
 *
 
388
 * The caller of this function must free the returned string.
 
389
 */
 
390
gchar*
 
391
egg_virtual_accelerator_name (guint                  accelerator_key,
 
392
                              guint                  keycode,
 
393
                              EggVirtualModifierType accelerator_mods)
 
394
{
 
395
  gchar *gtk_name;
 
396
  GdkModifierType gdkmods = 0;
 
397
 
 
398
  egg_keymap_resolve_virtual_modifiers (NULL, accelerator_mods, &gdkmods);
 
399
  gtk_name = gtk_accelerator_name (accelerator_key, gdkmods);
 
400
 
 
401
  if (!accelerator_key)
 
402
    {
 
403
        gchar *name;
 
404
        name = g_strdup_printf ("%s0x%02x", gtk_name, keycode);
 
405
        g_free (gtk_name);
 
406
        return name;
 
407
    }
 
408
 
 
409
  return gtk_name;
 
410
}
 
411
 
 
412
/**
 
413
 * egg_virtual_accelerator_label:
 
414
 * @accelerator_key:  accelerator keyval
 
415
 * @accelerator_mods: accelerator modifier mask
 
416
 * @returns:          a newly-allocated accelerator label
 
417
 *
 
418
 * Converts an accelerator keyval and modifier mask
 
419
 * into a (possibly translated) string that can be displayed to
 
420
 * a user.
 
421
 * For example, if you pass in #GDK_q and #EGG_VIRTUAL_CONTROL_MASK,
 
422
 * and you use a German locale, this function returns "Strg+Q".
 
423
 *
 
424
 * The caller of this function must free the returned string.
 
425
 */
 
426
gchar*
 
427
egg_virtual_accelerator_label (guint                  accelerator_key,
 
428
                               guint                  keycode,
 
429
                               EggVirtualModifierType accelerator_mods)
 
430
{
 
431
  gchar *gtk_label;
 
432
  GdkModifierType gdkmods = 0;
 
433
 
 
434
  egg_keymap_resolve_virtual_modifiers (NULL, accelerator_mods, &gdkmods);
 
435
  gtk_label = gtk_accelerator_get_label (accelerator_key, gdkmods);
 
436
 
 
437
  if (!accelerator_key)
 
438
    {
 
439
        gchar *label;
 
440
        label = g_strdup_printf ("%s0x%02x", gtk_label, keycode);
 
441
        g_free (gtk_label);
 
442
        return label;
 
443
    }
 
444
 
 
445
  return gtk_label;
 
446
}
 
447
 
 
448
void
 
449
egg_keymap_resolve_virtual_modifiers (GdkKeymap              *keymap,
 
450
                                      EggVirtualModifierType  virtual_mods,
 
451
                                      GdkModifierType        *concrete_mods)
 
452
{
 
453
  GdkModifierType concrete;
 
454
  int i;
 
455
  const EggModmap *modmap;
 
456
 
 
457
  g_return_if_fail (concrete_mods != NULL);
 
458
  g_return_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap));
 
459
 
 
460
  modmap = egg_keymap_get_modmap (keymap);
 
461
 
 
462
  /* Not so sure about this algorithm. */
 
463
 
 
464
  concrete = 0;
 
465
  for (i = 0; i < EGG_MODMAP_ENTRY_LAST; ++i)
 
466
    {
 
467
      if (modmap->mapping[i] & virtual_mods)
 
468
        concrete |= MODMAP_ENTRY_TO_MODIFIER (i);
 
469
    }
 
470
 
 
471
  *concrete_mods = concrete;
 
472
}
 
473
 
 
474
void
 
475
egg_keymap_virtualize_modifiers (GdkKeymap              *keymap,
 
476
                                 GdkModifierType         concrete_mods,
 
477
                                 EggVirtualModifierType *virtual_mods)
 
478
{
 
479
  GdkModifierType virtual;
 
480
  int i;
 
481
  const EggModmap *modmap;
 
482
 
 
483
  g_return_if_fail (virtual_mods != NULL);
 
484
  g_return_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap));
 
485
 
 
486
  modmap = egg_keymap_get_modmap (keymap);
 
487
 
 
488
  /* Not so sure about this algorithm. */
 
489
 
 
490
  virtual = 0;
 
491
  for (i = 0; i < EGG_MODMAP_ENTRY_LAST; ++i)
 
492
    {
 
493
      if (MODMAP_ENTRY_TO_MODIFIER (i) & concrete_mods)
 
494
        {
 
495
          EggVirtualModifierType cleaned;
 
496
 
 
497
          cleaned = modmap->mapping[i] & ~(EGG_VIRTUAL_MOD2_MASK |
 
498
                                           EGG_VIRTUAL_MOD3_MASK |
 
499
                                           EGG_VIRTUAL_MOD4_MASK |
 
500
                                           EGG_VIRTUAL_MOD5_MASK);
 
501
 
 
502
          if (cleaned != 0)
 
503
            {
 
504
              virtual |= cleaned;
 
505
            }
 
506
          else
 
507
            {
 
508
              /* Rather than dropping mod2->mod5 if not bound,
 
509
               * go ahead and use the concrete names
 
510
               */
 
511
              virtual |= modmap->mapping[i];
 
512
            }
 
513
        }
 
514
    }
 
515
 
 
516
  *virtual_mods = virtual;
 
517
}
 
518
 
 
519
static void
 
520
reload_modmap (GdkKeymap *keymap,
 
521
               EggModmap *modmap)
 
522
{
 
523
  XModifierKeymap *xmodmap;
 
524
  int map_size;
 
525
  int i;
 
526
 
 
527
  /* FIXME multihead */
 
528
  xmodmap = XGetModifierMapping (gdk_x11_get_default_xdisplay ());
 
529
 
 
530
  memset (modmap->mapping, 0, sizeof (modmap->mapping));
 
531
 
 
532
  /* there are 8 modifiers in the order shift, shift lock,
 
533
   * control, mod1-5 with up to max_keypermod bindings each
 
534
   */
 
535
  map_size = 8 * xmodmap->max_keypermod;
 
536
  for (i = 3 * xmodmap->max_keypermod; i < map_size; ++i)
 
537
    {
 
538
      /* get the key code at this point in the map,
 
539
       * see if its keysym is one we're interested in
 
540
       */
 
541
      int keycode = xmodmap->modifiermap[i];
 
542
      GdkKeymapKey *keys;
 
543
      guint *keyvals;
 
544
      int n_entries;
 
545
      int j;
 
546
      EggVirtualModifierType mask;
 
547
 
 
548
      keys = NULL;
 
549
      keyvals = NULL;
 
550
      n_entries = 0;
 
551
 
 
552
      gdk_keymap_get_entries_for_keycode (keymap,
 
553
                                          keycode,
 
554
                                          &keys, &keyvals, &n_entries);
 
555
 
 
556
      mask = 0;
 
557
      for (j = 0; j < n_entries; ++j)
 
558
        {
 
559
          if (keyvals[j] == GDK_KEY_Num_Lock)
 
560
            mask |= EGG_VIRTUAL_NUM_LOCK_MASK;
 
561
          else if (keyvals[j] == GDK_KEY_Scroll_Lock)
 
562
            mask |= EGG_VIRTUAL_SCROLL_LOCK_MASK;
 
563
          else if (keyvals[j] == GDK_KEY_Meta_L ||
 
564
                   keyvals[j] == GDK_KEY_Meta_R)
 
565
            mask |= EGG_VIRTUAL_META_MASK;
 
566
          else if (keyvals[j] == GDK_KEY_Hyper_L ||
 
567
                   keyvals[j] == GDK_KEY_Hyper_R)
 
568
            mask |= EGG_VIRTUAL_HYPER_MASK;
 
569
          else if (keyvals[j] == GDK_KEY_Super_L ||
 
570
                   keyvals[j] == GDK_KEY_Super_R)
 
571
            mask |= EGG_VIRTUAL_SUPER_MASK;
 
572
          else if (keyvals[j] == GDK_KEY_Mode_switch)
 
573
            mask |= EGG_VIRTUAL_MODE_SWITCH_MASK;
 
574
        }
 
575
 
 
576
      /* Mod1Mask is 1 << 3 for example, i.e. the
 
577
       * fourth modifier, i / keyspermod is the modifier
 
578
       * index
 
579
       */
 
580
      modmap->mapping[i/xmodmap->max_keypermod] |= mask;
 
581
 
 
582
      g_free (keyvals);
 
583
      g_free (keys);
 
584
    }
 
585
 
 
586
  /* Add in the not-really-virtual fixed entries */
 
587
  modmap->mapping[EGG_MODMAP_ENTRY_SHIFT] |= EGG_VIRTUAL_SHIFT_MASK;
 
588
  modmap->mapping[EGG_MODMAP_ENTRY_CONTROL] |= EGG_VIRTUAL_CONTROL_MASK;
 
589
  modmap->mapping[EGG_MODMAP_ENTRY_LOCK] |= EGG_VIRTUAL_LOCK_MASK;
 
590
  modmap->mapping[EGG_MODMAP_ENTRY_MOD1] |= EGG_VIRTUAL_ALT_MASK;
 
591
  modmap->mapping[EGG_MODMAP_ENTRY_MOD2] |= EGG_VIRTUAL_MOD2_MASK;
 
592
  modmap->mapping[EGG_MODMAP_ENTRY_MOD3] |= EGG_VIRTUAL_MOD3_MASK;
 
593
  modmap->mapping[EGG_MODMAP_ENTRY_MOD4] |= EGG_VIRTUAL_MOD4_MASK;
 
594
  modmap->mapping[EGG_MODMAP_ENTRY_MOD5] |= EGG_VIRTUAL_MOD5_MASK;
 
595
 
 
596
  XFreeModifiermap (xmodmap);
 
597
}
 
598
 
 
599
const EggModmap*
 
600
egg_keymap_get_modmap (GdkKeymap *keymap)
 
601
{
 
602
  EggModmap *modmap;
 
603
 
 
604
  if (keymap == NULL)
 
605
    keymap = gdk_keymap_get_default ();
 
606
 
 
607
  /* This is all a hack, much simpler when we can just
 
608
   * modify GDK directly.
 
609
   */
 
610
 
 
611
  modmap = g_object_get_data (G_OBJECT (keymap), "egg-modmap");
 
612
 
 
613
  if (modmap == NULL)
 
614
    {
 
615
      modmap = g_new0 (EggModmap, 1);
 
616
 
 
617
      /* FIXME modify keymap change events with an event filter
 
618
       * and force a reload if we get one
 
619
       */
 
620
 
 
621
      reload_modmap (keymap, modmap);
 
622
 
 
623
      g_object_set_data_full (G_OBJECT (keymap),
 
624
                              "egg-modmap",
 
625
                              modmap,
 
626
                              g_free);
 
627
    }
 
628
 
 
629
  g_assert (modmap != NULL);
 
630
 
 
631
  return modmap;
 
632
}