Browse Source

Merge pull request #18020 from bruvzg/input_fix_non_latin_and_add_hw_scancodes

Fix non-latin layout scancodes on Linux, adds access to physical scancodes.
Rémi Verschelde 5 years ago
parent
commit
e2b66cacf7
78 changed files with 736 additions and 299 deletions
  1. 8 6
      core/bind/core_bind.cpp
  2. 3 3
      core/bind/core_bind.h
  3. 15 15
      core/input_map.cpp
  4. 1 1
      core/os/input.cpp
  5. 1 1
      core/os/input.h
  6. 59 17
      core/os/input_event.cpp
  7. 9 4
      core/os/input_event.h
  8. 15 15
      core/project_settings.cpp
  9. 2 2
      doc/classes/@GlobalScope.xml
  10. 2 2
      doc/classes/Input.xml
  11. 18 6
      doc/classes/InputEventKey.xml
  12. 2 2
      doc/classes/MainLoop.xml
  13. 7 7
      doc/classes/OS.xml
  14. 1 1
      editor/code_editor.cpp
  15. 4 4
      editor/create_dialog.cpp
  16. 1 1
      editor/editor_audio_buses.cpp
  17. 2 2
      editor/editor_help.cpp
  18. 1 1
      editor/editor_help_search.cpp
  19. 1 1
      editor/editor_layouts_dialog.cpp
  20. 1 1
      editor/editor_settings.cpp
  21. 1 1
      editor/icons/Keyboard.svg
  22. 1 0
      editor/icons/KeyboardPhysical.svg
  23. 3 3
      editor/plugins/abstract_polygon_2d_editor.cpp
  24. 1 1
      editor/plugins/animation_blend_space_1d_editor.cpp
  25. 1 1
      editor/plugins/animation_blend_space_2d_editor.cpp
  26. 1 1
      editor/plugins/animation_player_editor_plugin.cpp
  27. 1 1
      editor/plugins/animation_state_machine_editor.cpp
  28. 1 1
      editor/plugins/asset_library_editor_plugin.cpp
  29. 11 11
      editor/plugins/canvas_item_editor_plugin.cpp
  30. 1 1
      editor/plugins/curve_editor_plugin.cpp
  31. 4 4
      editor/plugins/script_editor_plugin.cpp
  32. 1 1
      editor/plugins/script_text_editor.cpp
  33. 1 1
      editor/plugins/shader_editor_plugin.cpp
  34. 4 4
      editor/plugins/spatial_editor_plugin.cpp
  35. 1 1
      editor/plugins/text_editor.cpp
  36. 9 9
      editor/plugins/tile_map_editor_plugin.cpp
  37. 4 4
      editor/plugins/visual_shader_editor_plugin.cpp
  38. 6 6
      editor/project_manager.cpp
  39. 45 10
      editor/project_settings_editor.cpp
  40. 2 0
      editor/project_settings_editor.h
  41. 1 1
      editor/property_selector.cpp
  42. 1 1
      editor/quick_open.cpp
  43. 4 4
      editor/settings_config_dialog.cpp
  44. 5 5
      main/input_default.cpp
  45. 1 1
      main/input_default.h
  46. 4 4
      modules/gridmap/grid_map_editor_plugin.cpp
  47. 1 1
      modules/visual_script/visual_script_editor.cpp
  48. 1 1
      modules/visual_script/visual_script_property_selector.cpp
  49. 2 2
      platform/android/java/lib/src/org/godotengine/godot/Godot.java
  50. 1 1
      platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
  51. 4 2
      platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
  52. 6 6
      platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java
  53. 9 8
      platform/android/java_godot_lib_jni.cpp
  54. 1 1
      platform/android/java_godot_lib_jni.h
  55. 5 3
      platform/haiku/haiku_direct_window.cpp
  56. 2 2
      platform/iphone/os_iphone.cpp
  57. 1 1
      platform/javascript/dom_keys.inc
  58. 4 3
      platform/javascript/os_javascript.cpp
  59. 2 1
      platform/osx/os_osx.h
  60. 23 13
      platform/osx/os_osx.mm
  61. 4 2
      platform/uwp/app.cpp
  62. 2 1
      platform/uwp/os_uwp.cpp
  63. 2 1
      platform/uwp/os_uwp.h
  64. 164 0
      platform/windows/key_mapping_windows.cpp
  65. 1 0
      platform/windows/key_mapping_windows.h
  66. 6 3
      platform/windows/os_windows.cpp
  67. 134 0
      platform/x11/key_mapping_x11.cpp
  68. 1 0
      platform/x11/key_mapping_x11.h
  69. 28 14
      platform/x11/os_x11.cpp
  70. 1 1
      scene/gui/file_dialog.cpp
  71. 1 1
      scene/gui/gradient_edit.cpp
  72. 4 4
      scene/gui/graph_edit.cpp
  73. 4 4
      scene/gui/line_edit.cpp
  74. 1 1
      scene/gui/popup_menu.cpp
  75. 1 1
      scene/gui/rich_text_label.cpp
  76. 50 50
      scene/gui/text_edit.cpp
  77. 1 1
      scene/gui/tree.cpp
  78. 1 1
      scene/main/scene_tree.cpp

+ 8 - 6
core/bind/core_bind.cpp

@@ -1134,15 +1134,17 @@ String _OS::get_system_dir(SystemDir p_dir) const {
 	return OS::get_singleton()->get_system_dir(OS::SystemDir(p_dir));
 }
 
-String _OS::get_scancode_string(uint32_t p_code) const {
+String _OS::get_keycode_string(uint32_t p_code) const {
 
 	return keycode_get_string(p_code);
 }
-bool _OS::is_scancode_unicode(uint32_t p_unicode) const {
+
+bool _OS::is_keycode_unicode(uint32_t p_unicode) const {
 
 	return keycode_has_unicode(p_unicode);
 }
-int _OS::find_scancode_from_string(const String &p_code) const {
+
+int _OS::find_keycode_from_string(const String &p_code) const {
 
 	return find_keycode(p_code);
 }
@@ -1333,9 +1335,9 @@ void _OS::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("native_video_pause"), &_OS::native_video_pause);
 	ClassDB::bind_method(D_METHOD("native_video_unpause"), &_OS::native_video_unpause);
 
-	ClassDB::bind_method(D_METHOD("get_scancode_string", "code"), &_OS::get_scancode_string);
-	ClassDB::bind_method(D_METHOD("is_scancode_unicode", "code"), &_OS::is_scancode_unicode);
-	ClassDB::bind_method(D_METHOD("find_scancode_from_string", "string"), &_OS::find_scancode_from_string);
+	ClassDB::bind_method(D_METHOD("get_keycode_string", "code"), &_OS::get_keycode_string);
+	ClassDB::bind_method(D_METHOD("is_keycode_unicode", "code"), &_OS::is_keycode_unicode);
+	ClassDB::bind_method(D_METHOD("find_keycode_from_string", "string"), &_OS::find_keycode_from_string);
 
 	ClassDB::bind_method(D_METHOD("set_use_file_access_save_and_swap", "enabled"), &_OS::set_use_file_access_save_and_swap);
 

+ 3 - 3
core/bind/core_bind.h

@@ -266,9 +266,9 @@ public:
 
 	String get_unique_id() const;
 
-	String get_scancode_string(uint32_t p_code) const;
-	bool is_scancode_unicode(uint32_t p_unicode) const;
-	int find_scancode_from_string(const String &p_code) const;
+	String get_keycode_string(uint32_t p_code) const;
+	bool is_keycode_unicode(uint32_t p_unicode) const;
+	int find_keycode_from_string(const String &p_code) const;
 
 	void set_use_file_access_save_and_swap(bool p_enable);
 

+ 15 - 15
core/input_map.cpp

@@ -256,76 +256,76 @@ void InputMap::load_default() {
 
 	add_action("ui_accept");
 	key.instance();
-	key->set_scancode(KEY_ENTER);
+	key->set_keycode(KEY_ENTER);
 	action_add_event("ui_accept", key);
 
 	key.instance();
-	key->set_scancode(KEY_KP_ENTER);
+	key->set_keycode(KEY_KP_ENTER);
 	action_add_event("ui_accept", key);
 
 	key.instance();
-	key->set_scancode(KEY_SPACE);
+	key->set_keycode(KEY_SPACE);
 	action_add_event("ui_accept", key);
 
 	add_action("ui_select");
 	key.instance();
-	key->set_scancode(KEY_SPACE);
+	key->set_keycode(KEY_SPACE);
 	action_add_event("ui_select", key);
 
 	add_action("ui_cancel");
 	key.instance();
-	key->set_scancode(KEY_ESCAPE);
+	key->set_keycode(KEY_ESCAPE);
 	action_add_event("ui_cancel", key);
 
 	add_action("ui_focus_next");
 	key.instance();
-	key->set_scancode(KEY_TAB);
+	key->set_keycode(KEY_TAB);
 	action_add_event("ui_focus_next", key);
 
 	add_action("ui_focus_prev");
 	key.instance();
-	key->set_scancode(KEY_TAB);
+	key->set_keycode(KEY_TAB);
 	key->set_shift(true);
 	action_add_event("ui_focus_prev", key);
 
 	add_action("ui_left");
 	key.instance();
-	key->set_scancode(KEY_LEFT);
+	key->set_keycode(KEY_LEFT);
 	action_add_event("ui_left", key);
 
 	add_action("ui_right");
 	key.instance();
-	key->set_scancode(KEY_RIGHT);
+	key->set_keycode(KEY_RIGHT);
 	action_add_event("ui_right", key);
 
 	add_action("ui_up");
 	key.instance();
-	key->set_scancode(KEY_UP);
+	key->set_keycode(KEY_UP);
 	action_add_event("ui_up", key);
 
 	add_action("ui_down");
 	key.instance();
-	key->set_scancode(KEY_DOWN);
+	key->set_keycode(KEY_DOWN);
 	action_add_event("ui_down", key);
 
 	add_action("ui_page_up");
 	key.instance();
-	key->set_scancode(KEY_PAGEUP);
+	key->set_keycode(KEY_PAGEUP);
 	action_add_event("ui_page_up", key);
 
 	add_action("ui_page_down");
 	key.instance();
-	key->set_scancode(KEY_PAGEDOWN);
+	key->set_keycode(KEY_PAGEDOWN);
 	action_add_event("ui_page_down", key);
 
 	add_action("ui_home");
 	key.instance();
-	key->set_scancode(KEY_HOME);
+	key->set_keycode(KEY_HOME);
 	action_add_event("ui_home", key);
 
 	add_action("ui_end");
 	key.instance();
-	key->set_scancode(KEY_END);
+	key->set_keycode(KEY_END);
 	action_add_event("ui_end", key);
 
 	//set("display/window/handheld/orientation", "landscape");

+ 1 - 1
core/os/input.cpp

@@ -57,7 +57,7 @@ Input::MouseMode Input::get_mouse_mode() const {
 
 void Input::_bind_methods() {
 
-	ClassDB::bind_method(D_METHOD("is_key_pressed", "scancode"), &Input::is_key_pressed);
+	ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &Input::is_key_pressed);
 	ClassDB::bind_method(D_METHOD("is_mouse_button_pressed", "button"), &Input::is_mouse_button_pressed);
 	ClassDB::bind_method(D_METHOD("is_joy_button_pressed", "device", "button"), &Input::is_joy_button_pressed);
 	ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &Input::is_action_pressed);

+ 1 - 1
core/os/input.h

@@ -79,7 +79,7 @@ public:
 
 	static Input *get_singleton();
 
-	virtual bool is_key_pressed(int p_scancode) const = 0;
+	virtual bool is_key_pressed(int p_keycode) const = 0;
 	virtual bool is_mouse_button_pressed(int p_button) const = 0;
 	virtual bool is_joy_button_pressed(int p_device, int p_button) const = 0;
 	virtual bool is_action_pressed(const StringName &p_action) const = 0;

+ 59 - 17
core/os/input_event.cpp

@@ -237,19 +237,31 @@ bool InputEventKey::is_pressed() const {
 	return pressed;
 }
 
-void InputEventKey::set_scancode(uint32_t p_scancode) {
+void InputEventKey::set_keycode(uint32_t p_keycode) {
 
-	scancode = p_scancode;
+	keycode = p_keycode;
 }
-uint32_t InputEventKey::get_scancode() const {
 
-	return scancode;
+uint32_t InputEventKey::get_keycode() const {
+
+	return keycode;
+}
+
+void InputEventKey::set_physical_keycode(uint32_t p_keycode) {
+
+	physical_keycode = p_keycode;
+}
+
+uint32_t InputEventKey::get_physical_keycode() const {
+
+	return physical_keycode;
 }
 
 void InputEventKey::set_unicode(uint32_t p_unicode) {
 
 	unicode = p_unicode;
 }
+
 uint32_t InputEventKey::get_unicode() const {
 
 	return unicode;
@@ -259,14 +271,30 @@ void InputEventKey::set_echo(bool p_enable) {
 
 	echo = p_enable;
 }
+
 bool InputEventKey::is_echo() const {
 
 	return echo;
 }
 
-uint32_t InputEventKey::get_scancode_with_modifiers() const {
+uint32_t InputEventKey::get_keycode_with_modifiers() const {
 
-	uint32_t sc = scancode;
+	uint32_t sc = keycode;
+	if (get_control())
+		sc |= KEY_MASK_CTRL;
+	if (get_alt())
+		sc |= KEY_MASK_ALT;
+	if (get_shift())
+		sc |= KEY_MASK_SHIFT;
+	if (get_metakey())
+		sc |= KEY_MASK_META;
+
+	return sc;
+}
+
+uint32_t InputEventKey::get_physical_keycode_with_modifiers() const {
+
+	uint32_t sc = physical_keycode;
 	if (get_control())
 		sc |= KEY_MASK_CTRL;
 	if (get_alt())
@@ -281,7 +309,7 @@ uint32_t InputEventKey::get_scancode_with_modifiers() const {
 
 String InputEventKey::as_text() const {
 
-	String kc = keycode_get_string(scancode);
+	String kc = keycode_get_string(keycode);
 	if (kc == String())
 		return kc;
 
@@ -306,10 +334,18 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed
 	if (key.is_null())
 		return false;
 
-	uint32_t code = get_scancode_with_modifiers();
-	uint32_t event_code = key->get_scancode_with_modifiers();
+	bool match = false;
+	if (get_keycode() == 0) {
+		uint32_t code = get_physical_keycode_with_modifiers();
+		uint32_t event_code = key->get_physical_keycode_with_modifiers();
 
-	bool match = get_scancode() == key->get_scancode() && (!key->is_pressed() || (code & event_code) == code);
+		match = get_physical_keycode() == key->get_physical_keycode() && (!key->is_pressed() || (code & event_code) == code);
+	} else {
+		uint32_t code = get_keycode_with_modifiers();
+		uint32_t event_code = key->get_keycode_with_modifiers();
+
+		match = get_keycode() == key->get_keycode() && (!key->is_pressed() || (code & event_code) == code);
+	}
 	if (match) {
 		if (p_pressed != NULL)
 			*p_pressed = key->is_pressed();
@@ -325,8 +361,8 @@ bool InputEventKey::shortcut_match(const Ref<InputEvent> &p_event) const {
 	if (key.is_null())
 		return false;
 
-	uint32_t code = get_scancode_with_modifiers();
-	uint32_t event_code = key->get_scancode_with_modifiers();
+	uint32_t code = get_keycode_with_modifiers();
+	uint32_t event_code = key->get_keycode_with_modifiers();
 
 	return code == event_code;
 }
@@ -335,18 +371,23 @@ void InputEventKey::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventKey::set_pressed);
 
-	ClassDB::bind_method(D_METHOD("set_scancode", "scancode"), &InputEventKey::set_scancode);
-	ClassDB::bind_method(D_METHOD("get_scancode"), &InputEventKey::get_scancode);
+	ClassDB::bind_method(D_METHOD("set_keycode", "keycode"), &InputEventKey::set_keycode);
+	ClassDB::bind_method(D_METHOD("get_keycode"), &InputEventKey::get_keycode);
+
+	ClassDB::bind_method(D_METHOD("set_physical_keycode", "physical_keycode"), &InputEventKey::set_physical_keycode);
+	ClassDB::bind_method(D_METHOD("get_physical_keycode"), &InputEventKey::get_physical_keycode);
 
 	ClassDB::bind_method(D_METHOD("set_unicode", "unicode"), &InputEventKey::set_unicode);
 	ClassDB::bind_method(D_METHOD("get_unicode"), &InputEventKey::get_unicode);
 
 	ClassDB::bind_method(D_METHOD("set_echo", "echo"), &InputEventKey::set_echo);
 
-	ClassDB::bind_method(D_METHOD("get_scancode_with_modifiers"), &InputEventKey::get_scancode_with_modifiers);
+	ClassDB::bind_method(D_METHOD("get_keycode_with_modifiers"), &InputEventKey::get_keycode_with_modifiers);
+	ClassDB::bind_method(D_METHOD("get_physical_keycode_with_modifiers"), &InputEventKey::get_physical_keycode_with_modifiers);
 
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "scancode"), "set_scancode", "get_scancode");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "keycode"), "set_keycode", "get_keycode");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "physical_keycode"), "set_physical_keycode", "get_physical_keycode");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "unicode"), "set_unicode", "get_unicode");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "echo"), "set_echo", "is_echo");
 }
@@ -354,7 +395,8 @@ void InputEventKey::_bind_methods() {
 InputEventKey::InputEventKey() {
 
 	pressed = false;
-	scancode = 0;
+	keycode = 0;
+	physical_keycode = 0;
 	unicode = 0; ///unicode
 	echo = false;
 }

+ 9 - 4
core/os/input_event.h

@@ -256,7 +256,8 @@ class InputEventKey : public InputEventWithModifiers {
 
 	bool pressed; /// otherwise release
 
-	uint32_t scancode; ///< check keyboard.h , KeyCode enum, without modifier masks
+	uint32_t keycode; ///< check keyboard.h , KeyCode enum, without modifier masks
+	uint32_t physical_keycode;
 	uint32_t unicode; ///unicode
 
 	bool echo; /// true if this is an echo key
@@ -268,8 +269,11 @@ public:
 	void set_pressed(bool p_pressed);
 	virtual bool is_pressed() const;
 
-	void set_scancode(uint32_t p_scancode);
-	uint32_t get_scancode() const;
+	void set_keycode(uint32_t p_keycode);
+	uint32_t get_keycode() const;
+
+	void set_physical_keycode(uint32_t p_keycode);
+	uint32_t get_physical_keycode() const;
 
 	void set_unicode(uint32_t p_unicode);
 	uint32_t get_unicode() const;
@@ -277,7 +281,8 @@ public:
 	void set_echo(bool p_enable);
 	virtual bool is_echo() const;
 
-	uint32_t get_scancode_with_modifiers() const;
+	uint32_t get_keycode_with_modifiers() const;
+	uint32_t get_physical_keycode_with_modifiers() const;
 
 	virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const;
 	virtual bool shortcut_match(const Ref<InputEvent> &p_event) const;

+ 15 - 15
core/project_settings.cpp

@@ -1039,13 +1039,13 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_ENTER);
+	key->set_keycode(KEY_ENTER);
 	events.push_back(key);
 	key.instance();
-	key->set_scancode(KEY_KP_ENTER);
+	key->set_keycode(KEY_KP_ENTER);
 	events.push_back(key);
 	key.instance();
-	key->set_scancode(KEY_SPACE);
+	key->set_keycode(KEY_SPACE);
 	events.push_back(key);
 	joyb.instance();
 	joyb->set_button_index(JOY_BUTTON_0);
@@ -1058,7 +1058,7 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_SPACE);
+	key->set_keycode(KEY_SPACE);
 	events.push_back(key);
 	joyb.instance();
 	joyb->set_button_index(JOY_BUTTON_3);
@@ -1071,7 +1071,7 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_ESCAPE);
+	key->set_keycode(KEY_ESCAPE);
 	events.push_back(key);
 	joyb.instance();
 	joyb->set_button_index(JOY_BUTTON_1);
@@ -1084,7 +1084,7 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_TAB);
+	key->set_keycode(KEY_TAB);
 	events.push_back(key);
 	action["events"] = events;
 	GLOBAL_DEF("input/ui_focus_next", action);
@@ -1094,7 +1094,7 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_TAB);
+	key->set_keycode(KEY_TAB);
 	key->set_shift(true);
 	events.push_back(key);
 	action["events"] = events;
@@ -1105,7 +1105,7 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_LEFT);
+	key->set_keycode(KEY_LEFT);
 	events.push_back(key);
 	joyb.instance();
 	joyb->set_button_index(JOY_DPAD_LEFT);
@@ -1118,7 +1118,7 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_RIGHT);
+	key->set_keycode(KEY_RIGHT);
 	events.push_back(key);
 	joyb.instance();
 	joyb->set_button_index(JOY_DPAD_RIGHT);
@@ -1131,7 +1131,7 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_UP);
+	key->set_keycode(KEY_UP);
 	events.push_back(key);
 	joyb.instance();
 	joyb->set_button_index(JOY_DPAD_UP);
@@ -1144,7 +1144,7 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_DOWN);
+	key->set_keycode(KEY_DOWN);
 	events.push_back(key);
 	joyb.instance();
 	joyb->set_button_index(JOY_DPAD_DOWN);
@@ -1157,7 +1157,7 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_PAGEUP);
+	key->set_keycode(KEY_PAGEUP);
 	events.push_back(key);
 	action["events"] = events;
 	GLOBAL_DEF("input/ui_page_up", action);
@@ -1167,7 +1167,7 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_PAGEDOWN);
+	key->set_keycode(KEY_PAGEDOWN);
 	events.push_back(key);
 	action["events"] = events;
 	GLOBAL_DEF("input/ui_page_down", action);
@@ -1177,7 +1177,7 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_HOME);
+	key->set_keycode(KEY_HOME);
 	events.push_back(key);
 	action["events"] = events;
 	GLOBAL_DEF("input/ui_home", action);
@@ -1187,7 +1187,7 @@ ProjectSettings::ProjectSettings() {
 	action["deadzone"] = Variant(0.5f);
 	events = Array();
 	key.instance();
-	key->set_scancode(KEY_END);
+	key->set_keycode(KEY_END);
 	events.push_back(key);
 	action["events"] = events;
 	GLOBAL_DEF("input/ui_end", action);

+ 2 - 2
doc/classes/@GlobalScope.xml

@@ -4,7 +4,7 @@
 		Global scope constants and variables.
 	</brief_description>
 	<description>
-		Global scope constants and variables. This is all that resides in the globals, constants regarding error codes, scancodes, property hints, etc.
+		Global scope constants and variables. This is all that resides in the globals, constants regarding error codes, keycodes, property hints, etc.
 		Singletons are also documented here, since they can be accessed from anywhere.
 	</description>
 	<tutorials>
@@ -146,7 +146,7 @@
 			Vertical bottom alignment, usually for text-derived classes.
 		</constant>
 		<constant name="SPKEY" value="16777216">
-			Scancodes with this bit applied are non-printable.
+			Keycodes with this bit applied are non-printable.
 		</constant>
 		<constant name="KEY_ESCAPE" value="16777217" enum="KeyList">
 			Escape key.

+ 2 - 2
doc/classes/Input.xml

@@ -250,10 +250,10 @@
 		<method name="is_key_pressed" qualifiers="const">
 			<return type="bool">
 			</return>
-			<argument index="0" name="scancode" type="int">
+			<argument index="0" name="keycode" type="int">
 			</argument>
 			<description>
-				Returns [code]true[/code] if you are pressing the key. You can pass a [enum KeyList] constant.
+				Returns [code]true[/code] if you are pressing the key in the current keyboard layout. You can pass a [enum KeyList] constant.
 			</description>
 		</method>
 		<method name="is_mouse_button_pressed" qualifiers="const">

+ 18 - 6
doc/classes/InputEventKey.xml

@@ -10,12 +10,20 @@
 		<link>https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html</link>
 	</tutorials>
 	<methods>
-		<method name="get_scancode_with_modifiers" qualifiers="const">
+		<method name="get_keycode_with_modifiers" qualifiers="const">
 			<return type="int">
 			</return>
 			<description>
-				Returns the scancode combined with modifier keys such as [code]Shift[/code] or [code]Alt[/code]. See also [InputEventWithModifiers].
-				To get a human-readable representation of the [InputEventKey] with modifiers, use [code]OS.get_scancode_string(event.get_scancode_with_modifiers())[/code] where [code]event[/code] is the [InputEventKey].
+				Returns the keycode combined with modifier keys such as [code]Shift[/code] or [code]Alt[/code]. See also [InputEventWithModifiers].
+				To get a human-readable representation of the [InputEventKey] with modifiers, use [code]OS.get_keycode_string(event.get_keycode_with_modifiers())[/code] where [code]event[/code] is the [InputEventKey].
+			</description>
+		</method>
+		<method name="get_physical_keycode_with_modifiers" qualifiers="const">
+			<return type="int">
+			</return>
+			<description>
+				Returns the physical keycode combined with modifier keys such as [code]Shift[/code] or [code]Alt[/code]. See also [InputEventWithModifiers].
+				To get a human-readable representation of the [InputEventKey] with modifiers, use [code]OS.get_keycode_string(event.get_physical_keycode_with_modifiers())[/code] where [code]event[/code] is the [InputEventKey].
 			</description>
 		</method>
 	</methods>
@@ -26,9 +34,13 @@
 		<member name="pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false">
 			If [code]true[/code], the key's state is pressed. If [code]false[/code], the key's state is released.
 		</member>
-		<member name="scancode" type="int" setter="set_scancode" getter="get_scancode" default="0">
-			The key scancode, which corresponds to one of the [enum KeyList] constants.
-			To get a human-readable representation of the [InputEventKey], use [code]OS.get_scancode_string(event.scancode)[/code] where [code]event[/code] is the [InputEventKey].
+		<member name="keycode" type="int" setter="set_keycode" getter="get_keycode" default="0">
+			The key keycode, which corresponds to one of the [enum KeyList] constants. Represent key in the current keyboard layout.
+			To get a human-readable representation of the [InputEventKey], use [code]OS.get_keycode_string(event.keycode)[/code] where [code]event[/code] is the [InputEventKey].
+		</member>
+		<member name="physical_keycode" type="int" setter="set_physical_keycode" getter="get_physical_keycode" default="0">
+			Key physical keycode, which corresponds to one of the [enum KeyList] constants. Represent the physical location of a key on the 101/102-key US QWERTY keyboard.
+			To get a human-readable representation of the [InputEventKey], use [code]OS.get_keycode_string(event.keycode)[/code] where [code]event[/code] is the [InputEventKey].
 		</member>
 		<member name="unicode" type="int" setter="set_unicode" getter="get_unicode" default="0">
 			The key Unicode identifier (when relevant). Unicode identifiers for the composite characters and complex scripts may not be available unless IME input mode is active. See [method OS.set_ime_active] for more information.

+ 2 - 2
doc/classes/MainLoop.xml

@@ -26,9 +26,9 @@
 		func _input_event(event):
 		    # Record keys.
 		    if event is InputEventKey and event.pressed and !event.echo:
-		        keys_typed.append(OS.get_scancode_string(event.scancode))
+		        keys_typed.append(OS.get_keycode_string(event.keycode))
 		        # Quit on Escape press.
-		        if event.scancode == KEY_ESCAPE:
+		        if event.keycode == KEY_ESCAPE:
 		            quit = true
 		    # Quit on any mouse click.
 		    if event is InputEventMouseButton:

+ 7 - 7
doc/classes/OS.xml

@@ -124,13 +124,13 @@
 				[b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows.
 			</description>
 		</method>
-		<method name="find_scancode_from_string" qualifiers="const">
+		<method name="find_keycode_from_string" qualifiers="const">
 			<return type="int">
 			</return>
 			<argument index="0" name="string" type="String">
 			</argument>
 			<description>
-				Returns the scancode of the given string (e.g. "Escape").
+				Returns the keycode of the given string (e.g. "Escape").
 			</description>
 		</method>
 		<method name="get_audio_driver_count" qualifiers="const">
@@ -295,14 +295,14 @@
 				Returns the window size including decorations like window borders.
 			</description>
 		</method>
-		<method name="get_scancode_string" qualifiers="const">
+		<method name="get_keycode_string" qualifiers="const">
 			<return type="String">
 			</return>
 			<argument index="0" name="code" type="int">
 			</argument>
 			<description>
-				Returns the given scancode as a string (e.g. Return values: [code]"Escape"[/code], [code]"Shift+Escape"[/code]).
-				See also [member InputEventKey.scancode] and [method InputEventKey.get_scancode_with_modifiers].
+				Returns the given keycode as a string (e.g. Return values: [code]"Escape"[/code], [code]"Shift+Escape"[/code]).
+				See also [member InputEventKey.keycode] and [method InputEventKey.get_keycode_with_modifiers].
 			</description>
 		</method>
 		<method name="get_screen_count" qualifiers="const">
@@ -595,13 +595,13 @@
 				Returns [code]true[/code] if the [b]OK[/b] button should appear on the left and [b]Cancel[/b] on the right.
 			</description>
 		</method>
-		<method name="is_scancode_unicode" qualifiers="const">
+		<method name="is_keycode_unicode" qualifiers="const">
 			<return type="bool">
 			</return>
 			<argument index="0" name="code" type="int">
 			</argument>
 			<description>
-				Returns [code]true[/code] if the input scancode corresponds to a Unicode character.
+				Returns [code]true[/code] if the input keycode corresponds to a Unicode character.
 			</description>
 		</method>
 		<method name="is_stdout_verbose" qualifiers="const">

+ 1 - 1
editor/code_editor.cpp

@@ -122,7 +122,7 @@ void FindReplaceBar::_unhandled_input(const Ref<InputEvent> &p_event) {
 
 			bool accepted = true;
 
-			switch (k->get_scancode()) {
+			switch (k->get_keycode()) {
 
 				case KEY_ESCAPE: {
 

+ 4 - 4
editor/create_dialog.cpp

@@ -127,10 +127,10 @@ void CreateDialog::_text_changed(const String &p_newtext) {
 void CreateDialog::_sbox_input(const Ref<InputEvent> &p_ie) {
 
 	Ref<InputEventKey> k = p_ie;
-	if (k.is_valid() && (k->get_scancode() == KEY_UP ||
-								k->get_scancode() == KEY_DOWN ||
-								k->get_scancode() == KEY_PAGEUP ||
-								k->get_scancode() == KEY_PAGEDOWN)) {
+	if (k.is_valid() && (k->get_keycode() == KEY_UP ||
+								k->get_keycode() == KEY_DOWN ||
+								k->get_keycode() == KEY_PAGEUP ||
+								k->get_keycode() == KEY_PAGEDOWN)) {
 
 		search_options->call("_gui_input", k);
 		search_box->accept_event();

+ 1 - 1
editor/editor_audio_buses.cpp

@@ -549,7 +549,7 @@ void EditorAudioBus::_effect_add(int p_which) {
 void EditorAudioBus::_gui_input(const Ref<InputEvent> &p_event) {
 
 	Ref<InputEventKey> k = p_event;
-	if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_DELETE && !k->is_echo()) {
+	if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_DELETE && !k->is_echo()) {
 		accept_event();
 		emit_signal("delete_request");
 	}

+ 2 - 2
editor/editor_help.cpp

@@ -66,7 +66,7 @@ void EditorHelp::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
 
 	Ref<InputEventKey> k = p_ev;
 
-	if (k.is_valid() && k->get_control() && k->get_scancode() == KEY_F) {
+	if (k.is_valid() && k->get_control() && k->get_keycode() == KEY_F) {
 
 		search->grab_focus();
 		search->select_all();
@@ -1803,7 +1803,7 @@ void FindBar::_unhandled_input(const Ref<InputEvent> &p_event) {
 
 			bool accepted = true;
 
-			switch (k->get_scancode()) {
+			switch (k->get_keycode()) {
 
 				case KEY_ESCAPE: {
 

+ 1 - 1
editor/editor_help_search.cpp

@@ -66,7 +66,7 @@ void EditorHelpSearch::_search_box_gui_input(const Ref<InputEvent> &p_event) {
 	// Redirect up and down navigational key events to the results list.
 	Ref<InputEventKey> key = p_event;
 	if (key.is_valid()) {
-		switch (key->get_scancode()) {
+		switch (key->get_keycode()) {
 			case KEY_UP:
 			case KEY_DOWN:
 			case KEY_PAGEUP:

+ 1 - 1
editor/editor_layouts_dialog.cpp

@@ -45,7 +45,7 @@ void EditorLayoutsDialog::_line_gui_input(const Ref<InputEvent> &p_event) {
 		if (!k->is_pressed())
 			return;
 
-		switch (k->get_scancode()) {
+		switch (k->get_keycode()) {
 			case KEY_KP_ENTER:
 			case KEY_ENTER: {
 

+ 1 - 1
editor/editor_settings.cpp

@@ -1531,7 +1531,7 @@ Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p
 		ie.instance();
 
 		ie->set_unicode(p_keycode & KEY_CODE_MASK);
-		ie->set_scancode(p_keycode & KEY_CODE_MASK);
+		ie->set_keycode(p_keycode & KEY_CODE_MASK);
 		ie->set_shift(bool(p_keycode & KEY_MASK_SHIFT));
 		ie->set_alt(bool(p_keycode & KEY_MASK_ALT));
 		ie->set_control(bool(p_keycode & KEY_MASK_CTRL));

+ 1 - 1
editor/icons/Keyboard.svg

@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill-opacity=".99608" transform="translate(0 -1036.4)"><path d="m4 2a1 1 0 0 0 -1 1v9.084a1 .91667 0 0 0 1 .91602h8a1 .91667 0 0 0 1-.91602v-9.084a1 1 0 0 0 -1-1zm-3 2v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-9h-1v9a.99998.99998 0 0 1 -1 1h-10a1 1 0 0 1 -1-1v-9zm4 0h2v3l2-3h2l-2 3 2 4h-2l-2-4v4h-2z" fill="#e0e0e0" transform="translate(0 1036.4)"/><path d="m27 1038.4h7v14h-7z" fill="#fff"/></g></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M4 2a1 1 0 0 0-1 1v9.084c0 .506.448.916 1 .916h8c.552 0 1-.41 1-.916V3a1 1 0 0 0-1-1H4zm1.543 1.139h1.393L8.77 7.338h1.295v.437c.708.052 1.246.239 1.61.559.368.316.55.747.55 1.295 0 .552-.182.99-.55 1.314-.368.32-.906.505-1.61.553v.467H8.771v-.473c-.708-.06-1.247-.248-1.615-.564-.364-.316-.545-.75-.545-1.297 0-.548.181-.977.545-1.29.368-.315.907-.504 1.615-.564v-.437H7.307l-.282-.733H5.43l-.284.733H3.707l1.836-4.2zm.684 1.39l-.409 1.057h.817l-.408-1.057zm3.84 4.338v1.526c.28-.04.483-.12.607-.24.124-.125.185-.302.185-.53 0-.224-.063-.396-.191-.516-.124-.12-.326-.2-.602-.24zm-1.296.006c-.284.04-.487.12-.61.24-.12.116-.182.288-.182.516 0 .22.065.392.193.512.132.12.331.202.6.246V8.873z" fill="#e0e0e0" fill-opacity=".996"/><path d="M27 2h7v14h-7z" fill="#fff" fill-opacity=".996"/><path fill="#e0e0e0" fill-opacity=".996" d="M1 4v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-1v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4z"/></svg>

+ 1 - 0
editor/icons/KeyboardPhysical.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M4 2a1 1 0 0 0-1 1v9.084c0 .506.448.916 1 .916h8c.552 0 1-.41 1-.916V3a1 1 0 0 0-1-1zm2.762 1.768h2.476l3.264 7.464H9.898l-.502-1.3H6.561l-.502 1.3H3.498zm1.217 2.474L7.254 8.12h1.45z" fill="#e0e0e0" fill-opacity=".996"/><path d="M27 2h7v14h-7z" fill="#fff" fill-opacity=".996"/><path fill="#e0e0e0" fill-opacity=".996" d="M1 4v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-1v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4z"/></svg>

+ 3 - 3
editor/plugins/abstract_polygon_2d_editor.cpp

@@ -533,7 +533,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
 
 	if (k.is_valid() && k->is_pressed()) {
 
-		if (k->get_scancode() == KEY_DELETE || k->get_scancode() == KEY_BACKSPACE) {
+		if (k->get_keycode() == KEY_DELETE || k->get_keycode() == KEY_BACKSPACE) {
 
 			if (wip_active && selected_point.polygon == -1) {
 
@@ -555,10 +555,10 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
 					return true;
 				}
 			}
-		} else if (wip_active && k->get_scancode() == KEY_ENTER) {
+		} else if (wip_active && k->get_keycode() == KEY_ENTER) {
 
 			_wip_close();
-		} else if (wip_active && k->get_scancode() == KEY_ESCAPE) {
+		} else if (wip_active && k->get_keycode() == KEY_ESCAPE) {
 			_wip_cancel();
 		}
 	}

+ 1 - 1
editor/plugins/animation_blend_space_1d_editor.cpp

@@ -42,7 +42,7 @@ StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const {
 void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEvent> &p_event) {
 	Ref<InputEventKey> k = p_event;
 
-	if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_DELETE && !k->is_echo()) {
+	if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_DELETE && !k->is_echo()) {
 		if (selected_point != -1) {
 			_erase_selected();
 			accept_event();

+ 1 - 1
editor/plugins/animation_blend_space_2d_editor.cpp

@@ -73,7 +73,7 @@ StringName AnimationNodeBlendSpace2DEditor::get_blend_position_path() const {
 void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEvent> &p_event) {
 
 	Ref<InputEventKey> k = p_event;
-	if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_DELETE && !k->is_echo()) {
+	if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_DELETE && !k->is_echo()) {
 		if (selected_point != -1 || selected_triangle != -1) {
 			_erase_selected();
 			accept_event();

+ 1 - 1
editor/plugins/animation_player_editor_plugin.cpp

@@ -1268,7 +1268,7 @@ void AnimationPlayerEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
 	Ref<InputEventKey> k = p_ev;
 	if (is_visible_in_tree() && k.is_valid() && k->is_pressed() && !k->is_echo() && !k->get_alt() && !k->get_control() && !k->get_metakey()) {
 
-		switch (k->get_scancode()) {
+		switch (k->get_keycode()) {
 
 			case KEY_A: {
 				if (!k->get_shift())

+ 1 - 1
editor/plugins/animation_state_machine_editor.cpp

@@ -69,7 +69,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
 		return;
 
 	Ref<InputEventKey> k = p_event;
-	if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_DELETE && !k->is_echo()) {
+	if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_DELETE && !k->is_echo()) {
 		if (selected_node != StringName() || selected_transition_to != StringName() || selected_transition_from != StringName()) {
 			_erase_selected();
 			accept_event();

+ 1 - 1
editor/plugins/asset_library_editor_plugin.cpp

@@ -617,7 +617,7 @@ void EditorAssetLibrary::_unhandled_input(const Ref<InputEvent> &p_event) {
 
 	if (key.is_valid() && key->is_pressed()) {
 
-		if (key->get_scancode_with_modifiers() == (KEY_MASK_CMD | KEY_F) && is_visible_in_tree()) {
+		if (key->get_keycode_with_modifiers() == (KEY_MASK_CMD | KEY_F) && is_visible_in_tree()) {
 
 			filter->grab_focus();
 			filter->select_all();

+ 11 - 11
editor/plugins/canvas_item_editor_plugin.cpp

@@ -472,7 +472,7 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
 	if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
 		return;
 
-	if (k->get_scancode() == KEY_CONTROL || k->get_scancode() == KEY_ALT || k->get_scancode() == KEY_SHIFT) {
+	if (k->get_keycode() == KEY_CONTROL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT) {
 		viewport->update();
 	}
 
@@ -1315,7 +1315,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
 	// Drag the pivot (in pivot mode / with V key)
 	if (drag_type == DRAG_NONE) {
 		if ((b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
-				(k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_V)) {
+				(k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_V)) {
 			List<CanvasItem *> selection = _get_edited_canvas_items();
 
 			// Filters the selection with nodes that allow setting the pivot
@@ -1367,7 +1367,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
 
 		// Confirm the pivot move
 		if ((b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
-				(k.is_valid() && !k->is_pressed() && k->get_scancode() == KEY_V)) {
+				(k.is_valid() && !k->is_pressed() && k->get_keycode() == KEY_V)) {
 			_commit_canvas_item_state(drag_selection, TTR("Move pivot"));
 			drag_type = DRAG_NONE;
 			return true;
@@ -2109,7 +2109,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
 
 	// Move the canvas items with the arrow keys
 	if (k.is_valid() && k->is_pressed() && (tool == TOOL_SELECT || tool == TOOL_MOVE) &&
-			(k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) {
+			(k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_LEFT || k->get_keycode() == KEY_RIGHT)) {
 		if (!k->is_echo()) {
 			// Start moving the canvas items with the keyboard
 			drag_selection = _get_edited_canvas_items();
@@ -2135,13 +2135,13 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
 			bool move_local_base_rotated = k->get_control() || k->get_metakey();
 
 			Vector2 dir;
-			if (k->get_scancode() == KEY_UP)
+			if (k->get_keycode() == KEY_UP)
 				dir += Vector2(0, -1);
-			else if (k->get_scancode() == KEY_DOWN)
+			else if (k->get_keycode() == KEY_DOWN)
 				dir += Vector2(0, 1);
-			else if (k->get_scancode() == KEY_LEFT)
+			else if (k->get_keycode() == KEY_LEFT)
 				dir += Vector2(-1, 0);
-			else if (k->get_scancode() == KEY_RIGHT)
+			else if (k->get_keycode() == KEY_RIGHT)
 				dir += Vector2(1, 0);
 			if (k->get_shift())
 				dir *= grid_step * Math::pow(2.0, grid_step_multiplier);
@@ -2197,7 +2197,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
 	}
 
 	if (k.is_valid() && !k->is_pressed() && drag_type == DRAG_KEY_MOVE && tool == TOOL_SELECT &&
-			(k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) {
+			(k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_LEFT || k->get_keycode() == KEY_RIGHT)) {
 		// Confirm canvas items move by arrow keys
 		if ((!Input::get_singleton()->is_key_pressed(KEY_UP)) &&
 				(!Input::get_singleton()->is_key_pressed(KEY_DOWN)) &&
@@ -2210,7 +2210,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
 		return true;
 	}
 
-	return (k.is_valid() && (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)); // Accept the key event in any case
+	return (k.is_valid() && (k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_LEFT || k->get_keycode() == KEY_RIGHT)); // Accept the key event in any case
 }
 
 bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
@@ -2387,7 +2387,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
 		}
 	}
 
-	if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_ESCAPE && drag_type == DRAG_NONE && tool == TOOL_SELECT) {
+	if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_ESCAPE && drag_type == DRAG_NONE && tool == TOOL_SELECT) {
 		// Unselect everything
 		editor_selection->clear();
 		viewport->update();

+ 1 - 1
editor/plugins/curve_editor_plugin.cpp

@@ -238,7 +238,7 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) {
 		const InputEventKey &key = **key_ref;
 
 		if (key.is_pressed() && _selected_point != -1) {
-			if (key.get_scancode() == KEY_DELETE)
+			if (key.get_keycode() == KEY_DELETE)
 				remove_point(_selected_point);
 		}
 	}

+ 4 - 4
editor/plugins/script_editor_plugin.cpp

@@ -166,10 +166,10 @@ void ScriptEditorQuickOpen::_sbox_input(const Ref<InputEvent> &p_ie) {
 
 	Ref<InputEventKey> k = p_ie;
 
-	if (k.is_valid() && (k->get_scancode() == KEY_UP ||
-								k->get_scancode() == KEY_DOWN ||
-								k->get_scancode() == KEY_PAGEUP ||
-								k->get_scancode() == KEY_PAGEDOWN)) {
+	if (k.is_valid() && (k->get_keycode() == KEY_UP ||
+								k->get_keycode() == KEY_DOWN ||
+								k->get_keycode() == KEY_PAGEUP ||
+								k->get_keycode() == KEY_PAGEDOWN)) {
 
 		search_options->call("_gui_input", k);
 		search_box->accept_event();

+ 1 - 1
editor/plugins/script_text_editor.cpp

@@ -1600,7 +1600,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 	if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
 		local_pos = mb->get_global_position() - tx->get_global_position();
 		create_menu = true;
-	} else if (k.is_valid() && k->get_scancode() == KEY_MENU) {
+	} else if (k.is_valid() && k->get_keycode() == KEY_MENU) {
 		local_pos = tx->_get_cursor_pixel_pos();
 		create_menu = true;
 	}

+ 1 - 1
editor/plugins/shader_editor_plugin.cpp

@@ -522,7 +522,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 	}
 
 	Ref<InputEventKey> k = ev;
-	if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_MENU) {
+	if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) {
 		TextEdit *tx = shader_editor->get_text_edit();
 		_make_context_menu(tx->is_selection_active(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos()));
 		context_menu->grab_focus();

+ 4 - 4
editor/plugins/spatial_editor_plugin.cpp

@@ -1873,11 +1873,11 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
 		if (!orthogonal && ED_IS_SHORTCUT("spatial_editor/freelook_toggle", p_event)) {
 			set_freelook_active(!is_freelook_active());
 
-		} else if (k->get_scancode() == KEY_ESCAPE) {
+		} else if (k->get_keycode() == KEY_ESCAPE) {
 			set_freelook_active(false);
 		}
 
-		if (k->get_scancode() == KEY_SPACE) {
+		if (k->get_keycode() == KEY_SPACE) {
 			if (!k->is_pressed()) emit_signal("toggle_maximize_view", this);
 		}
 	}
@@ -2074,8 +2074,8 @@ static bool is_shortcut_pressed(const String &p_path) {
 		return false;
 	}
 	const Input &input = *Input::get_singleton();
-	int scancode = k->get_scancode();
-	return input.is_key_pressed(scancode);
+	int keycode = k->get_keycode();
+	return input.is_key_pressed(keycode);
 }
 
 void SpatialEditorViewport::_update_freelook(real_t delta) {

+ 1 - 1
editor/plugins/text_editor.cpp

@@ -582,7 +582,7 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
 	}
 
 	Ref<InputEventKey> k = ev;
-	if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_MENU) {
+	if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) {
 		TextEdit *tx = code_editor->get_text_edit();
 		int line = tx->cursor_get_line();
 		_make_context_menu(tx->is_selection_active(), tx->can_fold(line), tx->is_folded(line), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos()));

+ 9 - 9
editor/plugins/tile_map_editor_plugin.cpp

@@ -359,10 +359,10 @@ void TileMapEditor::_sbox_input(const Ref<InputEvent> &p_ie) {
 
 	Ref<InputEventKey> k = p_ie;
 
-	if (k.is_valid() && (k->get_scancode() == KEY_UP ||
-								k->get_scancode() == KEY_DOWN ||
-								k->get_scancode() == KEY_PAGEUP ||
-								k->get_scancode() == KEY_PAGEDOWN)) {
+	if (k.is_valid() && (k->get_keycode() == KEY_UP ||
+								k->get_keycode() == KEY_DOWN ||
+								k->get_keycode() == KEY_PAGEUP ||
+								k->get_keycode() == KEY_PAGEDOWN)) {
 
 		palette->call("_gui_input", k);
 		search_box->accept_event();
@@ -1377,7 +1377,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
 
 	if (k.is_valid() && k->is_pressed()) {
 
-		if (last_tool == TOOL_NONE && tool == TOOL_PICKING && k->get_scancode() == KEY_SHIFT && k->get_command()) {
+		if (last_tool == TOOL_NONE && tool == TOOL_PICKING && k->get_keycode() == KEY_SHIFT && k->get_command()) {
 			// trying to draw a rectangle with the painting tool, so change to the correct tool
 			tool = last_tool;
 
@@ -1385,7 +1385,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
 			_update_button_tool();
 		}
 
-		if (k->get_scancode() == KEY_ESCAPE) {
+		if (k->get_keycode() == KEY_ESCAPE) {
 
 			if (tool == TOOL_PASTING)
 				copydata.clear();
@@ -1506,7 +1506,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
 
 		if (tool == TOOL_NONE) {
 
-			if (k->get_scancode() == KEY_SHIFT && k->get_command()) {
+			if (k->get_keycode() == KEY_SHIFT && k->get_command()) {
 
 				tool = TOOL_PICKING;
 				_update_button_tool();
@@ -1514,9 +1514,9 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
 		} else if (tool == TOOL_PICKING) {
 
 #ifdef APPLE_STYLE_KEYS
-			if (k->get_scancode() == KEY_META) {
+			if (k->get_keycode() == KEY_META) {
 #else
-			if (k->get_scancode() == KEY_CONTROL) {
+			if (k->get_keycode() == KEY_CONTROL) {
 #endif
 				// Go back to that last tool if KEY_CONTROL was released.
 				tool = last_tool;

+ 4 - 4
editor/plugins/visual_shader_editor_plugin.cpp

@@ -1663,10 +1663,10 @@ void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos) {
 
 void VisualShaderEditor::_sbox_input(const Ref<InputEvent> &p_ie) {
 	Ref<InputEventKey> ie = p_ie;
-	if (ie.is_valid() && (ie->get_scancode() == KEY_UP ||
-								 ie->get_scancode() == KEY_DOWN ||
-								 ie->get_scancode() == KEY_ENTER ||
-								 ie->get_scancode() == KEY_KP_ENTER)) {
+	if (ie.is_valid() && (ie->get_keycode() == KEY_UP ||
+								 ie->get_keycode() == KEY_DOWN ||
+								 ie->get_keycode() == KEY_ENTER ||
+								 ie->get_keycode() == KEY_KP_ENTER)) {
 
 		members->call("_gui_input", ie);
 		node_filter->accept_event();

+ 6 - 6
editor/project_manager.cpp

@@ -1899,7 +1899,7 @@ void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) {
 		// This is handled by the platform implementation on macOS,
 		// so only define the shortcut on other platforms
 #ifndef OSX_ENABLED
-		if (k->get_scancode_with_modifiers() == (KEY_MASK_CMD | KEY_Q)) {
+		if (k->get_keycode_with_modifiers() == (KEY_MASK_CMD | KEY_Q)) {
 			_dim_window();
 			get_tree()->quit();
 		}
@@ -1908,9 +1908,9 @@ void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) {
 		if (tabs->get_current_tab() != 0)
 			return;
 
-		bool scancode_handled = true;
+		bool keycode_handled = true;
 
-		switch (k->get_scancode()) {
+		switch (k->get_keycode()) {
 
 			case KEY_ENTER: {
 
@@ -1967,14 +1967,14 @@ void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) {
 				if (k->get_command())
 					this->project_filter->search_box->grab_focus();
 				else
-					scancode_handled = false;
+					keycode_handled = false;
 			} break;
 			default: {
-				scancode_handled = false;
+				keycode_handled = false;
 			} break;
 		}
 
-		if (scancode_handled) {
+		if (keycode_handled) {
 			accept_event();
 		}
 	}

+ 45 - 10
editor/project_settings_editor.cpp

@@ -82,7 +82,7 @@ void ProjectSettingsEditor::_unhandled_input(const Ref<InputEvent> &p_event) {
 
 	if (k.is_valid() && is_window_modal_on_top() && k->is_pressed()) {
 
-		if (k->get_scancode_with_modifiers() == (KEY_MASK_CMD | KEY_F)) {
+		if (k->get_keycode_with_modifiers() == (KEY_MASK_CMD | KEY_F)) {
 			if (search_button->is_pressed()) {
 				search_box->grab_focus();
 				search_box->select_all();
@@ -110,7 +110,8 @@ void ProjectSettingsEditor::_notification(int p_what) {
 
 			translation_list->connect("button_pressed", callable_mp(this, &ProjectSettingsEditor::_translation_delete));
 			_update_actions();
-			popup_add->add_icon_item(get_icon("Keyboard", "EditorIcons"), TTR("Key "), INPUT_KEY); //"Key " - because the word 'key' has already been used as a key animation
+			popup_add->add_icon_item(get_icon("Keyboard", "EditorIcons"), TTR("Key"), INPUT_KEY); //"Key " - because the word 'key' has already been used as a key animation
+			popup_add->add_icon_item(get_icon("KeyboardPhysical", "EditorIcons"), TTR("Physical Key"), INPUT_KEY_PHYSICAL);
 			popup_add->add_icon_item(get_icon("JoyButton", "EditorIcons"), TTR("Joy Button"), INPUT_JOY_BUTTON);
 			popup_add->add_icon_item(get_icon("JoyAxis", "EditorIcons"), TTR("Joy Axis"), INPUT_JOY_MOTION);
 			popup_add->add_icon_item(get_icon("Mouse", "EditorIcons"), TTR("Mouse Button"), INPUT_MOUSE_BUTTON);
@@ -146,6 +147,7 @@ void ProjectSettingsEditor::_notification(int p_what) {
 			search_box->set_clear_button_enabled(true);
 			action_add_error->add_color_override("font_color", get_color("error_color", "Editor"));
 			popup_add->set_item_icon(popup_add->get_item_index(INPUT_KEY), get_icon("Keyboard", "EditorIcons"));
+			popup_add->set_item_icon(popup_add->get_item_index(INPUT_KEY_PHYSICAL), get_icon("KeyboardPhysical", "EditorIcons"));
 			popup_add->set_item_icon(popup_add->get_item_index(INPUT_JOY_BUTTON), get_icon("JoyButton", "EditorIcons"));
 			popup_add->set_item_icon(popup_add->get_item_index(INPUT_JOY_MOTION), get_icon("JoyAxis", "EditorIcons"));
 			popup_add->set_item_icon(popup_add->get_item_index(INPUT_MOUSE_BUTTON), get_icon("Mouse", "EditorIcons"));
@@ -361,7 +363,13 @@ void ProjectSettingsEditor::_press_a_key_confirm() {
 
 	Ref<InputEventKey> ie;
 	ie.instance();
-	ie->set_scancode(last_wait_for_key->get_scancode());
+	if (press_a_key_physical) {
+		ie->set_physical_keycode(last_wait_for_key->get_physical_keycode());
+		ie->set_keycode(0);
+	} else {
+		ie->set_physical_keycode(0);
+		ie->set_keycode(last_wait_for_key->get_keycode());
+	}
 	ie->set_shift(last_wait_for_key->get_shift());
 	ie->set_alt(last_wait_for_key->get_alt());
 	ie->set_control(last_wait_for_key->get_control());
@@ -379,8 +387,14 @@ void ProjectSettingsEditor::_press_a_key_confirm() {
 		Ref<InputEventKey> aie = events[i];
 		if (aie.is_null())
 			continue;
-		if (aie->get_scancode_with_modifiers() == ie->get_scancode_with_modifiers()) {
-			return;
+		if (!press_a_key_physical) {
+			if (aie->get_keycode_with_modifiers() == ie->get_keycode_with_modifiers()) {
+				return;
+			}
+		} else {
+			if (aie->get_physical_keycode_with_modifiers() == ie->get_physical_keycode_with_modifiers()) {
+				return;
+			}
 		}
 	}
 
@@ -441,10 +455,10 @@ void ProjectSettingsEditor::_wait_for_key(const Ref<InputEvent> &p_event) {
 
 	Ref<InputEventKey> k = p_event;
 
-	if (k.is_valid() && k->is_pressed() && k->get_scancode() != 0) {
+	if (k.is_valid() && k->is_pressed() && k->get_keycode() != 0) {
 
 		last_wait_for_key = p_event;
-		const String str = keycode_get_string(k->get_scancode_with_modifiers());
+		const String str = (press_a_key_physical) ? keycode_get_string(k->get_physical_keycode_with_modifiers()) + TTR(" (Physical)") : keycode_get_string(k->get_keycode_with_modifiers());
 
 		press_a_key_label->set_text(str);
 		press_a_key->get_ok()->set_disabled(false);
@@ -460,12 +474,23 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even
 
 		case INPUT_KEY: {
 
+			press_a_key_physical = false;
 			press_a_key_label->set_text(TTR("Press a Key..."));
 			press_a_key->get_ok()->set_disabled(true);
 			last_wait_for_key = Ref<InputEvent>();
 			press_a_key->popup_centered(Size2(250, 80) * EDSCALE);
 			press_a_key->grab_focus();
 
+		} break;
+		case INPUT_KEY_PHYSICAL: {
+
+			press_a_key_physical = true;
+			press_a_key_label->set_text(TTR("Press a Key..."));
+
+			last_wait_for_key = Ref<InputEvent>();
+			press_a_key->popup_centered(Size2(250, 80) * EDSCALE);
+			press_a_key->grab_focus();
+
 		} break;
 		case INPUT_MOUSE_BUTTON: {
 
@@ -547,7 +572,11 @@ void ProjectSettingsEditor::_edit_item(Ref<InputEvent> p_exiting_event) {
 	InputType ie_type;
 
 	if ((Ref<InputEventKey>(p_exiting_event)).is_valid()) {
-		ie_type = INPUT_KEY;
+		if ((Ref<InputEventKey>(p_exiting_event))->get_keycode() != 0) {
+			ie_type = INPUT_KEY;
+		} else {
+			ie_type = INPUT_KEY_PHYSICAL;
+		}
 
 	} else if ((Ref<InputEventJoypadButton>(p_exiting_event)).is_valid()) {
 		ie_type = INPUT_JOY_BUTTON;
@@ -745,10 +774,14 @@ void ProjectSettingsEditor::_update_actions() {
 			Ref<InputEventKey> k = event;
 			if (k.is_valid()) {
 
-				const String str = keycode_get_string(k->get_scancode_with_modifiers());
+				const String str = (k->get_keycode() == 0) ? keycode_get_string(k->get_physical_keycode_with_modifiers()) + TTR(" (Physical)") : keycode_get_string(k->get_keycode_with_modifiers());
 
 				action2->set_text(0, str);
-				action2->set_icon(0, get_icon("Keyboard", "EditorIcons"));
+				if ((k->get_keycode() != 0)) {
+					action2->set_icon(0, get_icon("Keyboard", "EditorIcons"));
+				} else {
+					action2->set_icon(0, get_icon("KeyboardPhysical", "EditorIcons"));
+				}
 			}
 
 			Ref<InputEventJoypadButton> jb = event;
@@ -1924,6 +1957,8 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
 	add_child(popup_add);
 	popup_add->connect("id_pressed", callable_mp(this, &ProjectSettingsEditor::_add_item), make_binds(Ref<InputEvent>()));
 
+	press_a_key_physical = false;
+
 	press_a_key = memnew(ConfirmationDialog);
 	press_a_key->set_focus_mode(FOCUS_ALL);
 	add_child(press_a_key);

+ 2 - 0
editor/project_settings_editor.h

@@ -45,6 +45,7 @@ class ProjectSettingsEditor : public AcceptDialog {
 
 	enum InputType {
 		INPUT_KEY,
+		INPUT_KEY_PHYSICAL,
 		INPUT_JOY_BUTTON,
 		INPUT_JOY_MOTION,
 		INPUT_MOUSE_BUTTON
@@ -77,6 +78,7 @@ class ProjectSettingsEditor : public AcceptDialog {
 	OptionButton *type;
 	PopupMenu *popup_add;
 	ConfirmationDialog *press_a_key;
+	bool press_a_key_physical;
 	Label *press_a_key_label;
 	ConfirmationDialog *device_input;
 	OptionButton *device_id;

+ 1 - 1
editor/property_selector.cpp

@@ -45,7 +45,7 @@ void PropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) {
 
 	if (k.is_valid()) {
 
-		switch (k->get_scancode()) {
+		switch (k->get_keycode()) {
 			case KEY_UP:
 			case KEY_DOWN:
 			case KEY_PAGEUP:

+ 1 - 1
editor/quick_open.cpp

@@ -83,7 +83,7 @@ void EditorQuickOpen::_sbox_input(const Ref<InputEvent> &p_ie) {
 	Ref<InputEventKey> k = p_ie;
 	if (k.is_valid()) {
 
-		switch (k->get_scancode()) {
+		switch (k->get_keycode()) {
 			case KEY_UP:
 			case KEY_DOWN:
 			case KEY_PAGEUP:

+ 4 - 4
editor/settings_config_dialog.cpp

@@ -163,7 +163,7 @@ void EditorSettingsDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
 			handled = true;
 		}
 
-		if (k->get_scancode_with_modifiers() == (KEY_MASK_CMD | KEY_F)) {
+		if (k->get_keycode_with_modifiers() == (KEY_MASK_CMD | KEY_F)) {
 			_focus_current_search_box();
 			handled = true;
 		}
@@ -317,10 +317,10 @@ void EditorSettingsDialog::_wait_for_key(const Ref<InputEvent> &p_event) {
 
 	Ref<InputEventKey> k = p_event;
 
-	if (k.is_valid() && k->is_pressed() && k->get_scancode() != 0) {
+	if (k.is_valid() && k->is_pressed() && k->get_keycode() != 0) {
 
 		last_wait_for_key = k;
-		const String str = keycode_get_string(k->get_scancode_with_modifiers());
+		const String str = keycode_get_string(k->get_keycode_with_modifiers());
 
 		press_a_key_label->set_text(str);
 		press_a_key->accept_event();
@@ -334,7 +334,7 @@ void EditorSettingsDialog::_press_a_key_confirm() {
 
 	Ref<InputEventKey> ie;
 	ie.instance();
-	ie->set_scancode(last_wait_for_key->get_scancode());
+	ie->set_keycode(last_wait_for_key->get_keycode());
 	ie->set_shift(last_wait_for_key->get_shift());
 	ie->set_control(last_wait_for_key->get_control());
 	ie->set_alt(last_wait_for_key->get_alt());

+ 5 - 5
main/input_default.cpp

@@ -73,10 +73,10 @@ InputDefault::SpeedTrack::SpeedTrack() {
 	reset();
 }
 
-bool InputDefault::is_key_pressed(int p_scancode) const {
+bool InputDefault::is_key_pressed(int p_keycode) const {
 
 	_THREAD_SAFE_METHOD_
-	return keys_pressed.has(p_scancode);
+	return keys_pressed.has(p_keycode);
 }
 
 bool InputDefault::is_mouse_button_pressed(int p_button) const {
@@ -271,11 +271,11 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool
 	_THREAD_SAFE_METHOD_
 
 	Ref<InputEventKey> k = p_event;
-	if (k.is_valid() && !k->is_echo() && k->get_scancode() != 0) {
+	if (k.is_valid() && !k->is_echo() && k->get_keycode() != 0) {
 		if (k->is_pressed())
-			keys_pressed.insert(k->get_scancode());
+			keys_pressed.insert(k->get_keycode());
 		else
-			keys_pressed.erase(k->get_scancode());
+			keys_pressed.erase(k->get_keycode());
 	}
 
 	Ref<InputEventMouseButton> mb = p_event;

+ 1 - 1
main/input_default.h

@@ -187,7 +187,7 @@ private:
 	bool use_accumulated_input;
 
 public:
-	virtual bool is_key_pressed(int p_scancode) const;
+	virtual bool is_key_pressed(int p_keycode) const;
 	virtual bool is_mouse_button_pressed(int p_button) const;
 	virtual bool is_joy_button_pressed(int p_device, int p_button) const;
 	virtual bool is_action_pressed(const StringName &p_action) const;

+ 4 - 4
modules/gridmap/grid_map_editor_plugin.cpp

@@ -752,7 +752,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu
 
 	if (k.is_valid()) {
 		if (k->is_pressed()) {
-			if (k->get_scancode() == KEY_ESCAPE) {
+			if (k->get_keycode() == KEY_ESCAPE) {
 
 				if (input_action == INPUT_PASTE) {
 					_clear_clipboard_data();
@@ -773,12 +773,12 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu
 
 			if (k->get_shift() && selection.active && input_action != INPUT_PASTE) {
 
-				if (k->get_scancode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL))) {
+				if (k->get_keycode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL))) {
 					selection.click[edit_axis]--;
 					_validate_selection();
 					return true;
 				}
-				if (k->get_scancode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_NEXT_LEVEL))) {
+				if (k->get_keycode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_NEXT_LEVEL))) {
 					selection.click[edit_axis]++;
 					_validate_selection();
 					return true;
@@ -842,7 +842,7 @@ void GridMapEditor::_sbox_input(const Ref<InputEvent> &p_ie) {
 
 	const Ref<InputEventKey> k = p_ie;
 
-	if (k.is_valid() && (k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_PAGEUP || k->get_scancode() == KEY_PAGEDOWN)) {
+	if (k.is_valid() && (k->get_keycode() == KEY_UP || k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_PAGEUP || k->get_keycode() == KEY_PAGEDOWN)) {
 
 		// Forward the key input to the ItemList so it can be scrolled
 		mesh_library_palette->call("_gui_input", k);

+ 1 - 1
modules/visual_script/visual_script_editor.cpp

@@ -1832,7 +1832,7 @@ void VisualScriptEditor::_fn_name_box_input(const Ref<InputEvent> &p_event) {
 		return;
 
 	Ref<InputEventKey> key = p_event;
-	if (key.is_valid() && key->is_pressed() && key->get_scancode() == KEY_ENTER) {
+	if (key.is_valid() && key->is_pressed() && key->get_keycode() == KEY_ENTER) {
 		function_name_edit->hide();
 		_rename_function(selected, function_name_box->get_text());
 		function_name_box->clear();

+ 1 - 1
modules/visual_script/visual_script_property_selector.cpp

@@ -51,7 +51,7 @@ void VisualScriptPropertySelector::_sbox_input(const Ref<InputEvent> &p_ie) {
 
 	if (k.is_valid()) {
 
-		switch (k->get_scancode()) {
+		switch (k->get_keycode()) {
 			case KEY_UP:
 			case KEY_DOWN:
 			case KEY_PAGEUP:

+ 2 - 2
platform/android/java/lib/src/org/godotengine/godot/Godot.java

@@ -990,8 +990,8 @@ public abstract class Godot extends Activity implements SensorEventListener, IDo
 					int keyCode;
 					if ((keyCode = cc[i]) != 0) {
 						// Simulate key down and up...
-						GodotLib.key(0, keyCode, true);
-						GodotLib.key(0, keyCode, false);
+						GodotLib.key(0, 0, keyCode, true);
+						GodotLib.key(0, 0, keyCode, false);
 					}
 				}
 			}

+ 1 - 1
platform/android/java/lib/src/org/godotengine/godot/GodotLib.java

@@ -136,7 +136,7 @@ public class GodotLib {
 	/**
 	 * Forward regular key events from the main thread to the GL thread.
 	 */
-	public static native void key(int p_scancode, int p_unicode_char, boolean p_pressed);
+	public static native void key(int p_keycode, int p_scancode, int p_unicode_char, boolean p_pressed);
 
 	/**
 	 * Forward game device's key events from the main thread to the GL thread.

+ 4 - 2
platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java

@@ -98,11 +98,12 @@ public class GodotInputHandler implements InputDeviceListener {
 				});
 			}
 		} else {
+			final int scanCode = event.getScanCode();
 			final int chr = event.getUnicodeChar(0);
 			queueEvent(new Runnable() {
 				@Override
 				public void run() {
-					GodotLib.key(keyCode, chr, false);
+					GodotLib.key(keyCode, scanCode, chr, false);
 				}
 			});
 		};
@@ -143,11 +144,12 @@ public class GodotInputHandler implements InputDeviceListener {
 				});
 			}
 		} else {
+			final int scanCode = event.getScanCode();
 			final int chr = event.getUnicodeChar(0);
 			queueEvent(new Runnable() {
 				@Override
 				public void run() {
-					GodotLib.key(keyCode, chr, true);
+					GodotLib.key(keyCode, scanCode, chr, true);
 				}
 			});
 		};

+ 6 - 6
platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java

@@ -91,8 +91,8 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 			@Override
 			public void run() {
 				for (int i = 0; i < count; ++i) {
-					GodotLib.key(KeyEvent.KEYCODE_DEL, 0, true);
-					GodotLib.key(KeyEvent.KEYCODE_DEL, 0, false);
+					GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, true);
+					GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, false);
 				}
 			}
 		});
@@ -110,8 +110,8 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 			@Override
 			public void run() {
 				for (int i = 0; i < count; ++i) {
-					GodotLib.key(0, newChars[i], true);
-					GodotLib.key(0, newChars[i], false);
+					GodotLib.key(0, 0, newChars[i], true);
+					GodotLib.key(0, 0, newChars[i], false);
 				}
 			}
 		});
@@ -127,8 +127,8 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 				public void run() {
 					for (int i = 0; i < characters.length(); i++) {
 						final int ch = characters.codePointAt(i);
-						GodotLib.key(0, ch, true);
-						GodotLib.key(0, ch, false);
+						GodotLib.key(0, 0, ch, true);
+						GodotLib.key(0, 0, ch, false);
 					}
 				}
 			});

+ 9 - 8
platform/android/java_godot_lib_jni.cpp

@@ -1167,28 +1167,29 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(
 	}
 }
 
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_keycode, jint p_scancode, jint p_unicode_char, jboolean p_pressed) {
 	if (step == 0)
 		return;
 
 	Ref<InputEventKey> ievent;
 	ievent.instance();
 	int val = p_unicode_char;
-	int scancode = android_get_keysym(p_scancode);
-	ievent->set_scancode(scancode);
+	int keycode = android_get_keysym(p_keycode);
+	int phy_keycode = android_get_keysym(p_scancode);
+	ievent->set_keycode(keycode);
+	ievent->set_physical_keycode(phy_keycode);
 	ievent->set_unicode(val);
 	ievent->set_pressed(p_pressed);
 
 	if (val == '\n') {
-		ievent->set_scancode(KEY_ENTER);
+		ievent->set_keycode(KEY_ENTER);
 	} else if (val == 61448) {
-		ievent->set_scancode(KEY_BACKSPACE);
+		ievent->set_keycode(KEY_BACKSPACE);
 		ievent->set_unicode(KEY_BACKSPACE);
 	} else if (val == 61453) {
-		ievent->set_scancode(KEY_ENTER);
+		ievent->set_keycode(KEY_ENTER);
 		ievent->set_unicode(KEY_ENTER);
-	} else if (p_scancode == 4) {
-
+	} else if (p_keycode == 4) {
 		os_android->main_loop_request_go_back();
 	}
 

+ 1 - 1
platform/android/java_godot_lib_jni.h

@@ -48,7 +48,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jo
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jobject obj, jint p_type, jint p_x, jint p_y);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubletap(JNIEnv *env, jobject obj, jint p_x, jint p_y);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jobject obj, jint p_x, jint p_y);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_keycode, jint p_scancode, jint p_unicode_char, jboolean p_pressed);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jobject obj, jint p_device, jint p_button, jboolean p_pressed);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jobject obj, jint p_device, jint p_axis, jfloat p_value);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jobject obj, jint p_device, jint p_hat_x, jint p_hat_y);

+ 5 - 3
platform/haiku/haiku_direct_window.cpp

@@ -273,7 +273,8 @@ void HaikuDirectWindow::HandleKeyboardEvent(BMessage *message) {
 	event.instance();
 	GetKeyModifierState(event, modifiers);
 	event->set_pressed(message->what == B_KEY_DOWN);
-	event->set_scancode(KeyMappingHaiku::get_keysym(raw_char, key));
+	event->set_keycode(KeyMappingHaiku::get_keysym(raw_char, key));
+	event->set_physical_keycode(KeyMappingHaiku::get_keysym(raw_char, key));
 	event->set_echo(message->HasInt32("be:key_repeat"));
 	event->set_unicode(0);
 
@@ -283,8 +284,9 @@ void HaikuDirectWindow::HandleKeyboardEvent(BMessage *message) {
 	}
 
 	//make it consistent across platforms.
-	if (event->get_scancode() == KEY_BACKTAB) {
-		event->set_scancode(KEY_TAB);
+	if (event->get_keycode() == KEY_BACKTAB) {
+		event->set_keycode(KEY_TAB);
+		event->set_physical_keycode(KEY_TAB);
 		event->set_shift(true);
 	}
 

+ 2 - 2
platform/iphone/os_iphone.cpp

@@ -135,7 +135,6 @@ Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p
 	RasterizerRD::make_current();
 #endif
 
-	
 	visual_server = memnew(VisualServerRaster);
 	// FIXME: Reimplement threaded rendering
 	if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
@@ -212,7 +211,8 @@ void OSIPhone::key(uint32_t p_key, bool p_pressed) {
 	ev.instance();
 	ev->set_echo(false);
 	ev->set_pressed(p_pressed);
-	ev->set_scancode(p_key);
+	ev->set_keycode(p_key);
+	ev->set_physical_keycode(p_key);
 	ev->set_unicode(p_key);
 	queue_event(ev);
 };

+ 1 - 1
platform/javascript/dom_keys.inc

@@ -218,7 +218,7 @@
 #define DOM_VK_PA1 0xFD
 #define DOM_VK_WIN_OEM_CLEAR 0xFE
 
-int dom2godot_scancode(int dom_keycode) {
+int dom2godot_keycode(int dom_keycode) {
 
 	if (DOM_VK_0 <= dom_keycode && dom_keycode <= DOM_VK_Z) {
 		// ASCII intersection

+ 4 - 3
platform/javascript/os_javascript.cpp

@@ -250,7 +250,8 @@ static Ref<InputEventKey> setup_key_event(const EmscriptenKeyboardEvent *emscrip
 	ev.instance();
 	ev->set_echo(emscripten_event->repeat);
 	dom2godot_mod(emscripten_event, ev);
-	ev->set_scancode(dom2godot_scancode(emscripten_event->keyCode));
+	ev->set_keycode(dom2godot_keycode(emscripten_event->keyCode));
+	ev->set_physical_keycode(dom2godot_keycode(emscripten_event->keyCode));
 
 	String unicode = String::utf8(emscripten_event->key);
 	// Check if empty or multi-character (e.g. `CapsLock`).
@@ -270,7 +271,7 @@ EM_BOOL OS_JavaScript::keydown_callback(int p_event_type, const EmscriptenKeyboa
 	OS_JavaScript *os = get_singleton();
 	Ref<InputEventKey> ev = setup_key_event(p_event);
 	ev->set_pressed(true);
-	if (ev->get_unicode() == 0 && keycode_has_unicode(ev->get_scancode())) {
+	if (ev->get_unicode() == 0 && keycode_has_unicode(ev->get_keycode())) {
 		// Defer to keypress event for legacy unicode retrieval.
 		os->deferred_key_event = ev;
 		// Do not suppress keypress event.
@@ -295,7 +296,7 @@ EM_BOOL OS_JavaScript::keyup_callback(int p_event_type, const EmscriptenKeyboard
 	Ref<InputEventKey> ev = setup_key_event(p_event);
 	ev->set_pressed(false);
 	get_singleton()->input->parse_input_event(ev);
-	return ev->get_scancode() != KEY_UNKNOWN && ev->get_scancode() != 0;
+	return ev->get_keycode() != KEY_UNKNOWN && ev->get_keycode() != 0;
 }
 
 // Mouse

+ 2 - 1
platform/osx/os_osx.h

@@ -69,7 +69,8 @@ public:
 		bool pressed;
 		bool echo;
 		bool raw;
-		uint32_t scancode;
+		uint32_t keycode;
+		uint32_t physical_keycode;
 		uint32_t unicode;
 	};
 

+ 23 - 13
platform/osx/os_osx.mm

@@ -157,7 +157,8 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
 
 			get_key_modifier_state([event modifierFlags], k);
 			k->set_pressed(true);
-			k->set_scancode(KEY_PERIOD);
+			k->set_keycode(KEY_PERIOD);
+			k->set_physical_keycode(KEY_PERIOD);
 			k->set_echo([event isARepeat]);
 
 			OS_OSX::singleton->push_input(k);
@@ -635,7 +636,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
 		ke.pressed = true;
 		ke.echo = false;
 		ke.raw = false; // IME input event
-		ke.scancode = 0;
+		ke.keycode = 0;
+		ke.physical_keycode = 0;
 		ke.unicode = codepoint;
 
 		push_to_key_event_buffer(ke);
@@ -1158,7 +1160,8 @@ static int remapKey(unsigned int key, unsigned int state) {
 				ke.osx_state = [event modifierFlags];
 				ke.pressed = true;
 				ke.echo = [event isARepeat];
-				ke.scancode = remapKey([event keyCode], [event modifierFlags]);
+				ke.keycode = remapKey([event keyCode], [event modifierFlags]);
+				ke.physical_keycode = translateKey([event keyCode]);
 				ke.raw = true;
 				ke.unicode = [characters characterAtIndex:i];
 
@@ -1170,7 +1173,8 @@ static int remapKey(unsigned int key, unsigned int state) {
 			ke.osx_state = [event modifierFlags];
 			ke.pressed = true;
 			ke.echo = [event isARepeat];
-			ke.scancode = remapKey([event keyCode], [event modifierFlags]);
+			ke.keycode = remapKey([event keyCode], [event modifierFlags]);
+			ke.physical_keycode = translateKey([event keyCode]);
 			ke.raw = false;
 			ke.unicode = 0;
 
@@ -1228,7 +1232,8 @@ static int remapKey(unsigned int key, unsigned int state) {
 		}
 
 		ke.osx_state = mod;
-		ke.scancode = remapKey(key, mod);
+		ke.keycode = remapKey(key, mod);
+		ke.physical_keycode = translateKey(key);
 		ke.unicode = 0;
 
 		push_to_key_event_buffer(ke);
@@ -1250,7 +1255,8 @@ static int remapKey(unsigned int key, unsigned int state) {
 				ke.osx_state = [event modifierFlags];
 				ke.pressed = false;
 				ke.echo = [event isARepeat];
-				ke.scancode = remapKey([event keyCode], [event modifierFlags]);
+				ke.keycode = remapKey([event keyCode], [event modifierFlags]);
+				ke.physical_keycode = translateKey([event keyCode]);
 				ke.raw = true;
 				ke.unicode = [characters characterAtIndex:i];
 
@@ -1262,7 +1268,8 @@ static int remapKey(unsigned int key, unsigned int state) {
 			ke.osx_state = [event modifierFlags];
 			ke.pressed = false;
 			ke.echo = [event isARepeat];
-			ke.scancode = remapKey([event keyCode], [event modifierFlags]);
+			ke.keycode = remapKey([event keyCode], [event modifierFlags]);
+			ke.physical_keycode = translateKey([event keyCode]);
 			ke.raw = true;
 			ke.unicode = 0;
 
@@ -2845,32 +2852,35 @@ void OS_OSX::process_key_events() {
 			get_key_modifier_state(ke.osx_state, k);
 			k->set_pressed(ke.pressed);
 			k->set_echo(ke.echo);
-			k->set_scancode(ke.scancode);
+			k->set_keycode(ke.keycode);
+			k->set_physical_keycode(ke.physical_keycode);
 			k->set_unicode(ke.unicode);
 
 			push_input(k);
 		} else {
 			// IME input
-			if ((i == 0 && ke.scancode == 0) || (i > 0 && key_event_buffer[i - 1].scancode == 0)) {
+			if ((i == 0 && ke.keycode == 0) || (i > 0 && key_event_buffer[i - 1].keycode == 0)) {
 				k.instance();
 
 				get_key_modifier_state(ke.osx_state, k);
 				k->set_pressed(ke.pressed);
 				k->set_echo(ke.echo);
-				k->set_scancode(0);
+				k->set_keycode(0);
+				k->set_physical_keycode(0);
 				k->set_unicode(ke.unicode);
 
 				push_input(k);
 			}
-			if (ke.scancode != 0) {
+			if (ke.keycode != 0) {
 				k.instance();
 
 				get_key_modifier_state(ke.osx_state, k);
 				k->set_pressed(ke.pressed);
 				k->set_echo(ke.echo);
-				k->set_scancode(ke.scancode);
+				k->set_keycode(ke.keycode);
+				k->set_physical_keycode(ke.physical_keycode);
 
-				if (i + 1 < key_event_pos && key_event_buffer[i + 1].scancode == 0) {
+				if (i + 1 < key_event_pos && key_event_buffer[i + 1].keycode == 0) {
 					k->set_unicode(key_event_buffer[i + 1].unicode);
 				}
 

+ 4 - 2
platform/uwp/app.cpp

@@ -410,14 +410,16 @@ void App::key_event(Windows::UI::Core::CoreWindow ^ sender, bool p_pressed, Wind
 
 		ke.type = OS_UWP::KeyEvent::MessageType::KEY_EVENT_MESSAGE;
 		ke.unicode = 0;
-		ke.scancode = KeyMappingWindows::get_keysym((unsigned int)key_args->VirtualKey);
+		ke.keycode = KeyMappingWindows::get_keysym((unsigned int)key_args->VirtualKey);
+		ke.physical_keycode = KeyMappingWindows::get_scansym((unsigned int)key_args->KeyStatus.ScanCode);
 		ke.echo = (!p_pressed && !key_args->KeyStatus.IsKeyReleased) || (p_pressed && key_args->KeyStatus.WasKeyDown);
 
 	} else {
 
 		ke.type = OS_UWP::KeyEvent::MessageType::CHAR_EVENT_MESSAGE;
 		ke.unicode = char_args->KeyCode;
-		ke.scancode = 0;
+		ke.keycode = 0;
+		ke.physical_keycode = 0;
 		ke.echo = (!p_pressed && !char_args->KeyStatus.IsKeyReleased) || (p_pressed && char_args->KeyStatus.WasKeyDown);
 	}
 

+ 2 - 1
platform/uwp/os_uwp.cpp

@@ -605,7 +605,8 @@ void OS_UWP::process_key_events() {
 		key_event->set_shift(kev.shift);
 		key_event->set_control(kev.control);
 		key_event->set_echo(kev.echo);
-		key_event->set_scancode(kev.scancode);
+		key_event->set_keycode(kev.keycode);
+		key_event->set_physical_keycode(kev.physical_keycode);
 		key_event->set_unicode(kev.unicode);
 		key_event->set_pressed(kev.pressed);
 

+ 2 - 1
platform/uwp/os_uwp.h

@@ -61,7 +61,8 @@ public:
 		bool alt, shift, control;
 		MessageType type;
 		bool pressed;
-		unsigned int scancode;
+		unsigned int keycode;
+		unsigned int physical_keycode;
 		unsigned int unicode;
 		bool echo;
 		CorePhysicalKeyStatus status;

+ 164 - 0
platform/windows/key_mapping_windows.cpp

@@ -238,6 +238,104 @@ VK_PA1 (0xFD)
 VK_OEM_CLEAR (0xFE)
 */
 
+static _WinTranslatePair _scancode_to_keycode[] = {
+
+	{ KEY_ESCAPE, 0x01 },
+	{ KEY_1, 0x02 },
+	{ KEY_2, 0x03 },
+	{ KEY_3, 0x04 },
+	{ KEY_4, 0x05 },
+	{ KEY_5, 0x06 },
+	{ KEY_6, 0x07 },
+	{ KEY_7, 0x08 },
+	{ KEY_8, 0x09 },
+	{ KEY_9, 0x0A },
+	{ KEY_0, 0x0B },
+	{ KEY_MINUS, 0x0C },
+	{ KEY_EQUAL, 0x0D },
+	{ KEY_BACKSPACE, 0x0E },
+	{ KEY_TAB, 0x0F },
+	{ KEY_Q, 0x10 },
+	{ KEY_W, 0x11 },
+	{ KEY_E, 0x12 },
+	{ KEY_R, 0x13 },
+	{ KEY_T, 0x14 },
+	{ KEY_Y, 0x15 },
+	{ KEY_U, 0x16 },
+	{ KEY_I, 0x17 },
+	{ KEY_O, 0x18 },
+	{ KEY_P, 0x19 },
+	{ KEY_BRACELEFT, 0x1A },
+	{ KEY_BRACERIGHT, 0x1B },
+	{ KEY_ENTER, 0x1C },
+	{ KEY_CONTROL, 0x1D },
+	{ KEY_A, 0x1E },
+	{ KEY_S, 0x1F },
+	{ KEY_D, 0x20 },
+	{ KEY_F, 0x21 },
+	{ KEY_G, 0x22 },
+	{ KEY_H, 0x23 },
+	{ KEY_J, 0x24 },
+	{ KEY_K, 0x25 },
+	{ KEY_L, 0x26 },
+	{ KEY_SEMICOLON, 0x27 },
+	{ KEY_APOSTROPHE, 0x28 },
+	{ KEY_QUOTELEFT, 0x29 },
+	{ KEY_SHIFT, 0x2A },
+	{ KEY_BACKSLASH, 0x2B },
+	{ KEY_Z, 0x2C },
+	{ KEY_X, 0x2D },
+	{ KEY_C, 0x2E },
+	{ KEY_V, 0x2F },
+	{ KEY_B, 0x30 },
+	{ KEY_N, 0x31 },
+	{ KEY_M, 0x32 },
+	{ KEY_COMMA, 0x33 },
+	{ KEY_PERIOD, 0x34 },
+	{ KEY_SLASH, 0x35 },
+	{ KEY_SHIFT, 0x36 },
+	{ KEY_PRINT, 0x37 },
+	{ KEY_ALT, 0x38 },
+	{ KEY_SPACE, 0x39 },
+	{ KEY_CAPSLOCK, 0x3A },
+	{ KEY_F1, 0x3B },
+	{ KEY_F2, 0x3C },
+	{ KEY_F3, 0x3D },
+	{ KEY_F4, 0x3E },
+	{ KEY_F5, 0x3F },
+	{ KEY_F6, 0x40 },
+	{ KEY_F7, 0x41 },
+	{ KEY_F8, 0x42 },
+	{ KEY_F9, 0x43 },
+	{ KEY_F10, 0x44 },
+	{ KEY_NUMLOCK, 0x45 },
+	{ KEY_SCROLLLOCK, 0x46 },
+	{ KEY_HOME, 0x47 },
+	{ KEY_UP, 0x48 },
+	{ KEY_PAGEUP, 0x49 },
+	{ KEY_KP_SUBTRACT, 0x4A },
+	{ KEY_LEFT, 0x4B },
+	{ KEY_KP_5, 0x4C },
+	{ KEY_RIGHT, 0x4D },
+	{ KEY_KP_ADD, 0x4E },
+	{ KEY_END, 0x4F },
+	{ KEY_DOWN, 0x50 },
+	{ KEY_PAGEDOWN, 0x51 },
+	{ KEY_INSERT, 0x52 },
+	{ KEY_DELETE, 0x53 },
+	//{ KEY_???, 0x56 }, //NON US BACKSLASH
+	{ KEY_F11, 0x57 },
+	{ KEY_F12, 0x58 },
+	{ KEY_META, 0x5B },
+	{ KEY_META, 0x5C },
+	{ KEY_MENU, 0x5D },
+	{ KEY_F13, 0x64 },
+	{ KEY_F14, 0x65 },
+	{ KEY_F15, 0x66 },
+	{ KEY_F16, 0x67 },
+	{ KEY_UNKNOWN, 0 }
+};
+
 unsigned int KeyMappingWindows::get_keysym(unsigned int p_code) {
 
 	for (int i = 0; _vk_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
@@ -251,3 +349,69 @@ unsigned int KeyMappingWindows::get_keysym(unsigned int p_code) {
 
 	return KEY_UNKNOWN;
 }
+
+unsigned int KeyMappingWindows::get_scansym(unsigned int p_code, bool p_extended) {
+	unsigned int keycode = KEY_UNKNOWN;
+	for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
+
+		if (_scancode_to_keycode[i].keycode == p_code) {
+			keycode = _scancode_to_keycode[i].keysym;
+			break;
+		}
+	}
+
+	if (p_extended) {
+		switch (keycode) {
+			case KEY_ENTER: {
+				keycode = KEY_KP_ENTER;
+			} break;
+			case KEY_SLASH: {
+				keycode = KEY_KP_DIVIDE;
+			} break;
+			case KEY_CAPSLOCK: {
+				keycode = KEY_KP_ADD;
+			} break;
+		}
+	} else {
+		switch (keycode) {
+			case KEY_NUMLOCK: {
+				keycode = KEY_PAUSE;
+			} break;
+			case KEY_HOME: {
+				keycode = KEY_KP_7;
+			} break;
+			case KEY_UP: {
+				keycode = KEY_KP_8;
+			} break;
+			case KEY_PAGEUP: {
+				keycode = KEY_KP_9;
+			} break;
+			case KEY_LEFT: {
+				keycode = KEY_KP_4;
+			} break;
+			case KEY_RIGHT: {
+				keycode = KEY_KP_6;
+			} break;
+			case KEY_END: {
+				keycode = KEY_KP_1;
+			} break;
+			case KEY_DOWN: {
+				keycode = KEY_KP_2;
+			} break;
+			case KEY_PAGEDOWN: {
+				keycode = KEY_KP_3;
+			} break;
+			case KEY_INSERT: {
+				keycode = KEY_KP_0;
+			} break;
+			case KEY_DELETE: {
+				keycode = KEY_KP_PERIOD;
+			} break;
+			case KEY_PRINT: {
+				keycode = KEY_KP_MULTIPLY;
+			} break;
+		}
+	}
+
+	return keycode;
+}

+ 1 - 0
platform/windows/key_mapping_windows.h

@@ -43,6 +43,7 @@ class KeyMappingWindows {
 
 public:
 	static unsigned int get_keysym(unsigned int p_code);
+	static unsigned int get_scansym(unsigned int p_code, bool p_extended);
 };
 
 #endif // KEY_MAPPING_WINDOWS_H

+ 6 - 3
platform/windows/os_windows.cpp

@@ -1133,7 +1133,8 @@ void OS_Windows::process_key_events() {
 					k->set_control(ke.control);
 					k->set_metakey(ke.meta);
 					k->set_pressed(true);
-					k->set_scancode(KeyMappingWindows::get_keysym(ke.wParam));
+					k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam));
+					k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24)));
 					k->set_unicode(ke.wParam);
 					if (k->get_unicode() && gr_mem) {
 						k->set_alt(false);
@@ -1163,11 +1164,13 @@ void OS_Windows::process_key_events() {
 
 				if ((ke.lParam & (1 << 24)) && (ke.wParam == VK_RETURN)) {
 					// Special case for Numpad Enter key
-					k->set_scancode(KEY_KP_ENTER);
+					k->set_keycode(KEY_KP_ENTER);
 				} else {
-					k->set_scancode(KeyMappingWindows::get_keysym(ke.wParam));
+					k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam));
 				}
 
+				k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24)));
+
 				if (i + 1 < key_event_pos && key_event_buffer[i + 1].uMsg == WM_CHAR) {
 					k->set_unicode(key_event_buffer[i + 1].wParam);
 				}

+ 134 - 0
platform/x11/key_mapping_x11.cpp

@@ -180,6 +180,140 @@ static _XTranslatePair _xkeysym_to_keycode[] = {
 	{ 0, 0 }
 };
 
+struct _TranslatePair {
+
+	unsigned int keysym;
+	unsigned int keycode;
+};
+
+static _TranslatePair _scancode_to_keycode[] = {
+
+	{ KEY_ESCAPE, 0x09 },
+	{ KEY_1, 0x0A },
+	{ KEY_2, 0x0B },
+	{ KEY_3, 0x0C },
+	{ KEY_4, 0x0D },
+	{ KEY_5, 0x0E },
+	{ KEY_6, 0x0F },
+	{ KEY_7, 0x10 },
+	{ KEY_8, 0x11 },
+	{ KEY_9, 0x12 },
+	{ KEY_0, 0x13 },
+	{ KEY_MINUS, 0x14 },
+	{ KEY_EQUAL, 0x15 },
+	{ KEY_BACKSPACE, 0x16 },
+	{ KEY_TAB, 0x17 },
+	{ KEY_Q, 0x18 },
+	{ KEY_W, 0x19 },
+	{ KEY_E, 0x1A },
+	{ KEY_R, 0x1B },
+	{ KEY_T, 0x1C },
+	{ KEY_Y, 0x1D },
+	{ KEY_U, 0x1E },
+	{ KEY_I, 0x1F },
+	{ KEY_O, 0x20 },
+	{ KEY_P, 0x21 },
+	{ KEY_BRACELEFT, 0x22 },
+	{ KEY_BRACERIGHT, 0x23 },
+	{ KEY_ENTER, 0x24 },
+	{ KEY_CONTROL, 0x25 },
+	{ KEY_A, 0x26 },
+	{ KEY_S, 0x27 },
+	{ KEY_D, 0x28 },
+	{ KEY_F, 0x29 },
+	{ KEY_G, 0x2A },
+	{ KEY_H, 0x2B },
+	{ KEY_J, 0x2C },
+	{ KEY_K, 0x2D },
+	{ KEY_L, 0x2E },
+	{ KEY_SEMICOLON, 0x2F },
+	{ KEY_APOSTROPHE, 0x30 },
+	{ KEY_QUOTELEFT, 0x31 },
+	{ KEY_SHIFT, 0x32 },
+	{ KEY_BACKSLASH, 0x33 },
+	{ KEY_Z, 0x34 },
+	{ KEY_X, 0x35 },
+	{ KEY_C, 0x36 },
+	{ KEY_V, 0x37 },
+	{ KEY_B, 0x38 },
+	{ KEY_N, 0x39 },
+	{ KEY_M, 0x3A },
+	{ KEY_COMMA, 0x3B },
+	{ KEY_PERIOD, 0x3C },
+	{ KEY_SLASH, 0x3D },
+	{ KEY_SHIFT, 0x3E },
+	{ KEY_KP_MULTIPLY, 0x3F },
+	{ KEY_ALT, 0x40 },
+	{ KEY_SPACE, 0x41 },
+	{ KEY_CAPSLOCK, 0x42 },
+	{ KEY_F1, 0x43 },
+	{ KEY_F2, 0x44 },
+	{ KEY_F3, 0x45 },
+	{ KEY_F4, 0x46 },
+	{ KEY_F5, 0x47 },
+	{ KEY_F6, 0x48 },
+	{ KEY_F7, 0x49 },
+	{ KEY_F8, 0x4A },
+	{ KEY_F9, 0x4B },
+	{ KEY_F10, 0x4C },
+	{ KEY_NUMLOCK, 0x4D },
+	{ KEY_SCROLLLOCK, 0x4E },
+	{ KEY_KP_7, 0x4F },
+	{ KEY_KP_8, 0x50 },
+	{ KEY_KP_9, 0x51 },
+	{ KEY_KP_SUBTRACT, 0x52 },
+	{ KEY_KP_4, 0x53 },
+	{ KEY_KP_5, 0x54 },
+	{ KEY_KP_6, 0x55 },
+	{ KEY_KP_ADD, 0x56 },
+	{ KEY_KP_1, 0x57 },
+	{ KEY_KP_2, 0x58 },
+	{ KEY_KP_3, 0x59 },
+	{ KEY_KP_0, 0x5A },
+	{ KEY_KP_PERIOD, 0x5B },
+	//{ KEY_???, 0x5E }, //NON US BACKSLASH
+	{ KEY_F11, 0x5F },
+	{ KEY_F12, 0x60 },
+	{ KEY_KP_ENTER, 0x68 },
+	{ KEY_CONTROL, 0x69 },
+	{ KEY_KP_DIVIDE, 0x6A },
+	{ KEY_PRINT, 0x6B },
+	{ KEY_ALT, 0x6C },
+	{ KEY_ENTER, 0x6D },
+	{ KEY_HOME, 0x6E },
+	{ KEY_UP, 0x6F },
+	{ KEY_PAGEUP, 0x70 },
+	{ KEY_LEFT, 0x71 },
+	{ KEY_RIGHT, 0x72 },
+	{ KEY_END, 0x73 },
+	{ KEY_DOWN, 0x74 },
+	{ KEY_PAGEDOWN, 0x75 },
+	{ KEY_INSERT, 0x76 },
+	{ KEY_DELETE, 0x77 },
+	{ KEY_VOLUMEMUTE, 0x79 },
+	{ KEY_VOLUMEDOWN, 0x7A },
+	{ KEY_VOLUMEUP, 0x7B },
+	{ KEY_PAUSE, 0x7F },
+	{ KEY_SUPER_L, 0x85 },
+	{ KEY_SUPER_R, 0x86 },
+	{ KEY_MENU, 0x87 },
+	{ KEY_UNKNOWN, 0 }
+};
+
+unsigned int KeyMappingX11::get_scancode(unsigned int p_code) {
+
+	unsigned int keycode = KEY_UNKNOWN;
+	for (int i = 0; _scancode_to_keycode[i].keysym != KEY_UNKNOWN; i++) {
+
+		if (_scancode_to_keycode[i].keycode == p_code) {
+			keycode = _scancode_to_keycode[i].keysym;
+			break;
+		}
+	}
+
+	return keycode;
+}
+
 unsigned int KeyMappingX11::get_keycode(KeySym p_keysym) {
 
 	// kinda bruteforce.. could optimize.

+ 1 - 0
platform/x11/key_mapping_x11.h

@@ -45,6 +45,7 @@ class KeyMappingX11 {
 
 public:
 	static unsigned int get_keycode(KeySym p_keysym);
+	static unsigned int get_scancode(unsigned int p_code);
 	static KeySym get_keysym(unsigned int p_code);
 	static unsigned int get_unicode_from_keysym(KeySym p_keysym);
 	static KeySym get_keysym_from_unicode(unsigned int p_unicode);

+ 28 - 14
platform/x11/os_x11.cpp

@@ -1888,6 +1888,8 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
 		if (status == XLookupChars) {
 			bool keypress = xkeyevent->type == KeyPress;
 			unsigned int keycode = KeyMappingX11::get_keycode(keysym_keycode);
+			unsigned int physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
+
 			if (keycode >= 'a' && keycode <= 'z')
 				keycode -= 'a' - 'A';
 
@@ -1896,23 +1898,29 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
 			for (int i = 0; i < tmp.length(); i++) {
 				Ref<InputEventKey> k;
 				k.instance();
-				if (keycode == 0 && tmp[i] == 0) {
+				if (physical_keycode == 0 && keycode == 0 && tmp[i] == 0) {
 					continue;
 				}
 
+				if (keycode == 0)
+					keycode = physical_keycode;
+
 				get_key_modifier_state(xkeyevent->state, k);
 
 				k->set_unicode(tmp[i]);
 
 				k->set_pressed(keypress);
 
-				k->set_scancode(keycode);
+				k->set_keycode(keycode);
+
+				k->set_physical_keycode(physical_keycode);
 
 				k->set_echo(false);
 
-				if (k->get_scancode() == KEY_BACKTAB) {
+				if (k->get_keycode() == KEY_BACKTAB) {
 					//make it consistent across platforms.
-					k->set_scancode(KEY_TAB);
+					k->set_keycode(KEY_TAB);
+					k->set_physical_keycode(KEY_TAB);
 					k->set_shift(true);
 				}
 
@@ -1942,6 +1950,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
 	// keysym, so it works in all platforms the same.
 
 	unsigned int keycode = KeyMappingX11::get_keycode(keysym_keycode);
+	unsigned int physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
 
 	/* Phase 3, obtain a unicode character from the keysym */
 
@@ -1961,9 +1970,12 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
 
 	bool keypress = xkeyevent->type == KeyPress;
 
-	if (keycode == 0 && unicode == 0)
+	if (physical_keycode == 0 && keycode == 0 && unicode == 0)
 		return;
 
+	if (keycode == 0)
+		keycode = physical_keycode;
+
 	/* Phase 5, determine modifier mask */
 
 	// No problems here, except I had no way to
@@ -2025,37 +2037,39 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
 	if (keycode >= 'a' && keycode <= 'z')
 		keycode -= 'a' - 'A';
 
-	k->set_scancode(keycode);
+	k->set_keycode(keycode);
+	k->set_physical_keycode(physical_keycode);
 	k->set_unicode(unicode);
 	k->set_echo(p_echo);
 
-	if (k->get_scancode() == KEY_BACKTAB) {
+	if (k->get_keycode() == KEY_BACKTAB) {
 		//make it consistent across platforms.
-		k->set_scancode(KEY_TAB);
+		k->set_keycode(KEY_TAB);
+		k->set_physical_keycode(KEY_TAB);
 		k->set_shift(true);
 	}
 
 	//don't set mod state if modifier keys are released by themselves
 	//else event.is_action() will not work correctly here
 	if (!k->is_pressed()) {
-		if (k->get_scancode() == KEY_SHIFT)
+		if (k->get_keycode() == KEY_SHIFT)
 			k->set_shift(false);
-		else if (k->get_scancode() == KEY_CONTROL)
+		else if (k->get_keycode() == KEY_CONTROL)
 			k->set_control(false);
-		else if (k->get_scancode() == KEY_ALT)
+		else if (k->get_keycode() == KEY_ALT)
 			k->set_alt(false);
-		else if (k->get_scancode() == KEY_META)
+		else if (k->get_keycode() == KEY_META)
 			k->set_metakey(false);
 	}
 
-	bool last_is_pressed = Input::get_singleton()->is_key_pressed(k->get_scancode());
+	bool last_is_pressed = Input::get_singleton()->is_key_pressed(k->get_keycode());
 	if (k->is_pressed()) {
 		if (last_is_pressed) {
 			k->set_echo(true);
 		}
 	}
 
-	//printf("key: %x\n",k->get_scancode());
+	//printf("key: %x\n",k->get_keycode());
 	input->accumulate_input_event(k);
 }
 

+ 1 - 1
scene/gui/file_dialog.cpp

@@ -85,7 +85,7 @@ void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
 
 			bool handled = true;
 
-			switch (k->get_scancode()) {
+			switch (k->get_keycode()) {
 
 				case KEY_H: {
 

+ 1 - 1
scene/gui/gradient_edit.cpp

@@ -96,7 +96,7 @@ void GradientEdit::_gui_input(const Ref<InputEvent> &p_event) {
 
 	Ref<InputEventKey> k = p_event;
 
-	if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_DELETE && grabbed != -1) {
+	if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_DELETE && grabbed != -1) {
 
 		points.remove(grabbed);
 		grabbed = -1;

+ 4 - 4
scene/gui/graph_edit.cpp

@@ -1043,22 +1043,22 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
 
 	if (k.is_valid()) {
 
-		if (k->get_scancode() == KEY_D && k->is_pressed() && k->get_command()) {
+		if (k->get_keycode() == KEY_D && k->is_pressed() && k->get_command()) {
 			emit_signal("duplicate_nodes_request");
 			accept_event();
 		}
 
-		if (k->get_scancode() == KEY_C && k->is_pressed() && k->get_command()) {
+		if (k->get_keycode() == KEY_C && k->is_pressed() && k->get_command()) {
 			emit_signal("copy_nodes_request");
 			accept_event();
 		}
 
-		if (k->get_scancode() == KEY_V && k->is_pressed() && k->get_command()) {
+		if (k->get_keycode() == KEY_V && k->is_pressed() && k->get_command()) {
 			emit_signal("paste_nodes_request");
 			accept_event();
 		}
 
-		if (k->get_scancode() == KEY_DELETE && k->is_pressed()) {
+		if (k->get_keycode() == KEY_DELETE && k->is_pressed()) {
 			emit_signal("delete_nodes_request");
 			accept_event();
 		}

+ 4 - 4
scene/gui/line_edit.cpp

@@ -165,7 +165,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
 #ifdef APPLE_STYLE_KEYS
 		if (k->get_control() && !k->get_shift() && !k->get_alt() && !k->get_command()) {
 			uint32_t remap_key = KEY_UNKNOWN;
-			switch (k->get_scancode()) {
+			switch (k->get_keycode()) {
 				case KEY_F: {
 					remap_key = KEY_RIGHT;
 				} break;
@@ -193,13 +193,13 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
 			}
 
 			if (remap_key != KEY_UNKNOWN) {
-				k->set_scancode(remap_key);
+				k->set_keycode(remap_key);
 				k->set_control(false);
 			}
 		}
 #endif
 
-		unsigned int code = k->get_scancode();
+		unsigned int code = k->get_keycode();
 
 		if (k->get_command() && is_shortcut_keys_enabled()) {
 
@@ -571,7 +571,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
 			if (handled) {
 				accept_event();
 			} else if (!k->get_command()) {
-				if (k->get_unicode() >= 32 && k->get_scancode() != KEY_DELETE) {
+				if (k->get_unicode() >= 32 && k->get_keycode() != KEY_DELETE) {
 
 					if (editable) {
 						selection_delete();

+ 1 - 1
scene/gui/popup_menu.cpp

@@ -1075,7 +1075,7 @@ bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_fo
 	Ref<InputEventKey> k = p_event;
 
 	if (k.is_valid()) {
-		code = k->get_scancode();
+		code = k->get_keycode();
 		if (code == 0)
 			code = k->get_unicode();
 		if (k->get_control())

+ 1 - 1
scene/gui/rich_text_label.cpp

@@ -1209,7 +1209,7 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
 	if (k.is_valid()) {
 		if (k->is_pressed() && !k->get_alt() && !k->get_shift()) {
 			bool handled = false;
-			switch (k->get_scancode()) {
+			switch (k->get_keycode()) {
 				case KEY_PAGEUP: {
 
 					if (vscroll->is_visible_in_tree()) {

+ 50 - 50
scene/gui/text_edit.cpp

@@ -2564,9 +2564,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 		k = k->duplicate(); // It will be modified later on.
 
 #ifdef OSX_ENABLED
-		if (k->get_scancode() == KEY_META) {
+		if (k->get_keycode() == KEY_META) {
 #else
-		if (k->get_scancode() == KEY_CONTROL) {
+		if (k->get_keycode() == KEY_CONTROL) {
 
 #endif
 			if (select_identifiers_enabled) {
@@ -2597,7 +2597,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			if (valid) {
 
 				if (!k->get_alt()) {
-					if (k->get_scancode() == KEY_UP) {
+					if (k->get_keycode() == KEY_UP) {
 
 						if (completion_index > 0) {
 							completion_index--;
@@ -2611,7 +2611,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 						return;
 					}
 
-					if (k->get_scancode() == KEY_DOWN) {
+					if (k->get_keycode() == KEY_DOWN) {
 
 						if (completion_index < completion_options.size() - 1) {
 							completion_index++;
@@ -2625,7 +2625,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 						return;
 					}
 
-					if (k->get_scancode() == KEY_PAGEUP) {
+					if (k->get_keycode() == KEY_PAGEUP) {
 
 						completion_index -= get_constant("completion_lines");
 						if (completion_index < 0)
@@ -2636,7 +2636,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 						return;
 					}
 
-					if (k->get_scancode() == KEY_PAGEDOWN) {
+					if (k->get_keycode() == KEY_PAGEDOWN) {
 
 						completion_index += get_constant("completion_lines");
 						if (completion_index >= completion_options.size())
@@ -2647,7 +2647,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 						return;
 					}
 
-					if (k->get_scancode() == KEY_HOME && completion_index > 0) {
+					if (k->get_keycode() == KEY_HOME && completion_index > 0) {
 
 						completion_index = 0;
 						completion_current = completion_options[completion_index];
@@ -2656,7 +2656,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 						return;
 					}
 
-					if (k->get_scancode() == KEY_END && completion_index < completion_options.size() - 1) {
+					if (k->get_keycode() == KEY_END && completion_index < completion_options.size() - 1) {
 
 						completion_index = completion_options.size() - 1;
 						completion_current = completion_options[completion_index];
@@ -2665,14 +2665,14 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 						return;
 					}
 
-					if (k->get_scancode() == KEY_KP_ENTER || k->get_scancode() == KEY_ENTER || k->get_scancode() == KEY_TAB) {
+					if (k->get_keycode() == KEY_KP_ENTER || k->get_keycode() == KEY_ENTER || k->get_keycode() == KEY_TAB) {
 
 						_confirm_completion();
 						accept_event();
 						return;
 					}
 
-					if (k->get_scancode() == KEY_BACKSPACE) {
+					if (k->get_keycode() == KEY_BACKSPACE) {
 
 						_reset_caret_blink_timer();
 
@@ -2682,7 +2682,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 						return;
 					}
 
-					if (k->get_scancode() == KEY_SHIFT) {
+					if (k->get_keycode() == KEY_SHIFT) {
 						accept_event();
 						return;
 					}
@@ -2726,20 +2726,20 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 		/* TEST CONTROL FIRST! */
 
 		// Some remaps for duplicate functions.
-		if (k->get_command() && !k->get_shift() && !k->get_alt() && !k->get_metakey() && k->get_scancode() == KEY_INSERT) {
+		if (k->get_command() && !k->get_shift() && !k->get_alt() && !k->get_metakey() && k->get_keycode() == KEY_INSERT) {
 
-			k->set_scancode(KEY_C);
+			k->set_keycode(KEY_C);
 		}
-		if (!k->get_command() && k->get_shift() && !k->get_alt() && !k->get_metakey() && k->get_scancode() == KEY_INSERT) {
+		if (!k->get_command() && k->get_shift() && !k->get_alt() && !k->get_metakey() && k->get_keycode() == KEY_INSERT) {
 
-			k->set_scancode(KEY_V);
+			k->set_keycode(KEY_V);
 			k->set_command(true);
 			k->set_shift(false);
 		}
 #ifdef APPLE_STYLE_KEYS
 		if (k->get_control() && !k->get_shift() && !k->get_alt() && !k->get_command()) {
 			uint32_t remap_key = KEY_UNKNOWN;
-			switch (k->get_scancode()) {
+			switch (k->get_keycode()) {
 				case KEY_F: {
 					remap_key = KEY_RIGHT;
 				} break;
@@ -2761,7 +2761,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			}
 
 			if (remap_key != KEY_UNKNOWN) {
-				k->set_scancode(remap_key);
+				k->set_keycode(remap_key);
 				k->set_control(false);
 			}
 		}
@@ -2779,7 +2779,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			bool unselect = false;
 			bool dobreak = false;
 
-			switch (k->get_scancode()) {
+			switch (k->get_keycode()) {
 
 				case KEY_TAB: {
 					if (k->get_shift()) {
@@ -2853,11 +2853,11 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 
 		selection.selecting_text = false;
 
-		bool scancode_handled = true;
+		bool keycode_handled = true;
 
-		// Special scancode test.
+		// Special keycode test.
 
-		switch (k->get_scancode()) {
+		switch (k->get_keycode()) {
 
 			case KEY_KP_ENTER:
 			case KEY_ENTER: {
@@ -2979,7 +2979,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 					completion_hint = "";
 					update();
 				} else {
-					scancode_handled = false;
+					keycode_handled = false;
 				}
 			} break;
 			case KEY_TAB: {
@@ -3052,7 +3052,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 				if (k->get_alt() && cursor.column > 1) {
 #else
 				if (k->get_alt()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				} else if (k->get_command() && cursor.column > 1) {
 #endif
@@ -3109,7 +3109,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			} break;
 			case KEY_KP_4: {
 				if (k->get_unicode() != 0) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 				[[fallthrough]];
@@ -3145,7 +3145,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 				} else if (k->get_alt()) {
 #else
 				if (k->get_alt()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				} else if (k->get_command()) {
 #endif
@@ -3185,7 +3185,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			} break;
 			case KEY_KP_6: {
 				if (k->get_unicode() != 0) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 				[[fallthrough]];
@@ -3207,7 +3207,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 				} else if (k->get_alt()) {
 #else
 				if (k->get_alt()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				} else if (k->get_command()) {
 #endif
@@ -3246,7 +3246,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			} break;
 			case KEY_KP_8: {
 				if (k->get_unicode() != 0) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 				[[fallthrough]];
@@ -3254,7 +3254,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			case KEY_UP: {
 
 				if (k->get_alt()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 #ifndef APPLE_STYLE_KEYS
@@ -3299,7 +3299,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			} break;
 			case KEY_KP_2: {
 				if (k->get_unicode() != 0) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 				[[fallthrough]];
@@ -3307,7 +3307,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			case KEY_DOWN: {
 
 				if (k->get_alt()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 #ifndef APPLE_STYLE_KEYS
@@ -3367,7 +3367,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 				if (k->get_alt() && cursor.column < curline_len - 1) {
 #else
 				if (k->get_alt()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				} else if (k->get_command() && cursor.column < curline_len - 1) {
 #endif
@@ -3422,7 +3422,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			} break;
 			case KEY_KP_7: {
 				if (k->get_unicode() != 0) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 				[[fallthrough]];
@@ -3483,7 +3483,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			} break;
 			case KEY_KP_1: {
 				if (k->get_unicode() != 0) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 				[[fallthrough]];
@@ -3530,7 +3530,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			} break;
 			case KEY_KP_9: {
 				if (k->get_unicode() != 0) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 				[[fallthrough]];
@@ -3553,7 +3553,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			} break;
 			case KEY_KP_3: {
 				if (k->get_unicode() != 0) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 				[[fallthrough]];
@@ -3578,7 +3578,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 
 #ifndef APPLE_STYLE_KEYS
 				if (!k->get_control() || k->get_shift() || k->get_alt()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 				if (is_shortcut_keys_enabled()) {
@@ -3586,7 +3586,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 				}
 #else
 				if ((!k->get_command() && !k->get_control())) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 				if (!k->get_shift() && k->get_command() && is_shortcut_keys_enabled())
@@ -3617,7 +3617,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			case KEY_E: {
 
 				if (!k->get_control() || k->get_command() || k->get_alt()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 
@@ -3642,7 +3642,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 					break;
 				}
 				if (!k->get_command() || k->get_shift() || k->get_alt()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 				if (is_shortcut_keys_enabled()) {
@@ -3653,7 +3653,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 			case KEY_C: {
 
 				if (!k->get_command() || k->get_shift() || k->get_alt()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 
@@ -3669,7 +3669,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 				}
 
 				if (!k->get_command()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 
@@ -3687,7 +3687,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 				}
 
 				if (!k->get_command()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 
@@ -3700,7 +3700,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 					break;
 				}
 				if (!k->get_command() || k->get_shift() || k->get_alt()) {
-					scancode_handled = false;
+					keycode_handled = false;
 					break;
 				}
 
@@ -3717,9 +3717,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 #endif
 
 					query_code_comple();
-					scancode_handled = true;
+					keycode_handled = true;
 				} else {
-					scancode_handled = false;
+					keycode_handled = false;
 				}
 
 			} break;
@@ -3736,20 +3736,20 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
 
 			default: {
 
-				scancode_handled = false;
+				keycode_handled = false;
 			} break;
 		}
 
-		if (scancode_handled)
+		if (keycode_handled)
 			accept_event();
 
-		if (k->get_scancode() == KEY_INSERT) {
+		if (k->get_keycode() == KEY_INSERT) {
 			set_insert_mode(!insert_mode);
 			accept_event();
 			return;
 		}
 
-		if (!scancode_handled && !k->get_command()) { // For German keyboards.
+		if (!keycode_handled && !k->get_command()) { // For German keyboards.
 
 			if (k->get_unicode() >= 32) {
 

+ 1 - 1
scene/gui/tree.cpp

@@ -2439,7 +2439,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
 
 			return;
 		} else {
-			if (k->get_scancode() != KEY_SHIFT)
+			if (k->get_keycode() != KEY_SHIFT)
 				last_keypress = 0;
 		}
 	}

+ 1 - 1
scene/main/scene_tree.cpp

@@ -435,7 +435,7 @@ void SceneTree::input_event(const Ref<InputEvent> &p_event) {
 	if (ScriptDebugger::get_singleton() && ScriptDebugger::get_singleton()->is_remote()) {
 		//quit from game window using F8
 		Ref<InputEventKey> k = ev;
-		if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_F8) {
+		if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_F8) {
 			ScriptDebugger::get_singleton()->request_quit();
 		}
 	}