Skip to content

Commit

Permalink
Merge pull request #39457 from bruvzg/kbd_layouts
Browse files Browse the repository at this point in the history
Add keyboard layout enumeration / set / get functions.
  • Loading branch information
akien-mga authored Jun 15, 2020
2 parents 2a96823 + 92352b1 commit d3c10e8
Show file tree
Hide file tree
Showing 9 changed files with 363 additions and 179 deletions.
66 changes: 46 additions & 20 deletions doc/classes/DisplayServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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">
Expand Down
119 changes: 94 additions & 25 deletions platform/linuxbsd/display_server_x11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_

XkbDescRec *xkbdesc = XkbAllocKeyboard();
ERR_FAIL_COND_V(!xkbdesc, LATIN_KEYBOARD_QWERTY);
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);

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;
}

XkbGetNames(x11_display, XkbSymbolsNameMask, xkbdesc);
ERR_FAIL_COND_V(!xkbdesc->names, LATIN_KEYBOARD_QWERTY);
ERR_FAIL_COND_V(!xkbdesc->names->symbols, LATIN_KEYBOARD_QWERTY);
int DisplayServerX11::keyboard_get_current_layout() const {
XkbStateRec state;
XkbGetState(x11_display, XkbUseCoreKbd, &state);
return state.group;
}

char *layout = XGetAtomName(x11_display, xkbdesc->names->symbols);
ERR_FAIL_COND_V(!layout, LATIN_KEYBOARD_QWERTY);
void DisplayServerX11::keyboard_set_current_layout(int p_index) {
ERR_FAIL_INDEX(p_index, keyboard_get_layout_count());
XkbLockGroup(x11_display, XkbUseCoreKbd, p_index);
}

Vector<String> info = String(layout).split("+");
ERR_FAIL_INDEX_V(1, info.size(), LATIN_KEYBOARD_QWERTY);
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++;
}
}

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;
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++;
}
}

return LATIN_KEYBOARD_QWERTY;
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) {
Expand Down
6 changes: 5 additions & 1 deletion platform/linuxbsd/display_server_x11.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,11 @@ class DisplayServerX11 : public DisplayServer {
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();

Expand Down
6 changes: 5 additions & 1 deletion platform/osx/display_server_osx.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,11 @@ class DisplayServerOSX : public DisplayServer {

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();
Expand Down
Loading

0 comments on commit d3c10e8

Please sign in to comment.