From d95b1b33e52a989b3c81114c7fc3c71a6405c05b Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sun, 18 May 2014 12:24:29 +0200 Subject: [PATCH] Cleanup of XKB detection code. --- src/x11_init.c | 38 ++++++++++++++------------------------ src/x11_platform.h | 1 + src/x11_window.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/x11_init.c b/src/x11_init.c index 89da8f85..95ea718c 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -40,14 +40,12 @@ static int translateKey(int keyCode) { int keySym; - int keysyms_per_keycode_return; - KeySym *keysyms; // Valid key code range is [8,255], according to the XLib manual if (keyCode < 8 || keyCode > 255) return GLFW_KEY_UNKNOWN; - if(_glfw.x11.xkb.available) + if (_glfw.x11.xkb.available) { // Try secondary keysym, for numeric keypad keys // Note: This way we always force "NumLock = ON", which is intentional @@ -80,13 +78,12 @@ static int translateKey(int keyCode) } else { - keysyms = - XGetKeyboardMapping(_glfw.x11.display, - keyCode, - 1, - &keysyms_per_keycode_return); - keySym = keysyms[0]; - XFree(keysyms); + int dummy; + KeySym* keySyms; + + keySyms = XGetKeyboardMapping(_glfw.x11.display, keyCode, 1, &dummy); + keySym = keySyms[0]; + XFree(keySyms); } switch (keySym) @@ -233,8 +230,7 @@ static int translateKey(int keyCode) // static void updateKeyCodeLUT(void) { - int keyCode; - int keyCodeGLFW, i; + int i, keyCode, keyCodeGLFW; char name[XkbKeyNameLength + 1]; XkbDescPtr descr; @@ -242,7 +238,7 @@ static void updateKeyCodeLUT(void) for (keyCode = 0; keyCode < 256; keyCode++) _glfw.x11.keyCodeLUT[keyCode] = GLFW_KEY_UNKNOWN; - if(_glfw.x11.xkb.available) + if (_glfw.x11.xkb.available) { // Use XKB to determine physical key locations independently of the current // keyboard layout @@ -451,8 +447,6 @@ static void detectEWMH(void) // static GLboolean initExtensions(void) { - Bool supported; - // Find or create window manager atoms _glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", @@ -524,18 +518,14 @@ static GLboolean initExtensions(void) &_glfw.x11.xkb.versionMajor, &_glfw.x11.xkb.versionMinor); - if(_glfw.x11.xkb.available) + if (_glfw.x11.xkb.available) { - if (!XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) - { - // X11: Failed to set detectable key repeat - _glfw.x11.xkb.available = GL_FALSE; - } + Bool supported; - if (!supported) + if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) { - // X11: Detectable key repeat is not supported - _glfw.x11.xkb.available = GL_FALSE; + if (supported) + _glfw.x11.xkb.detectable = GL_TRUE; } } diff --git a/src/x11_platform.h b/src/x11_platform.h index 5d090347..4193ba0e 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -176,6 +176,7 @@ typedef struct _GLFWlibraryX11 struct { GLboolean available; + GLboolean detectable; int majorOpcode; int eventBase; int errorBase; diff --git a/src/x11_window.c b/src/x11_window.c index 40ed759f..09d5fbd7 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -615,6 +615,36 @@ static void processEvent(XEvent *event) const int key = translateKey(event->xkey.keycode); const int mods = translateState(event->xkey.state); + if (!_glfw.x11.xkb.detectable) + { + // XKB detectable key repeat is not supported on this server + // For key repeats we will get KeyRelease/KeyPress pairs with + // similar or identical time stamps. User selected key repeat + // filtering is handled in _glfwInputKey/_glfwInputChar. + if (XEventsQueued(_glfw.x11.display, QueuedAfterReading)) + { + XEvent nextEvent; + XPeekEvent(_glfw.x11.display, &nextEvent); + + if (nextEvent.type == KeyPress && + nextEvent.xkey.window == event->xkey.window && + nextEvent.xkey.keycode == event->xkey.keycode) + { + // This last check is a hack to work around key repeats + // leaking through due to some sort of time drift + // Toshiyuki Takahashi can press a button 16 times per + // second so it's fairly safe to assume that no human is + // pressing the key 50 times per second (value is ms) + if ((nextEvent.xkey.time - event->xkey.time) < 20) + { + // This is a server-generated key repeat event + // Do not report anything for this event + break; + } + } + } + } + _glfwInputKey(window, key, event->xkey.keycode, GLFW_RELEASE, mods); break; }