4 #include <gdk/gdkwindow.h>
8 #include "eggaccelerators.h"
9 #include "tomboykeybinder.h"
11 /* Uncomment the next line to print a debug trace. */
17 # define TRACE(x) do {} while (FALSE);
20 typedef struct _Binding
{
21 TomboyBindkeyHandler handler
;
28 static GSList
*bindings
= NULL
;
29 static guint32 last_event_time
= 0;
30 static gboolean processing_event
= FALSE
;
32 static guint num_lock_mask
, caps_lock_mask
, scroll_lock_mask
;
35 lookup_ignorable_modifiers (GdkKeymap
*keymap
)
37 egg_keymap_resolve_virtual_modifiers (keymap
,
38 EGG_VIRTUAL_LOCK_MASK
,
41 egg_keymap_resolve_virtual_modifiers (keymap
,
42 EGG_VIRTUAL_NUM_LOCK_MASK
,
45 egg_keymap_resolve_virtual_modifiers (keymap
,
46 EGG_VIRTUAL_SCROLL_LOCK_MASK
,
51 grab_ungrab_with_ignorable_modifiers (GdkWindow
*rootwin
,
55 guint mod_masks
[] = {
56 0, /* modifier only */
60 num_lock_mask
| caps_lock_mask
,
61 num_lock_mask
| scroll_lock_mask
,
62 caps_lock_mask
| scroll_lock_mask
,
63 num_lock_mask
| caps_lock_mask
| scroll_lock_mask
,
67 for (i
= 0; i
< G_N_ELEMENTS (mod_masks
); i
++) {
69 XGrabKey (GDK_WINDOW_XDISPLAY (rootwin
),
71 binding
->modifiers
| mod_masks
[i
],
72 GDK_WINDOW_XWINDOW (rootwin
),
77 XUngrabKey (GDK_WINDOW_XDISPLAY (rootwin
),
79 binding
->modifiers
| mod_masks
[i
],
80 GDK_WINDOW_XWINDOW (rootwin
));
86 do_grab_key (Binding
*binding
)
88 GdkKeymap
*keymap
= gdk_keymap_get_default ();
89 GdkWindow
*rootwin
= gdk_get_default_root_window ();
91 EggVirtualModifierType virtual_mods
= 0;
94 if (keymap
== NULL
|| rootwin
== NULL
)
97 if (!egg_accelerator_parse_virtual (binding
->keystring
,
102 TRACE (g_print ("Got accel %d, %d\n", keysym
, virtual_mods
));
104 binding
->keycode
= XKeysymToKeycode (GDK_WINDOW_XDISPLAY (rootwin
),
106 if (binding
->keycode
== 0)
109 TRACE (g_print ("Got keycode %d\n", binding
->keycode
));
111 egg_keymap_resolve_virtual_modifiers (keymap
,
113 &binding
->modifiers
);
115 TRACE (g_print ("Got modmask %d\n", binding
->modifiers
));
117 gdk_error_trap_push ();
119 grab_ungrab_with_ignorable_modifiers (rootwin
,
125 if (gdk_error_trap_pop ()) {
126 g_warning ("Binding '%s' failed!\n", binding
->keystring
);
134 do_ungrab_key (Binding
*binding
)
136 GdkWindow
*rootwin
= gdk_get_default_root_window ();
138 TRACE (g_print ("Removing grab for '%s'\n", binding
->keystring
));
140 grab_ungrab_with_ignorable_modifiers (rootwin
,
147 static GdkFilterReturn
148 filter_func (GdkXEvent
*gdk_xevent
, GdkEvent
*event
, gpointer data
)
150 GdkFilterReturn return_val
= GDK_FILTER_CONTINUE
;
151 XEvent
*xevent
= (XEvent
*) gdk_xevent
;
155 TRACE (g_print ("Got Event! %d, %d\n", xevent
->type
, event
->type
));
157 switch (xevent
->type
) {
159 TRACE (g_print ("Got KeyPress! keycode: %d, modifiers: %d\n",
160 xevent
->xkey
.keycode
,
161 xevent
->xkey
.state
));
164 * Set the last event time for use when showing
165 * windows to avoid anti-focus-stealing code.
167 processing_event
= TRUE
;
168 last_event_time
= xevent
->xkey
.time
;
170 event_mods
= xevent
->xkey
.state
& ~(num_lock_mask
|
174 for (iter
= bindings
; iter
!= NULL
; iter
= iter
->next
) {
175 Binding
*binding
= (Binding
*) iter
->data
;
177 if (binding
->keycode
== xevent
->xkey
.keycode
&&
178 binding
->modifiers
== event_mods
) {
180 TRACE (g_print ("Calling handler for '%s'...\n",
181 binding
->keystring
));
183 (binding
->handler
) (binding
->keystring
,
188 processing_event
= FALSE
;
191 TRACE (g_print ("Got KeyRelease! \n"));
199 keymap_changed (GdkKeymap
*map
)
201 GdkKeymap
*keymap
= gdk_keymap_get_default ();
204 TRACE (g_print ("Keymap changed! Regrabbing keys..."));
206 for (iter
= bindings
; iter
!= NULL
; iter
= iter
->next
) {
207 Binding
*binding
= (Binding
*) iter
->data
;
208 do_ungrab_key (binding
);
211 lookup_ignorable_modifiers (keymap
);
213 for (iter
= bindings
; iter
!= NULL
; iter
= iter
->next
) {
214 Binding
*binding
= (Binding
*) iter
->data
;
215 do_grab_key (binding
);
220 tomboy_keybinder_init (void)
222 GdkKeymap
*keymap
= gdk_keymap_get_default ();
223 GdkWindow
*rootwin
= gdk_get_default_root_window ();
225 lookup_ignorable_modifiers (keymap
);
227 gdk_window_add_filter (rootwin
,
231 g_signal_connect (keymap
,
233 G_CALLBACK (keymap_changed
),
238 tomboy_keybinder_bind (const char *keystring
,
239 TomboyBindkeyHandler handler
,
245 binding
= g_new0 (Binding
, 1);
246 binding
->keystring
= g_strdup (keystring
);
247 binding
->handler
= handler
;
248 binding
->user_data
= user_data
;
250 /* Sets the binding's keycode and modifiers */
251 success
= do_grab_key (binding
);
254 bindings
= g_slist_prepend (bindings
, binding
);
256 g_free (binding
->keystring
);
262 tomboy_keybinder_unbind (const char *keystring
,
263 TomboyBindkeyHandler handler
)
267 for (iter
= bindings
; iter
!= NULL
; iter
= iter
->next
) {
268 Binding
*binding
= (Binding
*) iter
->data
;
270 if (strcmp (keystring
, binding
->keystring
) != 0 ||
271 handler
!= binding
->handler
)
274 do_ungrab_key (binding
);
276 bindings
= g_slist_remove (bindings
, binding
);
278 g_free (binding
->keystring
);
285 * From eggcellrenderkeys.c.
288 tomboy_keybinder_is_modifier (guint keycode
)
292 XModifierKeymap
*mod_keymap
;
293 gboolean retval
= FALSE
;
295 mod_keymap
= XGetModifierMapping (gdk_display
);
297 map_size
= 8 * mod_keymap
->max_keypermod
;
300 while (i
< map_size
) {
301 if (keycode
== mod_keymap
->modifiermap
[i
]) {
308 XFreeModifiermap (mod_keymap
);
314 tomboy_keybinder_get_current_event_time (void)
316 if (processing_event
)
317 return last_event_time
;
319 return GDK_CURRENT_TIME
;