diff options
author | koekeishiya <aasvi93@hotmail.com> | 2018-07-20 19:26:15 +0200 |
---|---|---|
committer | koekeishiya <aasvi93@hotmail.com> | 2018-07-20 19:26:15 +0200 |
commit | 0b03bdb56667fc3efcbf2624145409436cac9b78 (patch) | |
tree | bb5da0de9f7e18d7bcffda48f39acafd4c7a8df6 | |
parent | bee00428694c093baa805858e093815bd59ff112 (diff) | |
download | skhd-0b03bdb56667fc3efcbf2624145409436cac9b78.tar.gz skhd-0b03bdb56667fc3efcbf2624145409436cac9b78.zip |
#44 synthesize keypress; skhd -k "alt - h"
Diffstat (limited to '')
-rw-r--r-- | src/hotkey.h | 6 | ||||
-rw-r--r-- | src/parse.c | 55 | ||||
-rw-r--r-- | src/parse.h | 2 | ||||
-rw-r--r-- | src/skhd.c | 16 | ||||
-rw-r--r-- | src/synthesize.c | 92 | ||||
-rw-r--r-- | src/synthesize.h | 7 |
6 files changed, 176 insertions, 2 deletions
diff --git a/src/hotkey.h b/src/hotkey.h index c2caed5..e616303 100644 --- a/src/hotkey.h +++ b/src/hotkey.h @@ -5,6 +5,12 @@ #include <stdint.h> #include <stdbool.h> +#define Modifier_Keycode_Alt 0x3A +#define Modifier_Keycode_Shift 0x38 +#define Modifier_Keycode_Cmd 0x37 +#define Modifier_Keycode_Ctrl 0x3B +#define Modifier_Keycode_Fn 0x3F + enum osx_event_mask { Event_Mask_Alt = 0x00080000, diff --git a/src/parse.c b/src/parse.c index 79f4aba..a79d8a3 100644 --- a/src/parse.c +++ b/src/parse.c @@ -367,6 +367,53 @@ void parse_config(struct parser *parser) } } +struct hotkey * +parse_keypress(struct parser *parser) +{ + if ((parser_check(parser, Token_Modifier)) || + (parser_check(parser, Token_Literal)) || + (parser_check(parser, Token_Key_Hex)) || + (parser_check(parser, Token_Key))) { + struct hotkey *hotkey = malloc(sizeof(struct hotkey)); + memset(hotkey, 0, sizeof(struct hotkey)); + bool found_modifier; + + if ((found_modifier = parser_match(parser, Token_Modifier))) { + hotkey->flags = parse_modifier(parser); + if (parser->error) { + goto err; + } + } + + if (found_modifier) { + if (!parser_match(parser, Token_Dash)) { + parser_report_error(parser, Error_Unexpected_Token, "expected '-'"); + goto err; + } + } + + if (parser_match(parser, Token_Key)) { + hotkey->key = parse_key(parser); + } else if (parser_match(parser, Token_Key_Hex)) { + hotkey->key = parse_key_hex(parser); + } else if (parser_match(parser, Token_Literal)) { + parse_key_literal(parser, hotkey); + } else { + parser_report_error(parser, Error_Unexpected_Token, "expected key-literal"); + goto err; + } + + return hotkey; + + err: + free(hotkey); + return NULL; + } else { + parser_report_error(parser, Error_Unexpected_Token, "expected modifier or key-literal"); + } + return NULL; +} + struct token parser_peek(struct parser *parser) { @@ -445,6 +492,14 @@ bool parser_init(struct parser *parser, struct table *mode_map, char *file) return false; } +bool parser_init_text(struct parser *parser, char *text) +{ + memset(parser, 0, sizeof(struct parser)); + tokenizer_init(&parser->tokenizer, text); + parser_advance(parser); + return true; +} + void parser_destroy(struct parser *parser) { free(parser->tokenizer.buffer); diff --git a/src/parse.h b/src/parse.h index d3543b9..93fcfc6 100644 --- a/src/parse.h +++ b/src/parse.h @@ -23,6 +23,7 @@ enum parse_error_type void parse_config(struct parser *parser); +struct hotkey *parse_keypress(struct parser *parser); struct token parser_peek(struct parser *parser); struct token parser_previous(struct parser *parser); @@ -31,6 +32,7 @@ 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_text(struct parser *parser, char *text); void parser_destroy(struct parser *parser); void parser_report_error(struct parser *parser, enum parse_error_type error_type, const char *format, ...); @@ -17,6 +17,7 @@ #include "tokenize.h" #include "parse.h" #include "hotkey.h" +#include "synthesize.h" #include "hotload.c" #include "event_tap.c" @@ -24,6 +25,7 @@ #include "tokenize.c" #include "parse.c" #include "hotkey.c" +#include "synthesize.c" #define internal static extern bool CGSIsSecureEventInputSet(); @@ -123,10 +125,12 @@ internal bool parse_arguments(int argc, char **argv) { int option; - const char *short_option = "vc:"; + const char *short_option = "vc:k:t:"; struct option long_option[] = { { "version", no_argument, NULL, 'v' }, { "config", required_argument, NULL, 'c' }, + { "key", required_argument, NULL, 'k' }, + { "text", required_argument, NULL, 't' }, { NULL, 0, NULL, 0 } }; @@ -137,7 +141,15 @@ parse_arguments(int argc, char **argv) return true; } break; case 'c': { - config_file = strdup(optarg); + config_file = copy_string(optarg); + } break; + case 'k': { + synthesize_key(optarg); + return true; + } break; + case 't': { + synthesize_text(optarg); + return true; } break; } } diff --git a/src/synthesize.c b/src/synthesize.c new file mode 100644 index 0000000..0084604 --- /dev/null +++ b/src/synthesize.c @@ -0,0 +1,92 @@ +#include <Carbon/Carbon.h> + +#include "synthesize.h" +#include "locale.h" +#include "parse.h" +#include "hotkey.h" + +#define internal static + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" + +internal inline void +create_and_post_keyevent(uint16_t key, bool pressed) +{ + CGPostKeyboardEvent((CGCharCode)0, (CGKeyCode)key, pressed); +} + +internal inline void +synthesize_modifiers(struct hotkey *hotkey, bool pressed) +{ + if (has_flags(hotkey, Hotkey_Flag_Alt)) { + create_and_post_keyevent(Modifier_Keycode_Alt, pressed); + } + + if (has_flags(hotkey, Hotkey_Flag_Shift)) { + create_and_post_keyevent(Modifier_Keycode_Shift, pressed); + } + + if (has_flags(hotkey, Hotkey_Flag_Cmd)) { + create_and_post_keyevent(Modifier_Keycode_Cmd, pressed); + } + + if (has_flags(hotkey, Hotkey_Flag_Control)) { + create_and_post_keyevent(Modifier_Keycode_Ctrl, pressed); + } + + if (has_flags(hotkey, Hotkey_Flag_Fn)) { + create_and_post_keyevent(Modifier_Keycode_Fn, pressed); + } +} + +void synthesize_key(char *key_string) +{ + if (!initialize_keycode_map()) return; + struct parser parser; + parser_init_text(&parser, key_string); + + close(1); + close(2); + + struct hotkey *hotkey = parse_keypress(&parser); + if (!hotkey) return; + + CGSetLocalEventsSuppressionInterval(0.0f); + CGEnableEventStateCombining(false); + + synthesize_modifiers(hotkey, true); + create_and_post_keyevent(hotkey->key, true); + + create_and_post_keyevent(hotkey->key, false); + synthesize_modifiers(hotkey, false); +} + +void synthesize_text(char *text) +{ + CFStringRef text_ref = CFStringCreateWithCString(NULL, text, kCFStringEncodingUTF8); + CFIndex text_length = CFStringGetLength(text_ref); + + CGEventRef de = CGEventCreateKeyboardEvent(NULL, 0, true); + CGEventRef ue = CGEventCreateKeyboardEvent(NULL, 0, false); + + CGEventSetFlags(de, 0); + CGEventSetFlags(ue, 0); + + UniChar c; + for (CFIndex i = 0; i < text_length; ++i) + { + c = CFStringGetCharacterAtIndex(text_ref, i); + CGEventKeyboardSetUnicodeString(de, 1, &c); + CGEventPost(kCGAnnotatedSessionEventTap, de); + usleep(1000); + CGEventKeyboardSetUnicodeString(ue, 1, &c); + CGEventPost(kCGAnnotatedSessionEventTap, ue); + } + + CFRelease(ue); + CFRelease(de); + CFRelease(text_ref); +} + +#pragma clang diagnostic pop diff --git a/src/synthesize.h b/src/synthesize.h new file mode 100644 index 0000000..4a2b262 --- /dev/null +++ b/src/synthesize.h @@ -0,0 +1,7 @@ +#ifndef SKHD_SYNTHESIZE_H +#define SKHD_SYNTHESIZE_H + +void synthesize_key(char *key_string); +void synthesize_text(char *text); + +#endif |