From d15a5cefc89111577223bf0d2c4dcfc5a4817a6a Mon Sep 17 00:00:00 2001 From: Lexi Quinn Date: Sun, 16 Jan 2022 15:19:26 +1100 Subject: [PATCH] global hotkeys can now be configured with a file --- README.md | 2 +- src/keys.c | 51 +++++++++++++++++++++++++- src/keys.h | 6 ++++ src/splitsio.h | 14 ++++---- src/timer.c | 97 ++++++++++++++++++++++++++++++++++++++++++-------- src/timer.h | 5 +-- 6 files changed, 150 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index f292ecb..41c5652 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ segments after the first use of the split file is currently unsupported. | `T` | Toggle global hotkeys | YES | | `C` | Toggle compact UI | NO | -Customisable hotkeys without editing the source code coming soon! +Hotkeys can be configured in `$HOME/.config/quest/keymaps/default` ## Third Party Integration diff --git a/src/keys.c b/src/keys.c index 9c33231..147f603 100644 --- a/src/keys.c +++ b/src/keys.c @@ -5,7 +5,37 @@ char buf; int pipefd[2]; struct keymap km; -char *keystrings[2] = {"a", "b"}; +char *keystrings[KEYNUM] = { + "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k", "l", + "m", "n", "o", "p", "q", "r", + "s", "t", "u", "v", "w", "x", + "y", "z", "1", "2", "3", "4", + "5", "6", "7", "8", "9", "0", + "F1", "F2", "F3", "F4", "F5", "F6", + "F7", "F8", "F9", "F10", "F11", "F12", + "F13", "F14", "F15", "F16", "F17", "F18", + "F19", "F20", "F21", "F22", "F23", "F24", + "ESC", "`", "-", "=", "BSP", "TAB", + "CAP", "[", "]", "\\", ";", "\"", + "ENT", ",", ".", "/", " ", +}; + +uint16_t uiohookKeycodes[KEYNUM] = { + VC_A, VC_B, VC_C, VC_D, VC_E, VC_F, + VC_G, VC_H, VC_I, VC_J, VC_K, VC_L, + VC_M, VC_N, VC_O, VC_P, VC_Q, VC_R, + VC_S, VC_T, VC_U, VC_V, VC_W, VC_X, + VC_Y, VC_Z, VC_1, VC_2, VC_3, VC_4, + VC_5, VC_6, VC_7, VC_8, VC_9, VC_0, + VC_F1, VC_F2, VC_F3, VC_F4, VC_F5, VC_F6, + VC_F7, VC_F8, VC_F9, VC_F10, VC_F11, VC_F12, + VC_F13, VC_F14, VC_F15, VC_F16, VC_F17, VC_F18, + VC_F19, VC_F20, VC_F21, VC_F22, VC_F23, VC_F24, + VC_ESCAPE, VC_BACKQUOTE, VC_MINUS, VC_EQUALS, VC_BACKSPACE, VC_TAB, + VC_CAPS_LOCK, VC_OPEN_BRACKET, VC_CLOSE_BRACKET, VC_BACK_SLASH, VC_SEMICOLON, VC_QUOTE, + VC_ENTER, VC_COMMA, VC_PERIOD, VC_SLASH, VC_SPACE +}; bool logger_proc(unsigned int level, const char *format, ...) { return 0; @@ -70,3 +100,22 @@ int handleInput() skip(); return 0; } + +void loadKeymap() +{ + km.START = VC_R; + km.STOP = VC_F; + km.PAUSE = VC_D; + km.SPLIT = VC_E; + km.HOTKS = VC_T; + km.USPLT = VC_G; + km.SKIP = VC_V; +} + +uint16_t keystringToKeycode(char *keystring) { + for (int i = 0; i < KEYNUM; i++) + if (strcmp(keystring, keystrings[i]) == 0) + return uiohookKeycodes[i]; + return NULL; +} + diff --git a/src/keys.h b/src/keys.h index 4bb64c2..d03376d 100644 --- a/src/keys.h +++ b/src/keys.h @@ -14,6 +14,8 @@ #define K_USPLT 6 #define K_SKIP 7 +#define KEYNUM 77 + extern bool hotkeys_enabled; struct keymap @@ -31,9 +33,13 @@ extern char buf; extern int pipefd[2]; extern struct keymap km; +extern char *keystrings[77]; + bool logger_proc(unsigned int level, const char *format, ...); void dispatch_proc(uiohook_event * const event); int handleInput(); +void loadKeymap(); +uint16_t keystringToKeycode(char *keystring); #endif diff --git a/src/splitsio.h b/src/splitsio.h index e406030..c952907 100644 --- a/src/splitsio.h +++ b/src/splitsio.h @@ -1,14 +1,14 @@ -#ifndef SPLITSIO -#define SPLITSIO +#ifndef SPLITSIO_H +#define SPLITSIO_H #include "cJSON.h" #include "timer.h" -const char *schemaver; -const char *timersname; -const char *timerlname; -const char *timerver; -const char *timerlink; +//const char *schemaver; +//const char *timersname; +//const char *timerlname; +//const char *timerver; +//const char *timerlink; void importSplitsIO(cJSON *splitfile); void exportSplitsIO(); diff --git a/src/timer.c b/src/timer.c index 1fb7e71..9350d6f 100644 --- a/src/timer.c +++ b/src/timer.c @@ -21,6 +21,7 @@ bool dirty = false; //Run data char *filepath; +char *configpath; char *gameTitle = "title not loaded"; char *categoryTitle = "category not loaded"; int attempts = 0; @@ -120,17 +121,6 @@ void skip() stop(); } -void loadKeymap() -{ - km.START = VC_R; - km.STOP = VC_F; - km.PAUSE = VC_D; - km.SPLIT = VC_E; - km.HOTKS = VC_T; - km.USPLT = VC_G; - km.SKIP = VC_V; -} - void ftime(char *timestr, int rms, int decimals, bool sign) { if (decimals > 3 || decimals < 0) @@ -452,15 +442,94 @@ void calculateBestSegs() void loadConfig() { + cJSON *config = NULL; char path[256]; strcat(strcpy(path, getenv("HOME")), "/.config/quest"); mkdir(path, 0777); strcat(strcpy(path, getenv("HOME")), "/.config/quest/keymaps"); mkdir(path, 0777); strcat(strcpy(path, getenv("HOME")), "/.config/quest/keymaps/default"); + configpath = malloc(strlen(path)); + strcpy(configpath, path); - FILE* fp = fopen(path, "r"); - fclose(fp); + long length; + FILE* f = fopen(path, "rb"); + if (f != NULL) { + char *buffer = NULL; + fseek(f, 0, SEEK_END); + length = ftell(f); + fseek(f, 0, SEEK_SET); + buffer = malloc(length + 1); + if (buffer != NULL) + fread(buffer, 1, length, f); + fclose(f); + buffer[length] = '\0'; + + config = cJSON_Parse(buffer); + free(buffer); + + cJSON *startkey = cJSON_GetItem(config, "start"); + cJSON *stopkey = cJSON_GetItem(config, "stop"); + cJSON *pausekey = cJSON_GetItem(config, "pause"); + cJSON *splitkey = cJSON_GetItem(config, "split"); + cJSON *hotkskey = cJSON_GetItem(config, "toggle hotkeys"); + cJSON *uspltkey = cJSON_GetItem(config, "unsplit"); + cJSON *skipkey = cJSON_GetItem(config, "skip"); + + if (cJSON_IsString(startkey) && (startkey->valuestring != NULL)) + km.START = keystringToKeycode(startkey->valuestring); + if (cJSON_IsString(stopkey) && (stopkey->valuestring != NULL)) + km.STOP = keystringToKeycode(stopkey->valuestring); + if (cJSON_IsString(pausekey) && (pausekey->valuestring != NULL)) + km.PAUSE = keystringToKeycode(pausekey->valuestring); + if (cJSON_IsString(splitkey) && (splitkey->valuestring != NULL)) + km.SPLIT = keystringToKeycode(splitkey->valuestring); + if (cJSON_IsString(hotkskey) && (hotkskey->valuestring != NULL)) + km.HOTKS = keystringToKeycode(hotkskey->valuestring); + if (cJSON_IsString(uspltkey) && (uspltkey->valuestring != NULL)) + km.USPLT = keystringToKeycode(uspltkey->valuestring); + if (cJSON_IsString(skipkey) && (skipkey->valuestring != NULL)) + km.SKIP = keystringToKeycode(skipkey->valuestring); + } else { + config = cJSON_CreateObject(); + km.START = VC_R; + km.STOP = VC_F; + km.PAUSE = VC_D; + km.SPLIT = VC_E; + km.HOTKS = VC_T; + km.USPLT = VC_G; + km.SKIP = VC_V; + cJSON *startkey = cJSON_CreateString("r"); + cJSON_AddItemToObject(config, "start", startkey); + cJSON *stopkey = cJSON_CreateString("f"); + cJSON_AddItemToObject(config, "stop", stopkey); + cJSON *pausekey = cJSON_CreateString("d"); + cJSON_AddItemToObject(config, "pause", pausekey); + cJSON *splitkey = cJSON_CreateString("e"); + cJSON_AddItemToObject(config, "split", splitkey); + cJSON *hotkskey = cJSON_CreateString("t"); + cJSON_AddItemToObject(config, "toggle hotkeys", hotkskey); + cJSON *uspltkey = cJSON_CreateString("g"); + cJSON_AddItemToObject(config, "unsplit", uspltkey); + cJSON *skipkey = cJSON_CreateString("v"); + cJSON_AddItemToObject(config, "skip", skipkey); + saveConfig(config); + } + cJSON_Delete(config); +} + +void saveConfig(cJSON *config) +{ + char *string = cJSON_Print(config); + if (string != NULL) { + FILE *f = fopen(configpath, "w"); + if (f == NULL) + return; + + fwrite(string, 1, strlen(string), f); + + fclose(f); + } } //TODO: it'll be more efficent if all the segments pointers point at the same @@ -655,7 +724,7 @@ int main(int argc, char **argv) pipe(pipefd); fcntl(pipefd[0], F_SETFL, O_NONBLOCK); - loadKeymap(); + loadConfig(); cpid = fork(); if (cpid == 0) { diff --git a/src/timer.h b/src/timer.h index b275836..59ac506 100644 --- a/src/timer.h +++ b/src/timer.h @@ -3,6 +3,7 @@ #include "display.h" #include "keys.h" +#include "splitsio.h" #include #include #include @@ -52,7 +53,6 @@ void split(); void tpause(); void unsplit(); void skip(); -void loadKeymap(); void ftime(char *timestr, int rms, int decimals, bool sign); int timespecToMS(struct timespec t); void drawNotif(); @@ -62,8 +62,9 @@ void drawTimeColumn(); void toggleCompact(); void drawDisplay(); void resize(int i); -void importSplitsIO(cJSON *splitfile); void calculatePB(); +void loadConfig(); +void saveConfig(cJSON *config); void loadFile(); void saveFile(); int main(int argc, char **argv);