[3.2] Add keyboard layout enumeration / set / get functions (macOS, Windows, Linux/X11).
This commit is contained in:
parent
6c9b7c27d5
commit
2256946f79
11 changed files with 455 additions and 24 deletions
|
@ -569,6 +569,26 @@ String _OS::get_latin_keyboard_variant() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _OS::keyboard_get_layout_count() const {
|
||||||
|
return OS::get_singleton()->keyboard_get_layout_count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int _OS::keyboard_get_current_layout() const {
|
||||||
|
return OS::get_singleton()->keyboard_get_current_layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _OS::keyboard_set_current_layout(int p_index) {
|
||||||
|
OS::get_singleton()->keyboard_set_current_layout(p_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _OS::keyboard_get_layout_language(int p_index) const {
|
||||||
|
return OS::get_singleton()->keyboard_get_layout_language(p_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _OS::keyboard_get_layout_name(int p_index) const {
|
||||||
|
return OS::get_singleton()->keyboard_get_layout_name(p_index);
|
||||||
|
}
|
||||||
|
|
||||||
String _OS::get_model_name() const {
|
String _OS::get_model_name() const {
|
||||||
|
|
||||||
return OS::get_singleton()->get_model_name();
|
return OS::get_singleton()->get_model_name();
|
||||||
|
@ -1323,6 +1343,12 @@ void _OS::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_latin_keyboard_variant"), &_OS::get_latin_keyboard_variant);
|
ClassDB::bind_method(D_METHOD("get_latin_keyboard_variant"), &_OS::get_latin_keyboard_variant);
|
||||||
ClassDB::bind_method(D_METHOD("get_model_name"), &_OS::get_model_name);
|
ClassDB::bind_method(D_METHOD("get_model_name"), &_OS::get_model_name);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("keyboard_get_layout_count"), &_OS::keyboard_get_layout_count);
|
||||||
|
ClassDB::bind_method(D_METHOD("keyboard_get_current_layout"), &_OS::keyboard_get_current_layout);
|
||||||
|
ClassDB::bind_method(D_METHOD("keyboard_set_current_layout", "index"), &_OS::keyboard_set_current_layout);
|
||||||
|
ClassDB::bind_method(D_METHOD("keyboard_get_layout_language", "index"), &_OS::keyboard_get_layout_language);
|
||||||
|
ClassDB::bind_method(D_METHOD("keyboard_get_layout_name", "index"), &_OS::keyboard_get_layout_name);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("can_draw"), &_OS::can_draw);
|
ClassDB::bind_method(D_METHOD("can_draw"), &_OS::can_draw);
|
||||||
ClassDB::bind_method(D_METHOD("is_userfs_persistent"), &_OS::is_userfs_persistent);
|
ClassDB::bind_method(D_METHOD("is_userfs_persistent"), &_OS::is_userfs_persistent);
|
||||||
ClassDB::bind_method(D_METHOD("is_stdout_verbose"), &_OS::is_stdout_verbose);
|
ClassDB::bind_method(D_METHOD("is_stdout_verbose"), &_OS::is_stdout_verbose);
|
||||||
|
|
|
@ -242,6 +242,11 @@ public:
|
||||||
|
|
||||||
String get_locale() const;
|
String get_locale() const;
|
||||||
String get_latin_keyboard_variant() const;
|
String get_latin_keyboard_variant() const;
|
||||||
|
int keyboard_get_layout_count() const;
|
||||||
|
int keyboard_get_current_layout() const;
|
||||||
|
void keyboard_set_current_layout(int p_index);
|
||||||
|
String keyboard_get_layout_language(int p_index) const;
|
||||||
|
String keyboard_get_layout_name(int p_index) const;
|
||||||
|
|
||||||
String get_model_name() const;
|
String get_model_name() const;
|
||||||
|
|
||||||
|
|
|
@ -551,6 +551,24 @@ OS::LatinKeyboardVariant OS::get_latin_keyboard_variant() const {
|
||||||
return LATIN_KEYBOARD_QWERTY;
|
return LATIN_KEYBOARD_QWERTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int OS::keyboard_get_layout_count() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OS::keyboard_get_current_layout() const {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OS::keyboard_set_current_layout(int p_index) {}
|
||||||
|
|
||||||
|
String OS::keyboard_get_layout_language(int p_index) const {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String OS::keyboard_get_layout_name(int p_index) const {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
bool OS::is_joy_known(int p_device) {
|
bool OS::is_joy_known(int p_device) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -493,6 +493,12 @@ public:
|
||||||
|
|
||||||
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
|
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
|
||||||
|
|
||||||
|
virtual int keyboard_get_layout_count() const;
|
||||||
|
virtual int keyboard_get_current_layout() const;
|
||||||
|
virtual void keyboard_set_current_layout(int p_index);
|
||||||
|
virtual String keyboard_get_layout_language(int p_index) const;
|
||||||
|
virtual String keyboard_get_layout_name(int p_index) const;
|
||||||
|
|
||||||
virtual bool is_joy_known(int p_device);
|
virtual bool is_joy_known(int p_device);
|
||||||
virtual String get_joy_guid(int p_device) const;
|
virtual String get_joy_guid(int p_device) const;
|
||||||
|
|
||||||
|
|
|
@ -682,6 +682,52 @@
|
||||||
[b]Note:[/b] Only implemented on desktop platforms. On other platforms, it will always return [code]true[/code].
|
[b]Note:[/b] Only implemented on desktop platforms. On other platforms, it will always return [code]true[/code].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="keyboard_get_current_layout" qualifiers="const">
|
||||||
|
<return type="int">
|
||||||
|
</return>
|
||||||
|
<description>
|
||||||
|
Returns active keyboard layout index.
|
||||||
|
[b]Note:[/b] This method is implemented on Linux, macOS and Windows.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="keyboard_get_layout_count" qualifiers="const">
|
||||||
|
<return type="int">
|
||||||
|
</return>
|
||||||
|
<description>
|
||||||
|
Returns the number of keyboard layouts.
|
||||||
|
[b]Note:[/b] This method is implemented on Linux, macOS and Windows.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="keyboard_get_layout_language" qualifiers="const">
|
||||||
|
<return type="String">
|
||||||
|
</return>
|
||||||
|
<argument index="0" name="index" type="int">
|
||||||
|
</argument>
|
||||||
|
<description>
|
||||||
|
Returns the ISO-639/BCP-47 language code of the keyboard layout at position [code]index[/code].
|
||||||
|
[b]Note:[/b] This method is implemented on Linux, macOS and Windows.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="keyboard_get_layout_name" qualifiers="const">
|
||||||
|
<return type="String">
|
||||||
|
</return>
|
||||||
|
<argument index="0" name="index" type="int">
|
||||||
|
</argument>
|
||||||
|
<description>
|
||||||
|
Returns the localized name of the keyboard layout at position [code]index[/code].
|
||||||
|
[b]Note:[/b] This method is implemented on Linux, macOS and Windows.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="keyboard_set_current_layout">
|
||||||
|
<return type="void">
|
||||||
|
</return>
|
||||||
|
<argument index="0" name="index" type="int">
|
||||||
|
</argument>
|
||||||
|
<description>
|
||||||
|
Sets active keyboard layout.
|
||||||
|
[b]Note:[/b] This method is implemented on Linux, macOS and Windows.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="kill">
|
<method name="kill">
|
||||||
<return type="int" enum="Error">
|
<return type="int" enum="Error">
|
||||||
</return>
|
</return>
|
||||||
|
|
|
@ -248,6 +248,11 @@ public:
|
||||||
virtual String get_executable_path() const;
|
virtual String get_executable_path() const;
|
||||||
|
|
||||||
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
|
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
|
||||||
|
virtual int keyboard_get_layout_count() const;
|
||||||
|
virtual int keyboard_get_current_layout() const;
|
||||||
|
virtual void keyboard_set_current_layout(int p_index);
|
||||||
|
virtual String keyboard_get_layout_language(int p_index) const;
|
||||||
|
virtual String keyboard_get_layout_name(int p_index) const;
|
||||||
|
|
||||||
virtual void move_window_to_foreground();
|
virtual void move_window_to_foreground();
|
||||||
|
|
||||||
|
|
|
@ -1437,8 +1437,18 @@ void OS_OSX::initialize_core() {
|
||||||
SemaphoreOSX::make_default();
|
SemaphoreOSX::make_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 OS::LatinKeyboardVariant latin_variant = OS::LATIN_KEYBOARD_QWERTY;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2787,38 +2797,146 @@ static NSString *createStringForKeys(const CGKeyCode *keyCode, int length) {
|
||||||
return (NSString *)output;
|
return (NSString *)output;
|
||||||
}
|
}
|
||||||
|
|
||||||
OS::LatinKeyboardVariant OS_OSX::get_latin_keyboard_variant() const {
|
void _update_keyboard_layouts() {
|
||||||
|
@autoreleasepool {
|
||||||
|
TISInputSourceRef cur_source = TISCopyCurrentKeyboardInputSource();
|
||||||
|
NSString *cur_name = (NSString *)TISGetInputSourceProperty(cur_source, kTISPropertyLocalizedName);
|
||||||
|
CFRelease(cur_source);
|
||||||
|
|
||||||
static LatinKeyboardVariant layout = LATIN_KEYBOARD_QWERTY;
|
// 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]);
|
||||||
|
|
||||||
if (keyboard_layout_dirty) {
|
NSArray *langs = (NSArray *)TISGetInputSourceProperty((TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyInputSourceLanguages);
|
||||||
|
ly.code.parse_utf8([(NSString *)[langs objectAtIndex:0] UTF8String]);
|
||||||
|
kbd_layouts.push_back(ly);
|
||||||
|
|
||||||
layout = LATIN_KEYBOARD_QWERTY;
|
if ([name isEqualToString:cur_name]) {
|
||||||
|
current_layout = kbd_layouts.size() - 1;
|
||||||
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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
[list_ime release];
|
||||||
|
|
||||||
[test release];
|
// 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]);
|
||||||
|
|
||||||
keyboard_layout_dirty = false;
|
NSArray *langs = (NSArray *)TISGetInputSourceProperty((TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyInputSourceLanguages);
|
||||||
return layout;
|
ly.code.parse_utf8([(NSString *)[langs objectAtIndex:0] UTF8String]);
|
||||||
|
kbd_layouts.push_back(ly);
|
||||||
|
|
||||||
|
if ([name isEqualToString:cur_name]) {
|
||||||
|
current_layout = kbd_layouts.size() - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[list_kbd release];
|
||||||
}
|
}
|
||||||
|
|
||||||
return layout;
|
// Update latin variant
|
||||||
|
latin_variant = OS::LATIN_KEYBOARD_QWERTY;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if ([test isEqualToString:@"qwertz"]) {
|
||||||
|
latin_variant = OS::LATIN_KEYBOARD_QWERTZ;
|
||||||
|
} else if ([test isEqualToString:@"azerty"]) {
|
||||||
|
latin_variant = OS::LATIN_KEYBOARD_AZERTY;
|
||||||
|
} else if ([test isEqualToString:@"qzerty"]) {
|
||||||
|
latin_variant = OS::LATIN_KEYBOARD_QZERTY;
|
||||||
|
} else if ([test isEqualToString:@"',.pyf"]) {
|
||||||
|
latin_variant = OS::LATIN_KEYBOARD_DVORAK;
|
||||||
|
} else if ([test isEqualToString:@"xvlcwk"]) {
|
||||||
|
latin_variant = OS::LATIN_KEYBOARD_NEO;
|
||||||
|
} else if ([test isEqualToString:@"qwfpgj"]) {
|
||||||
|
latin_variant = OS::LATIN_KEYBOARD_COLEMAK;
|
||||||
|
}
|
||||||
|
|
||||||
|
[test release];
|
||||||
|
|
||||||
|
keyboard_layout_dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OS::LatinKeyboardVariant OS_OSX::get_latin_keyboard_variant() const {
|
||||||
|
|
||||||
|
if (keyboard_layout_dirty) {
|
||||||
|
_update_keyboard_layouts();
|
||||||
|
}
|
||||||
|
|
||||||
|
return latin_variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OS_OSX::keyboard_get_layout_count() const {
|
||||||
|
if (keyboard_layout_dirty) {
|
||||||
|
_update_keyboard_layouts();
|
||||||
|
}
|
||||||
|
return kbd_layouts.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OS_OSX::keyboard_set_current_layout(int p_index) {
|
||||||
|
if (keyboard_layout_dirty) {
|
||||||
|
_update_keyboard_layouts();
|
||||||
|
}
|
||||||
|
|
||||||
|
ERR_FAIL_INDEX(p_index, kbd_layouts.size());
|
||||||
|
|
||||||
|
NSString *cur_name = [NSString stringWithUTF8String:kbd_layouts[p_index].name.utf8().get_data()];
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
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 OS_OSX::keyboard_get_current_layout() const {
|
||||||
|
if (keyboard_layout_dirty) {
|
||||||
|
_update_keyboard_layouts();
|
||||||
|
}
|
||||||
|
|
||||||
|
return current_layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
String OS_OSX::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 OS_OSX::keyboard_get_layout_name(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].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OS_OSX::process_events() {
|
void OS_OSX::process_events() {
|
||||||
|
|
|
@ -3258,6 +3258,101 @@ OS::LatinKeyboardVariant OS_Windows::get_latin_keyboard_variant() const {
|
||||||
return LATIN_KEYBOARD_QWERTY;
|
return LATIN_KEYBOARD_QWERTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int OS_Windows::keyboard_get_layout_count() const {
|
||||||
|
return GetKeyboardLayoutList(0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int OS_Windows::keyboard_get_current_layout() const {
|
||||||
|
HKL cur_layout = GetKeyboardLayout(0);
|
||||||
|
|
||||||
|
int layout_count = GetKeyboardLayoutList(0, NULL);
|
||||||
|
HKL *layouts = (HKL *)memalloc(layout_count * sizeof(HKL));
|
||||||
|
GetKeyboardLayoutList(layout_count, layouts);
|
||||||
|
|
||||||
|
for (int i = 0; i < layout_count; i++) {
|
||||||
|
if (cur_layout == layouts[i]) {
|
||||||
|
memfree(layouts);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memfree(layouts);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OS_Windows::keyboard_set_current_layout(int p_index) {
|
||||||
|
int layout_count = GetKeyboardLayoutList(0, NULL);
|
||||||
|
|
||||||
|
ERR_FAIL_INDEX(p_index, layout_count);
|
||||||
|
|
||||||
|
HKL *layouts = (HKL *)memalloc(layout_count * sizeof(HKL));
|
||||||
|
GetKeyboardLayoutList(layout_count, layouts);
|
||||||
|
ActivateKeyboardLayout(layouts[p_index], KLF_SETFORPROCESS);
|
||||||
|
memfree(layouts);
|
||||||
|
}
|
||||||
|
|
||||||
|
String OS_Windows::keyboard_get_layout_language(int p_index) const {
|
||||||
|
int layout_count = GetKeyboardLayoutList(0, NULL);
|
||||||
|
|
||||||
|
ERR_FAIL_INDEX_V(p_index, layout_count, "");
|
||||||
|
|
||||||
|
HKL *layouts = (HKL *)memalloc(layout_count * sizeof(HKL));
|
||||||
|
GetKeyboardLayoutList(layout_count, layouts);
|
||||||
|
|
||||||
|
wchar_t buf[LOCALE_NAME_MAX_LENGTH];
|
||||||
|
memset(buf, 0, LOCALE_NAME_MAX_LENGTH * sizeof(wchar_t));
|
||||||
|
LCIDToLocaleName(MAKELCID(LOWORD(layouts[p_index]), SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
|
||||||
|
|
||||||
|
memfree(layouts);
|
||||||
|
|
||||||
|
return String(buf).substr(0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _get_full_layout_name_from_registry(HKL p_layout) {
|
||||||
|
String id = "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\" + String::num_int64((int64_t)p_layout, 16, false).lpad(8, "0");
|
||||||
|
String ret;
|
||||||
|
|
||||||
|
HKEY hkey;
|
||||||
|
wchar_t layout_text[1024];
|
||||||
|
memset(layout_text, 0, 1024 * sizeof(wchar_t));
|
||||||
|
|
||||||
|
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, (LPCWSTR)id.c_str(), 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD buffer = 1024;
|
||||||
|
DWORD vtype = REG_SZ;
|
||||||
|
if (RegQueryValueExW(hkey, L"Layout Text", NULL, &vtype, (LPBYTE)layout_text, &buffer) == ERROR_SUCCESS) {
|
||||||
|
ret = String(layout_text);
|
||||||
|
}
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
String OS_Windows::keyboard_get_layout_name(int p_index) const {
|
||||||
|
int layout_count = GetKeyboardLayoutList(0, NULL);
|
||||||
|
|
||||||
|
ERR_FAIL_INDEX_V(p_index, layout_count, "");
|
||||||
|
|
||||||
|
HKL *layouts = (HKL *)memalloc(layout_count * sizeof(HKL));
|
||||||
|
GetKeyboardLayoutList(layout_count, layouts);
|
||||||
|
|
||||||
|
String ret = _get_full_layout_name_from_registry(layouts[p_index]); // Try reading full name from Windows registry, fallback to locale name if failed (e.g. on Wine).
|
||||||
|
if (ret == String()) {
|
||||||
|
wchar_t buf[LOCALE_NAME_MAX_LENGTH];
|
||||||
|
memset(buf, 0, LOCALE_NAME_MAX_LENGTH * sizeof(wchar_t));
|
||||||
|
LCIDToLocaleName(MAKELCID(LOWORD(layouts[p_index]), SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0);
|
||||||
|
|
||||||
|
wchar_t name[1024];
|
||||||
|
memset(name, 0, 1024 * sizeof(wchar_t));
|
||||||
|
GetLocaleInfoEx(buf, LOCALE_SLOCALIZEDDISPLAYNAME, (LPWSTR)&name, 1024);
|
||||||
|
|
||||||
|
ret = String(name);
|
||||||
|
}
|
||||||
|
memfree(layouts);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void OS_Windows::release_rendering_thread() {
|
void OS_Windows::release_rendering_thread() {
|
||||||
|
|
||||||
gl_context->release_current();
|
gl_context->release_current();
|
||||||
|
|
|
@ -516,6 +516,11 @@ public:
|
||||||
virtual int get_processor_count() const;
|
virtual int get_processor_count() const;
|
||||||
|
|
||||||
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
|
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
|
||||||
|
virtual int keyboard_get_layout_count() const;
|
||||||
|
virtual int keyboard_get_current_layout() const;
|
||||||
|
virtual void keyboard_set_current_layout(int p_index);
|
||||||
|
virtual String keyboard_get_layout_language(int p_index) const;
|
||||||
|
virtual String keyboard_get_layout_name(int p_index) const;
|
||||||
|
|
||||||
virtual void enable_for_stealing_focus(ProcessID pid);
|
virtual void enable_for_stealing_focus(ProcessID pid);
|
||||||
virtual void move_window_to_foreground();
|
virtual void move_window_to_foreground();
|
||||||
|
|
|
@ -3474,6 +3474,108 @@ OS::LatinKeyboardVariant OS_X11::get_latin_keyboard_variant() const {
|
||||||
return LATIN_KEYBOARD_QWERTY;
|
return LATIN_KEYBOARD_QWERTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int OS_X11::keyboard_get_layout_count() const {
|
||||||
|
int _group_count = 0;
|
||||||
|
XkbDescRec *kbd = XkbAllocKeyboard();
|
||||||
|
if (kbd) {
|
||||||
|
kbd->dpy = x11_display;
|
||||||
|
XkbGetControls(x11_display, XkbAllControlsMask, kbd);
|
||||||
|
XkbGetNames(x11_display, XkbSymbolsNameMask, kbd);
|
||||||
|
|
||||||
|
const Atom *groups = kbd->names->groups;
|
||||||
|
if (kbd->ctrls != NULL) {
|
||||||
|
_group_count = kbd->ctrls->num_groups;
|
||||||
|
} else {
|
||||||
|
while (_group_count < XkbNumKbdGroups && groups[_group_count] != None) {
|
||||||
|
_group_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XkbFreeKeyboard(kbd, 0, true);
|
||||||
|
}
|
||||||
|
return _group_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OS_X11::keyboard_get_current_layout() const {
|
||||||
|
XkbStateRec state;
|
||||||
|
XkbGetState(x11_display, XkbUseCoreKbd, &state);
|
||||||
|
return state.group;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OS_X11::keyboard_set_current_layout(int p_index) {
|
||||||
|
ERR_FAIL_INDEX(p_index, keyboard_get_layout_count());
|
||||||
|
XkbLockGroup(x11_display, XkbUseCoreKbd, p_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
String OS_X11::keyboard_get_layout_language(int p_index) const {
|
||||||
|
String ret;
|
||||||
|
XkbDescRec *kbd = XkbAllocKeyboard();
|
||||||
|
if (kbd) {
|
||||||
|
kbd->dpy = x11_display;
|
||||||
|
XkbGetControls(x11_display, XkbAllControlsMask, kbd);
|
||||||
|
XkbGetNames(x11_display, XkbSymbolsNameMask, kbd);
|
||||||
|
XkbGetNames(x11_display, XkbGroupNamesMask, kbd);
|
||||||
|
|
||||||
|
int _group_count = 0;
|
||||||
|
const Atom *groups = kbd->names->groups;
|
||||||
|
if (kbd->ctrls != NULL) {
|
||||||
|
_group_count = kbd->ctrls->num_groups;
|
||||||
|
} else {
|
||||||
|
while (_group_count < XkbNumKbdGroups && groups[_group_count] != None) {
|
||||||
|
_group_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Atom names = kbd->names->symbols;
|
||||||
|
if (names != None) {
|
||||||
|
char *name = XGetAtomName(x11_display, names);
|
||||||
|
Vector<String> info = String(name).split("+");
|
||||||
|
if (p_index >= 0 && p_index < _group_count) {
|
||||||
|
if (p_index + 1 < info.size()) {
|
||||||
|
ret = info[p_index + 1]; // Skip "pc" at the start and "inet"/"group" at the end of symbols.
|
||||||
|
} else {
|
||||||
|
ret = "en"; // No symbol for layout fallback to "en".
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ERR_PRINT("Index " + itos(p_index) + "is out of bounds (" + itos(_group_count) + ").");
|
||||||
|
}
|
||||||
|
XFree(name);
|
||||||
|
}
|
||||||
|
XkbFreeKeyboard(kbd, 0, true);
|
||||||
|
}
|
||||||
|
return ret.substr(0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
String OS_X11::keyboard_get_layout_name(int p_index) const {
|
||||||
|
String ret;
|
||||||
|
XkbDescRec *kbd = XkbAllocKeyboard();
|
||||||
|
if (kbd) {
|
||||||
|
kbd->dpy = x11_display;
|
||||||
|
XkbGetControls(x11_display, XkbAllControlsMask, kbd);
|
||||||
|
XkbGetNames(x11_display, XkbSymbolsNameMask, kbd);
|
||||||
|
XkbGetNames(x11_display, XkbGroupNamesMask, kbd);
|
||||||
|
|
||||||
|
int _group_count = 0;
|
||||||
|
const Atom *groups = kbd->names->groups;
|
||||||
|
if (kbd->ctrls != NULL) {
|
||||||
|
_group_count = kbd->ctrls->num_groups;
|
||||||
|
} else {
|
||||||
|
while (_group_count < XkbNumKbdGroups && groups[_group_count] != None) {
|
||||||
|
_group_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_index >= 0 && p_index < _group_count) {
|
||||||
|
char *full_name = XGetAtomName(x11_display, groups[p_index]);
|
||||||
|
ret.parse_utf8(full_name);
|
||||||
|
XFree(full_name);
|
||||||
|
} else {
|
||||||
|
ERR_PRINT("Index " + itos(p_index) + "is out of bounds (" + itos(_group_count) + ").");
|
||||||
|
}
|
||||||
|
XkbFreeKeyboard(kbd, 0, true);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void OS_X11::update_real_mouse_position() {
|
void OS_X11::update_real_mouse_position() {
|
||||||
Window root_return, child_return;
|
Window root_return, child_return;
|
||||||
int root_x, root_y, win_x, win_y;
|
int root_x, root_y, win_x, win_y;
|
||||||
|
|
|
@ -329,6 +329,11 @@ public:
|
||||||
virtual Error move_to_trash(const String &p_path);
|
virtual Error move_to_trash(const String &p_path);
|
||||||
|
|
||||||
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
|
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
|
||||||
|
virtual int keyboard_get_layout_count() const;
|
||||||
|
virtual int keyboard_get_current_layout() const;
|
||||||
|
virtual void keyboard_set_current_layout(int p_index);
|
||||||
|
virtual String keyboard_get_layout_language(int p_index) const;
|
||||||
|
virtual String keyboard_get_layout_name(int p_index) const;
|
||||||
|
|
||||||
void update_real_mouse_position();
|
void update_real_mouse_position();
|
||||||
OS_X11();
|
OS_X11();
|
||||||
|
|
Loading…
Reference in a new issue