|
@@ -2987,85 +2987,129 @@ void DisplayServerOSX::cursor_set_custom_image(const RES &p_cursor, CursorShape
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+struct LayoutInfo {
|
|
|
|
+ String name;
|
|
|
|
+ String code;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static Vector<LayoutInfo> kbd_layouts;
|
|
|
|
+static int current_layout = 0;
|
|
static bool keyboard_layout_dirty = true;
|
|
static bool keyboard_layout_dirty = true;
|
|
static void keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) {
|
|
static void keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) {
|
|
|
|
+ kbd_layouts.clear();
|
|
|
|
+ current_layout = 0;
|
|
keyboard_layout_dirty = true;
|
|
keyboard_layout_dirty = true;
|
|
}
|
|
}
|
|
|
|
|
|
-// Returns string representation of keys, if they are printable.
|
|
|
|
-static NSString *createStringForKeys(const CGKeyCode *keyCode, int length) {
|
|
|
|
- TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
|
|
|
|
- if (!currentKeyboard)
|
|
|
|
- return nil;
|
|
|
|
|
|
+void _update_keyboard_layouts() {
|
|
|
|
+ @autoreleasepool {
|
|
|
|
+ TISInputSourceRef cur_source = TISCopyCurrentKeyboardInputSource();
|
|
|
|
+ NSString *cur_name = (NSString *)TISGetInputSourceProperty(cur_source, kTISPropertyLocalizedName);
|
|
|
|
+ CFRelease(cur_source);
|
|
|
|
|
|
- CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
|
|
|
|
- if (!layoutData)
|
|
|
|
- return nil;
|
|
|
|
|
|
+ // Enum IME layouts
|
|
|
|
+ NSDictionary *filter_ime = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardInputMode };
|
|
|
|
+ NSArray *list_ime = (NSArray *)TISCreateInputSourceList((CFDictionaryRef)filter_ime, false);
|
|
|
|
+ for (NSUInteger i = 0; i < [list_ime count]; i++) {
|
|
|
|
+ LayoutInfo ly;
|
|
|
|
+ NSString *name = (NSString *)TISGetInputSourceProperty((TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyLocalizedName);
|
|
|
|
+ ly.name.parse_utf8([name UTF8String]);
|
|
|
|
|
|
- const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);
|
|
|
|
|
|
+ NSArray *langs = (NSArray *)TISGetInputSourceProperty((TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyInputSourceLanguages);
|
|
|
|
+ ly.code.parse_utf8([(NSString *)[langs objectAtIndex:0] UTF8String]);
|
|
|
|
+ kbd_layouts.push_back(ly);
|
|
|
|
|
|
- OSStatus err;
|
|
|
|
- CFMutableStringRef output = CFStringCreateMutable(NULL, 0);
|
|
|
|
|
|
+ if ([name isEqualToString:cur_name]) {
|
|
|
|
+ current_layout = kbd_layouts.size() - 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ [list_ime release];
|
|
|
|
|
|
- for (int i = 0; i < length; ++i) {
|
|
|
|
- UInt32 keysDown = 0;
|
|
|
|
- UniChar chars[4];
|
|
|
|
- UniCharCount realLength;
|
|
|
|
|
|
+ // Enum plain keyboard layouts
|
|
|
|
+ NSDictionary *filter_kbd = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardLayout };
|
|
|
|
+ NSArray *list_kbd = (NSArray *)TISCreateInputSourceList((CFDictionaryRef)filter_kbd, false);
|
|
|
|
+ for (NSUInteger i = 0; i < [list_kbd count]; i++) {
|
|
|
|
+ LayoutInfo ly;
|
|
|
|
+ NSString *name = (NSString *)TISGetInputSourceProperty((TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyLocalizedName);
|
|
|
|
+ ly.name.parse_utf8([name UTF8String]);
|
|
|
|
|
|
- err = UCKeyTranslate(keyboardLayout,
|
|
|
|
- keyCode[i],
|
|
|
|
- kUCKeyActionDisplay,
|
|
|
|
- 0,
|
|
|
|
- LMGetKbdType(),
|
|
|
|
- kUCKeyTranslateNoDeadKeysBit,
|
|
|
|
- &keysDown,
|
|
|
|
- sizeof(chars) / sizeof(chars[0]),
|
|
|
|
- &realLength,
|
|
|
|
- chars);
|
|
|
|
|
|
+ NSArray *langs = (NSArray *)TISGetInputSourceProperty((TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyInputSourceLanguages);
|
|
|
|
+ ly.code.parse_utf8([(NSString *)[langs objectAtIndex:0] UTF8String]);
|
|
|
|
+ kbd_layouts.push_back(ly);
|
|
|
|
|
|
- if (err != noErr) {
|
|
|
|
- CFRelease(output);
|
|
|
|
- return nil;
|
|
|
|
|
|
+ if ([name isEqualToString:cur_name]) {
|
|
|
|
+ current_layout = kbd_layouts.size() - 1;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
- CFStringAppendCharacters(output, chars, 1);
|
|
|
|
|
|
+ [list_kbd release];
|
|
}
|
|
}
|
|
|
|
|
|
- return (NSString *)output;
|
|
|
|
|
|
+ keyboard_layout_dirty = false;
|
|
}
|
|
}
|
|
|
|
|
|
-DisplayServerOSX::LatinKeyboardVariant DisplayServerOSX::get_latin_keyboard_variant() const {
|
|
|
|
- _THREAD_SAFE_METHOD_
|
|
|
|
-
|
|
|
|
- static LatinKeyboardVariant layout = LATIN_KEYBOARD_QWERTY;
|
|
|
|
|
|
+int DisplayServerOSX::keyboard_get_layout_count() const {
|
|
|
|
+ if (keyboard_layout_dirty) {
|
|
|
|
+ _update_keyboard_layouts();
|
|
|
|
+ }
|
|
|
|
+ return kbd_layouts.size();
|
|
|
|
+}
|
|
|
|
|
|
|
|
+void DisplayServerOSX::keyboard_set_current_layout(int p_index) {
|
|
if (keyboard_layout_dirty) {
|
|
if (keyboard_layout_dirty) {
|
|
- layout = LATIN_KEYBOARD_QWERTY;
|
|
|
|
|
|
+ _update_keyboard_layouts();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ERR_FAIL_INDEX(p_index, kbd_layouts.size());
|
|
|
|
|
|
- CGKeyCode keys[] = { kVK_ANSI_Q, kVK_ANSI_W, kVK_ANSI_E, kVK_ANSI_R, kVK_ANSI_T, kVK_ANSI_Y };
|
|
|
|
- NSString *test = createStringForKeys(keys, 6);
|
|
|
|
|
|
+ NSString *cur_name = [NSString stringWithUTF8String:kbd_layouts[p_index].name.utf8().get_data()];
|
|
|
|
|
|
- if ([test isEqualToString:@"qwertz"]) {
|
|
|
|
- layout = LATIN_KEYBOARD_QWERTZ;
|
|
|
|
- } else if ([test isEqualToString:@"azerty"]) {
|
|
|
|
- layout = LATIN_KEYBOARD_AZERTY;
|
|
|
|
- } else if ([test isEqualToString:@"qzerty"]) {
|
|
|
|
- layout = LATIN_KEYBOARD_QZERTY;
|
|
|
|
- } else if ([test isEqualToString:@"',.pyf"]) {
|
|
|
|
- layout = LATIN_KEYBOARD_DVORAK;
|
|
|
|
- } else if ([test isEqualToString:@"xvlcwk"]) {
|
|
|
|
- layout = LATIN_KEYBOARD_NEO;
|
|
|
|
- } else if ([test isEqualToString:@"qwfpgj"]) {
|
|
|
|
- layout = LATIN_KEYBOARD_COLEMAK;
|
|
|
|
|
|
+ NSDictionary *filter_kbd = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardLayout };
|
|
|
|
+ NSArray *list_kbd = (NSArray *)TISCreateInputSourceList((CFDictionaryRef)filter_kbd, false);
|
|
|
|
+ for (NSUInteger i = 0; i < [list_kbd count]; i++) {
|
|
|
|
+ NSString *name = (NSString *)TISGetInputSourceProperty((TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyLocalizedName);
|
|
|
|
+ if ([name isEqualToString:cur_name]) {
|
|
|
|
+ TISSelectInputSource((TISInputSourceRef)[list_kbd objectAtIndex:i]);
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
+ [list_kbd release];
|
|
|
|
|
|
- [test release];
|
|
|
|
|
|
+ NSDictionary *filter_ime = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardInputMode };
|
|
|
|
+ NSArray *list_ime = (NSArray *)TISCreateInputSourceList((CFDictionaryRef)filter_ime, false);
|
|
|
|
+ for (NSUInteger i = 0; i < [list_ime count]; i++) {
|
|
|
|
+ NSString *name = (NSString *)TISGetInputSourceProperty((TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyLocalizedName);
|
|
|
|
+ if ([name isEqualToString:cur_name]) {
|
|
|
|
+ TISSelectInputSource((TISInputSourceRef)[list_ime objectAtIndex:i]);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ [list_ime release];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int DisplayServerOSX::keyboard_get_current_layout() const {
|
|
|
|
+ if (keyboard_layout_dirty) {
|
|
|
|
+ _update_keyboard_layouts();
|
|
|
|
+ }
|
|
|
|
|
|
- keyboard_layout_dirty = false;
|
|
|
|
- return layout;
|
|
|
|
|
|
+ return current_layout;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+String DisplayServerOSX::keyboard_get_layout_language(int p_index) const {
|
|
|
|
+ if (keyboard_layout_dirty) {
|
|
|
|
+ _update_keyboard_layouts();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), "");
|
|
|
|
+ return kbd_layouts[p_index].code;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+String DisplayServerOSX::keyboard_get_layout_name(int p_index) const {
|
|
|
|
+ if (keyboard_layout_dirty) {
|
|
|
|
+ _update_keyboard_layouts();
|
|
}
|
|
}
|
|
|
|
|
|
- return layout;
|
|
|
|
|
|
+ ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), "");
|
|
|
|
+ return kbd_layouts[p_index].name;
|
|
}
|
|
}
|
|
|
|
|
|
void DisplayServerOSX::_push_input(const Ref<InputEvent> &p_event) {
|
|
void DisplayServerOSX::_push_input(const Ref<InputEvent> &p_event) {
|