From 348b08cac5d404c53951f77808a6275c0bd13cb5 Mon Sep 17 00:00:00 2001 From: Calvin Date: Tue, 11 Feb 2014 16:05:20 -0500 Subject: nonsegfaulting nonworking dynamic hotkeys --- example_rc | 3 + hotkey.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 182 insertions(+), 17 deletions(-) create mode 100644 example_rc diff --git a/example_rc b/example_rc new file mode 100644 index 0000000..804cf8c --- /dev/null +++ b/example_rc @@ -0,0 +1,3 @@ +control+P dmenu_run & +control+mod1+G xterm & +mod1+G xterm & diff --git a/hotkey.c b/hotkey.c index 27051e8..c87c293 100644 --- a/hotkey.c +++ b/hotkey.c @@ -3,46 +3,208 @@ #include #include #include +#include #include +#include - -#define len(X) (sizeof X / sizeof X[0]) - -typedef struct { +typedef struct Key { char *command; unsigned int mod; - KeySym key; + KeySym keysym; } Key; -#include "keys.h" -int main() { - Display* dpy = XOpenDisplay(0); - Window root = DefaultRootWindow(dpy); - unsigned int i = 0; +// A horrible hack. +struct Key * parse_key(char *shortcut, char *command) { + + Key *key = malloc(sizeof(key)); + key->command = command; + key->mod = 0; + + + printf("%s\n", key->command); + size_t i = 0; + + char *token; + char **tokens = malloc(sizeof(char *) * 16); + size_t token_nb = 0; + + int key_set = 0; + int mod_set = 0; + + // load our tokens + while ((token = strsep(&shortcut, "+")) != NULL) { + tokens[token_nb] = token; + token_nb++; + } + + if(token_nb != 0) { + // Modifiers + + for(i = 0; i < token_nb; i++) { + // if it's a regular key + if(strlen(tokens[i]) == 1) { + if(key_set) { + return NULL; + } + key->keysym = XStringToKeysym(tokens[token_nb - 1]); + key_set = 1; + } + // if it's a mod key + else { + int mask = 0; + if(strcmp(tokens[i], "control") == 0) + mask = ControlMask; + else if(strcmp(tokens[i], "shift") == 0) + mask = ShiftMask; + else if(strcmp(tokens[i], "mod1") == 0) + mask = Mod1Mask; + else if(strcmp(tokens[i], "mod2") == 0) + mask = Mod2Mask; + else if(strcmp(tokens[i], "mod3") == 0) + mask = Mod3Mask; + else if(strcmp(tokens[i], "mod4") == 0) + mask = Mod4Mask; + if(mask) { + key->mod = key->mod | mask ; + mod_set = 1; + } + else { + return NULL; + } + } + } + } + + if(key_set && mod_set) { + return(key); + } + else { + free(key); + return NULL; + } +} + +struct Key **load_hotkeys(FILE *fh, size_t *key_len) { + char line[4096]; + int line_nb = 1; + + size_t realloc_size = 1; + *key_len = 0; + + struct Key **keys = malloc(sizeof(struct Key **)); + if(keys == NULL) { + printf("could not allocate keys\n"); + return NULL; + } + + while((fgets(line, 4096, fh)) != NULL) { + int res; + int error = 0; + char *shortcut, *command; + Key *key; + + res = sscanf(line, "%ms %m[^\n]+", &shortcut, &command); + if(res == 2) { + key = parse_key(shortcut, command); + } + else { + error = 1; + } - for(i = 0; i < len(hotkeys); i++) { - XGrabKey(dpy, XKeysymToKeycode(dpy,hotkeys[i].key), hotkeys[i].mod, root, False, GrabModeAsync, GrabModeAsync); + if(error) + fprintf(stderr, "Error:could not parse line %d: %s\n", line_nb, line); + else { + keys[*key_len] = key; + *key_len = *key_len + 1; + + realloc(keys, sizeof(struct Key *) * realloc_size); + realloc_size++; + + if(keys == NULL) { + printf("could not realloc keys\n"); + exit(EXIT_FAILURE); + } + } + + line_nb++; } + if(*key_len != 0) + return keys; + return NULL; +} + +void wait_for_input(Display* dpy, Window root, struct Key **hotkeys, size_t len) { + size_t i = 0; + XSelectInput(dpy, root, KeyPressMask ); while(1) { + XEvent ev; XNextEvent(dpy, &ev); if(ev.type == KeyPress) { - //ripped out of dwm XKeyEvent *kev = &ev.xkey; KeySym keysym = XKeycodeToKeysym(dpy, (KeyCode)kev->keycode, 0); - for(i = 0; i < len(hotkeys); i++) { - if(keysym == hotkeys[i].key && hotkeys[i].mod == kev->state) { - printf("executing '%s'\n", hotkeys[i].command); - system(hotkeys[i].command); + + for(i = 0; i < len; i++) { + if(keysym == hotkeys[i]->keysym && hotkeys[i]->mod == kev->state) { + printf("executing '%s'\n", hotkeys[i]->command); + system(hotkeys[i]->command); } } } } +} + +int main(int argc, char **argv) { + Display* dpy = XOpenDisplay(0); + Window root = DefaultRootWindow(dpy); + + + unsigned int i = 0; + + FILE *config_fh = NULL; + char *config_fn; + + size_t len = 0; + + struct Key **hotkeys = NULL; + + if(argc == 1) { + asprintf(&config_fn, "%s%s", getenv("HOME"), "/.hotkeyrc"); + config_fh = fopen(config_fn, "r"); + } + else if (argc == 2) { + config_fh = fopen(argv[1], "r"); + config_fn = argv[1]; + } + else { + fprintf(stderr, "usage: hotkeys config_file (default is ~/.hotkeyrc)\n"); + exit(EXIT_FAILURE); + } + + if(config_fh == NULL) { + fprintf(stderr, "could not open %s\n", config_fn); + exit(EXIT_FAILURE); + } + + hotkeys = load_hotkeys(config_fh, &len); + + if(hotkeys == NULL) { + fprintf(stderr, "Could not load any keys from %s. quitting...\n", config_fn); + exit(EXIT_FAILURE); + } + + for(i = 0; i < len; i++) { + printf("%d\n", hotkeys[i]->mod); + XGrabKey(dpy, XKeysymToKeycode(dpy,hotkeys[i]->keysym), hotkeys[i]->mod, root, False, GrabModeAsync, GrabModeAsync); + } + + wait_for_input(dpy, root, hotkeys, len); + XCloseDisplay(dpy); return 0; } -- cgit v1.2.1