Add keyboard layout enumeration / set / get functions (macOS, Windows, Linux/X11), remove latin variant function.
This commit is contained in:
parent
84abf5a979
commit
92352b1c23
9 changed files with 373 additions and 189 deletions
|
@ -127,12 +127,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_latin_keyboard_variant" qualifiers="const">
|
||||
<return type="int" enum="DisplayServer.LatinKeyboardVariant">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_name" qualifiers="const">
|
||||
<return type="String">
|
||||
</return>
|
||||
|
@ -389,6 +383,52 @@
|
|||
<description>
|
||||
</description>
|
||||
</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="mouse_get_absolute_position" qualifiers="const">
|
||||
<return type="Vector2i">
|
||||
</return>
|
||||
|
@ -1021,20 +1061,6 @@
|
|||
</constant>
|
||||
<constant name="WINDOW_FLAG_MAX" value="5" enum="WindowFlags">
|
||||
</constant>
|
||||
<constant name="LATIN_KEYBOARD_QWERTY" value="0" enum="LatinKeyboardVariant">
|
||||
</constant>
|
||||
<constant name="LATIN_KEYBOARD_QWERTZ" value="1" enum="LatinKeyboardVariant">
|
||||
</constant>
|
||||
<constant name="LATIN_KEYBOARD_AZERTY" value="2" enum="LatinKeyboardVariant">
|
||||
</constant>
|
||||
<constant name="LATIN_KEYBOARD_QZERTY" value="3" enum="LatinKeyboardVariant">
|
||||
</constant>
|
||||
<constant name="LATIN_KEYBOARD_DVORAK" value="4" enum="LatinKeyboardVariant">
|
||||
</constant>
|
||||
<constant name="LATIN_KEYBOARD_NEO" value="5" enum="LatinKeyboardVariant">
|
||||
</constant>
|
||||
<constant name="LATIN_KEYBOARD_COLEMAK" value="6" enum="LatinKeyboardVariant">
|
||||
</constant>
|
||||
<constant name="WINDOW_EVENT_MOUSE_ENTER" value="0" enum="WindowEvent">
|
||||
</constant>
|
||||
<constant name="WINDOW_EVENT_MOUSE_EXIT" value="1" enum="WindowEvent">
|
||||
|
|
|
@ -1846,37 +1846,106 @@ void DisplayServerX11::cursor_set_custom_image(const RES &p_cursor, CursorShape
|
|||
}
|
||||
}
|
||||
|
||||
DisplayServerX11::LatinKeyboardVariant DisplayServerX11::get_latin_keyboard_variant() const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
int DisplayServerX11::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);
|
||||
|
||||
XkbDescRec *xkbdesc = XkbAllocKeyboard();
|
||||
ERR_FAIL_COND_V(!xkbdesc, LATIN_KEYBOARD_QWERTY);
|
||||
|
||||
XkbGetNames(x11_display, XkbSymbolsNameMask, xkbdesc);
|
||||
ERR_FAIL_COND_V(!xkbdesc->names, LATIN_KEYBOARD_QWERTY);
|
||||
ERR_FAIL_COND_V(!xkbdesc->names->symbols, LATIN_KEYBOARD_QWERTY);
|
||||
|
||||
char *layout = XGetAtomName(x11_display, xkbdesc->names->symbols);
|
||||
ERR_FAIL_COND_V(!layout, LATIN_KEYBOARD_QWERTY);
|
||||
|
||||
Vector<String> info = String(layout).split("+");
|
||||
ERR_FAIL_INDEX_V(1, info.size(), LATIN_KEYBOARD_QWERTY);
|
||||
|
||||
if (info[1].find("colemak") != -1) {
|
||||
return LATIN_KEYBOARD_COLEMAK;
|
||||
} else if (info[1].find("qwertz") != -1) {
|
||||
return LATIN_KEYBOARD_QWERTZ;
|
||||
} else if (info[1].find("azerty") != -1) {
|
||||
return LATIN_KEYBOARD_AZERTY;
|
||||
} else if (info[1].find("qzerty") != -1) {
|
||||
return LATIN_KEYBOARD_QZERTY;
|
||||
} else if (info[1].find("dvorak") != -1) {
|
||||
return LATIN_KEYBOARD_DVORAK;
|
||||
} else if (info[1].find("neo") != -1) {
|
||||
return LATIN_KEYBOARD_NEO;
|
||||
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;
|
||||
}
|
||||
|
||||
return LATIN_KEYBOARD_QWERTY;
|
||||
int DisplayServerX11::keyboard_get_current_layout() const {
|
||||
XkbStateRec state;
|
||||
XkbGetState(x11_display, XkbUseCoreKbd, &state);
|
||||
return state.group;
|
||||
}
|
||||
|
||||
void DisplayServerX11::keyboard_set_current_layout(int p_index) {
|
||||
ERR_FAIL_INDEX(p_index, keyboard_get_layout_count());
|
||||
XkbLockGroup(x11_display, XkbUseCoreKbd, p_index);
|
||||
}
|
||||
|
||||
String DisplayServerX11::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 DisplayServerX11::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;
|
||||
}
|
||||
|
||||
DisplayServerX11::Property DisplayServerX11::_read_property(Display *p_display, Window p_window, Atom p_property) {
|
||||
|
|
|
@ -327,7 +327,11 @@ public:
|
|||
virtual CursorShape cursor_get_shape() const;
|
||||
virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
|
||||
|
||||
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 process_events();
|
||||
|
||||
|
|
|
@ -281,7 +281,11 @@ public:
|
|||
|
||||
virtual bool get_swap_ok_cancel();
|
||||
|
||||
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 process_events();
|
||||
virtual void force_process_and_drop_events();
|
||||
|
|
|
@ -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 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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
UInt32 keysDown = 0;
|
||||
UniChar chars[4];
|
||||
UniCharCount realLength;
|
||||
|
||||
err = UCKeyTranslate(keyboardLayout,
|
||||
keyCode[i],
|
||||
kUCKeyActionDisplay,
|
||||
0,
|
||||
LMGetKbdType(),
|
||||
kUCKeyTranslateNoDeadKeysBit,
|
||||
&keysDown,
|
||||
sizeof(chars) / sizeof(chars[0]),
|
||||
&realLength,
|
||||
chars);
|
||||
|
||||
if (err != noErr) {
|
||||
CFRelease(output);
|
||||
return nil;
|
||||
if ([name isEqualToString:cur_name]) {
|
||||
current_layout = kbd_layouts.size() - 1;
|
||||
}
|
||||
}
|
||||
[list_ime release];
|
||||
|
||||
CFStringAppendCharacters(output, chars, 1);
|
||||
// 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]);
|
||||
|
||||
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 ([name isEqualToString:cur_name]) {
|
||||
current_layout = kbd_layouts.size() - 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) {
|
||||
layout = LATIN_KEYBOARD_QWERTY;
|
||||
_update_keyboard_layouts();
|
||||
}
|
||||
return 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
[test release];
|
||||
|
||||
keyboard_layout_dirty = false;
|
||||
return layout;
|
||||
void DisplayServerOSX::keyboard_set_current_layout(int p_index) {
|
||||
if (keyboard_layout_dirty) {
|
||||
_update_keyboard_layouts();
|
||||
}
|
||||
|
||||
return layout;
|
||||
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 DisplayServerOSX::keyboard_get_current_layout() const {
|
||||
if (keyboard_layout_dirty) {
|
||||
_update_keyboard_layouts();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), "");
|
||||
return kbd_layouts[p_index].name;
|
||||
}
|
||||
|
||||
void DisplayServerOSX::_push_input(const Ref<InputEvent> &p_event) {
|
||||
|
|
|
@ -1372,70 +1372,99 @@ void DisplayServerWindows::enable_for_stealing_focus(OS::ProcessID pid) {
|
|||
AllowSetForegroundWindow(pid);
|
||||
}
|
||||
|
||||
DisplayServer::LatinKeyboardVariant DisplayServerWindows::get_latin_keyboard_variant() const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
int DisplayServerWindows::keyboard_get_layout_count() const {
|
||||
return GetKeyboardLayoutList(0, NULL);
|
||||
}
|
||||
|
||||
unsigned long azerty[] = {
|
||||
0x00020401, // Arabic (102) AZERTY
|
||||
0x0001080c, // Belgian (Comma)
|
||||
0x0000080c, // Belgian French
|
||||
0x0000040c, // French
|
||||
0 // <--- STOP MARK
|
||||
};
|
||||
unsigned long qwertz[] = {
|
||||
0x0000041a, // Croation
|
||||
0x00000405, // Czech
|
||||
0x00000407, // German
|
||||
0x00010407, // German (IBM)
|
||||
0x0000040e, // Hungarian
|
||||
0x0000046e, // Luxembourgish
|
||||
0x00010415, // Polish (214)
|
||||
0x00000418, // Romanian (Legacy)
|
||||
0x0000081a, // Serbian (Latin)
|
||||
0x0000041b, // Slovak
|
||||
0x00000424, // Slovenian
|
||||
0x0001042e, // Sorbian Extended
|
||||
0x0002042e, // Sorbian Standard
|
||||
0x0000042e, // Sorbian Standard (Legacy)
|
||||
0x0000100c, // Swiss French
|
||||
0x00000807, // Swiss German
|
||||
0 // <--- STOP MARK
|
||||
};
|
||||
unsigned long dvorak[] = {
|
||||
0x00010409, // US-Dvorak
|
||||
0x00030409, // US-Dvorak for left hand
|
||||
0x00040409, // US-Dvorak for right hand
|
||||
0 // <--- STOP MARK
|
||||
};
|
||||
int DisplayServerWindows::keyboard_get_current_layout() const {
|
||||
HKL cur_layout = GetKeyboardLayout(0);
|
||||
|
||||
char name[KL_NAMELENGTH + 1];
|
||||
name[0] = 0;
|
||||
GetKeyboardLayoutNameA(name);
|
||||
int layout_count = GetKeyboardLayoutList(0, NULL);
|
||||
HKL *layouts = (HKL *)memalloc(layout_count * sizeof(HKL));
|
||||
GetKeyboardLayoutList(layout_count, layouts);
|
||||
|
||||
unsigned long hex = strtoul(name, nullptr, 16);
|
||||
for (int i = 0; i < layout_count; i++) {
|
||||
if (cur_layout == layouts[i]) {
|
||||
memfree(layouts);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
memfree(layouts);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while (azerty[i] != 0) {
|
||||
if (azerty[i] == hex)
|
||||
return LATIN_KEYBOARD_AZERTY;
|
||||
i++;
|
||||
void DisplayServerWindows::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 DisplayServerWindows::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;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (qwertz[i] != 0) {
|
||||
if (qwertz[i] == hex)
|
||||
return LATIN_KEYBOARD_QWERTZ;
|
||||
i++;
|
||||
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;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (dvorak[i] != 0) {
|
||||
if (dvorak[i] == hex)
|
||||
return LATIN_KEYBOARD_DVORAK;
|
||||
i++;
|
||||
String DisplayServerWindows::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 LATIN_KEYBOARD_QWERTY;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DisplayServerWindows::process_events() {
|
||||
|
|
|
@ -523,7 +523,11 @@ public:
|
|||
|
||||
virtual void enable_for_stealing_focus(OS::ProcessID pid);
|
||||
|
||||
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 process_events();
|
||||
|
||||
|
|
|
@ -276,8 +276,23 @@ Error DisplayServer::dialog_input_text(String p_title, String p_description, Str
|
|||
return OK;
|
||||
}
|
||||
|
||||
DisplayServer::LatinKeyboardVariant DisplayServer::get_latin_keyboard_variant() const {
|
||||
return LATIN_KEYBOARD_QWERTY;
|
||||
int DisplayServer::keyboard_get_layout_count() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DisplayServer::keyboard_get_current_layout() const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void DisplayServer::keyboard_set_current_layout(int p_index) {
|
||||
}
|
||||
|
||||
String DisplayServer::keyboard_get_layout_language(int p_index) const {
|
||||
return "";
|
||||
}
|
||||
|
||||
String DisplayServer::keyboard_get_layout_name(int p_index) const {
|
||||
return "Not supported";
|
||||
}
|
||||
|
||||
void DisplayServer::force_process_and_drop_events() {
|
||||
|
@ -461,7 +476,11 @@ void DisplayServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("dialog_show", "title", "description", "buttons", "callback"), &DisplayServer::dialog_show);
|
||||
ClassDB::bind_method(D_METHOD("dialog_input_text", "title", "description", "existing_text", "callback"), &DisplayServer::dialog_input_text);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_latin_keyboard_variant"), &DisplayServer::get_latin_keyboard_variant);
|
||||
ClassDB::bind_method(D_METHOD("keyboard_get_layout_count"), &DisplayServer::keyboard_get_layout_count);
|
||||
ClassDB::bind_method(D_METHOD("keyboard_get_current_layout"), &DisplayServer::keyboard_get_current_layout);
|
||||
ClassDB::bind_method(D_METHOD("keyboard_set_current_layout", "index"), &DisplayServer::keyboard_set_current_layout);
|
||||
ClassDB::bind_method(D_METHOD("keyboard_get_layout_language", "index"), &DisplayServer::keyboard_get_layout_language);
|
||||
ClassDB::bind_method(D_METHOD("keyboard_get_layout_name", "index"), &DisplayServer::keyboard_get_layout_name);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("process_events"), &DisplayServer::process_events);
|
||||
ClassDB::bind_method(D_METHOD("force_process_and_drop_events"), &DisplayServer::force_process_and_drop_events);
|
||||
|
@ -543,14 +562,6 @@ void DisplayServer::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(WINDOW_FLAG_NO_FOCUS);
|
||||
BIND_ENUM_CONSTANT(WINDOW_FLAG_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(LATIN_KEYBOARD_QWERTY);
|
||||
BIND_ENUM_CONSTANT(LATIN_KEYBOARD_QWERTZ);
|
||||
BIND_ENUM_CONSTANT(LATIN_KEYBOARD_AZERTY);
|
||||
BIND_ENUM_CONSTANT(LATIN_KEYBOARD_QZERTY);
|
||||
BIND_ENUM_CONSTANT(LATIN_KEYBOARD_DVORAK);
|
||||
BIND_ENUM_CONSTANT(LATIN_KEYBOARD_NEO);
|
||||
BIND_ENUM_CONSTANT(LATIN_KEYBOARD_COLEMAK);
|
||||
|
||||
BIND_ENUM_CONSTANT(WINDOW_EVENT_MOUSE_ENTER);
|
||||
BIND_ENUM_CONSTANT(WINDOW_EVENT_MOUSE_EXIT);
|
||||
BIND_ENUM_CONSTANT(WINDOW_EVENT_FOCUS_IN);
|
||||
|
|
|
@ -324,17 +324,11 @@ public:
|
|||
virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback);
|
||||
virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback);
|
||||
|
||||
enum LatinKeyboardVariant {
|
||||
LATIN_KEYBOARD_QWERTY,
|
||||
LATIN_KEYBOARD_QWERTZ,
|
||||
LATIN_KEYBOARD_AZERTY,
|
||||
LATIN_KEYBOARD_QZERTY,
|
||||
LATIN_KEYBOARD_DVORAK,
|
||||
LATIN_KEYBOARD_NEO,
|
||||
LATIN_KEYBOARD_COLEMAK,
|
||||
};
|
||||
|
||||
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 process_events() = 0;
|
||||
|
||||
|
@ -384,6 +378,5 @@ VARIANT_ENUM_CAST(DisplayServer::ScreenOrientation)
|
|||
VARIANT_ENUM_CAST(DisplayServer::WindowMode)
|
||||
VARIANT_ENUM_CAST(DisplayServer::WindowFlags)
|
||||
VARIANT_ENUM_CAST(DisplayServer::CursorShape)
|
||||
VARIANT_ENUM_CAST(DisplayServer::LatinKeyboardVariant)
|
||||
|
||||
#endif // DISPLAY_SERVER_H
|
||||
|
|
Loading…
Reference in a new issue