dockapps/wmcliphist/hotkeys.c
2014-11-23 10:26:22 +00:00

199 lines
5.8 KiB
C

#include "wmcliphist.h"
#include <gdk/gdkkeysyms.h>
/* 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();
}