Compute lucene-style scores for our hits.
[beagle.git] / glue / tomboykeybinder.c
blob779904e1c727a9a7b0c214f15125f8f4746938ff
2 #include <string.h>
3 #include <gdk/gdk.h>
4 #include <gdk/gdkkeysyms.h>
5 #include <gdk/gdkwindow.h>
6 #include <gdk/gdkx.h>
7 #include <X11/Xlib.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. */
17 /* #define DEBUG */
19 #ifdef DEBUG
20 # define TRACE(x) x
21 #else
22 # define TRACE(x) do {} while (FALSE);
23 #endif
25 typedef struct _Binding {
26 TomboyBindkeyHandler handler;
27 gpointer user_data;
28 char *keystring;
29 uint keycode;
30 uint modifiers;
31 } Binding;
34 * Adapted from eggcellrenderkeys.c.
36 static guint
37 get_modifier_mask_for_keycode (guint keycode)
39 gint i;
40 gint map_size;
41 XModifierKeymap *mod_keymap;
42 guint retval = 0;
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]) {
50 retval = i;
51 break;
55 XFreeModifiermap (mod_keymap);
57 return retval;
60 gboolean
61 tomboy_keybinder_is_modifier (guint keycode)
63 return (get_modifier_mask_for_keycode (keycode) != 0);
66 static int
67 get_ignored_modifiers (void)
69 guint keyvals[] = { GDK_Num_Lock, GDK_Scroll_Lock, 0 };
70 int i;
71 GdkKeymapKey *keys;
72 int num_keys;
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)) {
81 int j;
83 for (j = 0; j < num_keys; j++)
84 ignored_modifiers |= get_modifier_mask_for_keycode (keys[j].keycode);
86 g_free (keys);
90 return (int) ignored_modifiers;
93 static gboolean
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;
100 guint keysym = 0;
101 int i;
103 if (keymap == NULL || rootwin == NULL)
104 return FALSE;
106 if (!egg_accelerator_parse_virtual (binding->keystring,
107 &keysym,
108 &virtual_mods))
109 return FALSE;
111 TRACE (g_print ("Got accel %d, %d\n", keysym, virtual_mods));
113 binding->keycode = XKeysymToKeycode (GDK_WINDOW_XDISPLAY (rootwin),
114 keysym);
115 if (binding->keycode == 0)
116 return FALSE;
118 TRACE (g_print ("Got keycode %d\n", binding->keycode));
120 egg_keymap_resolve_virtual_modifiers (keymap,
121 virtual_mods,
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 ()))
129 continue;
131 XGrabKey (GDK_WINDOW_XDISPLAY (rootwin),
132 binding->keycode,
133 binding->modifiers | i,
134 GDK_WINDOW_XWINDOW (rootwin),
135 True,
136 GrabModeAsync,
137 GrabModeAsync);
140 return TRUE;
143 static gboolean
144 do_ungrab_key (Binding *binding)
146 GdkWindow *rootwin = gdk_get_default_root_window ();
147 int i;
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 ()))
154 continue;
156 XUngrabKey (GDK_WINDOW_XDISPLAY (rootwin),
157 binding->keycode,
158 binding->modifiers | i,
159 GDK_WINDOW_XWINDOW (rootwin));
162 return TRUE;
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;
170 GSList *iter;
172 TRACE (g_print ("Got Event! %d, %d\n", xevent->type, event->type));
174 switch (xevent->type) {
175 case KeyPress:
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,
190 binding->user_data);
193 break;
194 case KeyRelease:
195 TRACE (g_print ("Got KeyRelease! \n"));
196 break;
199 return return_val;
202 void
203 keymap_changed (GdkKeymap *map)
205 GSList *iter;
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);
219 void
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,
226 filter_func,
227 NULL);
229 g_signal_connect (keymap,
230 "keys_changed",
231 G_CALLBACK (keymap_changed),
232 NULL);
235 void
236 tomboy_keybinder_bind (const char *keystring,
237 TomboyBindkeyHandler handler,
238 gpointer user_data)
240 Binding *binding;
241 gboolean success;
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);
251 if (success) {
252 bindings = g_slist_prepend (bindings, binding);
253 } else {
254 g_free (binding->keystring);
255 g_free (binding);
259 void
260 tomboy_keybinder_unbind (const char *keystring,
261 TomboyBindkeyHandler handler)
263 GSList *iter;
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)
270 continue;
272 do_ungrab_key (binding);
274 bindings = g_slist_remove (bindings, binding);
276 g_free (binding->keystring);
277 g_free (binding);
278 break;