1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qtestsupport_widgets.h"
5
6#include "qwidget.h"
7
8#include <QtGui/qwindow.h>
9#include <QtCore/qtestsupport_core.h>
10#include <QtCore/qthread.h>
11#include <QtGui/qtestsupport_gui.h>
12#include <QtGui/private/qevent_p.h>
13#include <QtGui/private/qeventpoint_p.h>
14#include <private/qguiapplication_p.h>
15#include <qpa/qplatformintegration.h>
16
17QT_BEGIN_NAMESPACE
18
19template <typename FunctorWindowGetter, typename FunctorPredicate, typename Timeout>
20static bool qWaitForWidgetWindow(FunctorWindowGetter windowGetter, FunctorPredicate predicate, Timeout timeout)
21{
22 if (!windowGetter())
23 return false;
24
25 return QTest::qWaitFor([&]() {
26 if (QWindow *window = windowGetter())
27 return predicate(window);
28 return false;
29 }, timeout);
30}
31
32/*!
33 \since 5.0
34
35 Returns \c true if \a widget is active within \a timeout milliseconds. Otherwise returns \c false.
36
37 The method is useful in tests that call QWidget::show() and rely on the widget actually being
38 active (i.e. being visible and having focus) before proceeding.
39
40 \note The method will time out and return \c false if another window prevents \a widget from
41 becoming active.
42
43 \note Since focus is an exclusive property, \a widget may loose its focus to another window at
44 any time - even after the method has returned \c true.
45
46 \sa qWaitForWindowExposed(), QWidget::isActiveWindow()
47*/
48Q_WIDGETS_EXPORT bool QTest::qWaitForWindowActive(QWidget *widget, int timeout)
49{
50 if (Q_UNLIKELY(!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))) {
51 qWarning() << "qWaitForWindowActive was called on a platform that doesn't support window"
52 << "activation. This means there is an error in the test and it should either"
53 << "check for the WindowActivation platform capability before calling"
54 << "qWaitForWindowActivate, use qWaitForWindowExposed instead, or skip the test."
55 << "Falling back to qWaitForWindowExposed.";
56 return qWaitForWindowExposed(widget, timeout);
57 }
58 return qWaitForWidgetWindow(windowGetter: [&]() { return widget->window()->windowHandle(); },
59 predicate: [&](QWindow *window) { return window->isActive(); },
60 timeout);
61}
62
63
64/*!
65 \since 6.7
66
67 Returns \c true, if \a widget is the focus window within \a timeout. Otherwise returns \c false.
68
69 The method is useful in tests that call QWidget::show() and rely on the widget
70 having focus (for receiving keyboard events e.g.) before proceeding.
71
72 \note The method will time out and return \c false if another window prevents \a widget from
73 becoming focused.
74
75 \note Since focus is an exclusive property, \a widget may loose its focus to another window at
76 any time - even after the method has returned \c true.
77
78 \sa qWaitForWindowExposed(), qWaitForWindowActive(), QGuiApplication::focusWindow()
79*/
80Q_WIDGETS_EXPORT bool QTest::qWaitForWindowFocused(QWidget *widget, QDeadlineTimer timeout)
81{
82 return qWaitForWidgetWindow(windowGetter: [&]() {
83 return widget->window()->windowHandle();
84 }, predicate: [&](QWindow *window) {
85 return qGuiApp->focusWindow() == window;
86 }, timeout);
87}
88
89/*!
90 \since 5.0
91
92 Returns \c true if \a widget is exposed within \a timeout milliseconds. Otherwise returns \c false.
93
94 The method is useful in tests that call QWidget::show() and rely on the widget actually being
95 being visible before proceeding.
96
97 \note A window mapped to screen may still not be considered exposed, if the window client area is
98 not visible, e.g. because it is completely covered by other windows.
99 In such cases, the method will time out and return \c false.
100
101 \sa qWaitForWindowActive(), QWidget::isVisible(), QWindow::isExposed()
102*/
103Q_WIDGETS_EXPORT bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout)
104{
105 return qWaitForWidgetWindow(windowGetter: [&]() { return widget->window()->windowHandle(); },
106 predicate: [&](QWindow *window) { return window->isExposed(); },
107 timeout);
108}
109
110namespace QTest {
111
112QTouchEventWidgetSequence::~QTouchEventWidgetSequence()
113{
114 if (commitWhenDestroyed)
115 QTouchEventWidgetSequence::commit();
116}
117
118QTouchEventWidgetSequence& QTouchEventWidgetSequence::press(int touchId, const QPoint &pt, QWidget *widget)
119{
120 auto &p = point(touchId);
121 QMutableEventPoint::setGlobalPosition(p, arg: mapToScreen(widget, pt));
122 QMutableEventPoint::setState(p, arg: QEventPoint::State::Pressed);
123 return *this;
124}
125QTouchEventWidgetSequence& QTouchEventWidgetSequence::move(int touchId, const QPoint &pt, QWidget *widget)
126{
127 auto &p = point(touchId);
128 QMutableEventPoint::setGlobalPosition(p, arg: mapToScreen(widget, pt));
129 QMutableEventPoint::setState(p, arg: QEventPoint::State::Updated);
130 return *this;
131}
132QTouchEventWidgetSequence& QTouchEventWidgetSequence::release(int touchId, const QPoint &pt, QWidget *widget)
133{
134 auto &p = point(touchId);
135 QMutableEventPoint::setGlobalPosition(p, arg: mapToScreen(widget, pt));
136 QMutableEventPoint::setState(p, arg: QEventPoint::State::Released);
137 return *this;
138}
139
140QTouchEventWidgetSequence& QTouchEventWidgetSequence::stationary(int touchId)
141{
142 auto &p = pointOrPreviousPoint(touchId);
143 QMutableEventPoint::setState(p, arg: QEventPoint::State::Stationary);
144 return *this;
145}
146
147bool QTouchEventWidgetSequence::commit(bool processEvents)
148{
149 bool ret = false;
150 if (points.isEmpty())
151 return ret;
152 QThread::sleep(nsec: std::chrono::milliseconds{1});
153 if (targetWindow) {
154 ret = qt_handleTouchEventv2(w: targetWindow, device, points: points.values());
155 } else if (targetWidget) {
156 ret = qt_handleTouchEventv2(w: targetWidget->windowHandle(), device, points: points.values());
157 }
158 if (processEvents)
159 QCoreApplication::processEvents();
160 previousPoints = points;
161 points.clear();
162 return ret;
163}
164
165QTest::QTouchEventWidgetSequence::QTouchEventWidgetSequence(QWidget *widget, QPointingDevice *aDevice, bool autoCommit)
166 : QTouchEventSequence(nullptr, aDevice, autoCommit), targetWidget(widget)
167{
168}
169
170QPoint QTouchEventWidgetSequence::mapToScreen(QWidget *widget, const QPoint &pt)
171{
172 if (widget)
173 return widget->mapToGlobal(pt);
174 return targetWidget ? targetWidget->mapToGlobal(pt) : pt;
175}
176
177} // namespace QTest
178
179QT_END_NAMESPACE
180

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtbase/src/widgets/kernel/qtestsupport_widgets.cpp