summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qwindowsysteminterface.cpp
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>2015-09-10 16:15:35 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2016-10-10 16:06:45 +0000
commit33d748bb88676b69e596ae77badfeaf5a69a33d1 (patch)
treeebc1393fe111cfd1bf8b1e84a652756afcbc46c9 /src/gui/kernel/qwindowsysteminterface.cpp
parent76f53791a198dac7634d4aedb774ed3a86d47c97 (diff)
Allow granular synchronous and asynchronous delivery of QPA events
The setSynchronousWindowSystemEvents() API of QWindowSystemInterface is supposed to be set globally by the platform plugin, not switched on and off to trigger async/sync deliver of events for a specific event. We introduce processWindowSystemEvent() in QWindowSystemInterfacePrivate to match postWindowSystemEvent(), where the former is synchronous and the latter is asynchronous. This is then coupled with a templated version of handleWindowSystemEvent() that then calls out to one of the two depending on the specialization that's used. The default specialization will decide based on the state set by setSynchronousWindowSystemEvents(), as before. This allows templated versions of handleMouseEvent, handleKeyEvent, etc to be added without maintaining two code paths, one for synchronous and one for asynchronous delivery, which in the end allows us to get away from using setSynchronousWindowSystemEvents() as a temporary switch to synchronous mode. The templates are defined in the QWindowSystemInterface source file, with explicit instantiations of the three supported modes of delivery, as having the definition in the header file would both require inlining, as well as qwindowsysteminterface.h having access to the private parts of QWindowSystemInterfacePrivate for the template function bodies. Task-number: QTBUG-56274 Change-Id: I54c34da1ad90ff243f11905529874695f556cfcd Reviewed-by: Jan Arve Sæther <jan-arve.saether@theqtcompany.com> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/gui/kernel/qwindowsysteminterface.cpp')
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp185
1 files changed, 112 insertions, 73 deletions
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index bb778bc5fc..b799f75090 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -70,6 +70,63 @@ QWindowSystemInterfacePrivate::WindowSystemEventList QWindowSystemInterfacePriva
extern QPointer<QWindow> qt_last_mouse_receiver;
/*!
+ Handles a window system event asynchronously by posting the event to Qt Gui.
+
+ \sa postWindowSystemEvent()
+*/
+template<>
+bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(WindowSystemEvent *ev)
+{
+ QWindowSystemInterfacePrivate::postWindowSystemEvent(ev);
+ return true;
+}
+
+/*!
+ Handles a window system event synchronously.
+
+ If the event is delivered from another thread than the Qt main thread the
+ window system event queue is flushed, which may deliver other events as
+ well.
+
+ \sa processWindowSystemEvent()
+*/
+template<>
+bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::SynchronousDelivery>(WindowSystemEvent *ev)
+{
+ return QWindowSystemInterfacePrivate::processWindowSystemEvent(ev);
+}
+
+/*!
+ Handles a window system event.
+
+ By default this function posts the event on the window system event queue and
+ wakes the Gui event dispatcher. Qt Gui will then handle the event asynchonously
+ at a later point. The return value is not used in asynchronous mode and will
+ always be true.
+
+ In synchronous mode Qt Gui will process the event immediately. The return value
+ indicates if Qt accepted the event. If the event is delivered from another thread
+ than the Qt main thread the window system event queue is flushed, which may deliver
+ other events as well.
+
+ \sa flushWindowSystemEvents(), processWindowSystemEvent(), setSynchronousWindowSystemEvents()
+*/
+template<>
+bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::DefaultDelivery>(QWindowSystemInterfacePrivate::WindowSystemEvent *ev)
+{
+ if (synchronousWindowSystemEvents)
+ return handleWindowSystemEvent<QWindowSystemInterface::SynchronousDelivery>(ev);
+ else
+ return handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(ev);
+}
+
+#define QT_DEFINE_QPA_EVENT_HANDLER(ReturnType, HandlerName, ...) \
+ template Q_GUI_EXPORT ReturnType QWindowSystemInterface::HandlerName<QWindowSystemInterface::DefaultDelivery>(__VA_ARGS__); \
+ template Q_GUI_EXPORT ReturnType QWindowSystemInterface::HandlerName<QWindowSystemInterface::SynchronousDelivery>(__VA_ARGS__); \
+ template Q_GUI_EXPORT ReturnType QWindowSystemInterface::HandlerName<QWindowSystemInterface::AsynchronousDelivery>(__VA_ARGS__); \
+ template<typename Delivery> ReturnType QWindowSystemInterface::HandlerName(__VA_ARGS__)
+
+/*!
\class QWindowSystemInterface
\since 5.0
\internal
@@ -81,18 +138,18 @@ extern QPointer<QWindow> qt_last_mouse_receiver;
until sendWindowSystemEvents() is called by the event dispatcher.
*/
-void QWindowSystemInterface::handleEnterEvent(QWindow *tlw, const QPointF &local, const QPointF &global)
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleEnterEvent, QWindow *tlw, const QPointF &local, const QPointF &global)
{
if (tlw) {
QWindowSystemInterfacePrivate::EnterEvent *e = new QWindowSystemInterfacePrivate::EnterEvent(tlw, local, global);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
}
-void QWindowSystemInterface::handleLeaveEvent(QWindow *tlw)
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleLeaveEvent, QWindow *tlw)
{
QWindowSystemInterfacePrivate::LeaveEvent *e = new QWindowSystemInterfacePrivate::LeaveEvent(tlw);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
/*!
@@ -104,15 +161,8 @@ void QWindowSystemInterface::handleLeaveEvent(QWindow *tlw)
*/
void QWindowSystemInterface::handleEnterLeaveEvent(QWindow *enter, QWindow *leave, const QPointF &local, const QPointF& global)
{
- bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents;
- if (wasSynchronous)
- setSynchronousWindowSystemEvents(false);
- handleLeaveEvent(leave);
+ handleLeaveEvent<AsynchronousDelivery>(leave);
handleEnterEvent(enter, local, global);
- if (wasSynchronous) {
- flushWindowSystemEvents();
- setSynchronousWindowSystemEvents(true);
- }
}
void QWindowSystemInterface::handleWindowActivated(QWindow *tlw, Qt::FocusReason r)
@@ -167,19 +217,19 @@ void QWindowSystemInterface::handleCloseEvent(QWindow *tlw, bool *accepted)
\a w == 0 means that the event is in global coords only, \a local will be ignored in this case
*/
-void QWindowSystemInterface::handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleMouseEvent, QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
{
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- handleMouseEvent(w, time, local, global, b, mods, source);
+ handleMouseEvent<Delivery>(w, time, local, global, b, mods, source);
}
-void QWindowSystemInterface::handleMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleMouseEvent, QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
{
QWindowSystemInterfacePrivate::MouseEvent * e =
new QWindowSystemInterfacePrivate::MouseEvent(w, timestamp, QHighDpi::fromNativeLocalPosition(local, w), QHighDpi::fromNativePixels(global, w), b, mods, source);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
@@ -217,11 +267,7 @@ bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestam
QEvent::ShortcutOverride, keyCode, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorepeat, count);
{
- // FIXME: Template handleWindowSystemEvent to support both sync and async delivery
- QScopedValueRollback<bool> syncRollback(QWindowSystemInterfacePrivate::synchronousWindowSystemEvents);
- QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = true;
-
- if (QWindowSystemInterfacePrivate::handleWindowSystemEvent(shortcutOverrideEvent))
+ if (QWindowSystemInterfacePrivate::handleWindowSystemEvent<SynchronousDelivery>(shortcutOverrideEvent))
return false;
}
}
@@ -248,13 +294,12 @@ bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestam
#endif
}
-
-bool QWindowSystemInterface::handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) {
+QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) {
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- return handleKeyEvent(w, time, t, k, mods, text, autorep, count);
+ return handleKeyEvent<Delivery>(w, time, t, k, mods, text, autorep, count);
}
-bool QWindowSystemInterface::handleKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count)
+QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count)
{
#if defined(Q_OS_OSX)
if (t == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(tlw, timestamp, k, mods, 0, 0, 0, text, autorep, count))
@@ -263,7 +308,7 @@ bool QWindowSystemInterface::handleKeyEvent(QWindow *tlw, ulong timestamp, QEven
QWindowSystemInterfacePrivate::KeyEvent * e =
new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, t, k, mods, text, autorep, count);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
@@ -394,6 +439,15 @@ void QWindowSystemInterfacePrivate::removeWindowSystemEvent(WindowSystemEvent *e
windowSystemEventQueue.remove(event);
}
+/*!
+ Posts a window system event to be handled asynchronously by Qt Gui.
+
+ This function posts the event on the window system event queue and wakes the
+ Gui event dispatcher. Qt Gui will then handle the event asynchonously at a
+ later point.
+
+ \sa flushWindowSystemEvents(), processWindowSystemEvent(), handleWindowSystemEvent()
+*/
void QWindowSystemInterfacePrivate::postWindowSystemEvent(WindowSystemEvent *ev)
{
windowSystemEventQueue.append(ev);
@@ -403,37 +457,32 @@ void QWindowSystemInterfacePrivate::postWindowSystemEvent(WindowSystemEvent *ev)
}
/*!
- Handles a window system event.
+ Processes a window system event synchronously.
- By default this function posts the event on the window system event queue and
- wakes the Gui event dispatcher. Qt Gui will then handle the event asynchonously
- at a later point. The return value is not used in asynchronous mode and will
- always be true.
+ Qt Gui will process the event immediately. The return value indicates if Qt
+ accepted the event.
- In synchronous mode Qt Gui will process the event immediately. The return value
- indicates if Qt accepted the event.
+ If the event is delivered from another thread than the Qt main thread the
+ window system event queue is flushed, which may deliver other events as
+ well.
- \sa flushWindowSystemEvents(), setSynchronousWindowSystemEvents()
+ \sa flushWindowSystemEvents(), postWindowSystemEvent(), handleWindowSystemEvent()
*/
-bool QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev)
+bool QWindowSystemInterfacePrivate::processWindowSystemEvent(WindowSystemEvent *ev)
{
bool accepted = true;
- if (synchronousWindowSystemEvents) {
- if (QThread::currentThread() == QGuiApplication::instance()->thread()) {
- // Process the event immediately on the current thread and return the accepted state.
- QGuiApplicationPrivate::processWindowSystemEvent(ev);
- accepted = ev->eventAccepted;
- delete ev;
- } else {
- // Post the event on the Qt main thread queue and flush the queue.
- // This will wake up the Gui thread which will process the event.
- // Return the accepted state for the last event on the queue,
- // which is the event posted by this function.
- postWindowSystemEvent(ev);
- accepted = QWindowSystemInterface::flushWindowSystemEvents();
- }
+ if (QThread::currentThread() == QGuiApplication::instance()->thread()) {
+ // Process the event immediately on the current thread and return the accepted state.
+ QGuiApplicationPrivate::processWindowSystemEvent(ev);
+ accepted = ev->eventAccepted;
+ delete ev;
} else {
+ // Post the event on the Qt main thread queue and flush the queue.
+ // This will wake up the Gui thread which will process the event.
+ // Return the accepted state for the last event on the queue,
+ // which is the event posted by this function.
postWindowSystemEvent(ev);
+ accepted = QWindowSystemInterface::flushWindowSystemEvents();
}
return accepted;
}
@@ -453,13 +502,6 @@ bool QWindowSystemInterface::isTouchDeviceRegistered(const QTouchDevice *device)
return QTouchDevicePrivate::isRegistered(device);
}
-void QWindowSystemInterface::handleTouchEvent(QWindow *w, QTouchDevice *device,
- const QList<TouchPoint> &points, Qt::KeyboardModifiers mods)
-{
- unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- handleTouchEvent(w, time, device, points, mods);
-}
-
QList<QTouchEvent::TouchPoint>
QWindowSystemInterfacePrivate::fromNativeTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points,
const QWindow *window,
@@ -530,7 +572,14 @@ QList<QWindowSystemInterface::TouchPoint>
return newList;
}
-void QWindowSystemInterface::handleTouchEvent(QWindow *tlw, ulong timestamp, QTouchDevice *device,
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchEvent, QWindow *w, QTouchDevice *device,
+ const QList<TouchPoint> &points, Qt::KeyboardModifiers mods)
+{
+ unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
+ handleTouchEvent<Delivery>(w, time, device, points, mods);
+}
+
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchEvent, QWindow *tlw, ulong timestamp, QTouchDevice *device,
const QList<TouchPoint> &points, Qt::KeyboardModifiers mods)
{
if (!points.size()) // Touch events must have at least one point
@@ -544,7 +593,7 @@ void QWindowSystemInterface::handleTouchEvent(QWindow *tlw, ulong timestamp, QTo
QWindowSystemInterfacePrivate::TouchEvent *e =
new QWindowSystemInterfacePrivate::TouchEvent(tlw, timestamp, type, device, touchPoints, mods);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
void QWindowSystemInterface::handleTouchCancelEvent(QWindow *w, QTouchDevice *device,
@@ -634,7 +683,7 @@ bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFl
// deferredFlushWindowSystemEvents from the Gui thread.
QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent(flags);
- QWindowSystemInterfacePrivate::postWindowSystemEvent(e);
+ QWindowSystemInterfacePrivate::handleWindowSystemEvent<SynchronousDelivery>(e);
QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex);
} else {
sendWindowSystemEvents(flags);
@@ -872,20 +921,13 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo
Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp)
{
- bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents;
- QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
const qreal factor = QHighDpiScaling::factor(w);
- QWindowSystemInterface::handleMouseEvent(w, timestamp, local * factor,
- global * factor, b, mods);
- QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous);
+ QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(w, timestamp, local * factor, global * factor, b, mods);
}
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)
{
- bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents;
- QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
- QWindowSystemInterface::handleKeyEvent(w, t, k, mods, text, autorep, count);
- QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous);
+ QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(w, t, k, mods, text, autorep, count);
}
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)
@@ -940,11 +982,8 @@ Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device,
const QList<QTouchEvent::TouchPoint> &points,
Qt::KeyboardModifiers mods = Qt::NoModifier)
{
- bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents;
- QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
- QWindowSystemInterface::handleTouchEvent(w, device,
- QWindowSystemInterfacePrivate::toNativeTouchPoints(points, w), mods);
- QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous);
+ QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(w, device,
+ QWindowSystemInterfacePrivate::toNativeTouchPoints(points, w), mods);
}
QWindowSystemEventHandler::~QWindowSystemEventHandler()