Browse Source

[macOS] Fix keyboard shortcuts on non QWERTY keyboard layouts.

bruvzg 7 years ago
parent
commit
5ba984fc8c
3 changed files with 106 additions and 125 deletions
  1. 0 121
      core/os/keyboard.cpp
  2. 0 1
      core/os/keyboard.h
  3. 106 3
      platform/osx/os_osx.mm

+ 0 - 121
core/os/keyboard.cpp

@@ -461,99 +461,6 @@ const char *find_keycode_name(int p_keycode) {
 	return "";
 	return "";
 }
 }
 
 
-struct _KeyCodeReplace {
-	int from;
-	int to;
-};
-
-static const _KeyCodeReplace _keycode_replace_qwertz[] = {
-	{ KEY_Y, KEY_Z },
-	{ KEY_Z, KEY_Y },
-	{ 0, 0 }
-};
-
-static const _KeyCodeReplace _keycode_replace_azerty[] = {
-	{ KEY_W, KEY_Z },
-	{ KEY_Z, KEY_W },
-	{ KEY_A, KEY_Q },
-	{ KEY_Q, KEY_A },
-	{ KEY_SEMICOLON, KEY_M },
-	{ KEY_M, KEY_SEMICOLON },
-	{ 0, 0 }
-};
-
-static const _KeyCodeReplace _keycode_replace_qzerty[] = {
-	{ KEY_W, KEY_Z },
-	{ KEY_Z, KEY_W },
-	{ KEY_SEMICOLON, KEY_M },
-	{ KEY_M, KEY_SEMICOLON },
-	{ 0, 0 }
-};
-
-static const _KeyCodeReplace _keycode_replace_dvorak[] = {
-	{ KEY_UNDERSCORE, KEY_BRACELEFT },
-	{ KEY_EQUAL, KEY_BRACERIGHT },
-	{ KEY_Q, KEY_APOSTROPHE },
-	{ KEY_W, KEY_COMMA },
-	{ KEY_E, KEY_PERIOD },
-	{ KEY_R, KEY_P },
-	{ KEY_T, KEY_Y },
-	{ KEY_Y, KEY_F },
-	{ KEY_U, KEY_G },
-	{ KEY_I, KEY_C },
-	{ KEY_O, KEY_R },
-	{ KEY_P, KEY_L },
-	{ KEY_BRACELEFT, KEY_SLASH },
-	{ KEY_BRACERIGHT, KEY_EQUAL },
-	{ KEY_A, KEY_A },
-	{ KEY_S, KEY_O },
-	{ KEY_D, KEY_E },
-	{ KEY_F, KEY_U },
-	{ KEY_G, KEY_I },
-	{ KEY_H, KEY_D },
-	{ KEY_J, KEY_H },
-	{ KEY_K, KEY_T },
-	{ KEY_L, KEY_N },
-	{ KEY_SEMICOLON, KEY_S },
-	{ KEY_APOSTROPHE, KEY_UNDERSCORE },
-	{ KEY_Z, KEY_SEMICOLON },
-	{ KEY_X, KEY_Q },
-	{ KEY_C, KEY_J },
-	{ KEY_V, KEY_K },
-	{ KEY_B, KEY_X },
-	{ KEY_N, KEY_B },
-	{ KEY_M, KEY_M },
-	{ KEY_COMMA, KEY_W },
-	{ KEY_PERIOD, KEY_V },
-	{ KEY_SLASH, KEY_Z },
-	{ 0, 0 }
-};
-
-static const _KeyCodeReplace _keycode_replace_neo[] = {
-	{ 0, 0 }
-};
-
-static const _KeyCodeReplace _keycode_replace_colemak[] = {
-	{ KEY_E, KEY_F },
-	{ KEY_R, KEY_P },
-	{ KEY_T, KEY_G },
-	{ KEY_Y, KEY_J },
-	{ KEY_U, KEY_L },
-	{ KEY_I, KEY_U },
-	{ KEY_O, KEY_Y },
-	{ KEY_P, KEY_SEMICOLON },
-	{ KEY_S, KEY_R },
-	{ KEY_D, KEY_S },
-	{ KEY_F, KEY_T },
-	{ KEY_G, KEY_D },
-	{ KEY_J, KEY_N },
-	{ KEY_K, KEY_E },
-	{ KEY_L, KEY_I },
-	{ KEY_SEMICOLON, KEY_O },
-	{ KEY_N, KEY_K },
-	{ 0, 0 }
-};
-
 int keycode_get_count() {
 int keycode_get_count() {
 
 
 	const _KeyCodeText *kct = &_keycodes[0];
 	const _KeyCodeText *kct = &_keycodes[0];
@@ -574,31 +481,3 @@ int keycode_get_value_by_index(int p_index) {
 const char *keycode_get_name_by_index(int p_index) {
 const char *keycode_get_name_by_index(int p_index) {
 	return _keycodes[p_index].text;
 	return _keycodes[p_index].text;
 }
 }
-
-int latin_keyboard_keycode_convert(int p_keycode) {
-
-	const _KeyCodeReplace *kcr = NULL;
-	switch (OS::get_singleton()->get_latin_keyboard_variant()) {
-
-		case OS::LATIN_KEYBOARD_QWERTY: return p_keycode; break;
-		case OS::LATIN_KEYBOARD_QWERTZ: kcr = _keycode_replace_qwertz; break;
-		case OS::LATIN_KEYBOARD_AZERTY: kcr = _keycode_replace_azerty; break;
-		case OS::LATIN_KEYBOARD_QZERTY: kcr = _keycode_replace_qzerty; break;
-		case OS::LATIN_KEYBOARD_DVORAK: kcr = _keycode_replace_dvorak; break;
-		case OS::LATIN_KEYBOARD_NEO: kcr = _keycode_replace_neo; break;
-		case OS::LATIN_KEYBOARD_COLEMAK: kcr = _keycode_replace_colemak; break;
-		default: return p_keycode;
-	}
-
-	if (!kcr) {
-		return p_keycode;
-	}
-
-	while (kcr->from) {
-		if (kcr->from == p_keycode)
-			return kcr->to;
-		kcr++;
-	}
-
-	return p_keycode;
-}

+ 0 - 1
core/os/keyboard.h

@@ -331,6 +331,5 @@ const char *find_keycode_name(int p_keycode);
 int keycode_get_count();
 int keycode_get_count();
 int keycode_get_value_by_index(int p_index);
 int keycode_get_value_by_index(int p_index);
 const char *keycode_get_name_by_index(int p_index);
 const char *keycode_get_name_by_index(int p_index);
-int latin_keyboard_keycode_convert(int p_keycode);
 
 
 #endif
 #endif

+ 106 - 3
platform/osx/os_osx.mm

@@ -192,6 +192,7 @@ static Vector2 get_mouse_pos(NSEvent *event) {
 	// Note: called before main loop init!
 	// Note: called before main loop init!
 	char *utfs = strdup([filename UTF8String]);
 	char *utfs = strdup([filename UTF8String]);
 	OS_OSX::singleton->open_with_filename.parse_utf8(utfs);
 	OS_OSX::singleton->open_with_filename.parse_utf8(utfs);
+	free(utfs);
 	return YES;
 	return YES;
 }
 }
 
 
@@ -838,6 +839,108 @@ static int translateKey(unsigned int key) {
 	return table[key];
 	return table[key];
 }
 }
 
 
+struct _KeyCodeMap {
+	UniChar kchar;
+	int kcode;
+};
+
+static const _KeyCodeMap _keycodes[55] = {
+	{ '`', KEY_QUOTELEFT },
+	{ '~', KEY_ASCIITILDE },
+	{ '0', KEY_KP_0 },
+	{ '1', KEY_KP_1 },
+	{ '2', KEY_KP_2 },
+	{ '3', KEY_KP_3 },
+	{ '4', KEY_KP_4 },
+	{ '5', KEY_KP_5 },
+	{ '6', KEY_KP_6 },
+	{ '7', KEY_KP_7 },
+	{ '8', KEY_KP_8 },
+	{ '9', KEY_KP_9 },
+	{ '-', KEY_MINUS },
+	{ '_', KEY_UNDERSCORE },
+	{ '=', KEY_EQUAL },
+	{ '+', KEY_PLUS },
+	{ 'q', KEY_Q },
+	{ 'w', KEY_W },
+	{ 'e', KEY_E },
+	{ 'r', KEY_R },
+	{ 't', KEY_T },
+	{ 'y', KEY_Y },
+	{ 'u', KEY_U },
+	{ 'i', KEY_I },
+	{ 'o', KEY_O },
+	{ 'p', KEY_P },
+	{ '[', KEY_BRACERIGHT },
+	{ ']', KEY_BRACELEFT },
+	{ '{', KEY_BRACERIGHT },
+	{ '}', KEY_BRACELEFT },
+	{ 'a', KEY_A },
+	{ 's', KEY_S },
+	{ 'd', KEY_D },
+	{ 'f', KEY_F },
+	{ 'g', KEY_G },
+	{ 'h', KEY_H },
+	{ 'j', KEY_J },
+	{ 'k', KEY_K },
+	{ 'l', KEY_L },
+	{ ';', KEY_SEMICOLON },
+	{ ':', KEY_COLON },
+	{ '\'', KEY_APOSTROPHE },
+	{ '\"', KEY_QUOTEDBL },
+	{ '\\', KEY_BACKSLASH },
+	{ '#', KEY_NUMBERSIGN },
+	{ 'z', KEY_Z },
+	{ 'x', KEY_X },
+	{ 'c', KEY_C },
+	{ 'v', KEY_V },
+	{ 'b', KEY_B },
+	{ 'n', KEY_N },
+	{ 'm', KEY_M },
+	{ ',', KEY_COMMA },
+	{ '.', KEY_PERIOD },
+	{ '/', KEY_SLASH }
+};
+
+static int remapKey(unsigned int key) {
+
+	TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
+	if (!currentKeyboard)
+		return translateKey(key);
+
+	CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
+	if (!layoutData)
+		return nil;
+
+	const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);
+
+	UInt32 keysDown = 0;
+	UniChar chars[4];
+	UniCharCount realLength;
+
+	OSStatus err = UCKeyTranslate(keyboardLayout,
+			key,
+			kUCKeyActionDisplay,
+			0,
+			LMGetKbdType(),
+			kUCKeyTranslateNoDeadKeysBit,
+			&keysDown,
+			sizeof(chars) / sizeof(chars[0]),
+			&realLength,
+			chars);
+
+	if (err != noErr) {
+		return translateKey(key);
+	}
+
+	for (unsigned int i = 0; i < 55; i++) {
+		if (_keycodes[i].kchar == chars[0]) {
+			return _keycodes[i].kcode;
+		}
+	}
+	return translateKey(key);
+}
+
 - (void)keyDown:(NSEvent *)event {
 - (void)keyDown:(NSEvent *)event {
 
 
 	//disable raw input in IME mode
 	//disable raw input in IME mode
@@ -847,7 +950,7 @@ static int translateKey(unsigned int key) {
 		ke.osx_state = [event modifierFlags];
 		ke.osx_state = [event modifierFlags];
 		ke.pressed = true;
 		ke.pressed = true;
 		ke.echo = [event isARepeat];
 		ke.echo = [event isARepeat];
-		ke.scancode = latin_keyboard_keycode_convert(translateKey([event keyCode]));
+		ke.scancode = remapKey([event keyCode]);
 		ke.unicode = 0;
 		ke.unicode = 0;
 
 
 		push_to_key_event_buffer(ke);
 		push_to_key_event_buffer(ke);
@@ -900,7 +1003,7 @@ static int translateKey(unsigned int key) {
 		}
 		}
 
 
 		ke.osx_state = mod;
 		ke.osx_state = mod;
-		ke.scancode = latin_keyboard_keycode_convert(translateKey(key));
+		ke.scancode = remapKey(key);
 		ke.unicode = 0;
 		ke.unicode = 0;
 
 
 		push_to_key_event_buffer(ke);
 		push_to_key_event_buffer(ke);
@@ -916,7 +1019,7 @@ static int translateKey(unsigned int key) {
 		ke.osx_state = [event modifierFlags];
 		ke.osx_state = [event modifierFlags];
 		ke.pressed = false;
 		ke.pressed = false;
 		ke.echo = false;
 		ke.echo = false;
-		ke.scancode = latin_keyboard_keycode_convert(translateKey([event keyCode]));
+		ke.scancode = remapKey([event keyCode]);
 		ke.unicode = 0;
 		ke.unicode = 0;
 
 
 		push_to_key_event_buffer(ke);
 		push_to_key_event_buffer(ke);