1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2001-2003 Bastien Nocera <hadess@hadess.net>
4
* Copyright (C) 2006-2007 William Jon McCann <mccann@jhu.edu>
5
* Copyright (C) 2008 Jens Granseuer <jensgr@gmx.net>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29
#include <X11/XKBlib.h>
30
#include <X11/extensions/XInput2.h>
31
#include <X11/extensions/XKB.h>
32
#include <gdk/gdkkeysyms.h>
34
#include "gsd-keygrab.h"
36
/* these are the mods whose combinations are ignored by the keygrabbing code */
37
static GdkModifierType gsd_ignored_mods = 0;
39
/* these are the ones we actually use for global keys, we always only check
41
static GdkModifierType gsd_used_mods = 0;
43
/* Taken from a comment in XF86keysym.h */
44
#define XF86KEYS_RANGE_MIN 0x10080001
45
#define XF86KEYS_RANGE_MAX 0x1008FFFF
47
#define FKEYS_RANGE_MIN GDK_KEY_F1
48
#define FKEYS_RANGE_MAX GDK_KEY_R15
50
#define IN_RANGE(x, min, max) (x >= min && x <= max)
53
setup_modifiers (void)
55
if (gsd_used_mods == 0 || gsd_ignored_mods == 0) {
56
GdkModifierType dynmods;
58
/* default modifiers */
60
0x2000 /*Xkb modifier*/ | GDK_LOCK_MASK | GDK_HYPER_MASK;
62
GDK_SHIFT_MASK | GDK_CONTROL_MASK |\
63
GDK_MOD1_MASK | GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK |\
64
GDK_MOD5_MASK | GDK_SUPER_MASK | GDK_META_MASK;
66
/* NumLock can be assigned to varying keys so we need to
67
* resolve and ignore it specially */
68
dynmods = XkbKeysymToModifiers (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_KEY_Num_Lock);
70
gsd_ignored_mods |= dynmods;
71
gsd_used_mods &= ~dynmods;
76
grab_key_real (guint keycode,
80
XIGrabModifiers *mods,
84
unsigned char mask[(XI_LASTEVENT + 7)/8];
86
memset (mask, 0, sizeof (mask));
87
XISetMask (mask, XI_KeyPress);
88
XISetMask (mask, XI_KeyRelease);
90
evmask.deviceid = XIAllMasterDevices;
91
evmask.mask_len = sizeof (mask);
95
XIGrabKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
98
GDK_WINDOW_XID (root),
100
synchronous ? GrabModeSync : GrabModeAsync,
106
XIUngrabKeycode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
109
GDK_WINDOW_XID (root),
115
/* Grab the key. In order to ignore GSD_IGNORED_MODS we need to grab
116
* all combinations of the ignored modifiers and those actually used
117
* for the binding (if any).
119
* inspired by all_combinations from gnome-panel/gnome-panel/global-keys.c
121
* This may generate X errors. The correct way to use this is like:
123
* gdk_error_trap_push ();
125
* grab_key_unsafe (key, grab, screens);
128
* if (gdk_error_trap_pop ())
129
* g_warning ("Grab failed, another application may already have access to key '%u'",
132
* This is not done in the function itself, to allow doing multiple grab_key
133
* operations with one flush only.
137
grab_key_internal (Key *key,
139
GsdKeygrabFlags flags,
142
int indexes[N_BITS]; /* indexes of bits we need to flip */
147
guint mask, modifiers;
153
mask = gsd_ignored_mods & ~key->state & GDK_MODIFIER_MASK;
155
/* XGrabKey requires real modifiers, not virtual ones */
156
modifiers = key->state;
157
gdk_keymap_map_virtual_modifiers (gdk_keymap_get_default (), &modifiers);
158
modifiers &= ~(GDK_META_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK);
160
/* If key doesn't have a usable modifier, we don't want
161
* to grab it, since the user might lose a useful key.
163
* The exception is the XFree86 keys and the Function keys
164
* (which are useful to grab without a modifier).
166
if (!(flags & GSD_KEYGRAB_ALLOW_UNMODIFIED) &&
167
(modifiers & gsd_used_mods) == 0 &&
168
!IN_RANGE(key->keysym, XF86KEYS_RANGE_MIN, XF86KEYS_RANGE_MAX) &&
169
!IN_RANGE(key->keysym, FKEYS_RANGE_MIN, FKEYS_RANGE_MAX) &&
170
key->keysym != GDK_KEY_Pause &&
171
key->keysym != GDK_KEY_Print &&
172
key->keysym != GDK_KEY_Scroll_Lock &&
173
key->keysym != GDK_KEY_Caps_Lock &&
174
key->keysym != GDK_KEY_Pause &&
175
key->keysym != GDK_KEY_Break &&
176
key->keysym != GDK_KEY_Menu) {
179
keycodes = g_string_new ("");
180
if (key->keycodes != NULL) {
183
for (c = key->keycodes; *c; ++c) {
184
g_string_printf (keycodes, " %u", *c);
187
g_warning ("Key 0x%x (keycodes: %s) with state 0x%x (resolved to 0x%x) "
188
" has no usable modifiers (usable modifiers are 0x%x)",
189
key->keysym, keycodes->str, key->state, modifiers, gsd_used_mods);
190
g_string_free (keycodes, TRUE);
196
/* store the indexes of all set bits in mask in the array */
197
for (i = 0; mask; ++i, mask >>= 1) {
205
all_mods = g_array_new (FALSE, TRUE, sizeof(XIGrabModifiers));
206
uppervalue = 1 << bits_set_cnt;
207
/* store all possible modifier combinations for our mask into all_mods */
208
for (i = 0; i < uppervalue; ++i) {
211
XIGrabModifiers *mod;
213
/* map bits in the counter to those in the mask */
214
for (j = 0; j < bits_set_cnt; ++j) {
216
result |= (1 << indexes[j]);
220
/* Grow the array by one, to fit our new XIGrabModifiers item */
221
g_array_set_size (all_mods, all_mods->len + 1);
222
mod = &g_array_index (all_mods, XIGrabModifiers, all_mods->len - 1);
223
mod->modifiers = result | modifiers;
226
/* Capture the actual keycodes with the modifier array */
227
for (l = screens; l; l = l->next) {
228
GdkScreen *screen = l->data;
231
for (code = key->keycodes; *code; ++code) {
232
grab_key_real (*code,
233
gdk_screen_get_root_window (screen),
235
flags & GSD_KEYGRAB_SYNCHRONOUS,
236
(XIGrabModifiers *) all_mods->data,
240
g_array_free (all_mods, TRUE);
244
get_keys_for_bit (guint bit,
254
right = &right_dummy;
261
*left = GDK_KEY_Shift_L;
262
*right = GDK_KEY_Shift_R;
264
case GDK_CONTROL_MASK:
265
*left = GDK_KEY_Control_L;
266
*right = GDK_KEY_Control_R;
269
*left = GDK_KEY_Caps_Lock;
270
*right = GDK_KEY_Shift_Lock;
274
*left = GDK_KEY_Alt_L;
275
*right = GDK_KEY_Alt_R;
278
*left = GDK_KEY_Super_L;
279
*right = GDK_KEY_Super_R;
285
get_mask_for_key (guint key)
288
case GDK_KEY_Shift_L:
289
case GDK_KEY_Shift_R:
290
return GDK_SHIFT_MASK;
291
case GDK_KEY_Control_L:
292
case GDK_KEY_Control_R:
293
return GDK_CONTROL_MASK;
294
case GDK_KEY_Caps_Lock:
295
case GDK_KEY_Shift_Lock:
296
return GDK_LOCK_MASK;
301
return GDK_MOD1_MASK;
302
case GDK_KEY_Super_L:
303
case GDK_KEY_Super_R:
304
return GDK_SUPER_MASK;
311
get_mirrored_key (guint key)
314
case GDK_KEY_Shift_L:
315
return GDK_KEY_Shift_R;
316
case GDK_KEY_Shift_R:
317
return GDK_KEY_Shift_L;
318
case GDK_KEY_Control_L:
319
return GDK_KEY_Control_R;
320
case GDK_KEY_Control_R:
321
return GDK_KEY_Control_L;
323
return GDK_KEY_Meta_R;
325
return GDK_KEY_Meta_L;
327
return GDK_KEY_Alt_R;
329
return GDK_KEY_Alt_L;
330
case GDK_KEY_Super_L:
331
return GDK_KEY_Super_R;
332
case GDK_KEY_Super_R:
333
return GDK_KEY_Super_L;
334
case GDK_KEY_Hyper_L:
335
return GDK_KEY_Hyper_R;
336
case GDK_KEY_Hyper_R:
337
return GDK_KEY_Hyper_L;
344
grab_key_unsafe (Key *key,
345
GsdKeygrabFlags flags,
348
guint key_mask = get_mask_for_key (key->keysym);
350
grab_key_internal (key, TRUE, flags, screens);
356
if ((key->state & key_mask) != 0) {
357
guint mirror = get_mirrored_key (key->keysym);
360
gint mirror_keys_len;
361
GdkKeymapKey *mirror_keys;
363
gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
368
copy.keysym = mirror;
369
copy.state = key->state;
370
copy.keycodes = g_new0 (guint, mirror_keys_len + 1);
372
for (j = 0; j < mirror_keys_len; j++)
373
copy.keycodes[j] = mirror_keys[j].keycode;
375
grab_key_internal (©, TRUE, flags, screens);
377
g_free (copy.keycodes);
378
g_free (mirror_keys);
382
for (i = 0; i < 8 * sizeof (guint); i++) {
384
gint left_keys_len, right_keys_len;
385
GdkKeymapKey *left_keys, *right_keys;
387
if (1 << i == key_mask || (key->state & 1 << i) == 0)
390
get_keys_for_bit (i, &left, &right);
392
if (left == 0 && right == 0)
401
gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
407
gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
412
copy.keysym = left != 0 ? left : right;
413
copy.state = (key->state | key_mask) & ~(1 << i);
414
copy.keycodes = g_new0 (guint, left_keys_len + right_keys_len + 1);
416
for (j = 0; j < left_keys_len; j++)
417
copy.keycodes[j] = left_keys[j].keycode;
418
for (j = 0; j < right_keys_len; j++)
419
copy.keycodes[left_keys_len + j] = right_keys[j].keycode;
421
grab_key_internal (©, TRUE, flags, screens);
423
g_free (copy.keycodes);
431
ungrab_key_unsafe (Key *key,
434
guint key_mask = get_mask_for_key (key->keysym);
436
grab_key_internal (key, FALSE, 0, screens);
442
if ((key->state & key_mask) != 0) {
443
guint mirror = get_mirrored_key (key->keysym);
446
gint mirror_keys_len;
447
GdkKeymapKey *mirror_keys;
449
gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
454
copy.keysym = mirror;
455
copy.state = key->state;
456
copy.keycodes = g_new0 (guint, mirror_keys_len + 1);
458
for (j = 0; j < mirror_keys_len; j++)
459
copy.keycodes[j] = mirror_keys[j].keycode;
461
grab_key_internal (©, FALSE, 0, screens);
463
g_free (copy.keycodes);
464
g_free (mirror_keys);
468
for (i = 0; i < 8 * sizeof (guint); i++) {
470
gint left_keys_len, right_keys_len;
471
GdkKeymapKey *left_keys, *right_keys;
473
if (1 << i == key_mask || (key->state & 1 << i) == 0)
476
get_keys_for_bit (i, &left, &right);
478
if (left == 0 && right == 0)
487
gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
493
gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
498
copy.keysym = left != 0 ? left : right;
499
copy.state = (key->state | key_mask) & ~(1 << i);
500
copy.keycodes = g_new0 (guint, left_keys_len + right_keys_len + 1);
502
for (j = 0; j < left_keys_len; j++)
503
copy.keycodes[j] = left_keys[j].keycode;
504
for (j = 0; j < right_keys_len; j++)
505
copy.keycodes[left_keys_len + j] = right_keys[j].keycode;
507
grab_key_internal (©, FALSE, 0, screens);
509
g_free (copy.keycodes);
517
have_xkb (Display *dpy)
519
static int have_xkb = -1;
521
if (have_xkb == -1) {
522
int opcode, error_base, major, minor, xkb_event_base;
524
have_xkb = XkbQueryExtension (dpy,
530
&& XkbUseExtension (dpy, &major, &minor);
537
key_uses_keycode (const Key *key, guint keycode)
539
if (key->keycodes != NULL) {
542
for (c = key->keycodes; *c; ++c) {
550
/* Adapted from _gdk_x11_device_xi2_translate_state()
551
* in gtk+/gdk/x11/gdkdevice-xi2.c */
553
device_xi2_translate_state (XIModifierState *mods_state,
554
XIGroupState *group_state)
559
state = (guint) mods_state->base | mods_state->latched | mods_state->locked;
561
group = group_state->base | group_state->latched | group_state->locked;
562
/* FIXME: do we need the XKB complications for this ? */
563
group = CLAMP(group, 0, 3);
564
state |= group << 13;
570
match_xi2_key (Key *key, XIDeviceEvent *event)
573
GdkModifierType consumed;
575
guint keycode, state;
582
state = device_xi2_translate_state (&event->mods, &event->group);
584
if (have_xkb (event->display))
585
group = XkbGroupForCoreState (state);
587
group = (state & GDK_KEY_Mode_switch) ? 1 : 0;
589
keycode = event->detail;
591
/* Check if we find a keysym that matches our current state */
592
if (gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (), keycode,
594
&keyval, NULL, NULL, &consumed)) {
595
guint key_bit, event_bit;
597
guint mask, full_mask;
599
/* HACK: we don't want to use SysRq as a keybinding, so we avoid
600
* its translation from Alt+Print. */
601
if (keyval == GDK_KEY_Sys_Req &&
602
(state & GDK_MOD1_MASK) != 0) {
604
keyval = GDK_KEY_Print;
607
/* The Key structure contains virtual modifiers, whereas
608
* the XEvent will be using the real modifier, so translate those */
609
key_bit = get_mask_for_key (key->keysym);
610
event_bit = get_mask_for_key (keyval);
612
full_mask = mask | key_bit;
613
gdk_keymap_map_virtual_modifiers (gdk_keymap_get_default (), &mask);
614
gdk_keymap_map_virtual_modifiers (gdk_keymap_get_default (), &full_mask);
615
mask &= ~(GDK_META_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK);
616
full_mask &= ~(GDK_META_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK);
618
gdk_keyval_convert_case (keyval, &lower, &upper);
620
/* If we are checking against the lower version of the
621
* keysym, we might need the Shift state for matching,
622
* so remove it from the consumed modifiers */
623
if (lower == key->keysym || event_bit != 0)
624
consumed &= ~GDK_SHIFT_MASK;
626
state &= ~consumed & gsd_used_mods;
628
if (key_bit != 0 && event_bit != 0) {
630
gdk_keymap_map_virtual_modifiers (gdk_keymap_get_default (), &state);
631
state &= ~(GDK_META_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK);
632
return state == full_mask;
635
return (lower == key->keysym || upper == key->keysym) && state == mask;
638
/* The key we passed doesn't have a keysym, so try with just the keycode */
640
&& key->state == (state & gsd_used_mods)
641
&& key_uses_keycode (key, keycode));
645
parse_key (const char *str)
651
g_str_equal (str, "disabled")) {
655
key = g_new0 (Key, 1);
656
gtk_accelerator_parse_with_keycode (str, &key->keysym, &key->keycodes, &key->state);
657
if (key->keysym == 0 &&
658
key->keycodes == NULL &&
672
g_free (key->keycodes);
677
grab_button_real (int deviceid,
681
XIGrabModifiers mods;
683
mods.modifiers = XIAnyModifier;
687
unsigned char mask[(XI_LASTEVENT + 7)/8];
689
memset (mask, 0, sizeof (mask));
690
XISetMask (mask, XI_ButtonRelease);
691
XISetMask (mask, XI_ButtonPress);
693
evmask.deviceid = deviceid;
694
evmask.mask_len = sizeof (mask);
697
XIGrabButton (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
700
GDK_WINDOW_XID (root),
709
XIUngrabButton (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
712
GDK_WINDOW_XID (root),
718
grab_button (int deviceid,
724
for (l = screens; l; l = l->next) {
725
GdkScreen *screen = l->data;
727
grab_button_real (deviceid,
729
gdk_screen_get_root_window (screen));