diff --git a/docs/keyboard-protocol.rst b/docs/keyboard-protocol.rst index 7b3f6faaa..c54be9acf 100644 --- a/docs/keyboard-protocol.rst +++ b/docs/keyboard-protocol.rst @@ -490,12 +490,12 @@ compatibility reasons. "LEFT", "``1 D``", "RIGHT", "``1 C``" "UP", "``1 A``", "DOWN", "``1 B``" "PAGE_UP", "``5 ~``", "PAGE_DOWN", "``6 ~``" - "HOME", "``1 H or CSI 7 ~``", "END", "``1 F or CSI 8 ~``" + "HOME", "``1 H or 7 ~``", "END", "``1 F or 8 ~``" "CAPS_LOCK", "``57358 u``", "SCROLL_LOCK", "``57359 u``" "NUM_LOCK", "``57360 u``", "PRINT_SCREEN", "``57361 u``" "PAUSE", "``57362 u``", "MENU", "``57363 u``" - "F1", "``1 P or CSI 11 ~``", "F2", "``1 Q or CSI 12 ~``" - "F3", "``1 R or CSI 13 ~``", "F4", "``1 S or CSI 14 ~``" + "F1", "``1 P or 11 ~``", "F2", "``1 Q or 12 ~``" + "F3", "``1 R or 13 ~``", "F4", "``1 S or 14 ~``" "F5", "``15 ~``", "F6", "``17 ~``" "F7", "``18 ~``", "F8", "``19 ~``" "F9", "``20 ~``", "F10", "``21 ~``" diff --git a/gen-key-constants.py b/gen-key-constants.py index 0d712aa20..9d3130101 100644 --- a/gen-key-constants.py +++ b/gen-key-constants.py @@ -7,111 +7,111 @@ from typing import Dict, List, Any from pprint import pformat functional_key_defs = '''# {{{ -# kitty XKB macOS -escape Escape - -enter Return - -tab Tab - -backspace BackSpace - -insert Insert - -delete Delete - -left Left - -right Right - -up Up - -down Down - -page_up Page_Up - -page_down Page_Down - -home Home - -end End - -caps_lock Caps_Lock - -scroll_lock Scroll_Lock - -num_lock Num_Lock - -print_screen Print - -pause Pause - -menu Menu - -f1 F1 - -f2 F2 - -f3 F3 - -f4 F4 - -f5 F5 - -f6 F6 - -f7 F7 - -f8 F8 - -f9 F9 - -f10 F10 - -f11 F11 - -f12 F12 - -f13 F13 - -f14 F14 - -f15 F15 - -f16 F16 - -f17 F17 - -f18 F18 - -f19 F19 - -f20 F20 - -f21 F21 - -f22 F22 - -f23 F23 - -f24 F24 - -f25 F25 - -f26 F26 - -f27 F27 - -f28 F28 - -f29 F29 - -f30 F30 - -f31 F31 - -f32 F32 - -f33 F33 - -f34 F34 - -f35 F35 - -kp_0 KP_0 - -kp_1 KP_1 - -kp_2 KP_2 - -kp_3 KP_3 - -kp_4 KP_4 - -kp_5 KP_5 - -kp_6 KP_6 - -kp_7 KP_7 - -kp_8 KP_8 - -kp_9 KP_9 - -kp_decimal KP_Decimal - -kp_divide KP_Divide - -kp_multiply KP_Multiply - -kp_subtract KP_Subtract - -kp_add KP_Add - -kp_enter KP_Enter - -kp_equal KP_Equal - -kp_separator KP_Separator - -kp_left KP_Left - -kp_right KP_Right - -kp_up KP_Up - -kp_down KP_Down - -kp_page_up KP_Page_Up - -kp_page_down KP_Page_Down - -kp_home KP_Home - -kp_end KP_End - -kp_insert KP_Insert - -kp_delete KP_Delete - -left_shift Shift_L - -left_control Control_L - -left_alt Alt_L - -left_super Super_L - -right_shift Shift_R - -right_control Control_R - -right_alt Alt_R - -right_super Super_R - -media_play XF86AudioPlay - -media_pause XF86AudioPause - -media_play_pause - - -media_reverse - - -media_stop XF86AudioStop - -media_fast_forward XF86AudioForward - -media_rewind XF86AudioRewind - -media_track_next XF86AudioNext - -media_track_previous XF86AudioPrev - -media_record XF86AudioRecord - -lower_volume XF86AudioLowerVolume - -raise_volume XF86AudioRaiseVolume - -mute_volume XF86AudioMute - +# kitty XKB macVK macU +escape Escape 0x35 - +enter Return 0x24 NSCarriageReturnCharacter +tab Tab 0x30 NSTabCharacter +backspace BackSpace 0x33 NSBackspaceCharacter +insert Insert 0x72 Insert +delete Delete 0x75 Delete +left Left 0x7B LeftArrow +right Right 0x7C RightArrow +up Up 0x7E UpArrow +down Down 0x7D DownArrow +page_up Page_Up 0x74 PageUp +page_down Page_Down 0x79 PageDown +home Home 0x73 Home +end End 0x77 End +caps_lock Caps_Lock 0x39 - +scroll_lock Scroll_Lock - ScrollLock +num_lock Num_Lock 0x47 ClearLine +print_screen Print - PrintScreen +pause Pause - Pause +menu Menu 0x6E Menu +f1 F1 0x7A F1 +f2 F2 0x78 F2 +f3 F3 0x63 F3 +f4 F4 0x76 F4 +f5 F5 0x60 F5 +f6 F6 0x61 F6 +f7 F7 0x62 F7 +f8 F8 0x64 F8 +f9 F9 0x65 F9 +f10 F10 0x6D F10 +f11 F11 0x67 F11 +f12 F12 0x6F F12 +f13 F13 0x69 F13 +f14 F14 0x6B F14 +f15 F15 0x71 F15 +f16 F16 0x6A F16 +f17 F17 0x40 F17 +f18 F18 0x4F F18 +f19 F19 0x50 F19 +f20 F20 0x5A F20 +f21 F21 - F21 +f22 F22 - F22 +f23 F23 - F23 +f24 F24 - F24 +f25 F25 - F25 +f26 F26 - F26 +f27 F27 - F27 +f28 F28 - F28 +f29 F29 - F29 +f30 F30 - F30 +f31 F31 - F31 +f32 F32 - F32 +f33 F33 - F33 +f34 F34 - F34 +f35 F35 - F35 +kp_0 KP_0 0x52 - +kp_1 KP_1 0x53 - +kp_2 KP_2 0x54 - +kp_3 KP_3 0x55 - +kp_4 KP_4 0x56 - +kp_5 KP_5 0x57 - +kp_6 KP_6 0x58 - +kp_7 KP_7 0x59 - +kp_8 KP_8 0x5B - +kp_9 KP_9 0x5C - +kp_decimal KP_Decimal 0x41 - +kp_divide KP_Divide 0x4B - +kp_multiply KP_Multiply 0x43 - +kp_subtract KP_Subtract 0x4E - +kp_add KP_Add 0x45 - +kp_enter KP_Enter 0x4C NSEnterCharacter +kp_equal KP_Equal 0x51 - +kp_separator KP_Separator - - +kp_left KP_Left - - +kp_right KP_Right - - +kp_up KP_Up - - +kp_down KP_Down - - +kp_page_up KP_Page_Up - - +kp_page_down KP_Page_Down - - +kp_home KP_Home - - +kp_end KP_End - - +kp_insert KP_Insert - - +kp_delete KP_Delete - - +left_shift Shift_L 0x38 - +left_control Control_L 0x3B - +left_alt Alt_L 0x3A - +left_super Super_L 0x37 - +right_shift Shift_R 0x3C - +right_control Control_R 0x3E - +right_alt Alt_R 0x3D - +right_super Super_R 0x36 - +media_play XF86AudioPlay - - +media_pause XF86AudioPause - - +media_play_pause - - - +media_reverse - - - +media_stop XF86AudioStop - - +media_fast_forward XF86AudioForward - - +media_rewind XF86AudioRewind - - +media_track_next XF86AudioNext - - +media_track_previous XF86AudioPrev - - +media_record XF86AudioRecord - - +lower_volume XF86AudioLowerVolume - - +raise_volume XF86AudioRaiseVolume - - +mute_volume XF86AudioMute - - ''' # }}} shift_map = {x[0]: x[1] for x in '`~ 1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ =+ [{ ]} \\| ;: \'" ,< .> /?'.split()} @@ -127,9 +127,64 @@ different_trailer_functionals = { 'f1': 'P', 'f2': 'Q', 'f3': 'R', 'f4': 'S', 'enter': 'u', 'tab': 'u', 'backspace': 'u', 'escape': 'u' } + +macos_ansi_key_codes = { # {{{ + 0x1D: ord('0'), + 0x12: ord('1'), + 0x13: ord('2'), + 0x14: ord('3'), + 0x15: ord('4'), + 0x17: ord('5'), + 0x16: ord('6'), + 0x1A: ord('7'), + 0x1C: ord('8'), + 0x19: ord('9'), + 0x00: ord('a'), + 0x0B: ord('b'), + 0x08: ord('c'), + 0x02: ord('d'), + 0x0E: ord('e'), + 0x03: ord('f'), + 0x05: ord('g'), + 0x04: ord('h'), + 0x22: ord('i'), + 0x26: ord('j'), + 0x28: ord('k'), + 0x25: ord('l'), + 0x2E: ord('m'), + 0x2D: ord('n'), + 0x1F: ord('o'), + 0x23: ord('p'), + 0x0C: ord('q'), + 0x0F: ord('r'), + 0x01: ord('s'), + 0x11: ord('t'), + 0x20: ord('u'), + 0x09: ord('v'), + 0x0D: ord('w'), + 0x07: ord('x'), + 0x10: ord('y'), + 0x06: ord('z'), + + 0x27: ord('\''), + 0x2A: ord('\\'), + 0x2B: ord(','), + 0x18: ord('='), + 0x32: ord('`'), + 0x21: ord('['), + 0x1B: ord('-'), + 0x2F: ord('.'), + 0x1E: ord(']'), + 0x29: ord(';'), + 0x2C: ord('/'), + 0x31: ord(' '), +} # }}} + functional_key_names: List[str] = [] name_to_code: Dict[str, int] = {} name_to_xkb: Dict[str, str] = {} +name_to_vk: Dict[str, int] = {} +name_to_macu: Dict[str, str] = {} start_code = 0xe000 for line in functional_key_defs.splitlines(): line = line.strip() @@ -141,6 +196,13 @@ for line in functional_key_defs.splitlines(): name_to_code[name] = len(name_to_code) + start_code if parts[1] != '-': name_to_xkb[name] = parts[1] + if parts[2] != '-': + name_to_vk[name] = int(parts[2], 16) + if parts[3] != '-': + val = parts[3] + if not val.startswith('NS'): + val = f'NS{val}FunctionKey' + name_to_macu[name] = val last_code = start_code + len(functional_key_names) - 1 ctrl_mapping = { ' ': 0, '@': 0, 'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, @@ -316,12 +378,33 @@ def generate_ctrl_mapping() -> None: patch_file('kitty/key_encoding.c', 'ctrl mapping', '\n'.join(mi)) +def generate_macos_mapping() -> None: + lines = [] + for k in sorted(macos_ansi_key_codes): + v = macos_ansi_key_codes[k] + lines.append(f' case 0x{k:x}: return 0x{v:x};') + patch_file('glfw/cocoa_window.m', 'vk to unicode', '\n'.join(lines)) + lines = [] + for name, vk in name_to_vk.items(): + lines.append(f' case 0x{vk:x}: return GLFW_FKEY_{name.upper()};') + patch_file('glfw/cocoa_window.m', 'vk to functional', '\n'.join(lines)) + lines = [] + for name, mac in name_to_macu.items(): + lines.append(f' case {mac}: return GLFW_FKEY_{name.upper()};') + patch_file('glfw/cocoa_window.m', 'macu to functional', '\n'.join(lines)) + lines = [] + for name, mac in name_to_macu.items(): + lines.append(f' case GLFW_FKEY_{name.upper()}: return {mac};') + patch_file('glfw/cocoa_window.m', 'functional to macu', '\n'.join(lines)) + + def main() -> None: generate_glfw_header() generate_xkb_mapping() generate_functional_table() generate_legacy_text_key_maps() generate_ctrl_mapping() + generate_macos_mapping() if __name__ == '__main__': diff --git a/glfw/cocoa_init.m b/glfw/cocoa_init.m index 5ae1052ff..1455ec071 100644 --- a/glfw/cocoa_init.m +++ b/glfw/cocoa_init.m @@ -175,138 +175,6 @@ static void createMenuBar(void) [NSApp performSelector:setAppleMenuSelector withObject:appMenu]; } -// Create key code translation tables -// -static void createKeyTables(void) -{ - int keycode; - - memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes)); - memset(_glfw.ns.key_to_keycode, -1, sizeof(_glfw.ns.key_to_keycode)); - - _glfw.ns.keycodes[0x1D] = GLFW_KEY_0; - _glfw.ns.keycodes[0x12] = GLFW_KEY_1; - _glfw.ns.keycodes[0x13] = GLFW_KEY_2; - _glfw.ns.keycodes[0x14] = GLFW_KEY_3; - _glfw.ns.keycodes[0x15] = GLFW_KEY_4; - _glfw.ns.keycodes[0x17] = GLFW_KEY_5; - _glfw.ns.keycodes[0x16] = GLFW_KEY_6; - _glfw.ns.keycodes[0x1A] = GLFW_KEY_7; - _glfw.ns.keycodes[0x1C] = GLFW_KEY_8; - _glfw.ns.keycodes[0x19] = GLFW_KEY_9; - _glfw.ns.keycodes[0x00] = GLFW_KEY_A; - _glfw.ns.keycodes[0x0B] = GLFW_KEY_B; - _glfw.ns.keycodes[0x08] = GLFW_KEY_C; - _glfw.ns.keycodes[0x02] = GLFW_KEY_D; - _glfw.ns.keycodes[0x0E] = GLFW_KEY_E; - _glfw.ns.keycodes[0x03] = GLFW_KEY_F; - _glfw.ns.keycodes[0x05] = GLFW_KEY_G; - _glfw.ns.keycodes[0x04] = GLFW_KEY_H; - _glfw.ns.keycodes[0x22] = GLFW_KEY_I; - _glfw.ns.keycodes[0x26] = GLFW_KEY_J; - _glfw.ns.keycodes[0x28] = GLFW_KEY_K; - _glfw.ns.keycodes[0x25] = GLFW_KEY_L; - _glfw.ns.keycodes[0x2E] = GLFW_KEY_M; - _glfw.ns.keycodes[0x2D] = GLFW_KEY_N; - _glfw.ns.keycodes[0x1F] = GLFW_KEY_O; - _glfw.ns.keycodes[0x23] = GLFW_KEY_P; - _glfw.ns.keycodes[0x0C] = GLFW_KEY_Q; - _glfw.ns.keycodes[0x0F] = GLFW_KEY_R; - _glfw.ns.keycodes[0x01] = GLFW_KEY_S; - _glfw.ns.keycodes[0x11] = GLFW_KEY_T; - _glfw.ns.keycodes[0x20] = GLFW_KEY_U; - _glfw.ns.keycodes[0x09] = GLFW_KEY_V; - _glfw.ns.keycodes[0x0D] = GLFW_KEY_W; - _glfw.ns.keycodes[0x07] = GLFW_KEY_X; - _glfw.ns.keycodes[0x10] = GLFW_KEY_Y; - _glfw.ns.keycodes[0x06] = GLFW_KEY_Z; - - _glfw.ns.keycodes[0x27] = GLFW_KEY_APOSTROPHE; - _glfw.ns.keycodes[0x2A] = GLFW_KEY_BACKSLASH; - _glfw.ns.keycodes[0x2B] = GLFW_KEY_COMMA; - _glfw.ns.keycodes[0x18] = GLFW_KEY_EQUAL; - _glfw.ns.keycodes[0x32] = GLFW_KEY_GRAVE_ACCENT; - _glfw.ns.keycodes[0x21] = GLFW_KEY_LEFT_BRACKET; - _glfw.ns.keycodes[0x1B] = GLFW_KEY_MINUS; - _glfw.ns.keycodes[0x2F] = GLFW_KEY_PERIOD; - _glfw.ns.keycodes[0x1E] = GLFW_KEY_RIGHT_BRACKET; - _glfw.ns.keycodes[0x29] = GLFW_KEY_SEMICOLON; - _glfw.ns.keycodes[0x2C] = GLFW_KEY_SLASH; - _glfw.ns.keycodes[0x0A] = GLFW_KEY_WORLD_1; - - _glfw.ns.keycodes[0x33] = GLFW_KEY_BACKSPACE; - _glfw.ns.keycodes[0x39] = GLFW_KEY_CAPS_LOCK; - _glfw.ns.keycodes[0x75] = GLFW_KEY_DELETE; - _glfw.ns.keycodes[0x7D] = GLFW_KEY_DOWN; - _glfw.ns.keycodes[0x77] = GLFW_KEY_END; - _glfw.ns.keycodes[0x24] = GLFW_KEY_ENTER; - _glfw.ns.keycodes[0x35] = GLFW_KEY_ESCAPE; - _glfw.ns.keycodes[0x7A] = GLFW_KEY_F1; - _glfw.ns.keycodes[0x78] = GLFW_KEY_F2; - _glfw.ns.keycodes[0x63] = GLFW_KEY_F3; - _glfw.ns.keycodes[0x76] = GLFW_KEY_F4; - _glfw.ns.keycodes[0x60] = GLFW_KEY_F5; - _glfw.ns.keycodes[0x61] = GLFW_KEY_F6; - _glfw.ns.keycodes[0x62] = GLFW_KEY_F7; - _glfw.ns.keycodes[0x64] = GLFW_KEY_F8; - _glfw.ns.keycodes[0x65] = GLFW_KEY_F9; - _glfw.ns.keycodes[0x6D] = GLFW_KEY_F10; - _glfw.ns.keycodes[0x67] = GLFW_KEY_F11; - _glfw.ns.keycodes[0x6F] = GLFW_KEY_F12; - _glfw.ns.keycodes[0x69] = GLFW_KEY_F13; - _glfw.ns.keycodes[0x6B] = GLFW_KEY_F14; - _glfw.ns.keycodes[0x71] = GLFW_KEY_F15; - _glfw.ns.keycodes[0x6A] = GLFW_KEY_F16; - _glfw.ns.keycodes[0x40] = GLFW_KEY_F17; - _glfw.ns.keycodes[0x4F] = GLFW_KEY_F18; - _glfw.ns.keycodes[0x50] = GLFW_KEY_F19; - _glfw.ns.keycodes[0x5A] = GLFW_KEY_F20; - _glfw.ns.keycodes[0x73] = GLFW_KEY_HOME; - _glfw.ns.keycodes[0x72] = GLFW_KEY_INSERT; - _glfw.ns.keycodes[0x7B] = GLFW_KEY_LEFT; - _glfw.ns.keycodes[0x3A] = GLFW_KEY_LEFT_ALT; - _glfw.ns.keycodes[0x3B] = GLFW_KEY_LEFT_CONTROL; - _glfw.ns.keycodes[0x38] = GLFW_KEY_LEFT_SHIFT; - _glfw.ns.keycodes[0x37] = GLFW_KEY_LEFT_SUPER; - _glfw.ns.keycodes[0x6E] = GLFW_KEY_MENU; - _glfw.ns.keycodes[0x47] = GLFW_KEY_NUM_LOCK; - _glfw.ns.keycodes[0x79] = GLFW_KEY_PAGE_DOWN; - _glfw.ns.keycodes[0x74] = GLFW_KEY_PAGE_UP; - _glfw.ns.keycodes[0x7C] = GLFW_KEY_RIGHT; - _glfw.ns.keycodes[0x3D] = GLFW_KEY_RIGHT_ALT; - _glfw.ns.keycodes[0x3E] = GLFW_KEY_RIGHT_CONTROL; - _glfw.ns.keycodes[0x3C] = GLFW_KEY_RIGHT_SHIFT; - _glfw.ns.keycodes[0x36] = GLFW_KEY_RIGHT_SUPER; - _glfw.ns.keycodes[0x31] = GLFW_KEY_SPACE; - _glfw.ns.keycodes[0x30] = GLFW_KEY_TAB; - _glfw.ns.keycodes[0x7E] = GLFW_KEY_UP; - - _glfw.ns.keycodes[0x52] = GLFW_KEY_KP_0; - _glfw.ns.keycodes[0x53] = GLFW_KEY_KP_1; - _glfw.ns.keycodes[0x54] = GLFW_KEY_KP_2; - _glfw.ns.keycodes[0x55] = GLFW_KEY_KP_3; - _glfw.ns.keycodes[0x56] = GLFW_KEY_KP_4; - _glfw.ns.keycodes[0x57] = GLFW_KEY_KP_5; - _glfw.ns.keycodes[0x58] = GLFW_KEY_KP_6; - _glfw.ns.keycodes[0x59] = GLFW_KEY_KP_7; - _glfw.ns.keycodes[0x5B] = GLFW_KEY_KP_8; - _glfw.ns.keycodes[0x5C] = GLFW_KEY_KP_9; - _glfw.ns.keycodes[0x45] = GLFW_KEY_KP_ADD; - _glfw.ns.keycodes[0x41] = GLFW_KEY_KP_DECIMAL; - _glfw.ns.keycodes[0x4B] = GLFW_KEY_KP_DIVIDE; - _glfw.ns.keycodes[0x4C] = GLFW_KEY_KP_ENTER; - _glfw.ns.keycodes[0x51] = GLFW_KEY_KP_EQUAL; - _glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY; - _glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT; - - for (keycode = 0; keycode < 256; keycode++) - { - // Store the reverse translation for faster key name lookup - if (_glfw.ns.keycodes[keycode] >= 0) - _glfw.ns.key_to_keycode[_glfw.ns.keycodes[keycode]] = keycode; - } -} - // Retrieve Unicode data for the current keyboard layout // static bool updateUnicodeDataNS(void) @@ -658,8 +526,6 @@ int _glfwPlatformInit(void) name:NSTextInputContextKeyboardSelectionDidChangeNotification object:nil]; - createKeyTables(); - _glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); if (!_glfw.ns.eventSource) return false; diff --git a/glfw/cocoa_platform.h b/glfw/cocoa_platform.h index 053bdb046..664c3e2b4 100644 --- a/glfw/cocoa_platform.h +++ b/glfw/cocoa_platform.h @@ -178,8 +178,6 @@ typedef struct _GLFWlibraryNS char keyName[64]; char text[256]; - short int keycodes[256]; - short int key_to_keycode[GLFW_KEY_LAST + 1]; char* clipboardString; CGPoint cascadePoint; // Where to place the cursor when re-enabled diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index fc8b3187e..eda5294f6 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -33,59 +33,244 @@ #include -#define PARAGRAPH_UTF_8 0xc2a7 // § -#define MASCULINE_UTF_8 0xc2ba // º -#define A_DIAERESIS_UPPER_CASE_UTF_8 0xc384 // Ä -#define O_DIAERESIS_UPPER_CASE_UTF_8 0xc396 // Ö -#define U_DIAERESIS_UPPER_CASE_UTF_8 0xc39c // Ü -#define S_SHARP_UTF_8 0xc39f // ß -#define A_GRAVE_LOWER_CASE_UTF_8 0xc3a0 // à -#define A_DIAERESIS_LOWER_CASE_UTF_8 0xc3a4 // ä -#define A_RING_LOWER_CASE_UTF_8 0xc3a5 // å -#define AE_LOWER_CASE_UTF_8 0xc3a6 // æ -#define C_CEDILLA_LOWER_CASE_UTF_8 0xc3a7 // ç -#define E_GRAVE_LOWER_CASE_UTF_8 0xc3a8 // è -#define E_ACUTE_LOWER_CASE_UTF_8 0xc3a9 // é -#define I_GRAVE_LOWER_CASE_UTF_8 0xc3ac // ì -#define N_TILDE_LOWER_CASE_UTF_8 0xc3b1 // ñ -#define O_GRAVE_LOWER_CASE_UTF_8 0xc3b2 // ò -#define O_DIAERESIS_LOWER_CASE_UTF_8 0xc3b6 // ö -#define O_SLASH_LOWER_CASE_UTF_8 0xc3b8 // ø -#define U_GRAVE_LOWER_CASE_UTF_8 0xc3b9 // ù -#define U_DIAERESIS_LOWER_CASE_UTF_8 0xc3bc // ü -#define CYRILLIC_A_LOWER_CASE_UTF_8 0xd0b0 // а -#define CYRILLIC_BE_LOWER_CASE_UTF_8 0xd0b1 // б -#define CYRILLIC_VE_LOWER_CASE_UTF_8 0xd0b2 // в -#define CYRILLIC_GHE_LOWER_CASE_UTF_8 0xd0b3 // г -#define CYRILLIC_DE_LOWER_CASE_UTF_8 0xd0b4 // д -#define CYRILLIC_IE_LOWER_CASE_UTF_8 0xd0b5 // е -#define CYRILLIC_ZHE_LOWER_CASE_UTF_8 0xd0b6 // ж -#define CYRILLIC_ZE_LOWER_CASE_UTF_8 0xd0b7 // з -#define CYRILLIC_I_LOWER_CASE_UTF_8 0xd0b8 // и -#define CYRILLIC_SHORT_I_LOWER_CASE_UTF_8 0xd0b9 // й -#define CYRILLIC_KA_LOWER_CASE_UTF_8 0xd0ba // к -#define CYRILLIC_EL_LOWER_CASE_UTF_8 0xd0bb // л -#define CYRILLIC_EM_LOWER_CASE_UTF_8 0xd0bc // м -#define CYRILLIC_EN_LOWER_CASE_UTF_8 0xd0bd // н -#define CYRILLIC_O_LOWER_CASE_UTF_8 0xd0be // о -#define CYRILLIC_PE_LOWER_CASE_UTF_8 0xd0bf // п -#define CYRILLIC_ER_LOWER_CASE_UTF_8 0xd180 // р -#define CYRILLIC_ES_LOWER_CASE_UTF_8 0xd181 // с -#define CYRILLIC_TE_LOWER_CASE_UTF_8 0xd182 // т -#define CYRILLIC_U_LOWER_CASE_UTF_8 0xd183 // у -#define CYRILLIC_EF_LOWER_CASE_UTF_8 0xd184 // ф -#define CYRILLIC_HA_LOWER_CASE_UTF_8 0xd185 // х -#define CYRILLIC_TSE_LOWER_CASE_UTF_8 0xd186 // ц -#define CYRILLIC_CHE_LOWER_CASE_UTF_8 0xd187 // ч -#define CYRILLIC_SHA_LOWER_CASE_UTF_8 0xd188 // ш -#define CYRILLIC_SHCHA_LOWER_CASE_UTF_8 0xd189 // щ -#define CYRILLIC_HARD_SIGN_LOWER_CASE_UTF_8 0xd18a // ъ -#define CYRILLIC_YERU_LOWER_CASE_UTF_8 0xd18b // ы -#define CYRILLIC_SOFT_SIGN_LOWER_CASE_UTF_8 0xd18c // ь -#define CYRILLIC_E_LOWER_CASE_UTF_8 0xd18d // э -#define CYRILLIC_YU_LOWER_CASE_UTF_8 0xd18e // ю -#define CYRILLIC_YA_LOWER_CASE_UTF_8 0xd18f // я -#define CYRILLIC_IO_LOWER_CASE_UTF_8 0xd191 // ё +static uint32_t +vk_code_to_functional_key_code(uint8_t key_code) { // {{{ + switch(key_code) { + /* start vk to functional (auto generated by gen-key-constants.py do not edit) */ + case 0x35: return GLFW_FKEY_ESCAPE; + case 0x24: return GLFW_FKEY_ENTER; + case 0x30: return GLFW_FKEY_TAB; + case 0x33: return GLFW_FKEY_BACKSPACE; + case 0x72: return GLFW_FKEY_INSERT; + case 0x75: return GLFW_FKEY_DELETE; + case 0x7b: return GLFW_FKEY_LEFT; + case 0x7c: return GLFW_FKEY_RIGHT; + case 0x7e: return GLFW_FKEY_UP; + case 0x7d: return GLFW_FKEY_DOWN; + case 0x74: return GLFW_FKEY_PAGE_UP; + case 0x79: return GLFW_FKEY_PAGE_DOWN; + case 0x73: return GLFW_FKEY_HOME; + case 0x77: return GLFW_FKEY_END; + case 0x39: return GLFW_FKEY_CAPS_LOCK; + case 0x47: return GLFW_FKEY_NUM_LOCK; + case 0x6e: return GLFW_FKEY_MENU; + case 0x7a: return GLFW_FKEY_F1; + case 0x78: return GLFW_FKEY_F2; + case 0x63: return GLFW_FKEY_F3; + case 0x76: return GLFW_FKEY_F4; + case 0x60: return GLFW_FKEY_F5; + case 0x61: return GLFW_FKEY_F6; + case 0x62: return GLFW_FKEY_F7; + case 0x64: return GLFW_FKEY_F8; + case 0x65: return GLFW_FKEY_F9; + case 0x6d: return GLFW_FKEY_F10; + case 0x67: return GLFW_FKEY_F11; + case 0x6f: return GLFW_FKEY_F12; + case 0x69: return GLFW_FKEY_F13; + case 0x6b: return GLFW_FKEY_F14; + case 0x71: return GLFW_FKEY_F15; + case 0x6a: return GLFW_FKEY_F16; + case 0x40: return GLFW_FKEY_F17; + case 0x4f: return GLFW_FKEY_F18; + case 0x50: return GLFW_FKEY_F19; + case 0x5a: return GLFW_FKEY_F20; + case 0x52: return GLFW_FKEY_KP_0; + case 0x53: return GLFW_FKEY_KP_1; + case 0x54: return GLFW_FKEY_KP_2; + case 0x55: return GLFW_FKEY_KP_3; + case 0x56: return GLFW_FKEY_KP_4; + case 0x57: return GLFW_FKEY_KP_5; + case 0x58: return GLFW_FKEY_KP_6; + case 0x59: return GLFW_FKEY_KP_7; + case 0x5b: return GLFW_FKEY_KP_8; + case 0x5c: return GLFW_FKEY_KP_9; + case 0x41: return GLFW_FKEY_KP_DECIMAL; + case 0x4b: return GLFW_FKEY_KP_DIVIDE; + case 0x43: return GLFW_FKEY_KP_MULTIPLY; + case 0x4e: return GLFW_FKEY_KP_SUBTRACT; + case 0x45: return GLFW_FKEY_KP_ADD; + case 0x4c: return GLFW_FKEY_KP_ENTER; + case 0x51: return GLFW_FKEY_KP_EQUAL; + case 0x38: return GLFW_FKEY_LEFT_SHIFT; + case 0x3b: return GLFW_FKEY_LEFT_CONTROL; + case 0x3a: return GLFW_FKEY_LEFT_ALT; + case 0x37: return GLFW_FKEY_LEFT_SUPER; + case 0x3c: return GLFW_FKEY_RIGHT_SHIFT; + case 0x3e: return GLFW_FKEY_RIGHT_CONTROL; + case 0x3d: return GLFW_FKEY_RIGHT_ALT; + case 0x36: return GLFW_FKEY_RIGHT_SUPER; +/* end vk to functional */ + default: + return 0; + } +} // }}} + +static uint32_t +vk_code_to_unicode(uint8_t key_code) { // {{{ + switch(key_code) { + /* start vk to unicode (auto generated by gen-key-constants.py do not edit) */ + case 0x0: return 0x61; + case 0x1: return 0x73; + case 0x2: return 0x64; + case 0x3: return 0x66; + case 0x4: return 0x68; + case 0x5: return 0x67; + case 0x6: return 0x7a; + case 0x7: return 0x78; + case 0x8: return 0x63; + case 0x9: return 0x76; + case 0xb: return 0x62; + case 0xc: return 0x71; + case 0xd: return 0x77; + case 0xe: return 0x65; + case 0xf: return 0x72; + case 0x10: return 0x79; + case 0x11: return 0x74; + case 0x12: return 0x31; + case 0x13: return 0x32; + case 0x14: return 0x33; + case 0x15: return 0x34; + case 0x16: return 0x36; + case 0x17: return 0x35; + case 0x18: return 0x3d; + case 0x19: return 0x39; + case 0x1a: return 0x37; + case 0x1b: return 0x2d; + case 0x1c: return 0x38; + case 0x1d: return 0x30; + case 0x1e: return 0x5d; + case 0x1f: return 0x6f; + case 0x20: return 0x75; + case 0x21: return 0x5b; + case 0x22: return 0x69; + case 0x23: return 0x70; + case 0x25: return 0x6c; + case 0x26: return 0x6a; + case 0x27: return 0x27; + case 0x28: return 0x6b; + case 0x29: return 0x3b; + case 0x2a: return 0x5c; + case 0x2b: return 0x2c; + case 0x2c: return 0x2f; + case 0x2d: return 0x6e; + case 0x2e: return 0x6d; + case 0x2f: return 0x2e; + case 0x31: return 0x20; + case 0x32: return 0x60; +/* end vk to unicode */ + default: + return 0; + } +} // }}} + +static uint32_t +mac_ucode_to_functional(uint32_t key_code) { // {{{ + switch(key_code) { + /* start macu to functional (auto generated by gen-key-constants.py do not edit) */ + case NSCarriageReturnCharacter: return GLFW_FKEY_ENTER; + case NSTabCharacter: return GLFW_FKEY_TAB; + case NSBackspaceCharacter: return GLFW_FKEY_BACKSPACE; + case NSInsertFunctionKey: return GLFW_FKEY_INSERT; + case NSDeleteFunctionKey: return GLFW_FKEY_DELETE; + case NSLeftArrowFunctionKey: return GLFW_FKEY_LEFT; + case NSRightArrowFunctionKey: return GLFW_FKEY_RIGHT; + case NSUpArrowFunctionKey: return GLFW_FKEY_UP; + case NSDownArrowFunctionKey: return GLFW_FKEY_DOWN; + case NSPageUpFunctionKey: return GLFW_FKEY_PAGE_UP; + case NSPageDownFunctionKey: return GLFW_FKEY_PAGE_DOWN; + case NSHomeFunctionKey: return GLFW_FKEY_HOME; + case NSEndFunctionKey: return GLFW_FKEY_END; + case NSScrollLockFunctionKey: return GLFW_FKEY_SCROLL_LOCK; + case NSClearLineFunctionKey: return GLFW_FKEY_NUM_LOCK; + case NSPrintScreenFunctionKey: return GLFW_FKEY_PRINT_SCREEN; + case NSPauseFunctionKey: return GLFW_FKEY_PAUSE; + case NSMenuFunctionKey: return GLFW_FKEY_MENU; + case NSF1FunctionKey: return GLFW_FKEY_F1; + case NSF2FunctionKey: return GLFW_FKEY_F2; + case NSF3FunctionKey: return GLFW_FKEY_F3; + case NSF4FunctionKey: return GLFW_FKEY_F4; + case NSF5FunctionKey: return GLFW_FKEY_F5; + case NSF6FunctionKey: return GLFW_FKEY_F6; + case NSF7FunctionKey: return GLFW_FKEY_F7; + case NSF8FunctionKey: return GLFW_FKEY_F8; + case NSF9FunctionKey: return GLFW_FKEY_F9; + case NSF10FunctionKey: return GLFW_FKEY_F10; + case NSF11FunctionKey: return GLFW_FKEY_F11; + case NSF12FunctionKey: return GLFW_FKEY_F12; + case NSF13FunctionKey: return GLFW_FKEY_F13; + case NSF14FunctionKey: return GLFW_FKEY_F14; + case NSF15FunctionKey: return GLFW_FKEY_F15; + case NSF16FunctionKey: return GLFW_FKEY_F16; + case NSF17FunctionKey: return GLFW_FKEY_F17; + case NSF18FunctionKey: return GLFW_FKEY_F18; + case NSF19FunctionKey: return GLFW_FKEY_F19; + case NSF20FunctionKey: return GLFW_FKEY_F20; + case NSF21FunctionKey: return GLFW_FKEY_F21; + case NSF22FunctionKey: return GLFW_FKEY_F22; + case NSF23FunctionKey: return GLFW_FKEY_F23; + case NSF24FunctionKey: return GLFW_FKEY_F24; + case NSF25FunctionKey: return GLFW_FKEY_F25; + case NSF26FunctionKey: return GLFW_FKEY_F26; + case NSF27FunctionKey: return GLFW_FKEY_F27; + case NSF28FunctionKey: return GLFW_FKEY_F28; + case NSF29FunctionKey: return GLFW_FKEY_F29; + case NSF30FunctionKey: return GLFW_FKEY_F30; + case NSF31FunctionKey: return GLFW_FKEY_F31; + case NSF32FunctionKey: return GLFW_FKEY_F32; + case NSF33FunctionKey: return GLFW_FKEY_F33; + case NSF34FunctionKey: return GLFW_FKEY_F34; + case NSF35FunctionKey: return GLFW_FKEY_F35; + case NSEnterCharacter: return GLFW_FKEY_KP_ENTER; +/* end macu to functional */ + default: + return 0; + } +} // }}} + +static inline bool +is_surrogate(UniChar uc) { return (uc - 0xd800u) < 2048u; } + +static inline uint32_t +get_first_codepoint(UniChar *utf16, UniCharCount num) { + if (!num) return 0; + if (!is_surrogate(*utf16)) return *utf16; + if (CFStringIsSurrogateHighCharacter(*utf16) && num > 1 && CFStringIsSurrogateLowCharacter(utf16[1])) return CFStringGetLongCharacterForSurrogatePair(utf16[0], utf16[1]); + return 0; +} + +static inline bool +is_pua_char(uint32_t ch) { + return (0xE000 <= ch && ch <= 0xF8FF) || (0xF0000 <= ch && ch <= 0xFFFFF) || (0x100000 <= ch || ch <= 0x10FFFF); +} + +static uint32_t +vk_to_unicode_key_with_current_layout(uint16_t keycode) +{ + UInt32 dead_key_state = 0; + UniChar characters[256]; + UniCharCount character_count = 0; + uint32_t ans = vk_code_to_functional_key_code(keycode); + if (ans) return ans; + + if (UCKeyTranslate([(NSData*) _glfw.ns.unicodeData bytes], + keycode, + kUCKeyActionDisplay, + 0, + LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, + &dead_key_state, + arraysz(characters), + &character_count, + characters) == noErr) { + uint32_t cp = get_first_codepoint(characters, character_count); + if (cp) { + if (cp < 32 || (0xF700 <= cp && cp <= 0xF8FF)) return mac_ucode_to_functional(cp); + if (cp >= 32 && !is_pua_char(cp)) return cp; + } + } + return vk_code_to_unicode(keycode); +} + // Returns the style mask corresponding to the window settings // @@ -336,167 +521,35 @@ safe_name_for_keycode(unsigned int keycode) { // Translates a macOS keycode to a GLFW keycode // -static int translateKey(unsigned int key, bool apply_keymap) +static uint32_t +translateKey(uint16_t vk_key, bool apply_keymap) { - if (apply_keymap) { - // Look for the effective key name after applying any keyboard layouts/mappings - const char *name_chars = _glfwPlatformGetNativeKeyName(key); - uint32_t name = 0; - if (name_chars) { - for (int i = 0; i < 4; i++) { - if (!name_chars[i]) break; - name <<= 8; - name |= (uint8_t)name_chars[i]; - } - } - if (name) { - // Key name - switch(name) { -#define K(ch, name) case ch: return GLFW_KEY_##name - K('!', EXCLAM); - K('"', DOUBLE_QUOTE); - K('#', NUMBER_SIGN); - K('$', DOLLAR); - K('&', AMPERSAND); - K('\'', APOSTROPHE); - K('(', PARENTHESIS_LEFT); - K(')', PARENTHESIS_RIGHT); - K('+', PLUS); - K(',', COMMA); - K('-', MINUS); - K('.', PERIOD); - K('/', SLASH); - K('0', 0); - K('1', 1); - K('2', 2); - K('3', 3); - K('5', 5); - K('6', 6); - K('7', 7); - K('8', 8); - K('9', 9); - K(':', COLON); - K(';', SEMICOLON); - K('<', LESS); - K('=', EQUAL); - K('>', GREATER); - K('@', AT); - K('A', A); K('a', A); - K('B', B); K('b', B); - K('C', C); K('c', C); - K('D', D); K('d', D); - K('E', E); K('e', E); - K('F', F); K('f', F); - K('G', G); K('g', G); - K('H', H); K('h', H); - K('I', I); K('i', I); - K('J', J); K('j', J); - K('K', K); K('k', K); - K('L', L); K('l', L); - K('M', M); K('m', M); - K('N', N); K('n', N); - K('O', O); K('o', O); - K('P', P); K('p', P); - K('Q', Q); K('q', Q); - K('R', R); K('r', R); - K('S', S); K('s', S); - K('T', T); K('t', T); - K('U', U); K('u', U); - K('V', V); K('v', V); - K('W', W); K('w', W); - K('X', X); K('x', X); - K('Y', Y); K('y', Y); - K('Z', Z); K('z', Z); - K('[', LEFT_BRACKET); - K('\\', BACKSLASH); - K(']', RIGHT_BRACKET); - K('^', CIRCUMFLEX); - K('_', UNDERSCORE); - K('`', GRAVE_ACCENT); - K(PARAGRAPH_UTF_8, PARAGRAPH); - K(MASCULINE_UTF_8, MASCULINE); - K(A_DIAERESIS_UPPER_CASE_UTF_8, A_DIAERESIS); - K(O_DIAERESIS_UPPER_CASE_UTF_8, O_DIAERESIS); - K(U_DIAERESIS_UPPER_CASE_UTF_8, U_DIAERESIS); - K(S_SHARP_UTF_8, S_SHARP); - K(A_GRAVE_LOWER_CASE_UTF_8, A_GRAVE); - K(A_DIAERESIS_LOWER_CASE_UTF_8, A_DIAERESIS); - K(A_RING_LOWER_CASE_UTF_8, A_RING); - K(AE_LOWER_CASE_UTF_8, AE); - K(C_CEDILLA_LOWER_CASE_UTF_8, C_CEDILLA); - K(E_GRAVE_LOWER_CASE_UTF_8, E_GRAVE); - K(E_ACUTE_LOWER_CASE_UTF_8, E_ACUTE); - K(I_GRAVE_LOWER_CASE_UTF_8, I_GRAVE); - K(N_TILDE_LOWER_CASE_UTF_8, N_TILDE); - K(O_GRAVE_LOWER_CASE_UTF_8, O_GRAVE); - K(O_DIAERESIS_LOWER_CASE_UTF_8, O_DIAERESIS); - K(O_SLASH_LOWER_CASE_UTF_8, O_SLASH); - K(U_GRAVE_LOWER_CASE_UTF_8, U_GRAVE); - K(U_DIAERESIS_LOWER_CASE_UTF_8, U_DIAERESIS); - K(CYRILLIC_A_LOWER_CASE_UTF_8, CYRILLIC_A); - K(CYRILLIC_BE_LOWER_CASE_UTF_8, CYRILLIC_BE); - K(CYRILLIC_VE_LOWER_CASE_UTF_8, CYRILLIC_VE); - K(CYRILLIC_GHE_LOWER_CASE_UTF_8, CYRILLIC_GHE); - K(CYRILLIC_DE_LOWER_CASE_UTF_8, CYRILLIC_DE); - K(CYRILLIC_IE_LOWER_CASE_UTF_8, CYRILLIC_IE); - K(CYRILLIC_ZHE_LOWER_CASE_UTF_8, CYRILLIC_ZHE); - K(CYRILLIC_ZE_LOWER_CASE_UTF_8, CYRILLIC_ZE); - K(CYRILLIC_I_LOWER_CASE_UTF_8, CYRILLIC_I); - K(CYRILLIC_SHORT_I_LOWER_CASE_UTF_8, CYRILLIC_SHORT_I); - K(CYRILLIC_KA_LOWER_CASE_UTF_8, CYRILLIC_KA); - K(CYRILLIC_EL_LOWER_CASE_UTF_8, CYRILLIC_EL); - K(CYRILLIC_EM_LOWER_CASE_UTF_8, CYRILLIC_EM); - K(CYRILLIC_EN_LOWER_CASE_UTF_8, CYRILLIC_EN); - K(CYRILLIC_O_LOWER_CASE_UTF_8, CYRILLIC_O); - K(CYRILLIC_PE_LOWER_CASE_UTF_8, CYRILLIC_PE); - K(CYRILLIC_ER_LOWER_CASE_UTF_8, CYRILLIC_ER); - K(CYRILLIC_ES_LOWER_CASE_UTF_8, CYRILLIC_ES); - K(CYRILLIC_TE_LOWER_CASE_UTF_8, CYRILLIC_TE); - K(CYRILLIC_U_LOWER_CASE_UTF_8, CYRILLIC_U); - K(CYRILLIC_EF_LOWER_CASE_UTF_8, CYRILLIC_EF); - K(CYRILLIC_HA_LOWER_CASE_UTF_8, CYRILLIC_HA); - K(CYRILLIC_TSE_LOWER_CASE_UTF_8, CYRILLIC_TSE); - K(CYRILLIC_CHE_LOWER_CASE_UTF_8, CYRILLIC_CHE); - K(CYRILLIC_SHA_LOWER_CASE_UTF_8, CYRILLIC_SHA); - K(CYRILLIC_SHCHA_LOWER_CASE_UTF_8, CYRILLIC_SHCHA); - K(CYRILLIC_HARD_SIGN_LOWER_CASE_UTF_8, CYRILLIC_HARD_SIGN); - K(CYRILLIC_YERU_LOWER_CASE_UTF_8, CYRILLIC_YERU); - K(CYRILLIC_SOFT_SIGN_LOWER_CASE_UTF_8, CYRILLIC_SOFT_SIGN); - K(CYRILLIC_E_LOWER_CASE_UTF_8, CYRILLIC_E); - K(CYRILLIC_YU_LOWER_CASE_UTF_8, CYRILLIC_YU); - K(CYRILLIC_YA_LOWER_CASE_UTF_8, CYRILLIC_YA); - K(CYRILLIC_IO_LOWER_CASE_UTF_8, CYRILLIC_IO); -#undef K - default: - break; - } - } - } - if (key >= sizeof(_glfw.ns.keycodes) / sizeof(_glfw.ns.keycodes[0])) - return GLFW_KEY_UNKNOWN; - - return _glfw.ns.keycodes[key]; + if (apply_keymap) return vk_to_unicode_key_with_current_layout(vk_key); + uint32_t ans = vk_code_to_functional_key_code(vk_key); + if (!ans) ans = vk_code_to_unicode(vk_key); + return ans; } // Translate a GLFW keycode to a Cocoa modifier flag // -static NSUInteger translateKeyToModifierFlag(int key) +static NSUInteger +translateKeyToModifierFlag(uint32_t key) { switch (key) { - case GLFW_KEY_LEFT_SHIFT: - case GLFW_KEY_RIGHT_SHIFT: + case GLFW_FKEY_LEFT_SHIFT: + case GLFW_FKEY_RIGHT_SHIFT: return NSEventModifierFlagShift; - case GLFW_KEY_LEFT_CONTROL: - case GLFW_KEY_RIGHT_CONTROL: + case GLFW_FKEY_LEFT_CONTROL: + case GLFW_FKEY_RIGHT_CONTROL: return NSEventModifierFlagControl; - case GLFW_KEY_LEFT_ALT: - case GLFW_KEY_RIGHT_ALT: + case GLFW_FKEY_LEFT_ALT: + case GLFW_FKEY_RIGHT_ALT: return NSEventModifierFlagOption; - case GLFW_KEY_LEFT_SUPER: - case GLFW_KEY_RIGHT_SUPER: + case GLFW_FKEY_LEFT_SUPER: + case GLFW_FKEY_RIGHT_SUPER: return NSEventModifierFlagCommand; - case GLFW_KEY_CAPS_LOCK: + case GLFW_FKEY_CAPS_LOCK: return NSEventModifierFlagCapsLock; } @@ -1072,15 +1125,15 @@ is_ascii_control_char(char x) { int action = GLFW_RELEASE; const unsigned int modifierFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; - const int key = translateKey([event keyCode], false); + const uint32_t key = translateKey([event keyCode], false); const int mods = translateFlags(modifierFlags); const NSUInteger keyFlag = translateKeyToModifierFlag(key); if (keyFlag & modifierFlags) { - int current_action == GLFW_RELEASE; + int current_action = GLFW_RELEASE; for (unsigned i = 0; i < arraysz(window->activated_keys); i++) { - if (window->activated_keys[i] == key) { + if (window->activated_keys[i].key == key) { current_action = window->activated_keys[i].action; break; } @@ -1976,9 +2029,72 @@ const char* _glfwPlatformGetNativeKeyName(int keycode) return _glfw.ns.keyName; } -int _glfwPlatformGetNativeKeyForKey(uint32_t key) +int _glfwPlatformGetNativeKeyForKey(uint32_t glfw_key) { - return _glfw.ns.key_to_keycode[key]; + if (GLFW_FKEY_FIRST <= glfw_key && glfw_key <= GLFW_FKEY_LAST) { // {{{ + switch(glfw_key) { + /* start functional to macu (auto generated by gen-key-constants.py do not edit) */ + case GLFW_FKEY_ENTER: return NSCarriageReturnCharacter; + case GLFW_FKEY_TAB: return NSTabCharacter; + case GLFW_FKEY_BACKSPACE: return NSBackspaceCharacter; + case GLFW_FKEY_INSERT: return NSInsertFunctionKey; + case GLFW_FKEY_DELETE: return NSDeleteFunctionKey; + case GLFW_FKEY_LEFT: return NSLeftArrowFunctionKey; + case GLFW_FKEY_RIGHT: return NSRightArrowFunctionKey; + case GLFW_FKEY_UP: return NSUpArrowFunctionKey; + case GLFW_FKEY_DOWN: return NSDownArrowFunctionKey; + case GLFW_FKEY_PAGE_UP: return NSPageUpFunctionKey; + case GLFW_FKEY_PAGE_DOWN: return NSPageDownFunctionKey; + case GLFW_FKEY_HOME: return NSHomeFunctionKey; + case GLFW_FKEY_END: return NSEndFunctionKey; + case GLFW_FKEY_SCROLL_LOCK: return NSScrollLockFunctionKey; + case GLFW_FKEY_NUM_LOCK: return NSClearLineFunctionKey; + case GLFW_FKEY_PRINT_SCREEN: return NSPrintScreenFunctionKey; + case GLFW_FKEY_PAUSE: return NSPauseFunctionKey; + case GLFW_FKEY_MENU: return NSMenuFunctionKey; + case GLFW_FKEY_F1: return NSF1FunctionKey; + case GLFW_FKEY_F2: return NSF2FunctionKey; + case GLFW_FKEY_F3: return NSF3FunctionKey; + case GLFW_FKEY_F4: return NSF4FunctionKey; + case GLFW_FKEY_F5: return NSF5FunctionKey; + case GLFW_FKEY_F6: return NSF6FunctionKey; + case GLFW_FKEY_F7: return NSF7FunctionKey; + case GLFW_FKEY_F8: return NSF8FunctionKey; + case GLFW_FKEY_F9: return NSF9FunctionKey; + case GLFW_FKEY_F10: return NSF10FunctionKey; + case GLFW_FKEY_F11: return NSF11FunctionKey; + case GLFW_FKEY_F12: return NSF12FunctionKey; + case GLFW_FKEY_F13: return NSF13FunctionKey; + case GLFW_FKEY_F14: return NSF14FunctionKey; + case GLFW_FKEY_F15: return NSF15FunctionKey; + case GLFW_FKEY_F16: return NSF16FunctionKey; + case GLFW_FKEY_F17: return NSF17FunctionKey; + case GLFW_FKEY_F18: return NSF18FunctionKey; + case GLFW_FKEY_F19: return NSF19FunctionKey; + case GLFW_FKEY_F20: return NSF20FunctionKey; + case GLFW_FKEY_F21: return NSF21FunctionKey; + case GLFW_FKEY_F22: return NSF22FunctionKey; + case GLFW_FKEY_F23: return NSF23FunctionKey; + case GLFW_FKEY_F24: return NSF24FunctionKey; + case GLFW_FKEY_F25: return NSF25FunctionKey; + case GLFW_FKEY_F26: return NSF26FunctionKey; + case GLFW_FKEY_F27: return NSF27FunctionKey; + case GLFW_FKEY_F28: return NSF28FunctionKey; + case GLFW_FKEY_F29: return NSF29FunctionKey; + case GLFW_FKEY_F30: return NSF30FunctionKey; + case GLFW_FKEY_F31: return NSF31FunctionKey; + case GLFW_FKEY_F32: return NSF32FunctionKey; + case GLFW_FKEY_F33: return NSF33FunctionKey; + case GLFW_FKEY_F34: return NSF34FunctionKey; + case GLFW_FKEY_F35: return NSF35FunctionKey; + case GLFW_FKEY_KP_ENTER: return NSEnterCharacter; +/* end functional to macu */ + default: + return 0; + } + } // }}} + if (!is_pua_char(glfw_key)) return glfw_key; + return 0; } int _glfwPlatformCreateCursor(_GLFWcursor* cursor, @@ -2348,10 +2464,9 @@ GLFWAPI void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun requestRenderFrame((_GLFWwindow*)w, callback); } -GLFWAPI void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, char *cocoa_key, size_t key_sz, int *cocoa_mods) { +GLFWAPI uint32_t +glfwGetCocoaKeyEquivalent(uint32_t glfw_key, int glfw_mods, int *cocoa_mods) { *cocoa_mods = 0; - memset(cocoa_key, 0, key_sz); - if (glfw_mods & GLFW_MOD_SHIFT) *cocoa_mods |= NSEventModifierFlagShift; if (glfw_mods & GLFW_MOD_CONTROL) @@ -2362,157 +2477,7 @@ GLFWAPI void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, char *cocoa_ *cocoa_mods |= NSEventModifierFlagCommand; if (glfw_mods & GLFW_MOD_CAPS_LOCK) *cocoa_mods |= NSEventModifierFlagCapsLock; - - uint32_t utf_8_key = 0; - unichar utf_16_key = 0; - -START_ALLOW_CASE_RANGE - switch(glfw_key) { -#define K8(ch, name) case GLFW_KEY_##name: utf_8_key = ch; break; -#define K16(ch, name) case GLFW_KEY_##name: utf_16_key = ch; break; - K8('!', EXCLAM); - K8('"', DOUBLE_QUOTE); - K8('#', NUMBER_SIGN); - K8('$', DOLLAR); - K8('&', AMPERSAND); - K8('\'', APOSTROPHE); - K8('(', PARENTHESIS_LEFT); - K8(')', PARENTHESIS_RIGHT); - K8('+', PLUS); - K8(',', COMMA); - K8('-', MINUS); - K8('.', PERIOD); - K8('/', SLASH); - K8('0', 0); - K8('1', 1); - K8('2', 2); - K8('3', 3); - K8('5', 5); - K8('6', 6); - K8('7', 7); - K8('8', 8); - K8('9', 9); - K8(':', COLON); - K8(';', SEMICOLON); - K8('<', LESS); - K8('=', EQUAL); - K8('>', GREATER); - K8('@', AT); - K8('[', LEFT_BRACKET); - K8('\\', BACKSLASH); - K8(']', RIGHT_BRACKET); - K8('^', CIRCUMFLEX); - K8('_', UNDERSCORE); - K8('`', GRAVE_ACCENT); - K8('a', A); - K8('b', B); - K8('c', C); - K8('d', D); - K8('e', E); - K8('f', F); - K8('g', G); - K8('h', H); - K8('i', I); - K8('j', J); - K8('k', K); - K8('l', L); - K8('m', M); - K8('n', N); - K8('o', O); - K8('p', P); - K8('q', Q); - K8('r', R); - K8('s', S); - K8('t', T); - K8('u', U); - K8('v', V); - K8('w', W); - K8('x', X); - K8('y', Y); - K8('z', Z); - K8(PARAGRAPH_UTF_8, PARAGRAPH); - K8(MASCULINE_UTF_8, MASCULINE); - K8(S_SHARP_UTF_8, S_SHARP); - K8(A_GRAVE_LOWER_CASE_UTF_8, A_GRAVE); - K8(A_DIAERESIS_LOWER_CASE_UTF_8, A_DIAERESIS); - K8(A_RING_LOWER_CASE_UTF_8, A_RING); - K8(AE_LOWER_CASE_UTF_8, AE); - K8(C_CEDILLA_LOWER_CASE_UTF_8, C_CEDILLA); - K8(E_GRAVE_LOWER_CASE_UTF_8, E_GRAVE); - K8(E_ACUTE_LOWER_CASE_UTF_8, E_ACUTE); - K8(I_GRAVE_LOWER_CASE_UTF_8, I_GRAVE); - K8(N_TILDE_LOWER_CASE_UTF_8, N_TILDE); - K8(O_GRAVE_LOWER_CASE_UTF_8, O_GRAVE); - K8(O_DIAERESIS_LOWER_CASE_UTF_8, O_DIAERESIS); - K8(O_SLASH_LOWER_CASE_UTF_8, O_SLASH); - K8(U_GRAVE_LOWER_CASE_UTF_8, U_GRAVE); - K8(U_DIAERESIS_LOWER_CASE_UTF_8, U_DIAERESIS); - K8(CYRILLIC_A_LOWER_CASE_UTF_8, CYRILLIC_A); - K8(CYRILLIC_BE_LOWER_CASE_UTF_8, CYRILLIC_BE); - K8(CYRILLIC_VE_LOWER_CASE_UTF_8, CYRILLIC_VE); - K8(CYRILLIC_GHE_LOWER_CASE_UTF_8, CYRILLIC_GHE); - K8(CYRILLIC_DE_LOWER_CASE_UTF_8, CYRILLIC_DE); - K8(CYRILLIC_IE_LOWER_CASE_UTF_8, CYRILLIC_IE); - K8(CYRILLIC_ZHE_LOWER_CASE_UTF_8, CYRILLIC_ZHE); - K8(CYRILLIC_ZE_LOWER_CASE_UTF_8, CYRILLIC_ZE); - K8(CYRILLIC_I_LOWER_CASE_UTF_8, CYRILLIC_I); - K8(CYRILLIC_SHORT_I_LOWER_CASE_UTF_8, CYRILLIC_SHORT_I); - K8(CYRILLIC_KA_LOWER_CASE_UTF_8, CYRILLIC_KA); - K8(CYRILLIC_EL_LOWER_CASE_UTF_8, CYRILLIC_EL); - K8(CYRILLIC_EM_LOWER_CASE_UTF_8, CYRILLIC_EM); - K8(CYRILLIC_EN_LOWER_CASE_UTF_8, CYRILLIC_EN); - K8(CYRILLIC_O_LOWER_CASE_UTF_8, CYRILLIC_O); - K8(CYRILLIC_PE_LOWER_CASE_UTF_8, CYRILLIC_PE); - K8(CYRILLIC_ER_LOWER_CASE_UTF_8, CYRILLIC_ER); - K8(CYRILLIC_ES_LOWER_CASE_UTF_8, CYRILLIC_ES); - K8(CYRILLIC_TE_LOWER_CASE_UTF_8, CYRILLIC_TE); - K8(CYRILLIC_U_LOWER_CASE_UTF_8, CYRILLIC_U); - K8(CYRILLIC_EF_LOWER_CASE_UTF_8, CYRILLIC_EF); - K8(CYRILLIC_HA_LOWER_CASE_UTF_8, CYRILLIC_HA); - K8(CYRILLIC_TSE_LOWER_CASE_UTF_8, CYRILLIC_TSE); - K8(CYRILLIC_CHE_LOWER_CASE_UTF_8, CYRILLIC_CHE); - K8(CYRILLIC_SHA_LOWER_CASE_UTF_8, CYRILLIC_SHA); - K8(CYRILLIC_SHCHA_LOWER_CASE_UTF_8, CYRILLIC_SHCHA); - K8(CYRILLIC_HARD_SIGN_LOWER_CASE_UTF_8, CYRILLIC_HARD_SIGN); - K8(CYRILLIC_YERU_LOWER_CASE_UTF_8, CYRILLIC_YERU); - K8(CYRILLIC_SOFT_SIGN_LOWER_CASE_UTF_8, CYRILLIC_SOFT_SIGN); - K8(CYRILLIC_E_LOWER_CASE_UTF_8, CYRILLIC_E); - K8(CYRILLIC_YU_LOWER_CASE_UTF_8, CYRILLIC_YU); - K8(CYRILLIC_YA_LOWER_CASE_UTF_8, CYRILLIC_YA); - K8(CYRILLIC_IO_LOWER_CASE_UTF_8, CYRILLIC_IO); - - K8(0x35, ESCAPE); - K8('\r', ENTER); - K8('\t', TAB); - K16(NSBackspaceCharacter, BACKSPACE); - K16(NSInsertFunctionKey, INSERT); - K16(NSDeleteCharacter, DELETE); - K16(NSLeftArrowFunctionKey, LEFT); - K16(NSRightArrowFunctionKey, RIGHT); - K16(NSUpArrowFunctionKey, UP); - K16(NSDownArrowFunctionKey, DOWN); - K16(NSPageUpFunctionKey, PAGE_UP); - K16(NSPageDownFunctionKey, PAGE_DOWN); - K16(NSHomeFunctionKey, HOME); - K16(NSEndFunctionKey, END); - K16(NSPrintFunctionKey, PRINT_SCREEN); - case GLFW_KEY_F1 ... GLFW_KEY_F24: - utf_16_key = NSF1FunctionKey + (glfw_key - GLFW_KEY_F1); break; -#undef K8 -#undef K16 -END_ALLOW_CASE_RANGE - } - if (utf_16_key != 0) { - strncpy(cocoa_key, [[NSString stringWithCharacters:&utf_16_key length:1] UTF8String], key_sz - 1); - } else { - unsigned str_pos = 0; - for (unsigned i = 0; i < 4 && str_pos < key_sz - 1; i++) { - uint8_t byte = (utf_8_key >> 24) & 0xff; - utf_8_key <<= 8; - if (byte != 0) cocoa_key[str_pos++] = byte; - } - cocoa_key[str_pos] = 0; - } + return _glfwPlatformGetNativeKeyForKey(glfw_key); } diff --git a/glfw/glfw.py b/glfw/glfw.py index 6174a25a0..83a9710cb 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -206,7 +206,7 @@ def generate_wrappers(glfw_header: str) -> None: GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *window, GLFWcocoatogglefullscreenfun callback) GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback) GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback) - void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, char* cocoa_key, size_t key_sz, int* cocoa_mods) + uint32_t glfwGetCocoaKeyEquivalent(uint32_t glfw_key, int glfw_mods, int* cocoa_mods) void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun callback) void* glfwGetX11Display(void) int32_t glfwGetX11Window(GLFWwindow* window) diff --git a/kitty/cocoa_window.m b/kitty/cocoa_window.m index 482dadd58..c41b15d0f 100644 --- a/kitty/cocoa_window.m +++ b/kitty/cocoa_window.m @@ -111,8 +111,9 @@ static NSEventModifierFlags new_window_mods = 0; static PyObject* cocoa_set_new_window_trigger(PyObject *self UNUSED, PyObject *args) { - int mods, key; - if (!PyArg_ParseTuple(args, "ii", &mods, &key)) return NULL; + int mods; + unsigned int key; + if (!PyArg_ParseTuple(args, "iI", &mods, &key)) return NULL; int nwm; get_cocoa_key_equivalent(key, mods, new_window_key, sizeof(new_window_key), &nwm); new_window_mods = nwm; diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 75075fb30..0f4ab121a 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -2071,7 +2071,7 @@ typedef GLFWapplicationwillfinishlaunchingfun (*glfwSetApplicationWillFinishLaun GFW_EXTERN glfwSetApplicationWillFinishLaunching_func glfwSetApplicationWillFinishLaunching_impl; #define glfwSetApplicationWillFinishLaunching glfwSetApplicationWillFinishLaunching_impl -typedef void (*glfwGetCocoaKeyEquivalent_func)(int, int, char*, size_t, int*); +typedef uint32_t (*glfwGetCocoaKeyEquivalent_func)(uint32_t, int, int*); GFW_EXTERN glfwGetCocoaKeyEquivalent_func glfwGetCocoaKeyEquivalent_impl; #define glfwGetCocoaKeyEquivalent glfwGetCocoaKeyEquivalent_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index c9579b5b2..bcf55a102 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -1223,8 +1223,10 @@ set_custom_cursor(PyObject *self UNUSED, PyObject *args) { #ifdef __APPLE__ void -get_cocoa_key_equivalent(int key, int mods, char *cocoa_key, size_t key_sz, int *cocoa_mods) { - glfwGetCocoaKeyEquivalent(key, mods, cocoa_key, key_sz, cocoa_mods); +get_cocoa_key_equivalent(uint32_t key, int mods, char *cocoa_key, size_t key_sz, int *cocoa_mods) { + memset(cocoa_key, 0, key_sz); + uint32_t ans = glfwGetCocoaKeyEquivalent(key, mods, cocoa_mods); + if (ans) encode_utf8(ans, cocoa_key); } static void diff --git a/kitty/key_encoding.c b/kitty/key_encoding.c index 4d9fdc602..9b86b3d35 100644 --- a/kitty/key_encoding.c +++ b/kitty/key_encoding.c @@ -47,11 +47,6 @@ convert_glfw_mods(int mods, KeyEvent *ev) { } -static inline int -encode_csi_string(const char csi_trailer, const char *payload, char *output) { - return snprintf(output, KEY_BUFFER_SIZE, "\x1b[%s%c", payload, csi_trailer); -} - static inline void init_encoding_data(EncodingData *ans, const KeyEvent *ev) { ans->add_actions = ev->report_all_event_types && ev->action != PRESS; diff --git a/kitty/state.h b/kitty/state.h index 6146d8fee..ab5c22010 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -258,7 +258,7 @@ void set_titlebar_color(OSWindow *w, color_type color); FONTS_DATA_HANDLE load_fonts_data(double, double, double); void send_prerendered_sprites_for_window(OSWindow *w); #ifdef __APPLE__ -void get_cocoa_key_equivalent(int, int, char *key, size_t key_sz, int*); +void get_cocoa_key_equivalent(uint32_t, int, char *key, size_t key_sz, int*); typedef enum { PREFERENCES_WINDOW = 1, NEW_OS_WINDOW = 2,