From 1f03520a20eb8d2a7236075c71b354b21a32b2a2 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Wed, 22 Apr 2015 13:39:39 +0300 Subject: Add a way to filter window system events This change introduces the class QWindowSystemEventHandler which can be used to hook into QWindowSystemInterfacePrivate to filter and dispatch window system events. One use case is to intercept key events from the underlying system in QtCompositor and feed them into the xkbcommon state, and to modify the events based on the resulting state. Change-Id: I829eb7d960420135990fb0f6db54c14eea3e8e48 Reviewed-by: Laszlo Agocs Reviewed-by: Gunnar Sletta --- src/gui/kernel/qwindowsysteminterface.cpp | 34 +++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'src/gui/kernel/qwindowsysteminterface.cpp') diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 8fa9a177ac..629bd02cd2 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -48,6 +48,7 @@ QElapsedTimer QWindowSystemInterfacePrivate::eventTime; bool QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = false; QWaitCondition QWindowSystemInterfacePrivate::eventsFlushed; QMutex QWindowSystemInterfacePrivate::flushEventMutex; +QWindowSystemEventHandler *QWindowSystemInterfacePrivate::eventHandler; //------------------------------------------------------------ // @@ -605,14 +606,32 @@ bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFla QWindowSystemInterfacePrivate::getWindowSystemEvent(); if (!event) break; - nevents++; - QGuiApplicationPrivate::processWindowSystemEvent(event); + + if (QWindowSystemInterfacePrivate::eventHandler) { + if (QWindowSystemInterfacePrivate::eventHandler->sendEvent(event)) + nevents++; + } else { + nevents++; + QGuiApplicationPrivate::processWindowSystemEvent(event); + } delete event; } return (nevents > 0); } +void QWindowSystemInterfacePrivate::installWindowSystemEventHandler(QWindowSystemEventHandler *handler) +{ + if (!eventHandler) + eventHandler = handler; +} + +void QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(QWindowSystemEventHandler *handler) +{ + if (eventHandler == handler) + eventHandler = 0; +} + void QWindowSystemInterface::setSynchronousWindowSystemEvents(bool enable) { QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = enable; @@ -836,4 +855,15 @@ Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device, QWindowSystemInterface::handleTouchEvent(w, device, touchPointList(points), mods); } +QWindowSystemEventHandler::~QWindowSystemEventHandler() +{ + QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(this); +} + +bool QWindowSystemEventHandler::sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) +{ + QGuiApplicationPrivate::processWindowSystemEvent(e); + return true; +} + QT_END_NAMESPACE -- cgit v1.2.3 From 66050f2ac875d451bec31e0d8ff507795b5b18d6 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 21 May 2015 15:12:21 +0200 Subject: Make event delivery from testlib synchronous Directly process events delivered from testlib in QGuiApplication. The old code put these events into the QPA event queue leading to race conditions with plugins delivering native events from a secondary thread. Change-Id: I5646b1014f681593d487c9d1e65053ba06206411 Reviewed-by: Simon Hausmann --- src/gui/kernel/qwindowsysteminterface.cpp | 70 +++++++++++++++++++------------ 1 file changed, 43 insertions(+), 27 deletions(-) (limited to 'src/gui/kernel/qwindowsysteminterface.cpp') diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 629bd02cd2..de8e5fbe64 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -811,12 +811,25 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo #endif Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier) { - QWindowSystemInterface::handleMouseEvent(w, local, global, b, mods); + unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); + QWindowSystemInterfacePrivate::MouseEvent e(w, timestamp, local, global, b, mods, Qt::MouseEventNotSynthesized); + QGuiApplicationPrivate::processWindowSystemEvent(&e); } Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1) { - QWindowSystemInterface::handleKeyEvent(w, t, k, mods, text, autorep, count); + unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); + + // This is special handling needed for OS X which eventually will call sendEvent(), on other platforms + // this might not be safe, e.g., on Android. See: QGuiApplicationPrivate::processKeyEvent() for + // shortcut overriding on other platforms. +#if defined(Q_OS_OSX) + if (t == QEvent::KeyPress && QWindowSystemInterface::tryHandleShortcutEvent(w, timestamp, k, mods, text)) + return; +#endif // Q_OS_OSX + + QWindowSystemInterfacePrivate::KeyEvent e(w, timestamp, t, k, mods, text, autorep, count); + QGuiApplicationPrivate::processWindowSystemEvent(&e); } Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1) @@ -824,35 +837,38 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int return QWindowSystemInterface::tryHandleShortcutEventToObject(o, timestamp, k, mods, text, autorep, count); } -static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoint& pt) -{ - QWindowSystemInterface::TouchPoint p; - p.id = pt.id(); - p.flags = pt.flags(); - p.normalPosition = pt.normalizedPos(); - p.area = pt.screenRect(); - p.pressure = pt.pressure(); - p.state = pt.state(); - p.velocity = pt.velocity(); - p.rawPositions = pt.rawScreenPositions(); - return p; -} -static QList touchPointList(const QList& pointList) -{ - QList newList; - - Q_FOREACH (QTouchEvent::TouchPoint p, pointList) - { - newList.append(touchPoint(p)); - } - return newList; -} -Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device, +Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device, const QList &points, Qt::KeyboardModifiers mods = Qt::NoModifier) { - QWindowSystemInterface::handleTouchEvent(w, device, touchPointList(points), mods); + unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); + + if (!points.size()) // Touch events must have at least one point + return; + + if (!QTouchDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices. + return; + + QEvent::Type type; + Qt::TouchPointStates states; + + QList::const_iterator point = points.constBegin(); + QList::const_iterator end = points.constEnd(); + while (point != end) { + states |= point->state(); + ++point; + } + + // Determine the event type based on the combined point states. + type = QEvent::TouchUpdate; + if (states == Qt::TouchPointPressed) + type = QEvent::TouchBegin; + else if (states == Qt::TouchPointReleased) + type = QEvent::TouchEnd; + + QWindowSystemInterfacePrivate::TouchEvent e(w, timestamp, type, device, points, mods); + QGuiApplicationPrivate::processWindowSystemEvent(&e); } QWindowSystemEventHandler::~QWindowSystemEventHandler() -- cgit v1.2.3 From beef975f92e42143c464d68afa6b8cd4f7ef7389 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 2 Jun 2015 08:43:17 +0200 Subject: Cleanup the mouse event handling in testlib Calling QCursor::setPos() to emulate mouse move events is a rather bad idea, as it creates round trips through the server, leading to timing issues etc. In addition, we should not call qapp->notify(), but rather route the events through the proper QPA interface. This is required to properly generate all other events such as enter/leave etc. As this breaks existing tests, put the new behavior behind an #ifdef for now. Like this, we can fix tests one by one, and then turn on the define by default for 5.6 (with a changelog message). We emulate timestamps to avoid creating double clicks by mistake. In addition, fix QGuiApplication::processMouseEvent to not push events back into the QPA event queue (as this is a bad hack and breaks the new testing system). Change-Id: I71774cb56674d7fb66b9a7cf1e1ada1629536408 Reviewed-by: Simon Hausmann --- src/gui/kernel/qwindowsysteminterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/gui/kernel/qwindowsysteminterface.cpp') diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index de8e5fbe64..823387b702 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -810,8 +810,8 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo } #endif -Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier) { - unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); +Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp) +{ QWindowSystemInterfacePrivate::MouseEvent e(w, timestamp, local, global, b, mods, Qt::MouseEventNotSynthesized); QGuiApplicationPrivate::processWindowSystemEvent(&e); } -- cgit v1.2.3