aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCalvin <calvin@bastille>2014-02-11 16:05:20 -0500
committerCalvin <calvin@bastille>2014-02-11 16:05:20 -0500
commit348b08cac5d404c53951f77808a6275c0bd13cb5 (patch)
treeff1f24271f7aa49d269c6b857a3ff5c887a15712
parentee4ad37a767bf96a516dd9d787fcf5fe67c43e89 (diff)
nonsegfaulting nonworking dynamic hotkeys
-rw-r--r--example_rc3
-rw-r--r--hotkey.c196
2 files changed, 182 insertions, 17 deletions
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 <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
+#include <errno.h>
-
-#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;
}