summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/widgets/kernel')
-rw-r--r--tests/auto/widgets/kernel/kernel.pro4
-rw-r--r--tests/auto/widgets/kernel/qaction/tst_qaction.cpp35
-rw-r--r--tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp6
-rw-r--r--tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST2
-rw-r--r--tests/auto/widgets/kernel/qgesturerecognizer/qgesturerecognizer.pro4
-rw-r--r--tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp337
-rw-r--r--tests/auto/widgets/kernel/qwidget/BLACKLIST2
-rw-r--r--tests/auto/widgets/kernel/qwidget/qwidget.pro2
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp306
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp73
10 files changed, 717 insertions, 54 deletions
diff --git a/tests/auto/widgets/kernel/kernel.pro b/tests/auto/widgets/kernel/kernel.pro
index 20720dc928..73fd934502 100644
--- a/tests/auto/widgets/kernel/kernel.pro
+++ b/tests/auto/widgets/kernel/kernel.pro
@@ -6,6 +6,7 @@ SUBDIRS=\
qboxlayout \
qdesktopwidget \
qformlayout \
+ qgesturerecognizer \
qgridlayout \
qlayout \
qstackedlayout \
@@ -19,4 +20,7 @@ SUBDIRS=\
qshortcut \
qsizepolicy
+darwin:SUBDIRS -= \ # Uses native recognizers
+ qgesturerecognizer \
+
SUBDIRS -= qsound
diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
index 88ddb7c11d..ac0174d19a 100644
--- a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
+++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
@@ -64,6 +64,7 @@ private slots:
void task229128TriggeredSignalWhenInActiongroup();
void repeat();
void setData();
+ void keysequence(); // QTBUG-53381
void disableShortcutsWithBlockedWidgets_data();
void disableShortcutsWithBlockedWidgets();
@@ -280,6 +281,40 @@ void tst_QAction::alternateShortcuts()
QTest::keyClick(&testWidget, Qt::Key_A, Qt::ControlModifier);
}
+void tst_QAction::keysequence()
+{
+ MyWidget testWidget(this);
+ testWidget.show();
+ QApplication::setActiveWindow(&testWidget);
+
+ {
+ QAction act(&testWidget);
+ testWidget.addAction(&act);
+
+ QKeySequence ks(QKeySequence::SelectAll);
+
+ act.setShortcut(ks);
+
+ QSignalSpy spy(&act, &QAction::triggered);
+
+ act.setAutoRepeat(true);
+ QTest::keySequence(&testWidget, ks);
+ QCoreApplication::processEvents();
+ QCOMPARE(spy.count(), 1); // act should have been triggered
+
+ act.setAutoRepeat(false);
+ QTest::keySequence(&testWidget, ks);
+ QCoreApplication::processEvents();
+ QCOMPARE(spy.count(), 2); //act should have been triggered a 2nd time
+
+ // end of the scope of the action, it will be destroyed and removed from widget
+ // This action should also unregister its shortcuts
+ }
+
+ // this tests a crash (if the action did not unregister its alternate shortcuts)
+ QTest::keyClick(&testWidget, Qt::Key_A, Qt::ControlModifier);
+}
+
void tst_QAction::enabledVisibleInteraction()
{
MyWidget testWidget(this);
diff --git a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
index 1dac242114..7262817d23 100644
--- a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
+++ b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
@@ -156,7 +156,7 @@ void tst_QBoxLayout::sizeHint()
lay1->addLayout(lay2);
window.setLayout(lay1);
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
label->setText("foooooooo baaaaaaar");
QSize sh = lay1->sizeHint();
QApplication::processEvents();
@@ -177,7 +177,7 @@ void tst_QBoxLayout::sizeConstraints()
lay->setSizeConstraint(QLayout::SetFixedSize);
window.setLayout(lay);
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
QSize sh = window.sizeHint();
delete lay->takeAt(1);
QVERIFY(sh.width() >= window.sizeHint().width() &&
@@ -224,7 +224,7 @@ void tst_QBoxLayout::setStyleShouldChangeSpacing()
style1->hspacing = 6;
window.setStyle(style1.data());
window.show();
- QTest::qWaitForWindowExposed(&window);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
int spacing = pb2->geometry().left() - pb1->geometry().right() - 1;
QCOMPARE(spacing, 6);
diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST b/tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST
new file mode 100644
index 0000000000..7f55c2dae0
--- /dev/null
+++ b/tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST
@@ -0,0 +1,2 @@
+[panGesture:Two finger]
+xcb
diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/qgesturerecognizer.pro b/tests/auto/widgets/kernel/qgesturerecognizer/qgesturerecognizer.pro
new file mode 100644
index 0000000000..7c9ddcfb03
--- /dev/null
+++ b/tests/auto/widgets/kernel/qgesturerecognizer/qgesturerecognizer.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase
+TARGET = tst_qgesturerecognizer
+QT += widgets testlib gui-private core-private
+SOURCES += tst_qgesturerecognizer.cpp
diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
new file mode 100644
index 0000000000..c3ebb838bb
--- /dev/null
+++ b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
@@ -0,0 +1,337 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QTest>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QGestureEvent>
+#include <QtGui/QScreen>
+#include <QtGui/QTouchDevice>
+#include <QtCore/QVector>
+#include <QtCore/QString>
+#include <QtCore/QHash>
+#include <QtCore/QDebug>
+
+class tst_QGestureRecognizer : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QGestureRecognizer();
+
+private Q_SLOTS:
+ void initTestCase();
+#ifndef QT_NO_GESTURES
+ void panGesture_data();
+ void panGesture();
+ void pinchGesture_data();
+ void pinchGesture();
+ void swipeGesture_data();
+ void swipeGesture();
+#endif // !QT_NO_GESTURES
+
+private:
+ const int m_fingerDistance;
+ QTouchDevice *m_touchDevice;
+};
+
+tst_QGestureRecognizer::tst_QGestureRecognizer()
+ : m_fingerDistance(qRound(QGuiApplication::primaryScreen()->physicalDotsPerInch() / 2.0))
+ , m_touchDevice(QTest::createTouchDevice())
+{
+ qputenv("QT_PAN_TOUCHPOINTS", "2"); // Prevent device detection of pan touch point count.
+}
+
+void tst_QGestureRecognizer::initTestCase()
+{
+}
+
+#ifndef QT_NO_GESTURES
+
+typedef QVector<Qt::GestureType> GestureTypeVector;
+
+class TestWidget : public QWidget
+{
+public:
+ explicit TestWidget(const GestureTypeVector &gestureTypes);
+
+ bool gestureReceived(Qt::GestureType gestureType) const
+ { return m_receivedGestures.value(gestureType); }
+
+protected:
+ bool event(QEvent * event) Q_DECL_OVERRIDE;
+
+private:
+ typedef QHash<Qt::GestureType, bool> GestureTypeHash;
+ GestureTypeHash m_receivedGestures;
+};
+
+TestWidget::TestWidget(const GestureTypeVector &gestureTypes)
+{
+ setAttribute(Qt::WA_AcceptTouchEvents);
+
+ foreach (Qt::GestureType gestureType, gestureTypes) {
+ grabGesture(gestureType);
+ m_receivedGestures.insert(gestureType, false);
+ }
+
+ const QRect geometry = QGuiApplication::primaryScreen()->availableGeometry();
+ const QSize size = geometry.size() / 2;
+ resize(size);
+ move(geometry.center() - QPoint(size.width() / 2, size.height() / 2));
+}
+
+bool TestWidget::event(QEvent * event)
+{
+ switch (event->type()) {
+ case QEvent::Gesture: {
+ const QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(event);
+ const GestureTypeHash::iterator hend = m_receivedGestures.end();
+ for (GestureTypeHash::iterator it = m_receivedGestures.begin(); it != hend; ++it) {
+ if (const QGesture *gesture = gestureEvent->gesture(it.key())) {
+ if (gesture->state() == Qt::GestureFinished)
+ it.value() = true;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return QWidget::event(event);
+}
+
+static void pressSequence(QTest::QTouchEventSequence &sequence,
+ QVector<QPoint> &points,
+ QWidget *widget)
+{
+ const int pointCount = points.size();
+ for (int p = 0; p < pointCount; ++p)
+ sequence.press(p, points.at(p), widget);
+ sequence.commit();
+}
+
+static void linearSequence(int n, const QPoint &delta,
+ QTest::QTouchEventSequence &sequence,
+ QVector<QPoint> &points,
+ QWidget *widget)
+{
+ const int pointCount = points.size();
+ for (int s = 0; s < n; ++s) {
+ for (int p = 0; p < pointCount; ++p) {
+ points[p] += delta;
+ sequence.move(p, points[p], widget);
+ }
+ sequence.commit();
+ }
+}
+
+static void releaseSequence(QTest::QTouchEventSequence &sequence,
+ QVector<QPoint> &points,
+ QWidget *widget)
+{
+ const int pointCount = points.size();
+ for (int p = 0; p < pointCount; ++p)
+ sequence.release(p, points[p], widget);
+ sequence.commit();
+}
+
+// --- Pan
+
+enum PanSubTest {
+ TwoFingerPanSubTest
+};
+
+void tst_QGestureRecognizer::panGesture_data()
+{
+ QTest::addColumn<int>("panSubTest");
+ QTest::addColumn<bool>("gestureExpected");
+ QTest::newRow("Two finger") << int(TwoFingerPanSubTest) << true;
+}
+
+void tst_QGestureRecognizer::panGesture()
+{
+ QFETCH(int, panSubTest);
+ QFETCH(bool, gestureExpected);
+
+ Q_UNUSED(panSubTest) // Single finger pan will be added later.
+
+ const int panPoints = 2;
+ const Qt::GestureType gestureType = Qt::PanGesture;
+ TestWidget widget(GestureTypeVector(1, gestureType));
+ widget.setWindowTitle(QTest::currentTestFunction());
+ widget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&widget));
+
+ QVector<QPoint> points;
+ for (int i = 0; i < panPoints; ++i)
+ points.append(QPoint(10 + i *20, 10 + i *20));
+
+ QTest::QTouchEventSequence panSequence = QTest::touchEvent(&widget, m_touchDevice);
+ pressSequence(panSequence, points, &widget);
+ linearSequence(5, QPoint(20, 20), panSequence, points, &widget);
+ releaseSequence(panSequence, points, &widget);
+
+ if (gestureExpected) {
+ QTRY_VERIFY(widget.gestureReceived(gestureType));
+ } else {
+ QCoreApplication::processEvents();
+ QVERIFY(!widget.gestureReceived(gestureType));
+ }
+}
+
+// --- Pinch
+
+enum PinchSubTest {
+ StandardPinchSubTest
+};
+
+void tst_QGestureRecognizer::pinchGesture_data()
+{
+ QTest::addColumn<int>("pinchSubTest");
+ QTest::addColumn<bool>("gestureExpected");
+ QTest::newRow("Standard") << int(StandardPinchSubTest) << true;
+}
+
+void tst_QGestureRecognizer::pinchGesture()
+{
+ QFETCH(int, pinchSubTest);
+ QFETCH(bool, gestureExpected);
+
+ Q_UNUSED(pinchSubTest)
+
+ const Qt::GestureType gestureType = Qt::PinchGesture;
+ TestWidget widget(GestureTypeVector(1, gestureType));
+ widget.setWindowTitle(QTest::currentTestFunction());
+ widget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&widget));
+
+ QVector<QPoint> points;
+ points.append(widget.rect().center());
+ points.append(points.front() + QPoint(0, 20));
+
+ QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(&widget, m_touchDevice);
+ pressSequence(pinchSequence, points, &widget);
+
+ for (int s = 0; s < 5; ++s) {
+ points[0] += QPoint(5, 30);
+ pinchSequence.move(0, points[0], &widget);
+ points[1] += QPoint(5, -30);
+ pinchSequence.move(1, points[1], &widget);
+ pinchSequence.commit();
+ }
+
+ releaseSequence(pinchSequence, points, &widget);
+
+ if (gestureExpected) {
+ QTRY_VERIFY(widget.gestureReceived(gestureType));
+ } else {
+ QCoreApplication::processEvents();
+ QVERIFY(!widget.gestureReceived(gestureType));
+ }
+}
+
+// --- Swipe
+
+enum SwipeSubTest {
+ SwipeLineSubTest,
+ SwipeDirectionChangeSubTest,
+ SwipeSmallDirectionChangeSubTest
+};
+
+void tst_QGestureRecognizer::swipeGesture_data()
+{
+ QTest::addColumn<int>("swipeSubTest");
+ QTest::addColumn<bool>("gestureExpected");
+ QTest::newRow("Line") << int(SwipeLineSubTest) << true;
+ QTest::newRow("DirectionChange") << int(SwipeDirectionChangeSubTest) << false;
+ QTest::newRow("SmallDirectionChange") << int(SwipeSmallDirectionChangeSubTest) << true;
+}
+
+void tst_QGestureRecognizer::swipeGesture()
+{
+ enum { swipePoints = 3 };
+
+ QFETCH(int, swipeSubTest);
+ QFETCH(bool, gestureExpected);
+
+ const Qt::GestureType gestureType = Qt::SwipeGesture;
+ TestWidget widget(GestureTypeVector(1, gestureType));
+ widget.setWindowTitle(QTest::currentTestFunction());
+ widget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&widget));
+
+ // Start a swipe sequence with 2 points (QTBUG-15768)
+ const QPoint fingerDistance(m_fingerDistance, m_fingerDistance);
+ QVector<QPoint> points;
+ for (int i = 0; i < swipePoints - 1; ++i)
+ points.append(fingerDistance + i * fingerDistance);
+
+ QTest::QTouchEventSequence swipeSequence = QTest::touchEvent(&widget, m_touchDevice);
+ pressSequence(swipeSequence, points, &widget);
+
+ // Press point #3
+ points.append(points.last() + fingerDistance);
+ swipeSequence.press(points.size() - 1, points.last(), &widget);
+ swipeSequence.commit();
+ Q_ASSERT(points.size() == swipePoints);
+
+ // Move.
+ const QPoint moveDelta(60, 20);
+ switch (swipeSubTest) {
+ case SwipeLineSubTest:
+ linearSequence(5, moveDelta, swipeSequence, points, &widget);
+ break;
+ case SwipeDirectionChangeSubTest:
+ linearSequence(5, moveDelta, swipeSequence, points, &widget);
+ linearSequence(3, QPoint(-moveDelta.x(), moveDelta.y()), swipeSequence, points, &widget);
+ break;
+ case SwipeSmallDirectionChangeSubTest: { // QTBUG-46195, small changes in direction should not cause the gesture to be canceled.
+ const QPoint smallChangeMoveDelta(50, 1);
+ linearSequence(5, smallChangeMoveDelta, swipeSequence, points, &widget);
+ linearSequence(1, QPoint(smallChangeMoveDelta.x(), -3), swipeSequence, points, &widget);
+ linearSequence(5, smallChangeMoveDelta, swipeSequence, points, &widget);
+ }
+ break;
+ }
+
+ releaseSequence(swipeSequence, points, &widget);
+
+ if (gestureExpected) {
+ QTRY_VERIFY(widget.gestureReceived(gestureType));
+ } else {
+ QCoreApplication::processEvents();
+ QVERIFY(!widget.gestureReceived(gestureType));
+ }
+}
+
+#endif // !QT_NO_GESTURES
+
+QTEST_MAIN(tst_QGestureRecognizer)
+
+#include "tst_qgesturerecognizer.moc"
diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST
index a04a67e4be..0b1d7b4437 100644
--- a/tests/auto/widgets/kernel/qwidget/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST
@@ -74,7 +74,7 @@ osx
[setClearAndResizeMask]
osx
[setToolTip]
-osx-10.9
+osx
[moveInResizeEvent]
ubuntu-14.04
[moveChild:right]
diff --git a/tests/auto/widgets/kernel/qwidget/qwidget.pro b/tests/auto/widgets/kernel/qwidget/qwidget.pro
index 3e4e96760b..c1908af2a2 100644
--- a/tests/auto/widgets/kernel/qwidget/qwidget.pro
+++ b/tests/auto/widgets/kernel/qwidget/qwidget.pro
@@ -12,7 +12,7 @@ aix-g++*:QMAKE_CXXFLAGS+=-fpermissive
CONFIG += x11inc
mac {
- LIBS += -framework Security -framework AppKit -framework Carbon
+ LIBS += -framework Security -framework AppKit
OBJECTIVE_SOURCES += tst_qwidget_mac_helpers.mm
}
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index c1bff5b00a..cf2794903e 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -50,6 +50,7 @@
#include <qcalendarwidget.h>
#include <qmainwindow.h>
#include <qdockwidget.h>
+#include <qrandom.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <QtGui/qpaintengine.h>
@@ -183,7 +184,10 @@ private slots:
void mapFromAndTo();
void focusChainOnHide();
void focusChainOnReparent();
- void setTabOrder();
+ void defaultTabOrder();
+ void reverseTabOrder();
+ void tabOrderWithProxy();
+ void tabOrderWithCompoundWidgets();
#ifdef Q_OS_WIN
void activation();
#endif
@@ -1650,79 +1654,281 @@ public:
class Composite : public QFrame
{
public:
- Composite(QWidget* parent = 0, const char* name = 0)
+ Composite(QWidget* parent = 0, const QString &name = 0)
: QFrame(parent)
{
setObjectName(name);
- //QHBoxLayout* hbox = new QHBoxLayout(this, 2, 0);
- //hbox->setAutoAdd(true);
+
+ lineEdit1 = new QLineEdit;
+ lineEdit2 = new QLineEdit;
+ lineEdit3 = new QLineEdit;
+ lineEdit3->setEnabled(false);
+
QHBoxLayout* hbox = new QHBoxLayout(this);
+ hbox->addWidget(lineEdit1);
+ hbox->addWidget(lineEdit2);
+ hbox->addWidget(lineEdit3);
+ }
- lineEdit = new QLineEdit(this);
- hbox->addWidget(lineEdit);
+public:
+ QLineEdit *lineEdit1;
+ QLineEdit *lineEdit2;
+ QLineEdit *lineEdit3;
+};
- button = new QPushButton(this);
- hbox->addWidget(button);
- button->setFocusPolicy( Qt::NoFocus );
+void tst_QWidget::defaultTabOrder()
+{
+ const int compositeCount = 2;
+ Container container;
+ Composite *composite[compositeCount];
- setFocusProxy( lineEdit );
- setFocusPolicy( Qt::StrongFocus );
+ QLineEdit *firstEdit = new QLineEdit;
+ container.box->addWidget(firstEdit);
- setTabOrder(lineEdit, button);
+ for (int i = 0; i < compositeCount; i++) {
+ composite[i] = new Composite();
+ container.box->addWidget(composite[i]);
}
-private:
- QLineEdit* lineEdit;
- QPushButton* button;
-};
+ QLineEdit *lastEdit = new QLineEdit();
+ container.box->addWidget(lastEdit);
-#define NUM_WIDGETS 4
+ container.show();
+ container.activateWindow();
+ qApp->setActiveWindow(&container);
+ QVERIFY(QTest::qWaitForWindowActive(&container));
-void tst_QWidget::setTabOrder()
-{
- QTest::qWait(100);
+ QTRY_VERIFY(firstEdit->hasFocus());
+ // Check that focus moves between the line edits when we tab forward
+ for (int i = 0; i < compositeCount; ++i) {
+ container.tab();
+ QVERIFY(composite[i]->lineEdit1->hasFocus());
+ QVERIFY(!composite[i]->lineEdit2->hasFocus());
+ container.tab();
+ QVERIFY(!composite[i]->lineEdit1->hasFocus());
+ QVERIFY(composite[i]->lineEdit2->hasFocus());
+ }
+
+ container.tab();
+ QVERIFY(lastEdit->hasFocus());
+
+ // Check that focus moves between the line edits in reverse
+ // order when we tab backwards
+ for (int i = compositeCount - 1; i >= 0; --i) {
+ container.backTab();
+ QVERIFY(!composite[i]->lineEdit1->hasFocus());
+ QVERIFY(composite[i]->lineEdit2->hasFocus());
+
+ container.backTab();
+ QVERIFY(composite[i]->lineEdit1->hasFocus());
+ QVERIFY(!composite[i]->lineEdit2->hasFocus());
+ }
+
+ container.backTab();
+ QVERIFY(firstEdit->hasFocus());
+}
+
+void tst_QWidget::reverseTabOrder()
+{
+ const int compositeCount = 2;
Container container;
- container.setObjectName("setTabOrder");
- container.setWindowTitle(container.objectName());
+ Composite* composite[compositeCount];
+
+ QLineEdit *firstEdit = new QLineEdit();
+ container.box->addWidget(firstEdit);
+
+ for (int i = 0; i < compositeCount; i++) {
+ composite[i] = new Composite();
+ container.box->addWidget(composite[i]);
+ }
+
+ QLineEdit *lastEdit = new QLineEdit();
+ container.box->addWidget(lastEdit);
- Composite* comp[NUM_WIDGETS];
+ // Reverse tab order inside each composite
+ for (int i = 0; i < compositeCount; ++i)
+ QWidget::setTabOrder(composite[i]->lineEdit2, composite[i]->lineEdit1);
- QLineEdit *firstEdit = new QLineEdit(&container);
+ container.show();
+ container.activateWindow();
+ qApp->setActiveWindow(&container);
+ QVERIFY(QTest::qWaitForWindowActive(&container));
+
+ QTRY_VERIFY(firstEdit->hasFocus());
+
+ // Check that focus moves in reverse order when tabbing inside the composites
+ // (but in the correct order when tabbing between them)
+ for (int i = 0; i < compositeCount; ++i) {
+ container.tab();
+ QVERIFY(!composite[i]->lineEdit1->hasFocus());
+ QVERIFY(composite[i]->lineEdit2->hasFocus());
+ container.tab();
+ QVERIFY(composite[i]->lineEdit1->hasFocus());
+ QVERIFY(!composite[i]->lineEdit2->hasFocus());
+ }
+
+ container.tab();
+ QVERIFY(lastEdit->hasFocus());
+
+ // Check that focus moves in "normal" order when tabbing backwards inside the
+ // composites (since backwards of reversed order cancels each other out),
+ // but in the reverse order when tabbing between them.
+ for (int i = compositeCount - 1; i >= 0; --i) {
+ container.backTab();
+ QVERIFY(composite[i]->lineEdit1->hasFocus());
+ QVERIFY(!composite[i]->lineEdit2->hasFocus());
+ container.backTab();
+ QVERIFY(!composite[i]->lineEdit1->hasFocus());
+ QVERIFY(composite[i]->lineEdit2->hasFocus());
+ }
+
+ container.backTab();
+ QVERIFY(firstEdit->hasFocus());
+}
+
+void tst_QWidget::tabOrderWithProxy()
+{
+ const int compositeCount = 2;
+ Container container;
+ Composite* composite[compositeCount];
+
+ QLineEdit *firstEdit = new QLineEdit();
container.box->addWidget(firstEdit);
- int i = 0;
- for(i = 0; i < NUM_WIDGETS; i++) {
- comp[i] = new Composite(&container);
- container.box->addWidget(comp[i]);
+ for (int i = 0; i < compositeCount; i++) {
+ composite[i] = new Composite();
+ container.box->addWidget(composite[i]);
+
+ // Set second child as focus proxy
+ composite[i]->setFocusPolicy(Qt::StrongFocus);
+ composite[i]->setFocusProxy(composite[i]->lineEdit2);
}
- QLineEdit *lastEdit = new QLineEdit(&container);
+ QLineEdit *lastEdit = new QLineEdit();
container.box->addWidget(lastEdit);
- container.setTabOrder(lastEdit, comp[NUM_WIDGETS-1]);
- for(i = NUM_WIDGETS-1; i > 0; i--) {
- container.setTabOrder(comp[i], comp[i-1]);
+ container.show();
+ container.activateWindow();
+ qApp->setActiveWindow(&container);
+ QVERIFY(QTest::qWaitForWindowActive(&container));
+
+ QTRY_VERIFY(firstEdit->hasFocus());
+
+ // Check that focus moves between the second line edits
+ // (the focus proxies) when we tab forward
+ for (int i = 0; i < compositeCount; ++i) {
+ container.tab();
+ QVERIFY(!composite[i]->lineEdit1->hasFocus());
+ QVERIFY(composite[i]->lineEdit2->hasFocus());
}
- container.setTabOrder(comp[0], firstEdit);
- int current = NUM_WIDGETS-1;
- lastEdit->setFocus();
+ container.tab();
+ QVERIFY(lastEdit->hasFocus());
+
+ // Check that focus moves between the line edits
+ // in reverse order when we tab backwards.
+ // Note that in this case, the focus proxies should not
+ // be taken into consideration, since they only take
+ // effect when tabbing forward
+ for (int i = compositeCount - 1; i >= 0; --i) {
+ container.backTab();
+ QVERIFY(!composite[i]->lineEdit1->hasFocus());
+ QVERIFY(composite[i]->lineEdit2->hasFocus());
+ container.backTab();
+ QVERIFY(composite[i]->lineEdit1->hasFocus());
+ QVERIFY(!composite[i]->lineEdit2->hasFocus());
+ }
+
+ container.backTab();
+ QVERIFY(firstEdit->hasFocus());
+}
+
+void tst_QWidget::tabOrderWithCompoundWidgets()
+{
+ const int compositeCount = 4;
+ Container container;
+ Composite *composite[compositeCount];
+
+ QLineEdit *firstEdit = new QLineEdit();
+ container.box->addWidget(firstEdit);
+
+ for (int i = 0; i < compositeCount; i++) {
+ composite[i] = new Composite(0, QStringLiteral("Composite: ") + QString::number(i));
+ container.box->addWidget(composite[i]);
+
+ // Let the composite handle focus, and set a child as focus proxy (use the second child, just
+ // to ensure that we don't just tab to the first child by coinsidence). This will make the
+ // composite "compound". Also enable the last line edit to have a bit more data to check when
+ // tabbing forwards.
+ composite[i]->setFocusPolicy(Qt::StrongFocus);
+ composite[i]->setFocusProxy(composite[i]->lineEdit2);
+ composite[i]->lineEdit3->setEnabled(true);
+ }
+
+ QLineEdit *lastEdit = new QLineEdit();
+ container.box->addWidget(lastEdit);
+
+ // Reverse tab order between each composite
+ // (but not inside them), including first and last line edit.
+ // The result should not affect local tab order inside each
+ // composite, only between them.
+ QWidget::setTabOrder(lastEdit, composite[compositeCount - 1]);
+ for (int i = compositeCount - 1; i >= 1; --i)
+ QWidget::setTabOrder(composite[i], composite[i-1]);
+ QWidget::setTabOrder(composite[0], firstEdit);
container.show();
container.activateWindow();
qApp->setActiveWindow(&container);
QVERIFY(QTest::qWaitForWindowActive(&container));
+ lastEdit->setFocus();
QTRY_VERIFY(lastEdit->hasFocus());
- container.tab();
- do {
- QVERIFY(comp[current]->focusProxy()->hasFocus());
+
+ // Check that focus moves between the line edits in the normal
+ // order when tabbing inside each compound, but in the reverse
+ // order when tabbing between them. Since the composites have
+ // lineEdit2 as focus proxy, lineEdit2 will be the first with focus
+ // when the compound gets focus, and lineEdit1 will therefore be skipped.
+ for (int i = compositeCount - 1; i >= 0; --i) {
+ container.tab();
+ Composite *c = composite[i];
+ QVERIFY(!c->lineEdit1->hasFocus());
+ QVERIFY(c->lineEdit2->hasFocus());
+ QVERIFY(!c->lineEdit3->hasFocus());
container.tab();
- current--;
- } while (current >= 0);
+ QVERIFY(!c->lineEdit1->hasFocus());
+ QVERIFY(!c->lineEdit2->hasFocus());
+ QVERIFY(c->lineEdit3->hasFocus());
+ }
+ container.tab();
QVERIFY(firstEdit->hasFocus());
+
+ // Check that focus moves in reverse order when backTab inside the composites, but
+ // in the 'correct' order when backTab between them (since the composites are in reverse tab
+ // order from before, which cancels it out). Note that when we backtab into a compound, we start
+ // at lineEdit3 rather than the focus proxy, since that is the reverse of what happens when we tab
+ // forward. And this time we will also backtab to lineEdit1, since there is no focus proxy that interferes.
+ for (int i = 0; i < compositeCount; ++i) {
+ container.backTab();
+ Composite *c = composite[i];
+ QVERIFY(!c->lineEdit1->hasFocus());
+ QVERIFY(!c->lineEdit2->hasFocus());
+ QVERIFY(c->lineEdit3->hasFocus());
+ container.backTab();
+ QVERIFY(!c->lineEdit1->hasFocus());
+ QVERIFY(c->lineEdit2->hasFocus());
+ QVERIFY(!c->lineEdit3->hasFocus());
+ container.backTab();
+ QVERIFY(c->lineEdit1->hasFocus());
+ QVERIFY(!c->lineEdit2->hasFocus());
+ QVERIFY(!c->lineEdit3->hasFocus());
+ }
+
+ container.backTab();
+ QVERIFY(lastEdit->hasFocus());
}
#ifdef Q_OS_WIN
@@ -1787,9 +1993,11 @@ void tst_QWidget::windowState()
QCOMPARE(widget1.pos(), pos);
QCOMPARE(widget1.size(), size);
-#define VERIFY_STATE(s) QCOMPARE(int(widget1.windowState() & stateMask), int(s))
+#define VERIFY_STATE(s) \
+ QCOMPARE(int(widget1.windowState() & stateMask), int(s)); \
+ QCOMPARE(int(widget1.windowHandle()->windowStates() & stateMask), int(s))
- const int stateMask = Qt::WindowMaximized|Qt::WindowMinimized|Qt::WindowFullScreen;
+ const auto stateMask = Qt::WindowMaximized | Qt::WindowMinimized | Qt::WindowFullScreen;
widget1.setWindowState(Qt::WindowMaximized);
QTest::qWait(100);
@@ -2079,7 +2287,7 @@ void tst_QWidget::resizeEvent()
wParent.resize(200, 200);
ResizeWidget wChild(&wParent);
wParent.show();
- QTest::qWaitForWindowExposed(&wParent);
+ QVERIFY(QTest::qWaitForWindowExposed(&wParent));
QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint
wParent.hide();
QSize safeSize(640,480);
@@ -2095,7 +2303,7 @@ void tst_QWidget::resizeEvent()
ResizeWidget wTopLevel;
wTopLevel.resize(200, 200);
wTopLevel.show();
- QTest::qWaitForWindowExposed(&wTopLevel);
+ QVERIFY(QTest::qWaitForWindowExposed(&wTopLevel));
QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels
wTopLevel.hide();
QSize safeSize(640,480);
@@ -2104,7 +2312,7 @@ void tst_QWidget::resizeEvent()
wTopLevel.resize(safeSize);
QCOMPARE (wTopLevel.m_resizeEventCount, 1);
wTopLevel.show();
- QTest::qWaitForWindowExposed(&wTopLevel);
+ QVERIFY(QTest::qWaitForWindowExposed(&wTopLevel));
QCOMPARE (wTopLevel.m_resizeEventCount, 2);
}
}
@@ -8060,8 +8268,8 @@ void tst_QWidget::setMaskInResizeEvent()
QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area.
expectedParentUpdate += testWidget.geometry(); // New testWidget area.
- QCOMPARE(w.paintedRegion, expectedParentUpdate);
- QCOMPARE(testWidget.paintedRegion, testWidget.mask());
+ QTRY_COMPARE(w.paintedRegion, expectedParentUpdate);
+ QTRY_COMPARE(testWidget.paintedRegion, testWidget.mask());
testWidget.paintedRegion = QRegion();
// Now resize the widget again, but in the oposite direction
@@ -9609,7 +9817,7 @@ void tst_QWidget::grab()
for (int row = 0; row < image.height(); ++row) {
QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(row));
for (int col = 0; col < image.width(); ++col)
- line[col] = qRgba(rand() & 255, row, col, opaque ? 255 : 127);
+ line[col] = qRgba(QRandomGenerator::global()->bounded(255), row, col, opaque ? 255 : 127);
}
QPalette pal = widget.palette();
@@ -10489,6 +10697,8 @@ void tst_QWidget::qmlSetParentHelper()
void tst_QWidget::testForOutsideWSRangeFlag()
{
+ QSKIP("Test assumes QWindows can have 0x0 size, see QTBUG-61953");
+
// QTBUG-49445
{
QWidget widget;
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
index e4564a8640..b76c4d35a8 100644
--- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -96,6 +96,11 @@ private slots:
void QTBUG_50561_QCocoaBackingStore_paintDevice_crash();
+ void setWindowState_data();
+ void setWindowState();
+
+ void nativeShow();
+
void QTBUG_56277_resize_on_showEvent();
};
@@ -842,7 +847,7 @@ void tst_QWidget_window::QTBUG_50561_QCocoaBackingStore_paintDevice_crash()
QMainWindow w;
w.addToolBar(new QToolBar(&w));
w.show();
- QTest::qWaitForWindowExposed(&w);
+ QVERIFY(QTest::qWaitForWindowExposed(&w));
// Simulate window system close
QCloseEvent *e = new QCloseEvent;
@@ -859,6 +864,72 @@ void tst_QWidget_window::QTBUG_50561_QCocoaBackingStore_paintDevice_crash()
w.close();
}
+void tst_QWidget_window::setWindowState_data()
+{
+ QString platformName = QGuiApplication::platformName().toLower();
+
+ QTest::addColumn<Qt::WindowStates>("state");
+ QTest::newRow("0") << Qt::WindowStates();
+ QTest::newRow("Qt::WindowMaximized") << Qt::WindowStates(Qt::WindowMaximized);
+ QTest::newRow("Qt::WindowMinimized") << Qt::WindowStates(Qt::WindowMinimized);
+ QTest::newRow("Qt::WindowFullScreen") << Qt::WindowStates(Qt::WindowFullScreen);
+
+ if (platformName != "xcb" && platformName != "windows" && !platformName.startsWith("wayland")
+ && platformName != "offscreen")
+ return; // Combination of states is not preserved on all platforms.
+ if (platformName == "xcb" && qgetenv("XDG_CURRENT_DESKTOP") != "KDE"
+ && qgetenv("XDG_CURRENT_DESKTOP") != "Unity")
+ return; // Not all window managers support state combinations.
+
+ QTest::newRow("Qt::WindowMaximized|Qt::WindowMinimized")
+ << (Qt::WindowMaximized | Qt::WindowMinimized);
+ QTest::newRow("Qt::WindowFullScreen|Qt::WindowMinimized")
+ << (Qt::WindowFullScreen | Qt::WindowMinimized);
+ QTest::newRow("Qt::WindowMaximized|Qt::WindowFullScreen")
+ << (Qt::WindowMaximized | Qt::WindowFullScreen);
+ QTest::newRow("Qt::WindowMaximized|Qt::WindowFullScreen|Qt::WindowMinimized")
+ << (Qt::WindowMaximized | Qt::WindowFullScreen | Qt::WindowMinimized);
+}
+
+void tst_QWidget_window::setWindowState()
+{
+ QFETCH(Qt::WindowStates, state);
+
+ // This tests make sure that the states are preserved when the window is shown.
+
+ QWidget w;
+ w.setWindowState(state);
+ QCOMPARE(w.windowState(), state);
+ w.show();
+ QCOMPARE(w.windowState(), state);
+ QCOMPARE(w.windowHandle()->windowStates(), state);
+ if (!(state & Qt::WindowMinimized))
+ QVERIFY(QTest::qWaitForWindowExposed(&w));
+ QTRY_COMPARE(w.windowState(), state);
+ QCOMPARE(w.windowHandle()->windowStates(), state);
+
+ // Minimizing keeps other states
+ w.showMinimized();
+ QCOMPARE(w.windowState(), state | Qt::WindowMinimized);
+ QTest::qWait(100);
+ QCOMPARE(w.windowState(), state | Qt::WindowMinimized);
+ QCOMPARE(w.windowHandle()->windowStates(), state | Qt::WindowMinimized);
+}
+
+void tst_QWidget_window::nativeShow()
+{
+ // Verify that a native widget can be shown using the QWindow::setVisible() API
+ QWidget w;
+ w.winId();
+ w.windowHandle()->setVisible(true);
+ QVERIFY(QTest::qWaitForWindowExposed(&w));
+ QVERIFY(w.isVisible());
+
+ // ... and that we can hide it
+ w.windowHandle()->setVisible(false);
+ QTRY_VERIFY(!w.isVisible());
+}
+
class ResizedOnShowEventWidget : public QWidget
{
public: