2
// This file comes from the Tomboy project.
3
// http://www.gnome.org/projects/tomboy/
6
* Copyright (C) 2004-2007 Alex Graveley
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Library General Public
10
* License as published by the Free Software Foundation; either
11
* version 2 of the License, or (at your option) any later version.
13
* This library is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Library General Public License for more details.
18
* You should have received a copy of the GNU Library General Public
19
* License along with this library; if not, write to the
20
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21
* Boston, MA 02111-1307, USA.
27
#include <gdk/gdkwindow.h>
31
#include "eggaccelerators.h"
32
#include "keybinder.h"
34
/* Uncomment the next line to print a debug trace. */
40
# define TRACE(x) do {} while (FALSE);
43
typedef struct _Binding {
44
GnomeDoBindkeyHandler handler;
51
static GSList *bindings = NULL;
52
static guint32 last_event_time = 0;
53
static gboolean processing_event = FALSE;
55
static guint num_lock_mask, caps_lock_mask, scroll_lock_mask;
58
lookup_ignorable_modifiers (GdkKeymap *keymap)
60
egg_keymap_resolve_virtual_modifiers (keymap,
61
EGG_VIRTUAL_LOCK_MASK,
64
egg_keymap_resolve_virtual_modifiers (keymap,
65
EGG_VIRTUAL_NUM_LOCK_MASK,
68
egg_keymap_resolve_virtual_modifiers (keymap,
69
EGG_VIRTUAL_SCROLL_LOCK_MASK,
74
grab_ungrab_with_ignorable_modifiers (GdkWindow *rootwin,
78
guint mod_masks [] = {
79
0, /* modifier only */
83
num_lock_mask | caps_lock_mask,
84
num_lock_mask | scroll_lock_mask,
85
caps_lock_mask | scroll_lock_mask,
86
num_lock_mask | caps_lock_mask | scroll_lock_mask,
90
for (i = 0; i < G_N_ELEMENTS (mod_masks); i++) {
92
XGrabKey (GDK_WINDOW_XDISPLAY (rootwin),
94
binding->modifiers | mod_masks [i],
95
GDK_WINDOW_XWINDOW (rootwin),
100
XUngrabKey (GDK_WINDOW_XDISPLAY (rootwin),
102
binding->modifiers | mod_masks [i],
103
GDK_WINDOW_XWINDOW (rootwin));
109
do_grab_key (Binding *binding)
111
GdkKeymap *keymap = gdk_keymap_get_default ();
112
GdkWindow *rootwin = gdk_get_default_root_window ();
114
EggVirtualModifierType virtual_mods = 0;
117
if (keymap == NULL || rootwin == NULL)
120
if (!egg_accelerator_parse_virtual (binding->keystring,
125
TRACE (g_print ("Got accel %d, %d\n", keysym, virtual_mods));
127
binding->keycode = XKeysymToKeycode (GDK_WINDOW_XDISPLAY (rootwin),
129
if (binding->keycode == 0)
132
TRACE (g_print ("Got keycode %d\n", binding->keycode));
134
egg_keymap_resolve_virtual_modifiers (keymap,
136
&binding->modifiers);
138
TRACE (g_print ("Got modmask %d\n", binding->modifiers));
140
gdk_error_trap_push ();
142
grab_ungrab_with_ignorable_modifiers (rootwin,
148
if (gdk_error_trap_pop ()) {
149
g_warning ("Binding '%s' failed!\n", binding->keystring);
157
do_ungrab_key (Binding *binding)
159
GdkWindow *rootwin = gdk_get_default_root_window ();
161
TRACE (g_print ("Removing grab for '%s'\n", binding->keystring));
163
grab_ungrab_with_ignorable_modifiers (rootwin,
170
static GdkFilterReturn
171
filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
173
GdkFilterReturn return_val = GDK_FILTER_CONTINUE;
174
XEvent *xevent = (XEvent *) gdk_xevent;
178
TRACE (g_print ("Got Event! %d, %d\n", xevent->type, event->type));
180
switch (xevent->type) {
182
TRACE (g_print ("Got KeyPress! keycode: %d, modifiers: %d\n",
183
xevent->xkey.keycode,
184
xevent->xkey.state));
187
* Set the last event time for use when showing
188
* windows to avoid anti-focus-stealing code.
190
processing_event = TRUE;
191
last_event_time = xevent->xkey.time;
193
event_mods = xevent->xkey.state & ~(num_lock_mask |
197
for (iter = bindings; iter != NULL; iter = iter->next) {
198
Binding *binding = (Binding *) iter->data;
200
if (binding->keycode == xevent->xkey.keycode &&
201
binding->modifiers == event_mods) {
203
TRACE (g_print ("Calling handler for '%s'...\n",
204
binding->keystring));
206
(binding->handler) (binding->keystring,
211
processing_event = FALSE;
214
TRACE (g_print ("Got KeyRelease! \n"));
222
keymap_changed (GdkKeymap *map)
224
GdkKeymap *keymap = gdk_keymap_get_default ();
227
TRACE (g_print ("Keymap changed! Regrabbing keys..."));
229
for (iter = bindings; iter != NULL; iter = iter->next) {
230
Binding *binding = (Binding *) iter->data;
231
do_ungrab_key (binding);
234
lookup_ignorable_modifiers (keymap);
236
for (iter = bindings; iter != NULL; iter = iter->next) {
237
Binding *binding = (Binding *) iter->data;
238
do_grab_key (binding);
243
wsbind_keybinder_init (void)
245
GdkKeymap *keymap = gdk_keymap_get_default ();
246
GdkWindow *rootwin = gdk_get_default_root_window ();
248
lookup_ignorable_modifiers (keymap);
250
gdk_window_add_filter (rootwin,
254
g_signal_connect (keymap,
256
G_CALLBACK (keymap_changed),
261
wsbind_keybinder_bind (const char *keystring,
262
GnomeDoBindkeyHandler handler,
268
binding = g_new0 (Binding, 1);
269
binding->keystring = g_strdup (keystring);
270
binding->handler = handler;
271
binding->user_data = user_data;
273
/* Sets the binding's keycode and modifiers */
274
success = do_grab_key (binding);
277
bindings = g_slist_prepend (bindings, binding);
279
g_free (binding->keystring);
285
wsbind_keybinder_unbind (const char *keystring,
286
GnomeDoBindkeyHandler handler)
290
for (iter = bindings; iter != NULL; iter = iter->next) {
291
Binding *binding = (Binding *) iter->data;
293
if (strcmp (keystring, binding->keystring) != 0 ||
294
handler != binding->handler)
297
do_ungrab_key (binding);
299
bindings = g_slist_remove (bindings, binding);
301
g_free (binding->keystring);
308
* From eggcellrenderkeys.c.
311
wsbind_keybinder_is_modifier (guint keycode)
315
XModifierKeymap *mod_keymap;
316
gboolean retval = FALSE;
318
mod_keymap = XGetModifierMapping (gdk_display);
320
map_size = 8 * mod_keymap->max_keypermod;
323
while (i < map_size) {
324
if (keycode == mod_keymap->modifiermap[i]) {
331
XFreeModifiermap (mod_keymap);
337
wsbind_keybinder_get_current_event_time (void)
339
if (processing_event)
340
return last_event_time;
342
return GDK_CURRENT_TIME;