diff options
author | koekeishiya <aasvi93@hotmail.com> | 2018-04-20 22:31:09 +0200 |
---|---|---|
committer | koekeishiya <aasvi93@hotmail.com> | 2018-04-20 22:31:09 +0200 |
commit | 9117aa1c79e3f352ee7eb122df64f1b6bd9e53d8 (patch) | |
tree | df4299b441d9bce4bf6d085c055c05902607cd63 /src | |
parent | e5f6d5df6db8128fc0b93643711d16adac6404d3 (diff) | |
parent | c1a8031fe255baddbea041ed2bfc32787afe2108 (diff) | |
download | skhd-9117aa1c79e3f352ee7eb122df64f1b6bd9e53d8.tar.gz skhd-9117aa1c79e3f352ee7eb122df64f1b6bd9e53d8.zip |
merge master
Diffstat (limited to 'src')
-rw-r--r-- | src/hashtable.h | 4 | ||||
-rw-r--r-- | src/locale.c | 147 | ||||
-rw-r--r-- | src/locale.h | 1 | ||||
-rw-r--r-- | src/skhd.c | 11 |
4 files changed, 111 insertions, 52 deletions
diff --git a/src/hashtable.h b/src/hashtable.h index 48ffaad..42d0166 100644 --- a/src/hashtable.h +++ b/src/hashtable.h @@ -89,7 +89,9 @@ void table_add(struct table *table, void *key, void *value) { struct bucket **bucket = table_get_bucket(table, key); if (*bucket) { - (*bucket)->value = value; + if (!(*bucket)->value) { + (*bucket)->value = value; + } } else { *bucket = table_new_bucket(key, value); ++table->count; diff --git a/src/locale.c b/src/locale.c index 974c3ae..464c3ba 100644 --- a/src/locale.c +++ b/src/locale.c @@ -1,45 +1,84 @@ #include "locale.h" +#include "hashtable.h" #include <Carbon/Carbon.h> #include <IOKit/hidsystem/ev_keymap.h> #define internal static #define local_persist static -internal CFStringRef -cfstring_from_keycode(CGKeyCode keycode) +internal struct table keymap_table; + +internal char * +copy_cf_string_to_c(CFStringRef string) { - TISInputSourceRef keyboard = TISCopyCurrentASCIICapableKeyboardLayoutInputSource(); - CFDataRef uchr = (CFDataRef) TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData); - CFRelease(keyboard); + CFStringEncoding encoding = kCFStringEncodingUTF8; + CFIndex length = CFStringGetLength(string); + CFIndex bytes = CFStringGetMaximumSizeForEncoding(length, encoding); + char *result = malloc(bytes + 1); - UCKeyboardLayout *keyboard_layout = (UCKeyboardLayout *) CFDataGetBytePtr(uchr); - if (keyboard_layout) { - UInt32 dead_key_state = 0; - UniCharCount max_string_length = 255; - UniCharCount string_length = 0; - UniChar unicode_string[max_string_length]; - - OSStatus status = UCKeyTranslate(keyboard_layout, keycode, - kUCKeyActionDown, 0, - LMGetKbdType(), 0, - &dead_key_state, - max_string_length, - &string_length, - unicode_string); - - if (string_length == 0 && dead_key_state) { - status = UCKeyTranslate(keyboard_layout, kVK_Space, - kUCKeyActionDown, 0, - LMGetKbdType(), 0, - &dead_key_state, - max_string_length, - &string_length, - unicode_string); - } + // NOTE(koekeishiya): Boolean: typedef -> unsigned char; false = 0, true != 0 + Boolean success = CFStringGetCString(string, result, bytes + 1, encoding); + if (!success) { + free(result); + result = NULL; + } + + return result; +} - if (string_length > 0 && status == noErr) { - return CFStringCreateWithCharacters(NULL, unicode_string, string_length); +internal int +hash_keymap(const char *a) +{ + unsigned long hash = 0, high; + while (*a) { + hash = (hash << 4) + *a++; + high = hash & 0xF0000000; + if (high) { + hash ^= (high >> 24); } + hash &= ~high; + } + return hash; +} + +internal bool +same_keymap(const char *a, const char *b) +{ + while (*a && *b && *a == *b) { + ++a; + ++b; + } + return *a == '\0' && *b == '\0'; +} + +internal CFStringRef +cfstring_from_keycode(UCKeyboardLayout *keyboard_layout, CGKeyCode keycode) +{ + UInt32 dead_key_state = 0; + UniCharCount max_string_length = 255; + UniCharCount string_length = 0; + UniChar unicode_string[max_string_length]; + + OSStatus status = UCKeyTranslate(keyboard_layout, keycode, + kUCKeyActionDown, 0, + LMGetKbdType(), 0, + &dead_key_state, + max_string_length, + &string_length, + unicode_string); + + if (string_length == 0 && dead_key_state) { + status = UCKeyTranslate(keyboard_layout, kVK_Space, + kUCKeyActionDown, 0, + LMGetKbdType(), 0, + &dead_key_state, + max_string_length, + &string_length, + unicode_string); + } + + if (string_length > 0 && status == noErr) { + return CFStringCreateWithCharacters(NULL, unicode_string, string_length); } return NULL; @@ -47,26 +86,38 @@ cfstring_from_keycode(CGKeyCode keycode) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" -uint32_t keycode_from_char(char key) +bool initialize_keycode_map() { - uint32_t keycode = 0; - local_persist CFMutableDictionaryRef keycode_map = NULL; - if (!keycode_map) { - keycode_map = CFDictionaryCreateMutable(kCFAllocatorDefault, 128, &kCFCopyStringDictionaryKeyCallBacks, NULL); - for (unsigned index = 0; index < 128; ++index) { - CFStringRef key_string = cfstring_from_keycode(index); - if (key_string) { - CFDictionaryAddValue(keycode_map, key_string, (const void *)index); - CFRelease(key_string); - } - } + TISInputSourceRef keyboard = TISCopyCurrentASCIICapableKeyboardLayoutInputSource(); + CFDataRef uchr = (CFDataRef) TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData); + CFRelease(keyboard); + + UCKeyboardLayout *keyboard_layout = (UCKeyboardLayout *) CFDataGetBytePtr(uchr); + if (!keyboard_layout) return false; + + table_init(&keymap_table, + 131, + (table_hash_func) hash_keymap, + (table_compare_func) same_keymap); + + for (unsigned index = 0; index < 128; ++index) { + CFStringRef key_string = cfstring_from_keycode(keyboard_layout, index); + if (!key_string) continue; + + char *c_key_string = copy_cf_string_to_c(key_string); + CFRelease(key_string); + if (!c_key_string) continue; + + table_add(&keymap_table, c_key_string, (void *)index); } - UniChar uni_char = key; - CFStringRef char_str = CFStringCreateWithCharacters(kCFAllocatorDefault, &uni_char, 1); - CFDictionaryGetValueIfPresent(keycode_map, char_str, (const void **)&keycode); - CFRelease(char_str); + return true; +} +#pragma clang diagnostic pop +uint32_t keycode_from_char(char key) +{ + char lookup_key[] = { key, '\0' }; + uint32_t keycode = (uint32_t) table_find(&keymap_table, &lookup_key); return keycode; } -#pragma clang diagnostic pop diff --git a/src/locale.h b/src/locale.h index 7e30d1c..653bcfd 100644 --- a/src/locale.h +++ b/src/locale.h @@ -3,6 +3,7 @@ #include <stdint.h> +bool initialize_keycode_map(); uint32_t keycode_from_char(char key); #endif @@ -41,9 +41,10 @@ extern bool CGSIsSecureEventInputSet(); internal unsigned major_version = 0; internal unsigned minor_version = 0; -internal unsigned patch_version = 10; -internal struct mode *current_mode; +internal unsigned patch_version = 14; +internal struct table hotkey_map; internal struct table mode_map; +internal struct mode *current_mode; internal char *config_file; internal void @@ -184,7 +185,11 @@ int main(int argc, char **argv) } if (!check_privileges()) { - error("skhd: must be run with accessibility access.\n"); + error("skhd: must be run with accessibility access! abort..\n"); + } + + if (!initialize_keycode_map()) { + error("skhd: could not initialize keycode map! abort..\n"); } if (!config_file) { |