Merge pull request #17827 from bruvzg/macos_shortcut_key_remapping_fix
[macOS] Fix keyboard shortcuts on non QWERTY keyboard layouts.
This commit is contained in:
commit
866254343b
3 changed files with 106 additions and 125 deletions
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue