diff options
-rw-r--r-- | src/gui/kernel/qtestsupport_gui.cpp | 81 | ||||
-rw-r--r-- | src/gui/kernel/qtestsupport_gui.h | 41 | ||||
-rw-r--r-- | src/testlib/qtesttouch.h | 165 | ||||
-rw-r--r-- | src/widgets/kernel/qtestsupport_widgets.cpp | 70 | ||||
-rw-r--r-- | src/widgets/kernel/qtestsupport_widgets.h | 27 | ||||
-rw-r--r-- | tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp | 10 | ||||
-rw-r--r-- | tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp | 12 |
7 files changed, 233 insertions, 173 deletions
diff --git a/src/gui/kernel/qtestsupport_gui.cpp b/src/gui/kernel/qtestsupport_gui.cpp index 79da26f2ca..ab48111fb5 100644 --- a/src/gui/kernel/qtestsupport_gui.cpp +++ b/src/gui/kernel/qtestsupport_gui.cpp @@ -45,6 +45,7 @@ #include "qwindow.h" #include <QtCore/qtestsupport_core.h> +#include <QtCore/qthread.h> #include <QtCore/QDebug> QT_BEGIN_NAMESPACE @@ -91,4 +92,84 @@ Q_GUI_EXPORT bool QTest::qWaitForWindowExposed(QWindow *window, int timeout) return QTest::qWaitFor([&]() { return window->isExposed(); }, timeout); } +namespace QTest { + +QTouchEventSequence::~QTouchEventSequence() +{ + if (commitWhenDestroyed) + commit(); +} +QTouchEventSequence& QTouchEventSequence::press(int touchId, const QPoint &pt, QWindow *window) +{ + auto &p = QMutableEventPoint::from(point(touchId)); + p.setGlobalPosition(mapToScreen(window, pt)); + p.setState(QEventPoint::State::Pressed); + return *this; +} +QTouchEventSequence& QTouchEventSequence::move(int touchId, const QPoint &pt, QWindow *window) +{ + auto &p = QMutableEventPoint::from(point(touchId)); + p.setGlobalPosition(mapToScreen(window, pt)); + p.setState(QEventPoint::State::Updated); + return *this; +} +QTouchEventSequence& QTouchEventSequence::release(int touchId, const QPoint &pt, QWindow *window) +{ + auto &p = QMutableEventPoint::from(point(touchId)); + p.setGlobalPosition(mapToScreen(window, pt)); + p.setState(QEventPoint::State::Released); + return *this; +} +QTouchEventSequence& QTouchEventSequence::stationary(int touchId) +{ + auto &p = QMutableEventPoint::from(pointOrPreviousPoint(touchId)); + p.setState(QEventPoint::State::Stationary); + return *this; +} + +void QTouchEventSequence::commit(bool processEvents) +{ + if (points.isEmpty()) + return; + QThread::msleep(1); + if (targetWindow) + qt_handleTouchEvent(targetWindow, device, points.values()); + if (processEvents) + QCoreApplication::processEvents(); + previousPoints = points; + points.clear(); +} + +QTouchEventSequence::QTouchEventSequence(QWindow *window, QPointingDevice *aDevice, bool autoCommit) + : targetWindow(window), device(aDevice), commitWhenDestroyed(autoCommit) +{ +} + +QPoint QTouchEventSequence::mapToScreen(QWindow *window, const QPoint &pt) +{ + if (window) + return window->mapToGlobal(pt); + return targetWindow ? targetWindow->mapToGlobal(pt) : pt; +} + +QEventPoint &QTouchEventSequence::point(int touchId) +{ + if (!points.contains(touchId)) + points[touchId] = QEventPoint(touchId); + return points[touchId]; +} + +QEventPoint &QTouchEventSequence::pointOrPreviousPoint(int touchId) +{ + if (!points.contains(touchId)) { + if (previousPoints.contains(touchId)) + points[touchId] = previousPoints.value(touchId); + else + points[touchId] = QEventPoint(touchId); + } + return points[touchId]; +} + +} // namespace QTest + QT_END_NAMESPACE diff --git a/src/gui/kernel/qtestsupport_gui.h b/src/gui/kernel/qtestsupport_gui.h index 86ff956ef8..5f1ac12936 100644 --- a/src/gui/kernel/qtestsupport_gui.h +++ b/src/gui/kernel/qtestsupport_gui.h @@ -41,15 +41,54 @@ #define QTESTSUPPORT_GUI_H #include <QtGui/qtguiglobal.h> +#include <QtGui/qevent.h> +#include <QtCore/qmap.h> QT_BEGIN_NAMESPACE class QWindow; +Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, const QPointingDevice *device, + const QList<QEventPoint> &points, + Qt::KeyboardModifiers mods = Qt::NoModifier); + namespace QTest { + Q_REQUIRED_RESULT Q_GUI_EXPORT bool qWaitForWindowActive(QWindow *window, int timeout = 5000); Q_REQUIRED_RESULT Q_GUI_EXPORT bool qWaitForWindowExposed(QWindow *window, int timeout = 5000); -} + +Q_GUI_EXPORT QPointingDevice * createTouchDevice(QInputDevice::DeviceType devType = QInputDevice::DeviceType::TouchScreen, + QInputDevice::Capabilities caps = QInputDevice::Capability::Position); + +class Q_GUI_EXPORT QTouchEventSequence +{ +public: + virtual ~QTouchEventSequence(); + QTouchEventSequence& press(int touchId, const QPoint &pt, QWindow *window = nullptr); + QTouchEventSequence& move(int touchId, const QPoint &pt, QWindow *window = nullptr); + QTouchEventSequence& release(int touchId, const QPoint &pt, QWindow *window = nullptr); + virtual QTouchEventSequence& stationary(int touchId); + + virtual void commit(bool processEvents = true); + +protected: + QTouchEventSequence(QWindow *window, QPointingDevice *aDevice, bool autoCommit); + + QPoint mapToScreen(QWindow *window, const QPoint &pt); + + QEventPoint &point(int touchId); + + QEventPoint &pointOrPreviousPoint(int touchId); + + QMap<int, QEventPoint> previousPoints; + QMap<int, QEventPoint> points; + QWindow *targetWindow; + QPointingDevice *device; + bool commitWhenDestroyed; + friend QTouchEventSequence touchEvent(QWindow *window, QPointingDevice *device, bool autoCommit); +}; + +} // namespace QTest QT_END_NAMESPACE diff --git a/src/testlib/qtesttouch.h b/src/testlib/qtesttouch.h index f976a6ef0a..4b13d86054 100644 --- a/src/testlib/qtesttouch.h +++ b/src/testlib/qtesttouch.h @@ -56,177 +56,22 @@ #include <QtGui/qpointingdevice.h> #ifdef QT_WIDGETS_LIB #include <QtWidgets/qwidget.h> +#include <QtWidgets/qtestsupport_widgets.h> +#else +#include <QtGui/qtestsupport_gui.h> #endif QT_BEGIN_NAMESPACE -Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, const QPointingDevice *device, - const QList<QEventPoint> &points, - Qt::KeyboardModifiers mods = Qt::NoModifier); - - namespace QTest { - Q_GUI_EXPORT QPointingDevice * createTouchDevice(QInputDevice::DeviceType devType = QInputDevice::DeviceType::TouchScreen, - QInputDevice::Capabilities caps = QInputDevice::Capability::Position); - - - class QTouchEventSequence - { - public: - ~QTouchEventSequence() - { - if (commitWhenDestroyed) - commit(); - } - QTouchEventSequence& press(int touchId, const QPoint &pt, QWindow *window = nullptr) - { - QEventPoint &p = point(touchId); - p.m_globalPos = mapToScreen(window, pt); - p.m_state = QEventPoint::State::Pressed; - return *this; - } - QTouchEventSequence& move(int touchId, const QPoint &pt, QWindow *window = nullptr) - { - QEventPoint &p = point(touchId); - p.m_globalPos = mapToScreen(window, pt); - p.m_state = QEventPoint::State::Updated; - return *this; - } - QTouchEventSequence& release(int touchId, const QPoint &pt, QWindow *window = nullptr) - { - QEventPoint &p = point(touchId); - p.m_globalPos = mapToScreen(window, pt); - p.m_state = QEventPoint::State::Released; - return *this; - } - QTouchEventSequence& stationary(int touchId) - { - QEventPoint &p = pointOrPreviousPoint(touchId); - p.m_state = QEventPoint::State::Stationary; - return *this; - } - -#ifdef QT_WIDGETS_LIB - QTouchEventSequence& press(int touchId, const QPoint &pt, QWidget *widget = nullptr) - { - QEventPoint &p = point(touchId); - p.m_globalPos = mapToScreen(widget, pt); - p.m_state = QEventPoint::State::Pressed; - return *this; - } - QTouchEventSequence& move(int touchId, const QPoint &pt, QWidget *widget = nullptr) - { - QEventPoint &p = point(touchId); - p.m_globalPos = mapToScreen(widget, pt); - p.m_state = QEventPoint::State::Updated; - return *this; - } - QTouchEventSequence& release(int touchId, const QPoint &pt, QWidget *widget = nullptr) - { - QEventPoint &p = point(touchId); - p.m_globalPos = mapToScreen(widget, pt); - p.m_state = QEventPoint::State::Released; - return *this; - } -#endif - - void commit(bool processEvents = true) - { - if (!points.isEmpty()) { - qSleep(1); - if (targetWindow) - { - qt_handleTouchEvent(targetWindow, device, points.values()); - } -#ifdef QT_WIDGETS_LIB - else if (targetWidget) - { - qt_handleTouchEvent(targetWidget->windowHandle(), device, points.values()); - } -#endif - } - if (processEvents) - QCoreApplication::processEvents(); - previousPoints = points; - points.clear(); - } - -private: -#ifdef QT_WIDGETS_LIB - QTouchEventSequence(QWidget *widget, QPointingDevice *aDevice, bool autoCommit) - : targetWidget(widget), targetWindow(nullptr), device(aDevice), commitWhenDestroyed(autoCommit) - { - } -#endif - QTouchEventSequence(QWindow *window, QPointingDevice *aDevice, bool autoCommit) - : -#ifdef QT_WIDGETS_LIB - targetWidget(nullptr), -#endif - targetWindow(window), device(aDevice), commitWhenDestroyed(autoCommit) - { - } - -#ifdef QT_WIDGETS_LIB - QPoint mapToScreen(QWidget *widget, const QPoint &pt) - { - if (widget) - return widget->mapToGlobal(pt); - return targetWidget ? targetWidget->mapToGlobal(pt) : pt; - } -#endif - QPoint mapToScreen(QWindow *window, const QPoint &pt) - { - if(window) - return window->mapToGlobal(pt); - return targetWindow ? targetWindow->mapToGlobal(pt) : pt; - } - - QMap<int, QEventPoint> previousPoints; - QMap<int, QEventPoint> points; -#ifdef QT_WIDGETS_LIB - QWidget *targetWidget; -#endif - QWindow *targetWindow; - QPointingDevice *device; - bool commitWhenDestroyed; -#if defined(QT_WIDGETS_LIB) || defined(Q_CLANG_QDOC) - friend QTouchEventSequence touchEvent(QWidget *widget, QPointingDevice *device, bool autoCommit); -#endif - friend QTouchEventSequence touchEvent(QWindow *window, QPointingDevice *device, bool autoCommit); - - protected: - // These don't make sense for public testing API, - // because we are getting rid of most public setters in QEventPoint. - // Each of these constructs a QEventPoint with null parent; in normal usage, - // the QTouchEvent constructor will set the points' parents to itself, later on. - QEventPoint &point(int touchId) - { - if (!points.contains(touchId)) - points[touchId] = QEventPoint(touchId); - return points[touchId]; - } - - QEventPoint &pointOrPreviousPoint(int touchId) - { - if (!points.contains(touchId)) { - if (previousPoints.contains(touchId)) - points[touchId] = previousPoints.value(touchId); - else - points[touchId] = QEventPoint(touchId); - } - return points[touchId]; - } - }; - #if defined(QT_WIDGETS_LIB) || defined(Q_CLANG_QDOC) inline - QTouchEventSequence touchEvent(QWidget *widget, + QTouchEventWidgetSequence touchEvent(QWidget *widget, QPointingDevice *device, bool autoCommit = true) { - return QTouchEventSequence(widget, device, autoCommit); + return QTouchEventWidgetSequence(widget, device, autoCommit); } #endif inline diff --git a/src/widgets/kernel/qtestsupport_widgets.cpp b/src/widgets/kernel/qtestsupport_widgets.cpp index c014579ea8..c9116fcef6 100644 --- a/src/widgets/kernel/qtestsupport_widgets.cpp +++ b/src/widgets/kernel/qtestsupport_widgets.cpp @@ -42,7 +42,10 @@ #include "qwidget.h" #include <QtGui/qwindow.h> +#include <QtCore/qtestsupport_core.h> +#include <QtCore/qthread.h> #include <QtGui/qtestsupport_gui.h> +#include <QtGui/private/qevent_p.h> QT_BEGIN_NAMESPACE @@ -87,4 +90,71 @@ Q_WIDGETS_EXPORT bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout) return false; } +namespace QTest { + +QTouchEventWidgetSequence::~QTouchEventWidgetSequence() +{ + if (commitWhenDestroyed) + commit(); +} + +QTouchEventWidgetSequence& QTouchEventWidgetSequence::press(int touchId, const QPoint &pt, QWidget *widget) +{ + auto &p = QMutableEventPoint::from(point(touchId)); + p.setGlobalPosition(mapToScreen(widget, pt)); + p.setState(QEventPoint::State::Pressed); + return *this; +} +QTouchEventWidgetSequence& QTouchEventWidgetSequence::move(int touchId, const QPoint &pt, QWidget *widget) +{ + auto &p = QMutableEventPoint::from(point(touchId)); + p.setGlobalPosition(mapToScreen(widget, pt)); + p.setState(QEventPoint::State::Updated); + return *this; +} +QTouchEventWidgetSequence& QTouchEventWidgetSequence::release(int touchId, const QPoint &pt, QWidget *widget) +{ + auto &p = QMutableEventPoint::from(point(touchId)); + p.setGlobalPosition(mapToScreen(widget, pt)); + p.setState(QEventPoint::State::Released); + return *this; +} + +QTouchEventWidgetSequence& QTouchEventWidgetSequence::stationary(int touchId) +{ + auto &p = QMutableEventPoint::from(pointOrPreviousPoint(touchId)); + p.setState(QEventPoint::State::Stationary); + return *this; +} + +void QTouchEventWidgetSequence::commit(bool processEvents) +{ + if (points.isEmpty()) + return; + QThread::msleep(1); + if (targetWindow) { + qt_handleTouchEvent(targetWindow, device, points.values()); + } else if (targetWidget) { + qt_handleTouchEvent(targetWidget->windowHandle(), device, points.values()); + } + if (processEvents) + QCoreApplication::processEvents(); + previousPoints = points; + points.clear(); +} + +QTest::QTouchEventWidgetSequence::QTouchEventWidgetSequence(QWidget *widget, QPointingDevice *aDevice, bool autoCommit) + : QTouchEventSequence(nullptr, aDevice, autoCommit), targetWidget(widget) +{ +} + +QPoint QTouchEventWidgetSequence::mapToScreen(QWidget *widget, const QPoint &pt) +{ + if (widget) + return widget->mapToGlobal(pt); + return targetWidget ? targetWidget->mapToGlobal(pt) : pt; +} + +} // namespace QTest + QT_END_NAMESPACE diff --git a/src/widgets/kernel/qtestsupport_widgets.h b/src/widgets/kernel/qtestsupport_widgets.h index 5b4f7e59ba..032cab10a8 100644 --- a/src/widgets/kernel/qtestsupport_widgets.h +++ b/src/widgets/kernel/qtestsupport_widgets.h @@ -41,15 +41,40 @@ #define QTESTSUPPORT_WIDGETS_H #include <QtWidgets/qtwidgetsglobal.h> +#include <QtGui/qtestsupport_gui.h> QT_BEGIN_NAMESPACE +class QPointingDevice; class QWidget; namespace QTest { + Q_REQUIRED_RESULT Q_WIDGETS_EXPORT bool qWaitForWindowActive(QWidget *widget, int timeout = 5000); Q_REQUIRED_RESULT Q_WIDGETS_EXPORT bool qWaitForWindowExposed(QWidget *widget, int timeout = 5000); -} + +class Q_WIDGETS_EXPORT QTouchEventWidgetSequence : public QTouchEventSequence +{ +public: + ~QTouchEventWidgetSequence() override; + QTouchEventWidgetSequence& press(int touchId, const QPoint &pt, QWidget *widget = nullptr); + QTouchEventWidgetSequence& move(int touchId, const QPoint &pt, QWidget *widget = nullptr); + QTouchEventWidgetSequence& release(int touchId, const QPoint &pt, QWidget *widget = nullptr); + QTouchEventWidgetSequence& stationary(int touchId) override; + + void commit(bool processEvents = true) override; + +private: + QTouchEventWidgetSequence(QWidget *widget, QPointingDevice *aDevice, bool autoCommit); + + QPoint mapToScreen(QWidget *widget, const QPoint &pt); + + QWidget *targetWidget = nullptr; + + friend QTouchEventWidgetSequence touchEvent(QWidget *widget, QPointingDevice *device, bool autoCommit); +}; + +} // namespace QTest QT_END_NAMESPACE diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp index 332d04ecd4..d1eaae9695 100644 --- a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp +++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp @@ -32,7 +32,7 @@ #include <QtWidgets/QGraphicsView> #include <QtWidgets/QGraphicsWidget> #include <QtWidgets/QWidget> -#include <QtTest> +#include <QtTest/QtTest> #include <qpa/qwindowsysteminterface.h> #include <qpa/qwindowsysteminterface_p.h> #include <private/qevent_p.h> @@ -1655,11 +1655,11 @@ void tst_QTouchEvent::crashInQGraphicsSceneAfterNotHandlingTouchBegin() QPoint centerPos = view.mapFromScene(rect->boundingRect().center()); // Touch the button - QTest::touchEvent(view.viewport(), touchScreenDevice).press(0, centerPos, static_cast<QWindow *>(0)); - QTest::touchEvent(view.viewport(), touchScreenDevice).release(0, centerPos, static_cast<QWindow *>(0)); + QTest::touchEvent(view.viewport(), touchScreenDevice).press(0, centerPos, nullptr); + QTest::touchEvent(view.viewport(), touchScreenDevice).release(0, centerPos, nullptr); // Touch outside of the button - QTest::touchEvent(view.viewport(), touchScreenDevice).press(0, view.mapFromScene(QPoint(10, 10)), static_cast<QWindow *>(0)); - QTest::touchEvent(view.viewport(), touchScreenDevice).release(0, view.mapFromScene(QPoint(10, 10)), static_cast<QWindow *>(0)); + QTest::touchEvent(view.viewport(), touchScreenDevice).press(0, view.mapFromScene(QPoint(10, 10)), nullptr); + QTest::touchEvent(view.viewport(), touchScreenDevice).release(0, view.mapFromScene(QPoint(10, 10)), nullptr); } void tst_QTouchEvent::touchBeginWithGraphicsWidget() diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp index fa1bc3e57a..b65f6a5ff6 100644 --- a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp +++ b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp @@ -126,7 +126,7 @@ bool TestWidget::event(QEvent * event) return QWidget::event(event); } -static void pressSequence(QTest::QTouchEventSequence &sequence, QList<QPoint> &points, +static void pressSequence(QTest::QTouchEventWidgetSequence &sequence, QList<QPoint> &points, QWidget *widget) { const int pointCount = points.size(); @@ -135,7 +135,7 @@ static void pressSequence(QTest::QTouchEventSequence &sequence, QList<QPoint> &p sequence.commit(); } -static void linearSequence(int n, const QPoint &delta, QTest::QTouchEventSequence &sequence, +static void linearSequence(int n, const QPoint &delta, QTest::QTouchEventWidgetSequence &sequence, QList<QPoint> &points, QWidget *widget) { const int pointCount = points.size(); @@ -148,7 +148,7 @@ static void linearSequence(int n, const QPoint &delta, QTest::QTouchEventSequenc } } -static void releaseSequence(QTest::QTouchEventSequence &sequence, QList<QPoint> &points, +static void releaseSequence(QTest::QTouchEventWidgetSequence &sequence, QList<QPoint> &points, QWidget *widget) { const int pointCount = points.size(); @@ -188,7 +188,7 @@ void tst_QGestureRecognizer::panGesture() for (int i = 0; i < panPoints; ++i) points.append(QPoint(10 + i *20, 10 + i *20)); - QTest::QTouchEventSequence panSequence = QTest::touchEvent(&widget, m_touchDevice); + QTest::QTouchEventWidgetSequence panSequence = QTest::touchEvent(&widget, m_touchDevice); pressSequence(panSequence, points, &widget); linearSequence(5, QPoint(20, 20), panSequence, points, &widget); releaseSequence(panSequence, points, &widget); @@ -231,7 +231,7 @@ void tst_QGestureRecognizer::pinchGesture() points.append(widget.rect().center()); points.append(points.front() + QPoint(0, 20)); - QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(&widget, m_touchDevice); + QTest::QTouchEventWidgetSequence pinchSequence = QTest::touchEvent(&widget, m_touchDevice); pressSequence(pinchSequence, points, &widget); for (int s = 0; s < 5; ++s) { @@ -288,7 +288,7 @@ void tst_QGestureRecognizer::swipeGesture() for (int i = 0; i < swipePoints - 1; ++i) points.append(fingerDistance + i * fingerDistance); - QTest::QTouchEventSequence swipeSequence = QTest::touchEvent(&widget, m_touchDevice); + QTest::QTouchEventWidgetSequence swipeSequence = QTest::touchEvent(&widget, m_touchDevice); pressSequence(swipeSequence, points, &widget); // Press point #3 |