aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkoekeishiya <aasvi93@hotmail.com>2019-03-03 18:39:34 +0100
committerkoekeishiya <aasvi93@hotmail.com>2019-03-03 18:39:34 +0100
commit56b94a6eed9fe4642382f533666dc19901fad3fc (patch)
tree6e026d8a145fad2143fe4cac1603f22a48195be9
parente23811d884b9dae356c84e4515ef52184aa3432c (diff)
downloadskhd-56b94a6eed9fe4642382f533666dc19901fad3fc.tar.gz
skhd-56b94a6eed9fe4642382f533666dc19901fad3fc.zip
#53 allow opt-out for applications
-rw-r--r--README.md14
-rw-r--r--examples/skhdrc8
-rw-r--r--src/hotkey.c14
-rw-r--r--src/hotkey.h5
-rw-r--r--src/parse.c41
-rw-r--r--src/parse.h3
-rw-r--r--src/skhd.c10
-rw-r--r--src/tokenize.c17
-rw-r--r--src/tokenize.h1
9 files changed, 104 insertions, 9 deletions
diff --git a/README.md b/README.md
index e0b9ded..3ab4481 100644
--- a/README.md
+++ b/README.md
@@ -11,8 +11,9 @@ feature comparison between **skhd** and **khd**
| hotload config file | [x] | [ ] |
| hotkey passthrough | [x] | [x] |
| modal hotkey-system | [x] | [x] |
-| use media-keys as hotkey | [x] | [ ] |
| application specific hotkey| [x] | [x] |
+| blacklist applications | [x] | [ ] |
+| use media-keys as hotkey | [x] | [ ] |
| modifier only hotkey | [ ] | [x] |
| caps-lock as hotkey | [ ] | [x] |
| mouse-buttons as hotkey | [ ] | [x] |
@@ -136,3 +137,14 @@ command = command is executed through '$SHELL -c' and
an EOL character signifies the end of the bind.
```
+
+General options that configure the behaviour of **skhd**:
+```
+# prevents skhd from monitoring events for listed processes
+.blacklist [
+ "terminal"
+ "qutebrowser"
+ "kitty"
+ "google chrome"
+]
+```
diff --git a/examples/skhdrc b/examples/skhdrc
index ffd0613..bf0f7a3 100644
--- a/examples/skhdrc
+++ b/examples/skhdrc
@@ -86,6 +86,14 @@
# "finder" : false
# ]
+# prevent skhd from monitoring events for specific applications
+#
+# .blacklist [
+# "kitty"
+# "terminal"
+# "qutebrowser"
+# ]
+
# open terminal, blazingly fast compared to iTerm/Hyper
cmd - return : /Applications/Kitty.app/Contents/MacOS/kitty --single-instance -d ~
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,