#include "wmcliphist.h" #include /* Exec on hotkey? */ int exec_hotkey = 1; /* hotkeys */ gchar menukey_str[32] = DEF_MENUKEY; guint menukey; guint menukey_mask; gchar prev_item_key_str[32] = DEF_PREV_ITEM_KEY; guint prev_item_key; guint prev_item_mask; gchar exec_item_key_str[32] = DEF_EXEC_ITEM_KEY; guint exec_item_key; guint exec_item_mask; /* * filter grabbed hotkeys */ GdkFilterReturn global_keys_filter(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) { XEvent *xevent = (XEvent *)gdk_xevent; begin_func("global_keys_filter"); if (xevent->type == KeyPress) { if (xevent->xkey.keycode == XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), menukey) && xevent->xkey.state & menukey_mask) { /* popup history menu */ gtk_menu_popup(GTK_MENU(menu_hist), NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME); return_val(GDK_FILTER_REMOVE); } else if (xevent->xkey.keycode == XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), prev_item_key) && xevent->xkey.state & prev_item_mask) { /* switch first two history items */ GList *second; if (history_items == NULL) { return_val(GDK_FILTER_REMOVE); } second = g_list_first(history_items)->next; if (second == NULL) { return_val(GDK_FILTER_REMOVE); } move_item_to_begin((HISTORY_ITEM *) second->data); return_val(GDK_FILTER_REMOVE); } else if (xevent->xkey.keycode == XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), exec_item_key) && xevent->xkey.state & exec_item_mask) { /* exec command on current item */ if (exec_hotkey) { HISTORY_ITEM *hist_item; hist_item = (HISTORY_ITEM *) g_list_first(history_items)->data; exec_item(hist_item->content, NULL); } return_val(GDK_FILTER_REMOVE); } } return_val(GDK_FILTER_CONTINUE); } /* * parse key string */ int hotkey_parse(char *hotkey, guint *key, guint *mask) { char c; char *tmp = g_new0(char, strlen(hotkey)); int i, idx = 0; begin_func("hotkey_parse"); *mask = 0; for (i = 0; i < strlen(hotkey); i++) { c = hotkey[i]; if (isalpha(c)) { tmp[idx++] = c; tmp[idx] = '\0'; } else if (c == '+' || c == '-') { idx = 0; if (strcasecmp(tmp, "control") == 0 || strcasecmp(tmp, "ctrl") == 0) *mask |= ControlMask; else if (strcasecmp(tmp, "alt") == 0) *mask |= Mod1Mask; else if (strcasecmp(tmp, "shift") == 0) *mask |= ShiftMask; else { fprintf(stderr, "Invalid key modifier: %s\n", tmp); g_free(tmp); return_val(-1); } } } if ((*key = gdk_keyval_from_name(tmp)) == GDK_KEY_VoidSymbol) { g_free(tmp); return_val(-1); } g_free(tmp); return_val(0); } #define grab_key(keysym, basemask) \ XGrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \ basemask, GDK_ROOT_WINDOW(), True, GrabModeAsync, \ GrabModeAsync); \ XGrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \ basemask | LockMask, GDK_ROOT_WINDOW(), True, \ GrabModeAsync, GrabModeAsync); \ XGrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \ basemask | Mod2Mask, GDK_ROOT_WINDOW(), True, \ GrabModeAsync, GrabModeAsync); \ XGrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \ basemask | Mod2Mask | LockMask, GDK_ROOT_WINDOW(), \ True, GrabModeAsync, GrabModeAsync); #define ungrab_key(keysym, basemask) \ XUngrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \ basemask, GDK_ROOT_WINDOW()); \ XUngrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \ basemask | LockMask, GDK_ROOT_WINDOW()); \ XUngrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \ basemask | Mod2Mask, GDK_ROOT_WINDOW()); \ XUngrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \ basemask | Mod2Mask | LockMask, GDK_ROOT_WINDOW()); /* * initialize hotkeys */ void hotkeys_init() { char msg_str[128]; begin_func("hotkeys_init"); if (hotkey_parse(menukey_str, &menukey, &menukey_mask) != 0) { sprintf(msg_str, "Invalid menu hotkey '%s'.\nFalling back to " "default (" DEF_MENUKEY ")\n", menukey_str); show_message(msg_str, "Warning", "OK", NULL, NULL); strcpy(menukey_str, DEF_MENUKEY); hotkey_parse(menukey_str, &menukey, &menukey_mask); } if (hotkey_parse(prev_item_key_str, &prev_item_key, &prev_item_mask) != 0) { sprintf(msg_str, "Invalid previous item hotkey '%s'.\n" "Falling back to default (" DEF_PREV_ITEM_KEY ")\n", prev_item_key_str); show_message(msg_str, "Warning", "OK", NULL, NULL); hotkey_parse(DEF_PREV_ITEM_KEY, &prev_item_key, &prev_item_mask); } if (hotkey_parse(exec_item_key_str, &exec_item_key, &exec_item_mask) != 0) { sprintf(msg_str, "Invalid exec hotkey '%s'.\n" "Falling back to default (" DEF_EXEC_ITEM_KEY ")\n", exec_item_key_str); show_message(msg_str, "Warning", "OK", NULL, NULL); hotkey_parse(DEF_EXEC_ITEM_KEY, &exec_item_key, &exec_item_mask); } gdk_window_add_filter(gdk_get_default_root_window(), global_keys_filter, NULL); grab_key(menukey, menukey_mask); grab_key(prev_item_key, prev_item_mask); grab_key(exec_item_key, exec_item_mask); return_void(); } /* * disable hotkeys */ void hotkeys_done() { begin_func("hotkeys_done"); ungrab_key(menukey, menukey_mask); return_void(); }