4 #include <gdk/gdkkeysyms.h>
5 #include <gdk/gdkwindow.h>
9 #include "eggaccelerators.h"
10 #include "tomboykeybinder.h"
12 static GSList
*bindings
= NULL
;
13 static guint ignored_modifiers
= 0;
16 /* Uncomment the next line to print a debug trace. */
22 # define TRACE(x) do {} while (FALSE);
25 typedef struct _Binding
{
26 TomboyBindkeyHandler handler
;
34 * Adapted from eggcellrenderkeys.c.
37 get_modifier_mask_for_keycode (guint keycode
)
41 XModifierKeymap
*mod_keymap
;
44 mod_keymap
= XGetModifierMapping (gdk_display
);
46 map_size
= 8 * mod_keymap
->max_keypermod
;
48 for (i
= 0; i
< map_size
; i
++) {
49 if (keycode
== mod_keymap
->modifiermap
[i
]) {
55 XFreeModifiermap (mod_keymap
);
61 tomboy_keybinder_is_modifier (guint keycode
)
63 return (get_modifier_mask_for_keycode (keycode
) != 0);
67 get_ignored_modifiers (void)
69 guint keyvals
[] = { GDK_Num_Lock
, GDK_Scroll_Lock
, 0 };
74 if (ignored_modifiers
!= 0)
75 return ignored_modifiers
;
77 ignored_modifiers
= GDK_LOCK_MASK
| 0x2000; /* Xkb modifier */
79 for (i
= 0; keyvals
[i
] != 0; i
++) {
80 if (gdk_keymap_get_entries_for_keyval (NULL
, keyvals
[i
], &keys
, &num_keys
)) {
83 for (j
= 0; j
< num_keys
; j
++)
84 ignored_modifiers
|= get_modifier_mask_for_keycode (keys
[j
].keycode
);
90 return (int) ignored_modifiers
;
94 do_grab_key (Binding
*binding
)
96 GdkKeymap
*keymap
= gdk_keymap_get_default ();
97 GdkWindow
*rootwin
= gdk_get_default_root_window ();
99 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 for (i
= 0; i
<= get_ignored_modifiers (); i
++) {
127 /* Check to ensure we're not including non-ignored modifiers */
128 if (i
& ~(get_ignored_modifiers ()))
131 XGrabKey (GDK_WINDOW_XDISPLAY (rootwin
),
133 binding
->modifiers
| i
,
134 GDK_WINDOW_XWINDOW (rootwin
),
144 do_ungrab_key (Binding
*binding
)
146 GdkWindow
*rootwin
= gdk_get_default_root_window ();
149 TRACE (g_print ("Removing grab for '%s'\n", binding
->keystring
));
151 for (i
= 0; i
<= get_ignored_modifiers (); i
++) {
152 /* Check to ensure we're not including non-ignored modifiers */
153 if (i
& ~(get_ignored_modifiers ()))
156 XUngrabKey (GDK_WINDOW_XDISPLAY (rootwin
),
158 binding
->modifiers
| i
,
159 GDK_WINDOW_XWINDOW (rootwin
));
165 static GdkFilterReturn
166 filter_func (GdkXEvent
*gdk_xevent
, GdkEvent
*event
, gpointer data
)
168 GdkFilterReturn return_val
= GDK_FILTER_CONTINUE
;
169 XEvent
*xevent
= (XEvent
*) gdk_xevent
;
172 TRACE (g_print ("Got Event! %d, %d\n", xevent
->type
, event
->type
));
174 switch (xevent
->type
) {
176 TRACE (g_print ("Got KeyPress! keycode: %d, modifiers: %d\n",
177 xevent
->xkey
.keycode
,
178 xevent
->xkey
.state
));
180 for (iter
= bindings
; iter
!= NULL
; iter
= iter
->next
) {
181 Binding
*binding
= (Binding
*) iter
->data
;
183 if (binding
->keycode
== xevent
->xkey
.keycode
&&
184 binding
->modifiers
== (xevent
->xkey
.state
& ~get_ignored_modifiers ())) {
186 TRACE (g_print ("Calling handler for '%s'...\n",
187 binding
->keystring
));
189 (binding
->handler
) (binding
->keystring
,
195 TRACE (g_print ("Got KeyRelease! \n"));
203 keymap_changed (GdkKeymap
*map
)
207 TRACE (g_print ("Keymap changed! Regrabbing keys..."));
209 ignored_modifiers
= 0;
211 for (iter
= bindings
; iter
!= NULL
; iter
= iter
->next
) {
212 Binding
*binding
= (Binding
*) iter
->data
;
214 do_ungrab_key (binding
);
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 gdk_window_add_filter (rootwin
,
229 g_signal_connect (keymap
,
231 G_CALLBACK (keymap_changed
),
236 tomboy_keybinder_bind (const char *keystring
,
237 TomboyBindkeyHandler handler
,
243 binding
= g_new0 (Binding
, 1);
244 binding
->keystring
= g_strdup (keystring
);
245 binding
->handler
= handler
;
246 binding
->user_data
= user_data
;
248 /* Sets the binding's keycode and modifiers */
249 success
= do_grab_key (binding
);
252 bindings
= g_slist_prepend (bindings
, binding
);
254 g_free (binding
->keystring
);
260 tomboy_keybinder_unbind (const char *keystring
,
261 TomboyBindkeyHandler handler
)
265 for (iter
= bindings
; iter
!= NULL
; iter
= iter
->next
) {
266 Binding
*binding
= (Binding
*) iter
->data
;
268 if (strcmp (keystring
, binding
->keystring
) != 0 ||
269 handler
!= binding
->handler
)
272 do_ungrab_key (binding
);
274 bindings
= g_slist_remove (bindings
, binding
);
276 g_free (binding
->keystring
);