From 0ba89ed91fe3599504e6dc1b6d5e761aa9f24a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 6 Jan 2012 15:03:24 +0100 Subject: Detect autoreapeat in xcb plugin. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now QKeyEvent::isAutoRepeat() would always return false. Change-Id: I7771bc7a7ec848ef280f99bada0a26eda188604e Reviewed-by: Jørgen Lind --- src/plugins/platforms/xcb/qxcbconnection.h | 4 +- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 83 +++++++++++++++++++++++++++++- src/plugins/platforms/xcb/qxcbkeyboard.h | 1 + 3 files changed, 85 insertions(+), 3 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index e41265c1e9..f2ad71b1db 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -340,7 +340,7 @@ public: xcb_generic_event_t *checkEvent(int type); template - inline xcb_generic_event_t *checkEvent(const T &checker); + inline xcb_generic_event_t *checkEvent(T &checker); typedef bool (*PeekFunc)(xcb_generic_event_t *); void addPeekFunc(PeekFunc f); @@ -428,7 +428,7 @@ private: #define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display())) template -xcb_generic_event_t *QXcbConnection::checkEvent(const T &checker) +xcb_generic_event_t *QXcbConnection::checkEvent(T &checker) { QXcbEventArray *eventqueue = m_reader->lock(); diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 0eee7e4ff3..641980b030 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -907,6 +907,7 @@ QString QXcbKeyboard::translateKeySym(xcb_keysym_t keysym, uint xmodifiers, QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection) : QXcbObject(connection) + , m_autorepeat_code(0) { m_key_symbols = xcb_key_symbols_alloc(xcb_connection()); setupModifiers(); @@ -1020,6 +1021,62 @@ void QXcbKeyboard::setMask(uint sym, uint mask) // #define XCB_KEYBOARD_DEBUG +class KeyChecker +{ +public: + KeyChecker(xcb_window_t window, xcb_keycode_t code, xcb_timestamp_t time) + : m_window(window) + , m_code(code) + , m_time(time) + , m_error(false) + , m_release(true) + { + } + + bool check(xcb_generic_event_t *ev) + { + if (m_error || !ev) + return false; + + int type = ev->response_type & ~0x80; + if (type != XCB_KEY_PRESS && type != XCB_KEY_RELEASE) + return false; + + xcb_key_press_event_t *event = (xcb_key_press_event_t *)ev; + + if (event->event != m_window || event->detail != m_code) { + m_error = true; + return false; + } + + if (type == XCB_KEY_PRESS) { + m_error = !m_release || event->time - m_time > 10; + return !m_error; + } + + if (m_release) { + m_error = true; + return false; + } + + m_release = true; + m_time = event->time; + + return false; + } + + bool release() const { return m_release; } + xcb_timestamp_t time() const { return m_time; } + +private: + xcb_window_t m_window; + xcb_keycode_t m_code; + xcb_timestamp_t m_time; + + bool m_error; + bool m_release; +}; + void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycode_t code, quint16 state, xcb_timestamp_t time) { @@ -1062,8 +1119,32 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod return; } + bool isAutoRepeat = false; + + if (type == QEvent::KeyPress) { + if (m_autorepeat_code == code) { + isAutoRepeat = true; + m_autorepeat_code = 0; + } + } else { + // look ahead for auto-repeat + KeyChecker checker(((QXcbWindow *)window->handle())->xcb_window(), code, time); + xcb_generic_event_t *event = connection()->checkEvent(checker); + if (event) { + isAutoRepeat = true; + free(event); + } + m_autorepeat_code = isAutoRepeat ? code : 0; + } + QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers, - code, 0, state, string.left(count)); + code, 0, state, string.left(count), isAutoRepeat); + + if (isAutoRepeat && type == QEvent::KeyRelease) { + // since we removed it from the event queue using checkEvent we need to send the key press here + QWindowSystemInterface::handleExtendedKeyEvent(window, time, QEvent::KeyPress, qtcode, modifiers, + code, 0, state, string.left(count), isAutoRepeat); + } } #ifdef XCB_USE_XLIB diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index 90fa4fab67..4a62dde11a 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -86,6 +86,7 @@ private: uint m_caps_lock_mask; xcb_key_symbols_t *m_key_symbols; + xcb_keycode_t m_autorepeat_code; }; QT_END_NAMESPACE -- cgit v1.2.3