2
* This code was original written by Alex Graveley for Tomboy
3
* (http://www.beatniksoftware.com/tomboy), which is also
4
* LGPL program. Thanks to him.
6
* - 14/05/2007 - Lincoln de Sousa <lincoln@archlinux-br.org>
8
* changing keybinder_bind return type from void to gboolean.
12
#include <gdk/gdkwindow.h>
17
#include "eggaccelerators.h"
18
#include "keybinder.h"
20
/* Uncomment the next line to print a debug trace. */
26
# define TRACE(x) do {} while (FALSE);
29
typedef struct _Binding {
30
BindkeyHandler handler;
37
static GSList *bindings = NULL;
38
static guint32 last_event_time = 0;
39
static gboolean processing_event = FALSE;
41
static guint num_lock_mask, caps_lock_mask, scroll_lock_mask;
44
lookup_ignorable_modifiers (GdkKeymap *keymap)
46
egg_keymap_resolve_virtual_modifiers (keymap,
47
EGG_VIRTUAL_LOCK_MASK,
50
egg_keymap_resolve_virtual_modifiers (keymap,
51
EGG_VIRTUAL_NUM_LOCK_MASK,
54
egg_keymap_resolve_virtual_modifiers (keymap,
55
EGG_VIRTUAL_SCROLL_LOCK_MASK,
60
grab_ungrab_with_ignorable_modifiers (GdkWindow *rootwin,
64
guint mod_masks [] = {
65
0, /* modifier only */
69
num_lock_mask | caps_lock_mask,
70
num_lock_mask | scroll_lock_mask,
71
caps_lock_mask | scroll_lock_mask,
72
num_lock_mask | caps_lock_mask | scroll_lock_mask,
76
for (i = 0; i < G_N_ELEMENTS (mod_masks); i++) {
78
XGrabKey (GDK_WINDOW_XDISPLAY (rootwin),
80
binding->modifiers | mod_masks [i],
81
GDK_WINDOW_XWINDOW (rootwin),
86
XUngrabKey (GDK_WINDOW_XDISPLAY (rootwin),
88
binding->modifiers | mod_masks [i],
89
GDK_WINDOW_XWINDOW (rootwin));
95
do_grab_key (Binding *binding)
97
GdkKeymap *keymap = gdk_keymap_get_default ();
98
GdkWindow *rootwin = gdk_get_default_root_window ();
100
EggVirtualModifierType virtual_mods = 0;
103
if (keymap == NULL || rootwin == NULL)
106
if (!egg_accelerator_parse_virtual (binding->keystring,
111
TRACE (g_print ("Got accel %d, %d\n", keysym, virtual_mods));
113
binding->keycode = XKeysymToKeycode (GDK_WINDOW_XDISPLAY (rootwin),
115
if (binding->keycode == 0)
118
TRACE (g_print ("Got keycode %d\n", binding->keycode));
120
egg_keymap_resolve_virtual_modifiers (keymap,
122
&binding->modifiers);
124
TRACE (g_print ("Got modmask %d\n", binding->modifiers));
126
gdk_error_trap_push ();
128
grab_ungrab_with_ignorable_modifiers (rootwin,
134
if (gdk_error_trap_pop ()) {
135
g_warning ("Binding '%s' failed!\n", binding->keystring);
143
do_ungrab_key (Binding *binding)
145
GdkWindow *rootwin = gdk_get_default_root_window ();
147
TRACE (g_print ("Removing grab for '%s'\n", binding->keystring));
149
grab_ungrab_with_ignorable_modifiers (rootwin,
156
static GdkFilterReturn
157
filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
159
GdkFilterReturn return_val = GDK_FILTER_CONTINUE;
160
XEvent *xevent = (XEvent *) gdk_xevent;
164
TRACE (g_print ("Got Event! %d, %d\n", xevent->type, event->type));
166
switch (xevent->type) {
168
TRACE (g_print ("Got KeyPress! keycode: %d, modifiers: %d\n",
169
xevent->xkey.keycode,
170
xevent->xkey.state));
173
* Set the last event time for use when showing
174
* windows to avoid anti-focus-stealing code.
176
processing_event = TRUE;
177
last_event_time = xevent->xkey.time;
179
event_mods = xevent->xkey.state & ~(num_lock_mask |
183
for (iter = bindings; iter != NULL; iter = iter->next) {
184
Binding *binding = (Binding *) iter->data;
186
if (binding->keycode == xevent->xkey.keycode &&
187
binding->modifiers == event_mods) {
189
TRACE (g_print ("Calling handler for '%s'...\n",
190
binding->keystring));
192
(binding->handler) (binding->keystring,
197
processing_event = FALSE;
200
TRACE (g_print ("Got KeyRelease! \n"));
208
keymap_changed (GdkKeymap *map)
210
GdkKeymap *keymap = gdk_keymap_get_default ();
213
TRACE (g_print ("Keymap changed! Regrabbing keys..."));
215
for (iter = bindings; iter != NULL; iter = iter->next) {
216
Binding *binding = (Binding *) iter->data;
217
do_ungrab_key (binding);
220
lookup_ignorable_modifiers (keymap);
222
for (iter = bindings; iter != NULL; iter = iter->next) {
223
Binding *binding = (Binding *) iter->data;
224
do_grab_key (binding);
229
keybinder_init (void)
231
GdkKeymap *keymap = gdk_keymap_get_default ();
232
GdkWindow *rootwin = gdk_get_default_root_window ();
234
lookup_ignorable_modifiers (keymap);
236
gdk_window_add_filter (rootwin,
240
g_signal_connect (keymap,
242
G_CALLBACK (keymap_changed),
247
keybinder_bind (const char *keystring,
248
BindkeyHandler handler,
254
binding = g_new0 (Binding, 1);
255
binding->keystring = g_strdup (keystring);
256
binding->handler = handler;
257
binding->user_data = user_data;
259
/* Sets the binding's keycode and modifiers */
260
success = do_grab_key (binding);
263
bindings = g_slist_prepend (bindings, binding);
266
g_free (binding->keystring);
273
keybinder_unbind (const char *keystring,
274
BindkeyHandler handler)
278
for (iter = bindings; iter != NULL; iter = iter->next) {
279
Binding *binding = (Binding *) iter->data;
281
if (strcmp (keystring, binding->keystring) != 0 ||
282
handler != binding->handler)
285
do_ungrab_key (binding);
287
bindings = g_slist_remove (bindings, binding);
289
g_free (binding->keystring);
296
* From eggcellrenderkeys.c.
299
keybinder_is_modifier (guint keycode)
303
XModifierKeymap *mod_keymap;
304
gboolean retval = FALSE;
306
mod_keymap = XGetModifierMapping (gdk_display);
308
map_size = 8 * mod_keymap->max_keypermod;
311
while (i < map_size) {
312
if (keycode == mod_keymap->modifiermap[i]) {
319
XFreeModifiermap (mod_keymap);
325
keybinder_get_current_event_time (void)
327
if (processing_event)
328
return last_event_time;
330
return GDK_CURRENT_TIME;