From 78264f333eb7c262380714ed6517562266f11a03 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 6 Jun 2011 10:02:06 +0200 Subject: Avoid setting the active window to null when there is a FocusIn queued. --- src/plugins/platforms/xcb/qxcbconnection.cpp | 20 ++++++++++++++++++++ src/plugins/platforms/xcb/qxcbconnection.h | 5 +++++ src/plugins/platforms/xcb/qxcbwindow.cpp | 16 +++++++++++++++- 3 files changed, 40 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 1d7611533a..6acc42208d 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -483,6 +483,11 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) printXcbEvent("Unhandled XCB event", event); } +void QXcbConnection::addPeekFunc(PeekFunc f) +{ + m_peekFuncs.append(f); +} + void QXcbConnection::processXcbEvents() { while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection())) @@ -498,6 +503,15 @@ void QXcbConnection::processXcbEvents() if (!response_type) { handleXcbError((xcb_generic_error_t *)event); } else { + QVector::iterator it = m_peekFuncs.begin(); + while (it != m_peekFuncs.end()) { + // These callbacks return true if the event is what they were + // waiting for, remove them from the list in that case. + if ((*it)(event)) + it = m_peekFuncs.erase(it); + else + ++it; + } handleXcbEvent(event); } @@ -506,6 +520,12 @@ void QXcbConnection::processXcbEvents() eventqueue.clear(); + // Indicate with a null event that the event the callbacks are waiting for + // is not in the queue currently. + Q_FOREACH (PeekFunc f, m_peekFuncs) + f(0); + m_peekFuncs.clear(); + xcb_flush(xcb_connection()); } diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index e0cb1d954e..51aa09fcef 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -284,6 +284,9 @@ public: QXcbWindow *platformWindowFromId(xcb_window_t id); + typedef bool (*PeekFunc)(xcb_generic_event_t *); + void addPeekFunc(PeekFunc f); + private slots: void processXcbEvents(); @@ -335,6 +338,8 @@ private: QVector eventqueue; WindowMapper m_mapper; + + QVector m_peekFuncs; }; #define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display())) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 9d6f3e01ad..3b70968dfc 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1087,9 +1087,23 @@ void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *) QWindowSystemInterface::handleWindowActivated(window()); } +static bool focusInPeeker(xcb_generic_event_t *event) +{ + if (!event) { + // FocusIn event is not in the queue, proceed with FocusOut normally. + QWindowSystemInterface::handleWindowActivated(0); + return true; + } + uint response_type = event->response_type & ~0x80; + return response_type == XCB_FOCUS_IN; +} + void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *) { - QWindowSystemInterface::handleWindowActivated(0); + // Do not set the active window to 0 if there is a FocusIn coming. + // There is however no equivalent for XPutBackEvent so register a + // callback for QXcbConnection instead. + connection()->addPeekFunc(focusInPeeker); } void QXcbWindow::updateSyncRequestCounter() -- cgit v1.2.3