~vcs-imports/gnome-mag/master

« back to all changes in this revision

Viewing changes to colorblind/keybinder/eggaccelerators.c

  • Committer: Carlos Eduardo Rodrigues Diógenes
  • Date: 2007-06-03 23:52:07 UTC
  • Revision ID: git-v1:42a8898cb38357218626e4c81555423da8ab37cd
Tags: GNOME_MAG_0_14_5
commit the changes of the colorblind applet

svn path=/trunk/; revision=515

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