2014-11-23 02:48:41 +00:00
|
|
|
#include "wmcliphist.h"
|
2014-11-23 02:48:37 +00:00
|
|
|
#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 ==
|
2014-11-23 02:48:44 +00:00
|
|
|
XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), menukey) &&
|
2014-11-23 02:48:37 +00:00
|
|
|
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 ==
|
2014-11-23 02:48:44 +00:00
|
|
|
XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), prev_item_key)
|
2014-11-23 02:48:37 +00:00
|
|
|
&& 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);
|
|
|
|
}
|
2014-11-23 02:48:42 +00:00
|
|
|
|
2014-11-23 02:48:37 +00:00
|
|
|
move_item_to_begin((HISTORY_ITEM *) second->data);
|
|
|
|
|
|
|
|
return_val(GDK_FILTER_REMOVE);
|
|
|
|
} else if (xevent->xkey.keycode ==
|
2014-11-23 02:48:44 +00:00
|
|
|
XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), exec_item_key) &&
|
2014-11-23 02:48:37 +00:00
|
|
|
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;
|
2014-11-23 02:48:42 +00:00
|
|
|
|
2014-11-23 02:48:37 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-23 02:48:44 +00:00
|
|
|
if ((*key = gdk_keyval_from_name(tmp)) == GDK_KEY_VoidSymbol) {
|
2014-11-23 02:48:37 +00:00
|
|
|
g_free(tmp);
|
|
|
|
return_val(-1);
|
|
|
|
}
|
2014-11-23 02:48:42 +00:00
|
|
|
|
2014-11-23 02:48:37 +00:00
|
|
|
g_free(tmp);
|
|
|
|
return_val(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define grab_key(keysym, basemask) \
|
2014-11-23 02:48:44 +00:00
|
|
|
XGrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \
|
2014-11-23 02:48:37 +00:00
|
|
|
basemask, GDK_ROOT_WINDOW(), True, GrabModeAsync, \
|
|
|
|
GrabModeAsync); \
|
2014-11-23 02:48:44 +00:00
|
|
|
XGrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \
|
2014-11-23 02:48:37 +00:00
|
|
|
basemask | LockMask, GDK_ROOT_WINDOW(), True, \
|
|
|
|
GrabModeAsync, GrabModeAsync); \
|
2014-11-23 02:48:44 +00:00
|
|
|
XGrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \
|
2014-11-23 02:48:37 +00:00
|
|
|
basemask | Mod2Mask, GDK_ROOT_WINDOW(), True, \
|
|
|
|
GrabModeAsync, GrabModeAsync); \
|
2014-11-23 02:48:44 +00:00
|
|
|
XGrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \
|
2014-11-23 02:48:37 +00:00
|
|
|
basemask | Mod2Mask | LockMask, GDK_ROOT_WINDOW(), \
|
|
|
|
True, GrabModeAsync, GrabModeAsync);
|
|
|
|
|
|
|
|
|
|
|
|
#define ungrab_key(keysym, basemask) \
|
2014-11-23 02:48:44 +00:00
|
|
|
XUngrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \
|
2014-11-23 02:48:37 +00:00
|
|
|
basemask, GDK_ROOT_WINDOW()); \
|
2014-11-23 02:48:44 +00:00
|
|
|
XUngrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \
|
2014-11-23 02:48:37 +00:00
|
|
|
basemask | LockMask, GDK_ROOT_WINDOW()); \
|
2014-11-23 02:48:44 +00:00
|
|
|
XUngrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \
|
2014-11-23 02:48:37 +00:00
|
|
|
basemask | Mod2Mask, GDK_ROOT_WINDOW()); \
|
2014-11-23 02:48:44 +00:00
|
|
|
XUngrabKey(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym), \
|
2014-11-23 02:48:37 +00:00
|
|
|
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);
|
|
|
|
}
|
2014-11-23 02:48:44 +00:00
|
|
|
gdk_window_add_filter(gdk_get_default_root_window(), global_keys_filter, NULL);
|
2014-11-23 02:48:37 +00:00
|
|
|
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();
|
|
|
|
}
|