You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-15 13:51:40 +00:00
Allow for mapping keycodes to current layout
This commit is contained in:
@@ -276,6 +276,14 @@
|
|||||||
[b]Note:[/b] This method is implemented on Linux, macOS and Windows.
|
[b]Note:[/b] This method is implemented on Linux, macOS and Windows.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="keyboard_get_keycode_from_physical" qualifiers="const">
|
||||||
|
<return type="int" enum="Key" />
|
||||||
|
<argument index="0" name="keycode" type="int" enum="Key" />
|
||||||
|
<description>
|
||||||
|
Converts a physical (US QWERTY) [code]keycode[/code] to one in the active keyboard layout.
|
||||||
|
[b]Note:[/b] This method is implemented on Linux, macOS and Windows.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="keyboard_get_layout_count" qualifiers="const">
|
<method name="keyboard_get_layout_count" qualifiers="const">
|
||||||
<return type="int" />
|
<return type="int" />
|
||||||
<description>
|
<description>
|
||||||
|
|||||||
@@ -2068,6 +2068,24 @@ String DisplayServerX11::keyboard_get_layout_name(int p_index) const {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Key DisplayServerX11::keyboard_get_keycode_from_physical(Key p_keycode) const {
|
||||||
|
unsigned int modifiers = p_keycode & KEY_MODIFIER_MASK;
|
||||||
|
unsigned int keycode_no_mod = p_keycode & KEY_CODE_MASK;
|
||||||
|
unsigned int xkeycode = KeyMappingX11::get_xlibcode((Key)keycode_no_mod);
|
||||||
|
KeySym xkeysym = XkbKeycodeToKeysym(x11_display, xkeycode, 0, 0);
|
||||||
|
if (xkeysym >= 'a' && xkeysym <= 'z') {
|
||||||
|
xkeysym -= ('a' - 'A');
|
||||||
|
}
|
||||||
|
|
||||||
|
Key key = KeyMappingX11::get_keycode(xkeysym);
|
||||||
|
// If not found, fallback to QWERTY.
|
||||||
|
// This should match the behavior of the event pump
|
||||||
|
if (key == KEY_NONE) {
|
||||||
|
return p_keycode;
|
||||||
|
}
|
||||||
|
return (Key)(key | modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
DisplayServerX11::Property DisplayServerX11::_read_property(Display *p_display, Window p_window, Atom p_property) {
|
DisplayServerX11::Property DisplayServerX11::_read_property(Display *p_display, Window p_window, Atom p_property) {
|
||||||
Atom actual_type = None;
|
Atom actual_type = None;
|
||||||
int actual_format = 0;
|
int actual_format = 0;
|
||||||
|
|||||||
@@ -372,6 +372,7 @@ public:
|
|||||||
virtual void keyboard_set_current_layout(int p_index) override;
|
virtual void keyboard_set_current_layout(int p_index) override;
|
||||||
virtual String keyboard_get_layout_language(int p_index) const override;
|
virtual String keyboard_get_layout_language(int p_index) const override;
|
||||||
virtual String keyboard_get_layout_name(int p_index) const override;
|
virtual String keyboard_get_layout_name(int p_index) const override;
|
||||||
|
virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const override;
|
||||||
|
|
||||||
virtual void process_events() override;
|
virtual void process_events() override;
|
||||||
|
|
||||||
|
|||||||
@@ -309,6 +309,18 @@ unsigned int KeyMappingX11::get_scancode(unsigned int p_code) {
|
|||||||
return keycode;
|
return keycode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int KeyMappingX11::get_xlibcode(unsigned int p_keysym) {
|
||||||
|
unsigned int code = 0;
|
||||||
|
for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
|
||||||
|
if (_scancode_to_keycode[i].keysym == p_keysym) {
|
||||||
|
code = _scancode_to_keycode[i].keycode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
Key KeyMappingX11::get_keycode(KeySym p_keysym) {
|
Key KeyMappingX11::get_keycode(KeySym p_keysym) {
|
||||||
// kinda bruteforce.. could optimize.
|
// kinda bruteforce.. could optimize.
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ class KeyMappingX11 {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static Key get_keycode(KeySym p_keysym);
|
static Key get_keycode(KeySym p_keysym);
|
||||||
|
static unsigned int get_xlibcode(unsigned int p_keysym);
|
||||||
static unsigned int get_scancode(unsigned int p_code);
|
static unsigned int get_scancode(unsigned int p_code);
|
||||||
static KeySym get_keysym(Key p_code);
|
static KeySym get_keysym(Key p_code);
|
||||||
static unsigned int get_unicode_from_keysym(KeySym p_keysym);
|
static unsigned int get_unicode_from_keysym(KeySym p_keysym);
|
||||||
|
|||||||
@@ -305,6 +305,7 @@ public:
|
|||||||
virtual void keyboard_set_current_layout(int p_index) override;
|
virtual void keyboard_set_current_layout(int p_index) override;
|
||||||
virtual String keyboard_get_layout_language(int p_index) const override;
|
virtual String keyboard_get_layout_language(int p_index) const override;
|
||||||
virtual String keyboard_get_layout_name(int p_index) const override;
|
virtual String keyboard_get_layout_name(int p_index) const override;
|
||||||
|
virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const override;
|
||||||
|
|
||||||
virtual void process_events() override;
|
virtual void process_events() override;
|
||||||
virtual void force_process_and_drop_events() override;
|
virtual void force_process_and_drop_events() override;
|
||||||
|
|||||||
@@ -930,11 +930,8 @@ static bool isNumpadKey(unsigned int key) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translates a OS X keycode to a Godot keycode
|
|
||||||
//
|
|
||||||
static Key translateKey(unsigned int key) {
|
|
||||||
// Keyboard symbol translation table
|
// Keyboard symbol translation table
|
||||||
static const Key table[128] = {
|
static const Key _osx_to_godot_table[128] = {
|
||||||
/* 00 */ KEY_A,
|
/* 00 */ KEY_A,
|
||||||
/* 01 */ KEY_S,
|
/* 01 */ KEY_S,
|
||||||
/* 02 */ KEY_D,
|
/* 02 */ KEY_D,
|
||||||
@@ -1065,11 +1062,23 @@ static Key translateKey(unsigned int key) {
|
|||||||
/* 7f */ KEY_UNKNOWN,
|
/* 7f */ KEY_UNKNOWN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Translates a OS X keycode to a Godot keycode
|
||||||
|
static Key translateKey(unsigned int key) {
|
||||||
if (key >= 128) {
|
if (key >= 128) {
|
||||||
return KEY_UNKNOWN;
|
return KEY_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
return table[key];
|
return _osx_to_godot_table[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translates a Godot keycode back to a OSX keycode
|
||||||
|
static unsigned int unmapKey(Key key) {
|
||||||
|
for (int i = 0; i <= 126; i++) {
|
||||||
|
if (_osx_to_godot_table[i] == key) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 127;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct _KeyCodeMap {
|
struct _KeyCodeMap {
|
||||||
@@ -3200,6 +3209,17 @@ String DisplayServerOSX::keyboard_get_layout_name(int p_index) const {
|
|||||||
return kbd_layouts[p_index].name;
|
return kbd_layouts[p_index].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Key DisplayServerOSX::keyboard_get_keycode_from_physical(Key p_keycode) const {
|
||||||
|
if (p_keycode == KEY_PAUSE) {
|
||||||
|
return p_keycode;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int modifiers = p_keycode & KEY_MODIFIER_MASK;
|
||||||
|
unsigned int keycode_no_mod = p_keycode & KEY_CODE_MASK;
|
||||||
|
unsigned int osx_keycode = unmapKey((Key)keycode_no_mod);
|
||||||
|
return (Key)(remapKey(osx_keycode, 0) | modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
void DisplayServerOSX::_push_input(const Ref<InputEvent> &p_event) {
|
void DisplayServerOSX::_push_input(const Ref<InputEvent> &p_event) {
|
||||||
Ref<InputEvent> ev = p_event;
|
Ref<InputEvent> ev = p_event;
|
||||||
Input::get_singleton()->parse_input_event(ev);
|
Input::get_singleton()->parse_input_event(ev);
|
||||||
|
|||||||
@@ -1476,6 +1476,42 @@ String DisplayServerWindows::keyboard_get_layout_language(int p_index) const {
|
|||||||
return String::utf16((const char16_t *)buf).substr(0, 2);
|
return String::utf16((const char16_t *)buf).substr(0, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Key DisplayServerWindows::keyboard_get_keycode_from_physical(Key p_keycode) const {
|
||||||
|
unsigned int modifiers = p_keycode & KEY_MODIFIER_MASK;
|
||||||
|
Key keycode_no_mod = (Key)(p_keycode & KEY_CODE_MASK);
|
||||||
|
|
||||||
|
if (keycode_no_mod == KEY_PRINT ||
|
||||||
|
keycode_no_mod == KEY_KP_ADD ||
|
||||||
|
keycode_no_mod == KEY_KP_5 ||
|
||||||
|
(keycode_no_mod >= KEY_0 && keycode_no_mod <= KEY_9)) {
|
||||||
|
return p_keycode;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int scancode = KeyMappingWindows::get_scancode(keycode_no_mod);
|
||||||
|
if (scancode == 0) {
|
||||||
|
return p_keycode;
|
||||||
|
}
|
||||||
|
|
||||||
|
HKL current_layout = GetKeyboardLayout(0);
|
||||||
|
UINT vk = MapVirtualKeyEx(scancode, MAPVK_VSC_TO_VK, current_layout);
|
||||||
|
if (vk == 0) {
|
||||||
|
return p_keycode;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT char_code = MapVirtualKeyEx(vk, MAPVK_VK_TO_CHAR, current_layout) & 0x7FFF;
|
||||||
|
// Unlike a similar Linux/BSD check which matches full Latin-1 range,
|
||||||
|
// we limit these to ASCII to fix some layouts, including Arabic ones
|
||||||
|
if (char_code >= 32 && char_code <= 127) {
|
||||||
|
// Godot uses 'braces' instead of 'brackets'
|
||||||
|
if (char_code == KEY_BRACKETLEFT || char_code == KEY_BRACKETRIGHT) {
|
||||||
|
char_code += 32;
|
||||||
|
}
|
||||||
|
return (Key)(char_code | modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Key)(KeyMappingWindows::get_keysym(vk) | modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
String _get_full_layout_name_from_registry(HKL p_layout) {
|
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 id = "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\" + String::num_int64((int64_t)p_layout, 16, false).lpad(8, "0");
|
||||||
String ret;
|
String ret;
|
||||||
|
|||||||
@@ -543,6 +543,7 @@ public:
|
|||||||
virtual void keyboard_set_current_layout(int p_index) override;
|
virtual void keyboard_set_current_layout(int p_index) override;
|
||||||
virtual String keyboard_get_layout_language(int p_index) const override;
|
virtual String keyboard_get_layout_language(int p_index) const override;
|
||||||
virtual String keyboard_get_layout_name(int p_index) const override;
|
virtual String keyboard_get_layout_name(int p_index) const override;
|
||||||
|
virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const override;
|
||||||
|
|
||||||
virtual int tablet_get_driver_count() const override;
|
virtual int tablet_get_driver_count() const override;
|
||||||
virtual String tablet_get_driver_name(int p_driver) const override;
|
virtual String tablet_get_driver_name(int p_driver) const override;
|
||||||
|
|||||||
@@ -345,6 +345,16 @@ unsigned int KeyMappingWindows::get_keysym(unsigned int p_code) {
|
|||||||
return KEY_UNKNOWN;
|
return KEY_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int KeyMappingWindows::get_scancode(Key p_keycode) {
|
||||||
|
for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
|
||||||
|
if (_scancode_to_keycode[i].keysym == p_keycode) {
|
||||||
|
return _scancode_to_keycode[i].keycode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int KeyMappingWindows::get_scansym(unsigned int p_code, bool p_extended) {
|
unsigned int KeyMappingWindows::get_scansym(unsigned int p_code, bool p_extended) {
|
||||||
unsigned int keycode = KEY_UNKNOWN;
|
unsigned int keycode = KEY_UNKNOWN;
|
||||||
for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
|
for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class KeyMappingWindows {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static unsigned int get_keysym(unsigned int p_code);
|
static unsigned int get_keysym(unsigned int p_code);
|
||||||
|
static unsigned int get_scancode(Key p_keycode);
|
||||||
static unsigned int get_scansym(unsigned int p_code, bool p_extended);
|
static unsigned int get_scansym(unsigned int p_code, bool p_extended);
|
||||||
static bool is_extended_key(unsigned int p_code);
|
static bool is_extended_key(unsigned int p_code);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -285,6 +285,10 @@ String DisplayServer::keyboard_get_layout_name(int p_index) const {
|
|||||||
return "Not supported";
|
return "Not supported";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Key DisplayServer::keyboard_get_keycode_from_physical(Key p_keycode) const {
|
||||||
|
ERR_FAIL_V_MSG(p_keycode, "Not supported by this display server.");
|
||||||
|
}
|
||||||
|
|
||||||
void DisplayServer::force_process_and_drop_events() {
|
void DisplayServer::force_process_and_drop_events() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,6 +456,7 @@ void DisplayServer::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("keyboard_set_current_layout", "index"), &DisplayServer::keyboard_set_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_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("keyboard_get_layout_name", "index"), &DisplayServer::keyboard_get_layout_name);
|
||||||
|
ClassDB::bind_method(D_METHOD("keyboard_get_keycode_from_physical", "keycode"), &DisplayServer::keyboard_get_keycode_from_physical);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("process_events"), &DisplayServer::process_events);
|
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);
|
ClassDB::bind_method(D_METHOD("force_process_and_drop_events"), &DisplayServer::force_process_and_drop_events);
|
||||||
|
|||||||
@@ -343,6 +343,7 @@ public:
|
|||||||
virtual void keyboard_set_current_layout(int p_index);
|
virtual void keyboard_set_current_layout(int p_index);
|
||||||
virtual String keyboard_get_layout_language(int p_index) const;
|
virtual String keyboard_get_layout_language(int p_index) const;
|
||||||
virtual String keyboard_get_layout_name(int p_index) const;
|
virtual String keyboard_get_layout_name(int p_index) const;
|
||||||
|
virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const;
|
||||||
|
|
||||||
virtual int tablet_get_driver_count() const { return 1; };
|
virtual int tablet_get_driver_count() const { return 1; };
|
||||||
virtual String tablet_get_driver_name(int p_driver) const { return "default"; };
|
virtual String tablet_get_driver_name(int p_driver) const { return "default"; };
|
||||||
|
|||||||
Reference in New Issue
Block a user