1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include <QtTest/qtest.h>
38#include "../shared/visualtestutil.h"
39
40#include <QtQuick/qquickview.h>
41#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
42#include <QtQuickTemplates2/private/qquickcontrol_p.h>
43#include <QtQuickTemplates2/private/qquickpageindicator_p.h>
44#include <QtQuickTemplates2/private/qquickscrollbar_p.h>
45#include <QtQuickTemplates2/private/qquicktextarea_p.h>
46
47#if QT_CONFIG(cursor)
48# include <QtGui/qscreen.h>
49# include <QtGui/qcursor.h>
50#endif
51
52using namespace QQuickVisualTestUtil;
53
54class tst_cursor : public QQmlDataTest
55{
56 Q_OBJECT
57
58private slots:
59 void init();
60 void controls_data();
61 void controls();
62 void editable();
63 void pageIndicator();
64 void scrollBar();
65};
66
67void tst_cursor::init()
68{
69#if QT_CONFIG(cursor)
70 // Ensure mouse cursor was not left by previous tests where widgets
71 // will appear, as it could cause events and interfere with the tests.
72 const QScreen *screen = QGuiApplication::primaryScreen();
73 const QRect availableGeometry = screen->availableGeometry();
74 QCursor::setPos(availableGeometry.topLeft());
75#endif
76}
77
78void tst_cursor::controls_data()
79{
80 QTest::addColumn<QString>(name: "testFile");
81
82 QTest::newRow(dataTag: "buttons") << "buttons.qml";
83 QTest::newRow(dataTag: "containers") << "containers.qml";
84 QTest::newRow(dataTag: "sliders") << "sliders.qml";
85}
86
87void tst_cursor::controls()
88{
89 QFETCH(QString, testFile);
90
91 QQuickView view(testFileUrl(fileName: testFile));
92 view.show();
93 QVERIFY(QTest::qWaitForWindowActive(&view));
94
95 QQuickItem *mouseArea = view.rootObject();
96 QVERIFY(mouseArea);
97 QCOMPARE(mouseArea->cursor().shape(), Qt::ForbiddenCursor);
98
99 QQuickItem *column = mouseArea->childItems().value(i: 0);
100 QVERIFY(column);
101
102 const auto controls = column->childItems();
103 for (QQuickItem *control : controls) {
104 QCOMPARE(control->cursor().shape(), Qt::ArrowCursor);
105
106 QTest::mouseMove(window: &view, pos: control->mapToScene(point: QPointF(-1, -1)).toPoint());
107 QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor);
108
109 QTest::mouseMove(window: &view, pos: control->mapToScene(point: QPointF(0, 0)).toPoint());
110 QCOMPARE(view.cursor().shape(), Qt::ArrowCursor);
111
112 QTest::mouseMove(window: &view, pos: control->mapToScene(point: QPointF(control->width() + 1, control->height() + 1)).toPoint());
113 QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor);
114 }
115}
116
117void tst_cursor::editable()
118{
119 QQuickView view(testFileUrl(fileName: "editable.qml"));
120 view.show();
121 QVERIFY(QTest::qWaitForWindowActive(&view));
122
123 QQuickItem *mouseArea = view.rootObject();
124 QVERIFY(mouseArea);
125 QCOMPARE(mouseArea->cursor().shape(), Qt::ForbiddenCursor);
126
127 QQuickItem *column = mouseArea->childItems().value(i: 0);
128 QVERIFY(column);
129
130 const auto children = column->childItems();
131 for (QQuickItem *child : children) {
132 QQuickControl *control = qobject_cast<QQuickControl *>(object: child);
133 QVERIFY(control);
134 QCOMPARE(control->cursor().shape(), Qt::ArrowCursor);
135 QCOMPARE(control->contentItem()->cursor().shape(), Qt::IBeamCursor);
136
137 QTest::mouseMove(window: &view, pos: control->mapToScene(point: QPointF(-1, -1)).toPoint());
138 QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor);
139
140 QTest::mouseMove(window: &view, pos: control->mapToScene(point: QPointF(control->width() / 2, control->height() / 2)).toPoint());
141 QCOMPARE(view.cursor().shape(), Qt::IBeamCursor);
142
143 control->setProperty(name: "editable", value: false);
144 QCOMPARE(control->cursor().shape(), Qt::ArrowCursor);
145 QCOMPARE(control->contentItem()->cursor().shape(), Qt::ArrowCursor);
146 QCOMPARE(view.cursor().shape(), Qt::ArrowCursor);
147
148 QTest::mouseMove(window: &view, pos: control->mapToScene(point: QPointF(control->width() + 1, control->height() + 1)).toPoint());
149 QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor);
150 }
151}
152
153void tst_cursor::pageIndicator()
154{
155 QQuickView view(testFileUrl(fileName: "pageindicator.qml"));
156 view.show();
157 QVERIFY(QTest::qWaitForWindowActive(&view));
158
159 QQuickItem *mouseArea = view.rootObject();
160 QVERIFY(mouseArea);
161 QCOMPARE(mouseArea->cursor().shape(), Qt::ForbiddenCursor);
162
163 QQuickPageIndicator *indicator = qobject_cast<QQuickPageIndicator *>(object: mouseArea->childItems().value(i: 0));
164 QVERIFY(indicator);
165
166 QTest::mouseMove(window: &view, pos: indicator->mapToScene(point: QPointF(-1, -1)).toPoint());
167 QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor);
168
169 QTest::mouseMove(window: &view, pos: indicator->mapToScene(point: QPointF(0, 0)).toPoint());
170 QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor);
171
172 indicator->setInteractive(true);
173 QCOMPARE(view.cursor().shape(), Qt::ArrowCursor);
174
175 QTest::mouseMove(window: &view, pos: indicator->mapToScene(point: QPointF(indicator->width() + 1, indicator->height() + 1)).toPoint());
176 QCOMPARE(view.cursor().shape(), Qt::ForbiddenCursor);
177}
178
179// QTBUG-59629
180void tst_cursor::scrollBar()
181{
182 // Ensure that the mouse cursor has the correct shape when over a scrollbar
183 // which is itself over a text area with IBeamCursor.
184 QQuickApplicationHelper helper(this, QStringLiteral("scrollbar.qml"));
185 QVERIFY2(helper.ready, helper.failureMessage());
186 QQuickApplicationWindow *window = helper.appWindow;
187 window->show();
188 QVERIFY(QTest::qWaitForWindowActive(window));
189
190 QQuickScrollBar *scrollBar = helper.appWindow->property(name: "scrollBar").value<QQuickScrollBar*>();
191 QVERIFY(scrollBar);
192
193 QQuickTextArea *textArea = helper.appWindow->property(name: "textArea").value<QQuickTextArea*>();
194 QVERIFY(textArea);
195
196 textArea->setText(QString("\n").repeated(times: 100));
197
198 const QPoint textAreaPos(window->width() / 2, window->height() / 2);
199 QTest::mouseMove(window, pos: textAreaPos);
200 QCOMPARE(window->cursor().shape(), textArea->cursor().shape());
201 QCOMPARE(textArea->cursor().shape(), Qt::CursorShape::IBeamCursor);
202
203 const QPoint scrollBarPos(window->width() - scrollBar->width() / 2, window->height() / 2);
204 QTest::mouseMove(window, pos: scrollBarPos);
205
206 QVERIFY(scrollBar->isActive());
207 QCOMPARE(window->cursor().shape(), scrollBar->cursor().shape());
208 QCOMPARE(scrollBar->cursor().shape(), Qt::CursorShape::ArrowCursor);
209
210 scrollBar->setInteractive(false);
211 QCOMPARE(window->cursor().shape(), textArea->cursor().shape());
212}
213
214QTEST_MAIN(tst_cursor)
215
216#include "tst_cursor.moc"
217

source code of qtquickcontrols2/tests/auto/cursor/tst_cursor.cpp