diff --git a/glfw/cocoa_init.m b/glfw/cocoa_init.m index a35f182d3..4ca95d6aa 100644 --- a/glfw/cocoa_init.m +++ b/glfw/cocoa_init.m @@ -179,10 +179,10 @@ static void createMenuBar(void) // static void createKeyTables(void) { - int scancode; + int keycode; memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes)); - memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes)); + 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; @@ -299,11 +299,11 @@ static void createKeyTables(void) _glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY; _glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT; - for (scancode = 0; scancode < 256; scancode++) + for (keycode = 0; keycode < 256; keycode++) { // Store the reverse translation for faster key name lookup - if (_glfw.ns.keycodes[scancode] >= 0) - _glfw.ns.scancodes[_glfw.ns.keycodes[scancode]] = scancode; + if (_glfw.ns.keycodes[keycode] >= 0) + _glfw.ns.key_to_keycode[_glfw.ns.keycodes[keycode]] = keycode; } } diff --git a/glfw/cocoa_platform.h b/glfw/cocoa_platform.h index 8941aab77..0b399d02e 100644 --- a/glfw/cocoa_platform.h +++ b/glfw/cocoa_platform.h @@ -166,7 +166,7 @@ typedef struct _GLFWlibraryNS char keyName[64]; char text[256]; short int keycodes[256]; - short int scancodes[GLFW_KEY_LAST + 1]; + 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 5a32407f6..1576d92e8 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -327,8 +327,8 @@ format_text(const char *src) { } static const char* -safe_name_for_scancode(unsigned int scancode) { - const char *ans = _glfwPlatformGetScancodeName(scancode); +safe_name_for_keycode(unsigned int keycode) { + const char *ans = _glfwPlatformGetNativeKeyName(keycode); if (!ans) return ""; if ((1 <= ans[0] && ans[0] <= 31) || ans[0] == 127) ans = ""; return ans; @@ -341,7 +341,7 @@ static int translateKey(unsigned int key, bool apply_keymap) { if (apply_keymap) { // Look for the effective key name after applying any keyboard layouts/mappings - const char *name_chars = _glfwPlatformGetScancodeName(key); + const char *name_chars = _glfwPlatformGetNativeKeyName(key); uint32_t name = 0; if (name_chars) { for (int i = 0; i < 4; i++) { @@ -965,16 +965,16 @@ is_ascii_control_char(char x) { - (void)keyDown:(NSEvent *)event { - const unsigned int scancode = [event keyCode]; + const unsigned int keycode = [event keyCode]; const NSUInteger flags = [event modifierFlags]; const int mods = translateFlags(flags); - const int key = translateKey(scancode, true); - const bool process_text = !window->ns.textInputFilterCallback || window->ns.textInputFilterCallback(key, mods, scancode, flags) != 1; + const int key = translateKey(keycode, true); + const bool process_text = !window->ns.textInputFilterCallback || window->ns.textInputFilterCallback(key, mods, keycode, flags) != 1; const bool previous_has_marked_text = [self hasMarkedText]; [self unmarkText]; _glfw.ns.text[0] = 0; GLFWkeyevent glfw_keyevent; - _glfwInitializeKeyEvent(&glfw_keyevent, key, scancode, GLFW_PRESS, mods); + _glfwInitializeKeyEvent(&glfw_keyevent, key, keycode, GLFW_PRESS, mods); if (!_glfw.ns.unicodeData) { // Using the cocoa API for key handling is disabled, as there is no // reliable way to handle dead keys using it. Only use it if the @@ -989,7 +989,7 @@ is_ascii_control_char(char x) { const bool in_compose_sequence = window->ns.deadKeyState != 0; if (UCKeyTranslate( [(NSData*) _glfw.ns.unicodeData bytes], - scancode, + keycode, kUCKeyActionDown, convert_cocoa_to_carbon_modifiers(flags), LMGetKbdType(), @@ -999,20 +999,20 @@ is_ascii_control_char(char x) { &char_count, text ) != noErr) { - debug_key(@"UCKeyTranslate failed for scancode: 0x%x (%@) %@\n", - scancode, @(safe_name_for_scancode(scancode)), @(format_mods(mods))); + debug_key(@"UCKeyTranslate failed for keycode: 0x%x (%@) %@\n", + keycode, @(safe_name_for_keycode(keycode)), @(format_mods(mods))); window->ns.deadKeyState = 0; return; } - debug_key(@"scancode: 0x%x (%@) %@char_count: %lu deadKeyState: %u repeat: %d", - scancode, @(safe_name_for_scancode(scancode)), @(format_mods(mods)), char_count, window->ns.deadKeyState, event.ARepeat); + debug_key(@"keycode: 0x%x (%@) %@char_count: %lu deadKeyState: %u repeat: %d", + keycode, @(safe_name_for_keycode(keycode)), @(format_mods(mods)), char_count, window->ns.deadKeyState, event.ARepeat); if (process_text) { // this will call insertText which will fill up _glfw.ns.text [self interpretKeyEvents:[NSArray arrayWithObject:event]]; } else { window->ns.deadKeyState = 0; } - if (window->ns.deadKeyState && (char_count == 0 || scancode == 0x75)) { + if (window->ns.deadKeyState && (char_count == 0 || keycode == 0x75)) { // 0x75 is the delete key which needs to be ignored during a compose sequence debug_key(@"Sending pre-edit text for dead key (text: %@ markedText: %@).\n", @(format_text(_glfw.ns.text)), markedText); glfw_keyevent.text = [[markedText string] UTF8String]; @@ -1896,14 +1896,14 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode UNUSED) updateCursorMode(window); } -const char* _glfwPlatformGetScancodeName(int scancode) +const char* _glfwPlatformGetNativeKeyName(int keycode) { UInt32 deadKeyState = 0; UniChar characters[8]; UniCharCount characterCount = 0; if (UCKeyTranslate([(NSData*) _glfw.ns.unicodeData bytes], - scancode, + keycode, kUCKeyActionDisplay, 0, LMGetKbdType(), @@ -1923,9 +1923,9 @@ const char* _glfwPlatformGetScancodeName(int scancode) return _glfw.ns.keyName; } -int _glfwPlatformGetKeyScancode(int key) +int _glfwPlatformGetNativeKeyForKey(int key) { - return _glfw.ns.scancodes[key]; + return _glfw.ns.key_to_keycode[key]; } int _glfwPlatformCreateCursor(_GLFWcursor* cursor, diff --git a/glfw/glfw.py b/glfw/glfw.py index b8857caa4..90f8a73f0 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -171,7 +171,7 @@ def generate_wrappers(glfw_header): int32_t glfwGetX11Window(GLFWwindow* window) void glfwSetPrimarySelectionString(GLFWwindow* window, const char* string) const char* glfwGetPrimarySelectionString(GLFWwindow* window, void) - int glfwGetXKBScancode(const char* key_name, int case_sensitive) + int glfwGetNativeKeyForName(const char* key_name, int case_sensitive) void glfwRequestWaylandFrameEvent(GLFWwindow *handle, unsigned long long id, GLFWwaylandframecallbackfunc callback) unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, \ const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data) diff --git a/glfw/glfw3.h b/glfw/glfw3.h index c29f4e1ef..1305e867e 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1211,8 +1211,8 @@ typedef struct GLFWkeyevent // The [keyboard key](@ref keys) that was pressed or released. int key; - // The system-specific scancode of the key. - int scancode; + // The platform-specific identifier of the key. + int native_key; // The event action. Either `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`. int action; @@ -1565,7 +1565,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int); * This is the function pointer type for key callbacks. A keyboard * key callback function has the following signature: * @code - * void function_name(GLFWwindow* window, int key, int scancode, int action, int mods) + * void function_name(GLFWwindow* window, int key, int native_key, int action, int mods) * @endcode * The semantics of this function are that the key that is interacted with on the * keyboard is reported, and the text, if any generated by the key is reported. @@ -4114,9 +4114,9 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); * __Do not use this function__ for [text input](@ref input_char). You will * break text input for many languages even if it happens to work for yours. * - * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used to identify the key, - * otherwise the scancode is ignored. If you specify a non-printable key, or - * `GLFW_KEY_UNKNOWN` and a scancode that maps to a non-printable key, this + * If the key is `GLFW_KEY_UNKNOWN`, the keycode is used to identify the key, + * otherwise the keycode is ignored. If you specify a non-printable key, or + * `GLFW_KEY_UNKNOWN` and a keycode that maps to a non-printable key, this * function returns `NULL` but does not emit an error. * * This behavior allows you to always pass in the arguments in the @@ -4215,7 +4215,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); * language and should be localized along with other user interface text. * * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. - * @param[in] scancode The scancode of the key to query. + * @param[in] native_key The platform-specifc identifier of the key to query. * @return The UTF-8 encoded, layout-specific name of the key, or `NULL`. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref @@ -4235,17 +4235,17 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); * * @ingroup input */ -GLFWAPI const char* glfwGetKeyName(int key, int scancode); +GLFWAPI const char* glfwGetKeyName(int key, int native_key); -/*! @brief Returns the platform-specific scancode of the specified key. +/*! @brief Returns the platform-specific identifier of the specified key. * - * This function returns the platform-specific scancode of the specified key. + * This function returns the platform-specific identifier of the specified key. * * If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this * method will return `-1`. * * @param[in] key Any [named key](@ref keys). - * @return The platform-specific scancode for the key, or `-1` if an + * @return The platform-specific identifier for the key, or `-1` if an * [error](@ref error_handling) occurred. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref @@ -4259,7 +4259,7 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode); * * @ingroup input */ -GLFWAPI int glfwGetKeyScancode(int key); +GLFWAPI int glfwGetNativeKeyForKey(int key); /*! @brief Returns the last reported state of a keyboard key for the specified * window. diff --git a/glfw/ibus_glfw.c b/glfw/ibus_glfw.c index 2153f78b3..13f7fe5e6 100644 --- a/glfw/ibus_glfw.c +++ b/glfw/ibus_glfw.c @@ -407,7 +407,7 @@ key_event_processed(DBusMessage *msg, const char* errmsg, void *data) { failed = true; } else { glfw_dbus_get_args(msg, "Failed to get IBUS handled key from reply", DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID); - debug("IBUS processed scancode: 0x%x release: %d handled: %u\n", ev->glfw_ev.scancode, is_release, handled); + debug("IBUS processed native_key: 0x%x release: %d handled: %u\n", ev->glfw_ev.native_key, is_release, handled); } glfw_xkb_key_from_ime(ev, handled ? true : false, failed); free(ev); diff --git a/glfw/input.c b/glfw/input.c index 87820b57a..afa179768 100644 --- a/glfw/input.c +++ b/glfw/input.c @@ -257,10 +257,10 @@ static bool parseMapping(_GLFWmapping* mapping, const char* string) ////// GLFW event API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int scancode, int action, int mods) +void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int native_key, int action, int mods) { ev->key = key; - ev->scancode = scancode; + ev->native_key = native_key; ev->action = action; ev->mods = mods; ev->text = NULL; @@ -756,7 +756,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); } -GLFWAPI const char* glfwGetKeyName(int key, int scancode) +GLFWAPI const char* glfwGetKeyName(int key, int native_key) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); @@ -769,13 +769,13 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode) return NULL; } - scancode = _glfwPlatformGetKeyScancode(key); + native_key = _glfwPlatformGetNativeKeyForKey(key); } - return _glfwPlatformGetScancodeName(scancode); + return _glfwPlatformGetNativeKeyName(native_key); } -GLFWAPI int glfwGetKeyScancode(int key) +GLFWAPI int glfwGetNativeKeyForKey(int key) { _GLFW_REQUIRE_INIT_OR_RETURN(-1); @@ -785,7 +785,7 @@ GLFWAPI int glfwGetKeyScancode(int key) return GLFW_RELEASE; } - return _glfwPlatformGetKeyScancode(key); + return _glfwPlatformGetNativeKeyForKey(key); } GLFWAPI int glfwGetKey(GLFWwindow* handle, int key) diff --git a/glfw/internal.h b/glfw/internal.h index bb54b151c..8ea3de86d 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -640,8 +640,8 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape void _glfwPlatformDestroyCursor(_GLFWcursor* cursor); void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor); -const char* _glfwPlatformGetScancodeName(int scancode); -int _glfwPlatformGetKeyScancode(int key); +const char* _glfwPlatformGetNativeKeyName(int native_key); +int _glfwPlatformGetNativeKeyForKey(int key); void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor); void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos); @@ -758,7 +758,7 @@ void _glfwInputWindowDamage(_GLFWwindow* window); void _glfwInputWindowCloseRequest(_GLFWwindow* window); void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor); -void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int scancode, int action, int mods); +void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int native_key, int action, int mods); void _glfwInputKeyboard(_GLFWwindow *window, GLFWkeyevent *ev); void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int flags); void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods); diff --git a/glfw/null_window.c b/glfw/null_window.c index c567ca598..c7a759ade 100644 --- a/glfw/null_window.c +++ b/glfw/null_window.c @@ -307,12 +307,12 @@ const char* _glfwPlatformGetClipboardString(void) return NULL; } -const char* _glfwPlatformGetScancodeName(int scancode UNUSED) +const char* _glfwPlatformGetNativeKeyName(int native_key UNUSED) { return ""; } -int _glfwPlatformGetKeyScancode(int key UNUSED) +int _glfwPlatformGetNativeKeyForKey(int key UNUSED) { return -1; } diff --git a/glfw/window.c b/glfw/window.c index 14d0da95d..c693a0a02 100644 --- a/glfw/window.c +++ b/glfw/window.c @@ -57,9 +57,9 @@ void _glfwInputWindowFocus(_GLFWwindow* window, bool focused) { if (window->keys[key] == GLFW_PRESS) { - const int scancode = _glfwPlatformGetKeyScancode(key); + const int native_key = _glfwPlatformGetNativeKeyForKey(key); GLFWkeyevent ev; - _glfwInitializeKeyEvent(&ev, key, scancode, GLFW_RELEASE, 0); + _glfwInitializeKeyEvent(&ev, key, native_key, GLFW_RELEASE, 0); _glfwInputKeyboard(window, &ev); } } diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 15c030e3f..8fcbc1431 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -1269,12 +1269,12 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode UNUSED) _glfwPlatformSetCursor(window, window->wl.currentCursor); } -const char* _glfwPlatformGetScancodeName(int scancode) +const char* _glfwPlatformGetNativeKeyName(int native_key) { - return glfw_xkb_keysym_name(scancode); + return glfw_xkb_keysym_name(native_key); } -int _glfwPlatformGetKeyScancode(int key) +int _glfwPlatformGetNativeKeyForKey(int key) { return glfw_xkb_sym_for_key(key); } @@ -2032,7 +2032,7 @@ GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* handle) return window->wl.surface; } -GLFWAPI int glfwGetXKBScancode(const char* keyName, bool caseSensitive) { +GLFWAPI int glfwGetNativeKeyForName(const char* keyName, bool caseSensitive) { return glfw_xkb_keysym_from_name(keyName, caseSensitive); } diff --git a/glfw/x11_window.c b/glfw/x11_window.c index 815296fd8..f5e426a48 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -2586,13 +2586,13 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) XFlush(_glfw.x11.display); } -const char* _glfwPlatformGetScancodeName(int scancode) +const char* _glfwPlatformGetNativeKeyName(int native_key) { - return glfw_xkb_keysym_name(scancode); + return glfw_xkb_keysym_name(native_key); } -int _glfwPlatformGetKeyScancode(int key) +int _glfwPlatformGetNativeKeyForKey(int key) { return glfw_xkb_sym_for_key(key); } @@ -2871,7 +2871,7 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* handle) return window->x11.handle; } -GLFWAPI int glfwGetXKBScancode(const char* keyName, bool caseSensitive) { +GLFWAPI int glfwGetNativeKeyForName(const char* keyName, bool caseSensitive) { return glfw_xkb_keysym_from_name(keyName, caseSensitive); } diff --git a/glfw/xkb_glfw.c b/glfw/xkb_glfw.c index a1981810d..a554acd21 100644 --- a/glfw/xkb_glfw.c +++ b/glfw/xkb_glfw.c @@ -437,11 +437,11 @@ glfw_xkb_update_modifiers(_GLFWXKBData *xkb, xkb_mod_mask_t depressed, xkb_mod_m } bool -glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode) { +glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t keycode) { #ifdef _GLFW_WAYLAND - scancode += 8; + keycode += 8; #endif - return xkb_keymap_key_repeats(xkb->keymap, scancode); + return xkb_keymap_key_repeats(xkb->keymap, keycode); } @@ -549,10 +549,10 @@ glfw_xkb_key_from_ime(_GLFWIBUSKeyEvent *ev, bool handled_by_ime, bool failed) { xkb_keycode_t prev_handled_press = last_handled_press_keycode; last_handled_press_keycode = 0; bool is_release = ev->glfw_ev.action == GLFW_RELEASE; - debug("From IBUS: scancode: 0x%x name: %s is_release: %d\n", ev->glfw_ev.scancode, glfw_xkb_keysym_name(ev->glfw_ev.key), is_release); - if (window && !handled_by_ime && !(is_release && ev->glfw_ev.scancode == (int) prev_handled_press)) { + debug("From IBUS: native_key: 0x%x name: %s is_release: %d\n", ev->glfw_ev.native_key, glfw_xkb_keysym_name(ev->glfw_ev.key), is_release); + if (window && !handled_by_ime && !(is_release && ev->glfw_ev.native_key == (int) prev_handled_press)) { debug("↳ to application: glfw_keycode: 0x%x (%s) keysym: 0x%x (%s) action: %s %s text: %s\n", - ev->glfw_ev.scancode, _glfwGetKeyName(ev->glfw_ev.scancode), ev->glfw_ev.key, glfw_xkb_keysym_name(ev->glfw_ev.key), + ev->glfw_ev.native_key, _glfwGetKeyName(ev->glfw_ev.native_key), ev->glfw_ev.key, glfw_xkb_keysym_name(ev->glfw_ev.key), (ev->glfw_ev.action == GLFW_RELEASE ? "RELEASE" : (ev->glfw_ev.action == GLFW_PRESS ? "PRESS" : "REPEAT")), format_mods(ev->glfw_ev.mods), ev->glfw_ev.text ); @@ -560,15 +560,16 @@ glfw_xkb_key_from_ime(_GLFWIBUSKeyEvent *ev, bool handled_by_ime, bool failed) { ev->glfw_ev.ime_state = 0; _glfwInputKeyboard(window, &ev->glfw_ev); } else debug("↳ discarded\n"); - if (!is_release && handled_by_ime) last_handled_press_keycode = ev->glfw_ev.scancode; + if (!is_release && handled_by_ime) + last_handled_press_keycode = ev->glfw_ev.native_key; } void -glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action) { +glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t xkb_keycode, int action) { static char key_text[64] = {0}; const xkb_keysym_t *syms, *clean_syms, *default_syms; xkb_keysym_t xkb_sym; - xkb_keycode_t code_for_sym = scancode, ibus_keycode = scancode; + xkb_keycode_t code_for_sym = xkb_keycode, ibus_keycode = xkb_keycode; GLFWkeyevent glfw_ev; _glfwInitializeKeyEvent(&glfw_ev, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0); // init with default values #ifdef _GLFW_WAYLAND @@ -576,7 +577,7 @@ glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t #else ibus_keycode -= 8; #endif - debug("%s scancode: 0x%x ", action == GLFW_RELEASE ? "Release" : "Press", scancode); + debug("%s xkb_keycode: 0x%x ", action == GLFW_RELEASE ? "Release" : "Press", xkb_keycode); XKBStateGroup *sg = &xkb->states; int num_syms = xkb_state_key_get_syms(sg->state, code_for_sym, &syms); int num_clean_syms = xkb_state_key_get_syms(sg->clean_state, code_for_sym, &clean_syms); @@ -635,8 +636,17 @@ glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t xkb_sym, glfw_xkb_keysym_name(xkb_sym) ); + // NOTE: On linux, the reported native key identifier is the XKB keysym value. + // Do not confuse `native_key` with `xkb_keycode` (the native keycode reported for the + // glfw event VS the X internal code for a key). + // + // We use the XKB keysym instead of the X keycode to be able to go back-and-forth between + // the GLFW keysym and the XKB keysym when needed, which is not possible using the X keycode, + // because of the lost information when resolving the keycode to the keysym, like consumed + // mods. + glfw_ev.native_key = xkb_sym; + glfw_ev.action = action; - glfw_ev.scancode = xkb_sym; glfw_ev.key = glfw_sym; glfw_ev.mods = sg->modifiers; glfw_ev.text = key_text; @@ -647,7 +657,7 @@ glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t ibus_ev.window_id = window->id; ibus_ev.ibus_keysym = syms[0]; if (ibus_process_key(&ibus_ev, &xkb->ibus)) { - debug("↳ to IBUS: scancode: 0x%x keysym: 0x%x (%s) %s\n", ibus_ev.ibus_keycode, ibus_ev.ibus_keysym, glfw_xkb_keysym_name(ibus_ev.ibus_keysym), format_mods(ibus_ev.glfw_ev.mods)); + debug("↳ to IBUS: keycode: 0x%x keysym: 0x%x (%s) %s\n", ibus_ev.ibus_keycode, ibus_ev.ibus_keysym, glfw_xkb_keysym_name(ibus_ev.ibus_keysym), format_mods(ibus_ev.glfw_ev.mods)); } else { _glfwInputKeyboard(window, &glfw_ev); } diff --git a/glfw/xkb_glfw.h b/glfw/xkb_glfw.h index c454a2d5b..eea09fbaa 100644 --- a/glfw/xkb_glfw.h +++ b/glfw/xkb_glfw.h @@ -87,10 +87,10 @@ void glfw_xkb_release(_GLFWXKBData *xkb); bool glfw_xkb_create_context(_GLFWXKBData *xkb); bool glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str); void glfw_xkb_update_modifiers(_GLFWXKBData *xkb, xkb_mod_mask_t depressed, xkb_mod_mask_t latched, xkb_mod_mask_t locked, xkb_layout_index_t base_group, xkb_layout_index_t latched_group, xkb_layout_index_t locked_group); -bool glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode); +bool glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t keycode); const char* glfw_xkb_keysym_name(xkb_keysym_t sym); xkb_keysym_t glfw_xkb_sym_for_key(int key); -void glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action); +void glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t keycode, int action); int glfw_xkb_keysym_from_name(const char *name, bool case_sensitive); void glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, int b, int c, int d); void glfw_xkb_key_from_ime(_GLFWIBUSKeyEvent *ev, bool handled_by_ime, bool failed); diff --git a/kitty/boss.py b/kitty/boss.py index 76b4a6825..2629c019f 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -512,27 +512,27 @@ class Boss: if t is not None: return t.active_window - def dispatch_special_key(self, key, scancode, action, mods): + def dispatch_special_key(self, key, native_key, action, mods): # Handles shortcuts, return True if the key was consumed - key_action = get_shortcut(self.keymap, mods, key, scancode) + key_action = get_shortcut(self.keymap, mods, key, native_key) if key_action is None: - sequences = get_shortcut(self.opts.sequence_map, mods, key, scancode) + sequences = get_shortcut(self.opts.sequence_map, mods, key, native_key) if sequences: self.pending_sequences = sequences set_in_sequence_mode(True) return True else: - self.current_key_press_info = key, scancode, action, mods + self.current_key_press_info = key, native_key, action, mods return self.dispatch_action(key_action) - def process_sequence(self, key, scancode, action, mods): + def process_sequence(self, key, native_key, action, mods): if not self.pending_sequences: set_in_sequence_mode(False) remaining = {} matched_action = None for seq, key_action in self.pending_sequences.items(): - if shortcut_matches(seq[0], mods, key, scancode): + if shortcut_matches(seq[0], mods, key, native_key): seq = seq[1:] if seq: remaining[seq] = key_action diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index 98cfba9e8..f3dfafbba 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -245,8 +245,8 @@ load_glfw(const char* path) { *(void **) (&glfwGetKeyName_impl) = dlsym(handle, "glfwGetKeyName"); if (glfwGetKeyName_impl == NULL) fail("Failed to load glfw function glfwGetKeyName with error: %s", dlerror()); - *(void **) (&glfwGetKeyScancode_impl) = dlsym(handle, "glfwGetKeyScancode"); - if (glfwGetKeyScancode_impl == NULL) fail("Failed to load glfw function glfwGetKeyScancode with error: %s", dlerror()); + *(void **) (&glfwGetNativeKeyForKey_impl) = dlsym(handle, "glfwGetNativeKeyForKey"); + if (glfwGetNativeKeyForKey_impl == NULL) fail("Failed to load glfw function glfwGetNativeKeyForKey with error: %s", dlerror()); *(void **) (&glfwGetKey_impl) = dlsym(handle, "glfwGetKey"); if (glfwGetKey_impl == NULL) fail("Failed to load glfw function glfwGetKey with error: %s", dlerror()); @@ -401,7 +401,7 @@ load_glfw(const char* path) { *(void **) (&glfwGetPrimarySelectionString_impl) = dlsym(handle, "glfwGetPrimarySelectionString"); - *(void **) (&glfwGetXKBScancode_impl) = dlsym(handle, "glfwGetXKBScancode"); + *(void **) (&glfwGetNativeKeyForName_impl) = dlsym(handle, "glfwGetNativeKeyForName"); *(void **) (&glfwRequestWaylandFrameEvent_impl) = dlsym(handle, "glfwRequestWaylandFrameEvent"); diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 282ddd8c5..5c194f906 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -971,8 +971,8 @@ typedef struct GLFWkeyevent // The [keyboard key](@ref keys) that was pressed or released. int key; - // The system-specific scancode of the key. - int scancode; + // The platform-specific identifier of the key. + int native_key; // The event action. Either `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`. int action; @@ -1325,7 +1325,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int); * This is the function pointer type for key callbacks. A keyboard * key callback function has the following signature: * @code - * void function_name(GLFWwindow* window, int key, int scancode, int action, int mods) + * void function_name(GLFWwindow* window, int key, int native_key, int action, int mods) * @endcode * The semantics of this function are that the key that is interacted with on the * keyboard is reported, and the text, if any generated by the key is reported. @@ -1889,9 +1889,9 @@ typedef const char* (*glfwGetKeyName_func)(int, int); glfwGetKeyName_func glfwGetKeyName_impl; #define glfwGetKeyName glfwGetKeyName_impl -typedef int (*glfwGetKeyScancode_func)(int); -glfwGetKeyScancode_func glfwGetKeyScancode_impl; -#define glfwGetKeyScancode glfwGetKeyScancode_impl +typedef int (*glfwGetNativeKeyForKey_func)(int); +glfwGetNativeKeyForKey_func glfwGetNativeKeyForKey_impl; +#define glfwGetNativeKeyForKey glfwGetNativeKeyForKey_impl typedef int (*glfwGetKey_func)(GLFWwindow*, int); glfwGetKey_func glfwGetKey_impl; @@ -2113,9 +2113,9 @@ typedef const char* (*glfwGetPrimarySelectionString_func)(GLFWwindow*); glfwGetPrimarySelectionString_func glfwGetPrimarySelectionString_impl; #define glfwGetPrimarySelectionString glfwGetPrimarySelectionString_impl -typedef int (*glfwGetXKBScancode_func)(const char*, int); -glfwGetXKBScancode_func glfwGetXKBScancode_impl; -#define glfwGetXKBScancode glfwGetXKBScancode_impl +typedef int (*glfwGetNativeKeyForName_func)(const char*, int); +glfwGetNativeKeyForName_func glfwGetNativeKeyForName_impl; +#define glfwGetNativeKeyForName glfwGetNativeKeyForName_impl typedef void (*glfwRequestWaylandFrameEvent_func)(GLFWwindow*, unsigned long long, GLFWwaylandframecallbackfunc); glfwRequestWaylandFrameEvent_func glfwRequestWaylandFrameEvent_impl; diff --git a/kitty/glfw.c b/kitty/glfw.c index 62edb54d6..e7f680eb1 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -451,7 +451,7 @@ toggle_maximized_for_os_window(OSWindow *w) { #ifdef __APPLE__ static int -filter_option(int key UNUSED, int mods, unsigned int scancode UNUSED, unsigned long flags) { +filter_option(int key UNUSED, int mods, unsigned int native_key UNUSED, unsigned long flags) { if ((mods == GLFW_MOD_ALT) || (mods == (GLFW_MOD_ALT | GLFW_MOD_SHIFT))) { if (OPT(macos_option_as_alt) == 3) return 1; if (cocoa_alt_option_key_pressed(flags)) return 1; @@ -830,9 +830,9 @@ glfw_get_physical_dpi(PYNOARG) { static PyObject* glfw_get_key_name(PyObject UNUSED *self, PyObject *args) { - int key, scancode; - if (!PyArg_ParseTuple(args, "ii", &key, &scancode)) return NULL; - return Py_BuildValue("s", glfwGetKeyName(key, scancode)); + int key, native_key; + if (!PyArg_ParseTuple(args, "ii", &key, &native_key)) return NULL; + return Py_BuildValue("s", glfwGetKeyName(key, native_key)); } static PyObject* diff --git a/kitty/keys.c b/kitty/keys.c index 0b581b1a9..7139d80e3 100644 --- a/kitty/keys.c +++ b/kitty/keys.c @@ -26,7 +26,7 @@ key_to_bytes(int glfw_key, bool smkx, bool extended, int mods, int action) { #define SPECIAL_INDEX(key) ((key & 0x7f) | ( (mods & 0xF) << 7)) #define IS_ALT_MODS(mods) (mods == GLFW_MOD_ALT || mods == (GLFW_MOD_ALT | GLFW_MOD_SHIFT)) -typedef struct { int mods, scancode; } NativeKey; +typedef struct { int mods, native_key; } NativeKey; static NativeKey *native_special_keys = NULL; static size_t native_special_keys_capacity = 0, native_special_keys_count = 0; @@ -39,7 +39,7 @@ set_special_key_combo(int glfw_key, int mods, bool is_native) { if (native_special_keys == NULL) fatal("Out of memory"); } native_special_keys[native_special_keys_count].mods = mods; - native_special_keys[native_special_keys_count++].scancode = glfw_key; + native_special_keys[native_special_keys_count++].native_key = glfw_key; } else { uint16_t key = key_map[glfw_key]; if (key != UINT8_MAX) { @@ -96,7 +96,7 @@ is_ascii_control_char(char c) { } static inline bool -check_if_special(int key, int mods, int scancode) { +check_if_special(int key, int mods, int native_key) { uint16_t qkey = (0 <= key && key < (ssize_t)arraysz(key_map)) ? key_map[key] : UINT8_MAX; bool special = false; if (qkey != UINT8_MAX) { @@ -104,7 +104,8 @@ check_if_special(int key, int mods, int scancode) { special = needs_special_handling[qkey]; } for (size_t i = 0; !special && i < native_special_keys_count; i++) { - if (scancode == native_special_keys[i].scancode && mods == native_special_keys[i].mods) special = true; + if (native_key == native_special_keys[i].native_key && mods == native_special_keys[i].mods) + special = true; } return special; } @@ -123,11 +124,11 @@ update_ime_position(OSWindow *os_window, Window* w, Screen *screen) { void on_key_input(GLFWkeyevent *ev) { Window *w = active_window(); - int action = ev->action, scancode = ev->scancode, key = ev->key, mods = ev->mods; + int action = ev->action, native_key = ev->native_key, key = ev->key, mods = ev->mods; const char *text = ev->text ? ev->text : ""; debug("on_key_input: glfw key: %d native_code: 0x%x action: %s mods: 0x%x text: '%s' state: %d ", - key, scancode, + key, native_key, (action == GLFW_RELEASE ? "RELEASE" : (action == GLFW_PRESS ? "PRESS" : "REPEAT")), mods, text, ev->ime_state); if (!w) { debug("no active window, ignoring\n"); return; } @@ -161,13 +162,13 @@ on_key_input(GLFWkeyevent *ev) { if ( action != GLFW_RELEASE && key != GLFW_KEY_LEFT_SHIFT && key != GLFW_KEY_RIGHT_SHIFT && key != GLFW_KEY_LEFT_ALT && key != GLFW_KEY_RIGHT_ALT && key != GLFW_KEY_LEFT_CONTROL && key != GLFW_KEY_RIGHT_CONTROL - ) call_boss(process_sequence, "iiii", key, scancode, action, mods); + ) call_boss(process_sequence, "iiii", key, native_key, action, mods); return; } bool has_text = text[0] && !is_ascii_control_char(text[0]); if (action == GLFW_PRESS || action == GLFW_REPEAT) { - if (check_if_special(key, mods, scancode)) { - PyObject *ret = PyObject_CallMethod(global_state.boss, "dispatch_special_key", "iiii", key, scancode, action, mods); + if (check_if_special(key, mods, native_key)) { + PyObject *ret = PyObject_CallMethod(global_state.boss, "dispatch_special_key", "iiii", key, native_key, action, mods); if (ret == NULL) { PyErr_Print(); } else { bool consumed = ret == Py_True; @@ -228,9 +229,9 @@ PYWRAP1(key_for_native_key_name) { int case_sensitive = 0; PA("s|p", &name, &case_sensitive); #ifndef __APPLE__ - if (glfwGetXKBScancode) { // if this function is called before GLFW is initialized glfwGetXKBScancode will be NULL - int scancode = glfwGetXKBScancode(name, case_sensitive); - if (scancode) return Py_BuildValue("i", scancode); + if (glfwGetNativeKeyForName) { // if this function is called before GLFW is initialized glfwGetNativeKeyForName will be NULL + int native_key = glfwGetNativeKeyForName(name, case_sensitive); + if (native_key) return Py_BuildValue("i", native_key); } #endif Py_RETURN_NONE; diff --git a/kitty/keys.py b/kitty/keys.py index 49a36acce..88fae002b 100644 --- a/kitty/keys.py +++ b/kitty/keys.py @@ -264,7 +264,7 @@ def key_to_bytes(key, smkx, extended, mods, action): return bytes(data) -def interpret_key_event(key, scancode, mods, window, action): +def interpret_key_event(key, native_key, mods, window, action): screen = window.screen if ( action == defines.GLFW_PRESS or @@ -275,17 +275,17 @@ def interpret_key_event(key, scancode, mods, window, action): return b'' -def get_shortcut(keymap, mods, key, scancode): +def get_shortcut(keymap, mods, key, native_key): mods &= 0b1111 ans = keymap.get((mods, False, key)) if ans is None: - ans = keymap.get((mods, True, scancode)) + ans = keymap.get((mods, True, native_key)) return ans -def shortcut_matches(s, mods, key, scancode): +def shortcut_matches(s, mods, key, native_key): mods &= 0b1111 - q = scancode if s[1] else key + q = native_key if s[1] else key return s[0] & 0b1111 == mods & 0b1111 and s[2] == q