diff options
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 54 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbeventdispatcher.cpp | 7 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbeventqueue.cpp | 29 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbeventqueue.h | 5 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbintegration.cpp | 2 |
6 files changed, 90 insertions, 11 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index c1f0b71414..a4294956c1 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1020,11 +1020,10 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) printXcbEvent(lcQpaEvents(), "Event", event); long result = 0; // Used only by MS Windows - QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); - bool handledByNativeEventFilter = dispatcher && dispatcher->filterNativeEvent( - m_nativeInterface->nativeEventType(), event, &result); - if (handledByNativeEventFilter) - return; + if (QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance()) { + if (dispatcher->filterNativeEvent(m_nativeInterface->nativeEventType(), event, &result)) + return; + } uint response_type = event->response_type & ~0x80; @@ -1451,7 +1450,47 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event) const return false; } -void QXcbConnection::processXcbEvents() +bool QXcbConnection::isUserInputEvent(xcb_generic_event_t *event) const +{ + auto eventType = event->response_type & ~0x80; + bool isInputEvent = eventType == XCB_BUTTON_PRESS || + eventType == XCB_BUTTON_RELEASE || + eventType == XCB_KEY_PRESS || + eventType == XCB_KEY_RELEASE || + eventType == XCB_MOTION_NOTIFY || + eventType == XCB_ENTER_NOTIFY || + eventType == XCB_LEAVE_NOTIFY; + if (isInputEvent) + return true; + +#if QT_CONFIG(xcb_xinput) + if (connection()->hasXInput2()) { + isInputEvent = isXIType(event, m_xiOpCode, XCB_INPUT_BUTTON_PRESS) || + isXIType(event, m_xiOpCode, XCB_INPUT_BUTTON_RELEASE) || + isXIType(event, m_xiOpCode, XCB_INPUT_MOTION) || + isXIType(event, m_xiOpCode, XCB_INPUT_TOUCH_BEGIN) || + isXIType(event, m_xiOpCode, XCB_INPUT_TOUCH_UPDATE) || + isXIType(event, m_xiOpCode, XCB_INPUT_TOUCH_END) || + isXIType(event, m_xiOpCode, XCB_INPUT_ENTER) || + isXIType(event, m_xiOpCode, XCB_INPUT_LEAVE) || + // wacom driver's way of reporting tool proximity + isXIType(event, m_xiOpCode, XCB_INPUT_PROPERTY); + } + if (isInputEvent) + return true; +#endif + + if (eventType == XCB_CLIENT_MESSAGE) { + auto clientMessage = reinterpret_cast<const xcb_client_message_event_t *>(event); + if (clientMessage->format == 32 && clientMessage->type == atom(QXcbAtom::WM_PROTOCOLS)) + if (clientMessage->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW)) + isInputEvent = true; + } + + return isInputEvent; +} + +void QXcbConnection::processXcbEvents(QEventLoop::ProcessEventsFlags flags) { int connection_error = xcb_connection_has_error(xcb_connection()); if (connection_error) { @@ -1461,13 +1500,14 @@ void QXcbConnection::processXcbEvents() m_eventQueue->flushBufferedEvents(); - while (xcb_generic_event_t *event = m_eventQueue->takeFirst()) { + while (xcb_generic_event_t *event = m_eventQueue->takeFirst(flags)) { QScopedPointer<xcb_generic_event_t, QScopedPointerPodDeleter> eventGuard(event); if (!(event->response_type & ~0x80)) { handleXcbError(reinterpret_cast<xcb_generic_error_t *>(event)); continue; } + if (compressEvent(event)) continue; diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 3fb64f01a4..96591c7994 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -475,6 +475,8 @@ public: Qt::MouseButtons queryMouseButtons() const; Qt::KeyboardModifiers queryKeyboardModifiers() const; + bool isUserInputEvent(xcb_generic_event_t *event) const; + #if QT_CONFIG(xcb_xinput) void xi2SelectStateEvents(); void xi2SelectDeviceEvents(xcb_window_t window); @@ -495,7 +497,7 @@ public: QXcbGlIntegration *glIntegration() const; void flush() { xcb_flush(m_connection); } - void processXcbEvents(); + void processXcbEvents(QEventLoop::ProcessEventsFlags flags); protected: bool event(QEvent *e) override; diff --git a/src/plugins/platforms/xcb/qxcbeventdispatcher.cpp b/src/plugins/platforms/xcb/qxcbeventdispatcher.cpp index 252c1c62e3..3cb2a5b5ef 100644 --- a/src/plugins/platforms/xcb/qxcbeventdispatcher.cpp +++ b/src/plugins/platforms/xcb/qxcbeventdispatcher.cpp @@ -58,7 +58,7 @@ QXcbUnixEventDispatcher::~QXcbUnixEventDispatcher() bool QXcbUnixEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) { const bool didSendEvents = QEventDispatcherUNIX::processEvents(flags); - m_connection->processXcbEvents(); + m_connection->processXcbEvents(flags); // The following line should not be necessary after QTBUG-70095 return QWindowSystemInterface::sendWindowSystemEvents(flags) || didSendEvents; } @@ -99,9 +99,10 @@ static gboolean xcbSourceCheck(GSource *source) static gboolean xcbSourceDispatch(GSource *source, GSourceFunc, gpointer) { auto xcbEventSource = reinterpret_cast<XcbEventSource *>(source); - xcbEventSource->connection->processXcbEvents(); + QEventLoop::ProcessEventsFlags flags = xcbEventSource->dispatcher->flags(); + xcbEventSource->connection->processXcbEvents(flags); // The following line should not be necessary after QTBUG-70095 - QWindowSystemInterface::sendWindowSystemEvents(xcbEventSource->dispatcher->flags()); + QWindowSystemInterface::sendWindowSystemEvents(flags); return true; } diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp index d7d70536a0..20589fc550 100644 --- a/src/plugins/platforms/xcb/qxcbeventqueue.cpp +++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp @@ -114,6 +114,35 @@ QXcbEventQueue::~QXcbEventQueue() qCDebug(lcQpaEventReader) << "nodes on heap:" << m_nodesOnHeap; } +xcb_generic_event_t *QXcbEventQueue::takeFirst(QEventLoop::ProcessEventsFlags flags) +{ + // This is the level at which we were moving excluded user input events into + // separate queue in Qt 4 (see qeventdispatcher_x11.cpp). In this case + // QXcbEventQueue represents Xlib's internal event queue. In Qt 4, Xlib's + // event queue peeking APIs would not see these events anymore, the same way + // our peeking functions do not consider m_inputEvents. This design is + // intentional to keep the same behavior. We could do filtering directly on + // QXcbEventQueue, without the m_inputEvents, but it is not clear if it is + // needed by anyone who peeks at the native event queue. + + bool excludeUserInputEvents = flags.testFlag(QEventLoop::ExcludeUserInputEvents); + if (excludeUserInputEvents) { + xcb_generic_event_t *event = nullptr; + while ((event = takeFirst())) { + if (m_connection->isUserInputEvent(event)) { + m_inputEvents << event; + continue; + } + break; + } + return event; + } + + if (!m_inputEvents.isEmpty()) + return m_inputEvents.takeFirst(); + return takeFirst(); +} + xcb_generic_event_t *QXcbEventQueue::takeFirst() { if (isEmpty()) diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.h b/src/plugins/platforms/xcb/qxcbeventqueue.h index 0096437dba..235f2824be 100644 --- a/src/plugins/platforms/xcb/qxcbeventqueue.h +++ b/src/plugins/platforms/xcb/qxcbeventqueue.h @@ -41,6 +41,8 @@ #include <QtCore/QThread> #include <QtCore/QHash> +#include <QtCore/QEventLoop> +#include <QtCore/QVector> #include <xcb/xcb.h> @@ -81,6 +83,7 @@ public: void run() override; bool isEmpty() const { return m_head == m_flushedTail && !m_head->event; } + xcb_generic_event_t *takeFirst(QEventLoop::ProcessEventsFlags flags); xcb_generic_event_t *takeFirst(); void flushBufferedEvents(); void wakeUpDispatcher(); @@ -124,6 +127,8 @@ private: bool m_peekerIndexCacheDirty = false; QHash<qint32, QXcbEventNode *> m_peekerToNode; + QVector<xcb_generic_event_t *> m_inputEvents; + // debug stats quint64 m_nodesOnHeap = 0; }; diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index d030b22fc8..9a7d193767 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -137,6 +137,8 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char m_instance = this; qApp->setAttribute(Qt::AA_CompressHighFrequencyEvents, true); + QWindowSystemInterface::setPlatformFiltersEvents(true); + qRegisterMetaType<QXcbWindow*>(); #if QT_CONFIG(xcb_xlib) XInitThreads(); |