From 56b94a6eed9fe4642382f533666dc19901fad3fc Mon Sep 17 00:00:00 2001 From: koekeishiya Date: Sun, 3 Mar 2019 18:39:34 +0100 Subject: #53 allow opt-out for applications --- src/hotkey.c | 14 ++++++++++++-- src/hotkey.h | 5 +++-- src/parse.c | 41 ++++++++++++++++++++++++++++++++++++++++- src/parse.h | 3 ++- src/skhd.c | 10 ++++++++-- src/tokenize.c | 17 +++++++++++++++++ src/tokenize.h | 1 + 7 files changed, 83 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/hotkey.c b/src/hotkey.c index 9b6b85a..780aa3a 100644 --- a/src/hotkey.c +++ b/src/hotkey.c @@ -74,7 +74,7 @@ unsigned long hash_hotkey(struct hotkey *a) return a->key; } -bool same_mode(char *a, char *b) +bool compare_string(char *a, char *b) { while (*a && *b && *a == *b) { ++a; @@ -83,7 +83,7 @@ bool same_mode(char *a, char *b) return *a == '\0' && *b == '\0'; } -unsigned long hash_mode(char *key) +unsigned long hash_string(char *key) { unsigned long hash = 0, high; while(*key) { @@ -228,6 +228,16 @@ next:; } } +void free_blacklist(struct table *blacklst) +{ + int count; + void **items = table_reset(blacklst, &count); + for (int index = 0; index < count; ++index) { + char *item = (char *) items[index]; + free(item); + } +} + internal void cgevent_lrmod_flag_to_hotkey_lrmod_flag(CGEventFlags eventflags, uint32_t *flags, int mod) { diff --git a/src/hotkey.h b/src/hotkey.h index 372715d..4611b09 100644 --- a/src/hotkey.h +++ b/src/hotkey.h @@ -100,8 +100,8 @@ clear_flags(struct hotkey *hotkey, uint32_t flag) #undef internal -bool same_mode(char *a, char *b); -unsigned long hash_mode(char *key); +bool compare_string(char *a, char *b); +unsigned long hash_string(char *key); bool same_hotkey(struct hotkey *a, struct hotkey *b); unsigned long hash_hotkey(struct hotkey *a); @@ -111,6 +111,7 @@ bool intercept_systemkey(CGEventRef event, struct hotkey *eventkey); bool find_and_exec_hotkey(struct hotkey *k, struct table *t, struct mode **m, struct carbon_event *carbon); void free_mode_map(struct table *mode_map); +void free_blacklist(struct table *blacklst); void init_shell(void); diff --git a/src/parse.c b/src/parse.c index 760485d..4e673f4 100644 --- a/src/parse.c +++ b/src/parse.c @@ -384,6 +384,41 @@ void parse_declaration(struct parser *parser) } } +void parse_option_blacklist(struct parser *parser) +{ + if (parser_match(parser, Token_String)) { + struct token name_token = parser_previous(parser); + char *name = copy_string_count(name_token.text, name_token.length); + for (char *s = name; *s; ++s) *s = tolower(*s); + debug("\t%s\n", name); + table_add(parser->blacklst, name, name); + parse_option_blacklist(parser); + } else if (parser_match(parser, Token_EndList)) { + if (parser->blacklst->count == 0) { + parser_report_error(parser, parser_previous(parser), "list must contain at least one value\n"); + } + } else { + parser_report_error(parser, parser_peek(parser), "expected process name or ']'\n"); + } +} + +void parse_option(struct parser *parser) +{ + parser_match(parser, Token_Option); + struct token option = parser_previous(parser); + if (token_equals(option, "blacklist")) { + if (parser_match(parser, Token_BeginList)) { + debug("blacklist :: #%d {\n", option.line); + parse_option_blacklist(parser); + debug("}\n"); + } else { + parser_report_error(parser, option, "expected '[' followed by list of process names\n"); + } + } else { + parser_report_error(parser, option, "invalid option specified\n"); + } +} + void parse_config(struct parser *parser) { struct mode *mode; @@ -392,6 +427,7 @@ void parse_config(struct parser *parser) while (!parser_eof(parser)) { if (parser->error) { free_mode_map(parser->mode_map); + free_blacklist(parser->blacklst); return; } @@ -408,6 +444,8 @@ void parse_config(struct parser *parser) } } else if (parser_check(parser, Token_Decl)) { parse_declaration(parser); + } else if (parser_check(parser, Token_Option)) { + parse_option(parser); } else { parser_report_error(parser, parser_peek(parser), "expected decl, modifier or key-literal\n"); } @@ -512,12 +550,13 @@ void parser_report_error(struct parser *parser, struct token token, const char * parser->error = true; } -bool parser_init(struct parser *parser, struct table *mode_map, char *file) +bool parser_init(struct parser *parser, struct table *mode_map, struct table *blacklst, char *file) { memset(parser, 0, sizeof(struct parser)); char *buffer = read_file(file); if (buffer) { parser->mode_map = mode_map; + parser->blacklst = blacklst; tokenizer_init(&parser->tokenizer, buffer); parser_advance(parser); return true; diff --git a/src/parse.h b/src/parse.h index 35bc62e..95813c2 100644 --- a/src/parse.h +++ b/src/parse.h @@ -11,6 +11,7 @@ struct parser struct token current_token; struct tokenizer tokenizer; struct table *mode_map; + struct table *blacklst; bool error; }; @@ -23,7 +24,7 @@ bool parser_eof(struct parser *parser); struct token parser_advance(struct parser *parser); bool parser_check(struct parser *parser, enum token_type type); bool parser_match(struct parser *parser, enum token_type type); -bool parser_init(struct parser *parser, struct table *mode_map, char *file); +bool parser_init(struct parser *parser, struct table *mode_map, struct table *blacklst, char *file); bool parser_init_text(struct parser *parser, char *text); void parser_destroy(struct parser *parser); void parser_report_error(struct parser *parser, struct token token, const char *format, ...); diff --git a/src/skhd.c b/src/skhd.c index 05e955f..ceea857 100644 --- a/src/skhd.c +++ b/src/skhd.c @@ -48,13 +48,14 @@ global struct event_tap event_tap; global struct hotloader hotloader; global struct mode *current_mode; global struct table mode_map; +global struct table blacklst; global char *config_file; internal void parse_config_helper(char *absolutepath) { struct parser parser; - if (parser_init(&parser, &mode_map, absolutepath)) { + if (parser_init(&parser, &mode_map, &blacklst, absolutepath)) { parse_config(&parser); parser_destroy(&parser); } else { @@ -68,6 +69,7 @@ internal HOTLOADER_CALLBACK(config_handler) BEGIN_TIMED_BLOCK("hotload_config"); debug("skhd: config-file has been modified.. reloading config\n"); free_mode_map(&mode_map); + free_blacklist(&blacklst); parse_config_helper(absolutepath); END_TIMED_BLOCK(); } @@ -78,6 +80,7 @@ internal CF_NOTIFICATION_CALLBACK(keymap_handler) if (initialize_keycode_map()) { debug("skhd: input source changed.. reloading config\n"); free_mode_map(&mode_map); + free_blacklist(&blacklst); parse_config_helper(config_file); } END_TIMED_BLOCK(); @@ -93,6 +96,7 @@ internal EVENT_TAP_CALLBACK(key_handler) CGEventTapEnable(event_tap->handle, 1); } break; case kCGEventKeyDown: { + if (table_find(&blacklst, carbon.process_name)) return event; if (!current_mode) return event; BEGIN_TIMED_BLOCK("handle_keypress"); @@ -103,6 +107,7 @@ internal EVENT_TAP_CALLBACK(key_handler) if (result) return NULL; } break; case NX_SYSDEFINED: { + if (table_find(&blacklst, carbon.process_name)) return event; if (!current_mode) return event; struct hotkey eventkey; @@ -236,7 +241,8 @@ int main(int argc, char **argv) signal(SIGCHLD, SIG_IGN); init_shell(); - table_init(&mode_map, 13, (table_hash_func) hash_mode, (table_compare_func) same_mode); + table_init(&mode_map, 13, (table_hash_func) hash_string, (table_compare_func) compare_string); + table_init(&blacklst, 13, (table_hash_func) hash_string, (table_compare_func) compare_string); END_SCOPED_TIMED_BLOCK(); BEGIN_SCOPED_TIMED_BLOCK("parse_config"); diff --git a/src/tokenize.c b/src/tokenize.c index a0fd93d..eaf0e3a 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -79,6 +79,14 @@ eat_string(struct tokenizer *tokenizer) } } +internal void +eat_option(struct tokenizer *tokenizer) +{ + while (*tokenizer->at && !isspace(*tokenizer->at)) { + advance(tokenizer); + } +} + internal inline bool isidentifier(char c) { @@ -150,6 +158,15 @@ get_token(struct tokenizer *tokenizer) case '*': { token.type = Token_Wildcard; } break; case '[': { token.type = Token_BeginList; } break; case ']': { token.type = Token_EndList; } break; + case '.': { + token.text = tokenizer->at; + token.line = tokenizer->line; + token.cursor = tokenizer->cursor; + + eat_option(tokenizer); + token.length = tokenizer->at - token.text; + token.type = Token_Option; + } break; case '"': { token.text = tokenizer->at; token.line = tokenizer->line; diff --git a/src/tokenize.h b/src/tokenize.h index 4592ac9..4df5df3 100644 --- a/src/tokenize.h +++ b/src/tokenize.h @@ -56,6 +56,7 @@ enum token_type Token_Unbound, Token_Wildcard, Token_String, + Token_Option, Token_BeginList, Token_EndList, -- cgit v1.2.3