xcb: use keyboard event source window to determine auto-repeat value

The xcb auto-repeat checking code checks for queued events on the target
(focused) window. This breaks down if you have a native child widget,
and QKeyEvent::autoRepeat is never true.

Task-number: QTBUG-21500
Change-Id: Ia979edfa8a3afce07a3e1cbaa778541ffb9ce5dc
Reviewed-by: Gatis Paeglis <gatis.paeglis@digia.com>
This commit is contained in:
Dyami Caliri 2014-06-18 22:20:05 -07:00 committed by Gatis Paeglis
parent 8688dfcd7c
commit 07c34fcc8a
3 changed files with 18 additions and 17 deletions

View File

@ -466,7 +466,7 @@ break;
if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->event)) { \ if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->event)) { \
handled = eventListener->handleGenericEvent(event, &result); \ handled = eventListener->handleGenericEvent(event, &result); \
if (!handled) \ if (!handled) \
m_keyboard->handler(m_focusWindow ? m_focusWindow : eventListener, e); \ m_keyboard->handler(e); \
} \ } \
} \ } \
break; break;

View File

@ -1295,7 +1295,7 @@ private:
bool m_release; bool m_release;
}; };
void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycode_t code, void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, xcb_keycode_t code,
quint16 state, xcb_timestamp_t time) quint16 state, xcb_timestamp_t time)
{ {
Q_XCB_NOOP(connection()); Q_XCB_NOOP(connection());
@ -1303,6 +1303,13 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
if (!m_config) if (!m_config)
return; return;
QXcbWindow *source = connection()->platformWindowFromId(sourceWindow);
QXcbWindow *targetWindow = connection()->focusWindow() ? connection()->focusWindow() : source;
if (!targetWindow || !source)
return;
if (type == QEvent::KeyPress)
targetWindow->updateNetWmUserTime(time);
// It is crucial the order of xkb_state_key_get_one_sym & xkb_state_update_key operations is not reversed! // It is crucial the order of xkb_state_key_get_one_sym & xkb_state_update_key operations is not reversed!
xcb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, code); xcb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, code);
@ -1343,7 +1350,7 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
} }
} else { } else {
// look ahead for auto-repeat // look ahead for auto-repeat
KeyChecker checker(((QXcbWindow *)window->handle())->xcb_window(), code, time); KeyChecker checker(source->xcb_window(), code, time);
xcb_generic_event_t *event = connection()->checkEvent(checker); xcb_generic_event_t *event = connection()->checkEvent(checker);
if (event) { if (event) {
isAutoRepeat = true; isAutoRepeat = true;
@ -1359,6 +1366,7 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
filtered = inputContext->filterEvent(&event); filtered = inputContext->filterEvent(&event);
} }
QWindow *window = targetWindow->window();
if (!filtered) { if (!filtered) {
if (type == QEvent::KeyPress && qtcode == Qt::Key_Menu) { if (type == QEvent::KeyPress && qtcode == Qt::Key_Menu) {
const QPoint globalPos = window->screen()->handle()->cursor()->pos(); const QPoint globalPos = window->screen()->handle()->cursor()->pos();
@ -1401,21 +1409,14 @@ QString QXcbKeyboard::lookupString(struct xkb_state *state, xcb_keycode_t code)
return QString::fromUtf8(chars); return QString::fromUtf8(chars);
} }
void QXcbKeyboard::handleKeyPressEvent(QXcbWindowEventListener *eventListener, const xcb_key_press_event_t *event) void QXcbKeyboard::handleKeyPressEvent(const xcb_key_press_event_t *event)
{ {
QXcbWindow *window = eventListener->toWindow(); handleKeyEvent(event->event, QEvent::KeyPress, event->detail, event->state, event->time);
if (!window)
return;
window->updateNetWmUserTime(event->time);
handleKeyEvent(window->window(), QEvent::KeyPress, event->detail, event->state, event->time);
} }
void QXcbKeyboard::handleKeyReleaseEvent(QXcbWindowEventListener *eventListener, const xcb_key_release_event_t *event) void QXcbKeyboard::handleKeyReleaseEvent(const xcb_key_release_event_t *event)
{ {
QXcbWindow *window = eventListener->toWindow(); handleKeyEvent(event->event, QEvent::KeyRelease, event->detail, event->state, event->time);
if (!window)
return;
handleKeyEvent(window->window(), QEvent::KeyRelease, event->detail, event->state, event->time);
} }
void QXcbKeyboard::handleMappingNotifyEvent(const void *event) void QXcbKeyboard::handleMappingNotifyEvent(const void *event)

View File

@ -64,8 +64,8 @@ public:
~QXcbKeyboard(); ~QXcbKeyboard();
void handleKeyPressEvent(QXcbWindowEventListener *eventListener, const xcb_key_press_event_t *event); void handleKeyPressEvent(const xcb_key_press_event_t *event);
void handleKeyReleaseEvent(QXcbWindowEventListener *eventListener, const xcb_key_release_event_t *event); void handleKeyReleaseEvent(const xcb_key_release_event_t *event);
void handleMappingNotifyEvent(const void *event); void handleMappingNotifyEvent(const void *event);
Qt::KeyboardModifiers translateModifiers(int s) const; Qt::KeyboardModifiers translateModifiers(int s) const;
@ -83,7 +83,7 @@ public:
#endif #endif
protected: protected:
void handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycode_t code, quint16 state, xcb_timestamp_t time); void handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, xcb_keycode_t code, quint16 state, xcb_timestamp_t time);
void resolveMaskConflicts(); void resolveMaskConflicts();
QString lookupString(struct xkb_state *state, xcb_keycode_t code) const; QString lookupString(struct xkb_state *state, xcb_keycode_t code) const;