diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 63fd6ee2655..8d097e497ee 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -2179,8 +2179,7 @@ GLFWAPI void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun requestRenderFrame((_GLFWwindow*)w, callback); } -GLFWAPI void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, unsigned short *cocoa_key, int *cocoa_mods) { - *cocoa_key = 0; +GLFWAPI void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, char **cocoa_key, int *cocoa_mods) { *cocoa_mods = 0; if (glfw_mods & GLFW_MOD_SHIFT) @@ -2194,148 +2193,164 @@ GLFWAPI void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, unsigned sho 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 K(ch, name) case GLFW_KEY_##name: *cocoa_key = ch; break; - 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('[', LEFT_BRACKET); - K('\\', BACKSLASH); - K(']', RIGHT_BRACKET); - K('^', CIRCUMFLEX); - K('_', UNDERSCORE); - K('`', GRAVE_ACCENT); - K('a', A); - K('b', B); - K('c', C); - K('d', D); - K('e', E); - K('f', F); - K('g', G); - K('h', H); - K('i', I); - K('j', J); - K('k', K); - K('l', L); - K('m', M); - K('n', N); - K('o', O); - K('p', P); - K('q', Q); - K('r', R); - K('s', S); - K('t', T); - K('u', U); - K('v', V); - K('w', W); - K('x', X); - K('y', Y); - K('z', Z); - K(PARAGRAPH_UTF_8, PARAGRAPH); - K(MASCULINE_UTF_8, MASCULINE); - 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); - - K(0x35, ESCAPE); - K('\r', ENTER); - K('\t', TAB); - K(NSBackspaceCharacter, BACKSPACE); - K(NSInsertFunctionKey, INSERT); - K(NSDeleteCharacter, DELETE); - K(NSLeftArrowFunctionKey, LEFT); - K(NSRightArrowFunctionKey, RIGHT); - K(NSUpArrowFunctionKey, UP); - K(NSDownArrowFunctionKey, DOWN); - K(NSPageUpFunctionKey, PAGE_UP); - K(NSPageDownFunctionKey, PAGE_DOWN); - K(NSHomeFunctionKey, HOME); - K(NSEndFunctionKey, END); - K(NSPrintFunctionKey, PRINT_SCREEN); +#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: - *cocoa_key = NSF1FunctionKey + (glfw_key - GLFW_KEY_F1); break; - case GLFW_KEY_KP_0 ... GLFW_KEY_KP_9: - *cocoa_key = NSEventModifierFlagNumericPad | (0x52 + (glfw_key - GLFW_KEY_KP_0)); break; - K((unichar)(0x41|NSEventModifierFlagNumericPad), KP_DECIMAL); - K((unichar)(0x43|NSEventModifierFlagNumericPad), KP_MULTIPLY); - K((unichar)(0x45|NSEventModifierFlagNumericPad), KP_ADD); - K((unichar)(0x4B|NSEventModifierFlagNumericPad), KP_DIVIDE); - K((unichar)(0x4E|NSEventModifierFlagNumericPad), KP_SUBTRACT); - K((unichar)(0x51|NSEventModifierFlagNumericPad), KP_EQUAL); -#undef K + utf_16_key = NSF1FunctionKey + (glfw_key - GLFW_KEY_F1); break; +#undef K8 +#undef K16 END_ALLOW_CASE_RANGE } + if (utf_16_key != 0) { + NSString *tmp_cocoa_key = [NSString stringWithCharacters:&utf_16_key length:1]; + *cocoa_key = _glfw_strdup([tmp_cocoa_key UTF8String]); + } else { + // 5 chars for one UTF-8 character plus a null byte should be enough + // Use 4 * 4 + 1 chars to allow returning at least four unicode characters in the future, should the need arise + char tmp_cocoa_key[4 * 4 + 1]; + int str_pos = 0; + for (int i = 0; i < 4; i++) { + uint8_t byte = (utf_8_key >> 24) & 0xff; + utf_8_key <<= 8; + if (byte != 0) { + tmp_cocoa_key[str_pos] = byte; + str_pos++; + } + } + tmp_cocoa_key[str_pos] = 0; + *cocoa_key = _glfw_strdup(tmp_cocoa_key); + } } diff --git a/glfw/glfw.py b/glfw/glfw.py index f6d699d27fb..663c505c374 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -166,7 +166,7 @@ def generate_wrappers(glfw_header): GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *window, GLFWcocoatogglefullscreenfun callback) GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback) GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback) - void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, void* cocoa_key, int* cocoa_mods) + void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, char **cocoa_key, 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 308b5737a80..e112e001601 100644 --- a/kitty/cocoa_window.m +++ b/kitty/cocoa_window.m @@ -97,7 +97,7 @@ + (GlobalMenuTarget *) shared_instance @end -static unichar new_window_key = 0; +static char* new_window_key = NULL; static NSEventModifierFlags new_window_mods = 0; static PyObject* @@ -253,7 +253,7 @@ - (void)openFilesFromPasteboard:(NSPasteboard *)pasteboard type:(int)type { [preferences_menu_item setTarget:global_menu_target]; [appMenu addItem:preferences_menu_item]; if (new_window_key) { - NSString *s = [NSString stringWithCharacters:&new_window_key length:1]; + NSString *s = @(new_window_key); new_os_window_menu_item = [[NSMenuItem alloc] initWithTitle:@"New OS window" action:@selector(new_os_window:) keyEquivalent:s]; [new_os_window_menu_item setKeyEquivalentModifierMask:new_window_mods]; [new_os_window_menu_item setTarget:global_menu_target]; @@ -473,6 +473,8 @@ - (void)openFilesFromPasteboard:(NSPasteboard *)pasteboard type:(int)type { dockMenu = nil; if (notification_activated_callback) Py_DECREF(notification_activated_callback); notification_activated_callback = NULL; + free(new_window_key); + new_window_key = NULL; } // autoreleasepool } diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 420fbf8fac7..20257cebec9 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -2083,7 +2083,7 @@ typedef GLFWapplicationwillfinishlaunchingfun (*glfwSetApplicationWillFinishLaun glfwSetApplicationWillFinishLaunching_func glfwSetApplicationWillFinishLaunching_impl; #define glfwSetApplicationWillFinishLaunching glfwSetApplicationWillFinishLaunching_impl -typedef void (*glfwGetCocoaKeyEquivalent_func)(int, int, void*, int*); +typedef void (*glfwGetCocoaKeyEquivalent_func)(int, int, char**, int*); glfwGetCocoaKeyEquivalent_func glfwGetCocoaKeyEquivalent_impl; #define glfwGetCocoaKeyEquivalent glfwGetCocoaKeyEquivalent_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index 5737d65867d..cb808c015a7 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -1079,7 +1079,7 @@ set_custom_cursor(PyObject *self UNUSED, PyObject *args) { #ifdef __APPLE__ void -get_cocoa_key_equivalent(int key, int mods, unsigned short *cocoa_key, int *cocoa_mods) { +get_cocoa_key_equivalent(int key, int mods, char **cocoa_key, int *cocoa_mods) { glfwGetCocoaKeyEquivalent(key, mods, cocoa_key, cocoa_mods); } diff --git a/kitty/state.h b/kitty/state.h index 96b253b275c..8886e5eb26d 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -225,7 +225,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, unsigned short*, int*); +void get_cocoa_key_equivalent(int, int, char**, int*); typedef enum { PREFERENCES_WINDOW = 1, NEW_OS_WINDOW = 2,