diff options
Diffstat (limited to 'src/gui/kernel/qwindowsysteminterface.cpp')
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface.cpp | 248 |
1 files changed, 150 insertions, 98 deletions
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 1b7edb1278..667304859e 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,22 +161,15 @@ 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) +QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowActivated, QWindow *tlw, Qt::FocusReason r) { QWindowSystemInterfacePrivate::ActivatedWindowEvent *e = new QWindowSystemInterfacePrivate::ActivatedWindowEvent(tlw, r); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); } void QWindowSystemInterface::handleWindowStateChanged(QWindow *tlw, Qt::WindowState newState) @@ -147,10 +197,25 @@ void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState /*! If \a oldRect is null, Qt will use the previously reported geometry instead. */ -void QWindowSystemInterface::handleGeometryChange(QWindow *tlw, const QRect &newRect, const QRect &oldRect) +QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *tlw, const QRect &newRect, const QRect &oldRect) { QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(tlw, QHighDpi::fromNativePixels(newRect, tlw), QHighDpi::fromNativePixels(oldRect, tlw)); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); +} + +QWindowSystemInterfacePrivate::ExposeEvent::ExposeEvent(QWindow *window, const QRegion ®ion) + : WindowSystemEvent(Expose) + , window(window) + , isExposed(window && window->handle() ? window->handle()->isExposed() : false) + , region(region) +{ +} + +QT_DEFINE_QPA_EVENT_HANDLER(void, handleExposeEvent, QWindow *tlw, const QRegion ®ion) +{ + QWindowSystemInterfacePrivate::ExposeEvent *e = + new QWindowSystemInterfacePrivate::ExposeEvent(tlw, QHighDpi::fromNativeLocalExposedRegion(region, tlw)); + QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); } void QWindowSystemInterface::handleCloseEvent(QWindow *tlw, bool *accepted) @@ -167,19 +232,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 +282,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; } } @@ -236,7 +297,7 @@ bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestam #else Q_UNUSED(window) Q_UNUSED(timestamp) - Q_UNUSED(key) + Q_UNUSED(keyCode) Q_UNUSED(modifiers) Q_UNUSED(nativeScanCode) Q_UNUSED(nativeVirtualKey) @@ -248,13 +309,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 +323,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, @@ -360,15 +420,6 @@ void QWindowSystemInterface::handleWheelEvent(QWindow *tlw, ulong timestamp, con QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } - -QWindowSystemInterfacePrivate::ExposeEvent::ExposeEvent(QWindow *exposed, const QRegion ®ion) - : WindowSystemEvent(Expose) - , exposed(exposed) - , isExposed(exposed && exposed->handle() ? exposed->handle()->isExposed() : false) - , region(region) -{ -} - int QWindowSystemInterfacePrivate::windowSystemEventsQueued() { return windowSystemEventQueue.count(); @@ -394,6 +445,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 +463,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 +508,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, @@ -474,7 +522,10 @@ QList<QTouchEvent::TouchPoint> QList<QWindowSystemInterface::TouchPoint>::const_iterator end = points.constEnd(); while (point != end) { p.setId(point->id); + if (point->uniqueId >= 0) + p.setUniqueId(point->uniqueId); p.setPressure(point->pressure); + p.setRotation(point->rotation); states |= point->state; p.setState(point->state); @@ -527,7 +578,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 @@ -541,23 +599,23 @@ 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, +QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchCancelEvent, QWindow *w, QTouchDevice *device, Qt::KeyboardModifiers mods) { unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleTouchCancelEvent(w, time, device, mods); + handleTouchCancelEvent<Delivery>(w, time, device, mods); } -void QWindowSystemInterface::handleTouchCancelEvent(QWindow *w, ulong timestamp, QTouchDevice *device, +QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchCancelEvent, QWindow *w, ulong timestamp, QTouchDevice *device, Qt::KeyboardModifiers mods) { QWindowSystemInterfacePrivate::TouchEvent *e = new QWindowSystemInterfacePrivate::TouchEvent(w, timestamp, QEvent::TouchCancel, device, QList<QTouchEvent::TouchPoint>(), mods); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); } void QWindowSystemInterface::handleScreenOrientationChange(QScreen *screen, Qt::ScreenOrientation orientation) @@ -594,13 +652,6 @@ void QWindowSystemInterface::handleThemeChange(QWindow *tlw) QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } -void QWindowSystemInterface::handleExposeEvent(QWindow *tlw, const QRegion ®ion) -{ - QWindowSystemInterfacePrivate::ExposeEvent *e = - new QWindowSystemInterfacePrivate::ExposeEvent(tlw, QHighDpi::fromNativeLocalExposedRegion(region, tlw)); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); -} - void QWindowSystemInterface::deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags) { Q_ASSERT(QThread::currentThread() == QGuiApplication::instance()->thread()); @@ -631,7 +682,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<AsynchronousDelivery>(e); QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex); } else { sendWindowSystemEvents(flags); @@ -869,20 +920,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) @@ -922,15 +966,23 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int #endif } +namespace QTest +{ + Q_GUI_EXPORT QTouchDevice * createTouchDevice(QTouchDevice::DeviceType devType = QTouchDevice::TouchScreen) + { + QTouchDevice *ret = new QTouchDevice(); + ret->setType(devType); + QWindowSystemInterface::registerTouchDevice(ret); + return ret; + } +} + 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() |