summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qassociativeiterable.h15
-rw-r--r--src/corelib/kernel/qsequentialiterable.h15
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp7
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp10
-rw-r--r--src/testlib/qtest.h8
-rw-r--r--src/widgets/itemviews/qtreeview.cpp11
-rw-r--r--src/widgets/kernel/qstandardgestures.cpp10
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp23
-rw-r--r--tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp108
9 files changed, 160 insertions, 47 deletions
diff --git a/src/corelib/kernel/qassociativeiterable.h b/src/corelib/kernel/qassociativeiterable.h
index 4f9bbf67bfb..c042fe4a0ec 100644
--- a/src/corelib/kernel/qassociativeiterable.h
+++ b/src/corelib/kernel/qassociativeiterable.h
@@ -21,9 +21,8 @@ QT_WARNING_DISABLE_DEPRECATED
Q_CORE_EXPORT QT_DEPRECATED_VERSION_X_6_15(text)
#endif
-class
-QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaAssociation::Iterable::Iterator instead.")
-QAssociativeIterator : public QIterator<QMetaAssociation>
+// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header
+class QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaAssociation's iterables and iterators instead.") QAssociativeIterator : public QIterator<QMetaAssociation>
{
public:
using key_type = QVariant;
@@ -42,9 +41,8 @@ public:
QVariantPointer<QAssociativeIterator> operator->() const;
};
-class
-QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaAssociation::Iterable::ConstIterator instead.")
-QAssociativeConstIterator : public QConstIterator<QMetaAssociation>
+// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header
+class QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaAssociation's iterables and iterators instead.") QAssociativeConstIterator : public QConstIterator<QMetaAssociation>
{
public:
using key_type = QVariant;
@@ -63,9 +61,8 @@ public:
QVariantConstPointer operator->() const;
};
-class
-QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaAssociation::Iterable instead.")
-QAssociativeIterable : public QIterable<QMetaAssociation>
+// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header
+class QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaAssociation's iterables and iterators instead.") QAssociativeIterable : public QIterable<QMetaAssociation>
{
public:
using iterator = QTaggedIterator<QAssociativeIterator, void>;
diff --git a/src/corelib/kernel/qsequentialiterable.h b/src/corelib/kernel/qsequentialiterable.h
index 76908bdae4b..b2e690ea9cf 100644
--- a/src/corelib/kernel/qsequentialiterable.h
+++ b/src/corelib/kernel/qsequentialiterable.h
@@ -21,9 +21,8 @@ QT_WARNING_DISABLE_DEPRECATED
Q_CORE_EXPORT QT_DEPRECATED_VERSION_X_6_15(text)
#endif
-class
-QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaSequence::Iterable::Iterator instead.")
-QSequentialIterator : public QIterator<QMetaSequence>
+// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header
+class QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaSequence's iterables and iterators instead.") QSequentialIterator : public QIterator<QMetaSequence>
{
public:
using value_type = QVariant;
@@ -38,9 +37,8 @@ public:
QVariantPointer<QSequentialIterator> operator->() const;
};
-class
-QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaSequence::Iterable::ConstIterator instead.")
-QSequentialConstIterator : public QConstIterator<QMetaSequence>
+// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header
+class QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaSequence's iterables and iterators instead.") QSequentialConstIterator : public QConstIterator<QMetaSequence>
{
public:
using value_type = QVariant;
@@ -55,9 +53,8 @@ public:
QVariantConstPointer operator->() const;
};
-class
-QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaSequence::Iterable instead.")
-QSequentialIterable : public QIterable<QMetaSequence>
+// Keep this a single long line, otherwise syncqt doesn't create a class forwarding header
+class QT_CORE_DEPRECATED_EXPORT_VERSION_X_6_15("Use QMetaSequence's iterables and iterators instead.") QSequentialIterable : public QIterable<QMetaSequence>
{
public:
using iterator = QTaggedIterator<QSequentialIterator, void>;
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 9459e8bdfd3..f96f154f5b1 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -4035,10 +4035,13 @@ void QWindowsWindow::requestUpdate()
// the Posted event on the GUI thread.
if (m_vsyncUpdatePending.testAndSetAcquire(UpdateState::Requested, UpdateState::Posted)) {
QWindowsWindow *oldSelf = this;
- QMetaObject::invokeMethod(w, [w, oldSelf] {
+ qsizetype oldCallbackId = m_vsyncServiceCallbackId;
+ QMetaObject::invokeMethod(w, [w, oldSelf, oldCallbackId] {
// 'oldSelf' is only used for comparison, don't access it directly!
auto *self = static_cast<QWindowsWindow *>(w->handle());
- if (self && self == oldSelf) {
+ // NOTE: In the off chance that the window got destroyed and recreated with the
+ // same address, we also check that the callback id is the same.
+ if (self && self == oldSelf && self->m_vsyncServiceCallbackId == oldCallbackId) {
// The platform window is still alive
self->m_vsyncUpdatePending.storeRelease(UpdateState::Ready);
self->deliverUpdateRequest();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index e2f181aa628..2ea3fe38e1c 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -596,6 +596,16 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
*pRetVal = QComVariant{ accessible->text(QAccessible::Help) }.release();
break;
case UIA_HasKeyboardFocusPropertyId:
+ // If the top-level window has no focused child, report the top-level
+ // widget (window). If it already has a focused widget, it will be
+ // reported automatically.
+ if (topLevelWindow) {
+ QAccessibleInterface *focusacc = accessible->focusChild();
+ if (!focusacc) {
+ *pRetVal = QComVariant{ accessible->state().active ? true : false }.release();
+ break;
+ }
+ }
*pRetVal = QComVariant{ accessible->state().focused ? true : false }.release();
break;
case UIA_IsKeyboardFocusablePropertyId:
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index 431f91d5474..10bb63040c8 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -181,16 +181,16 @@ inline bool qCompare(quint32 const &t1, quint64 const &t2, const char *actual,
}
namespace Internal {
-template <typename T, typename = void>
-struct HasInitMain : std::false_type{};
+template <typename T>
+using InitMainTest = decltype(&T::initMain);
template <typename T>
-struct HasInitMain<T, std::void_t<decltype(&T::initMain)>> : std::true_type {};
+constexpr inline bool hasInitMain = qxp::is_detected_v<InitMainTest, T>;
template<typename T>
void callInitMain()
{
- if constexpr (HasInitMain<T>::value)
+ if constexpr (hasInitMain<T>)
T::initMain();
}
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 570566793dc..0f0496ad04d 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -1622,12 +1622,6 @@ void QTreeViewPrivate::calcLogicalIndices(
const auto indicesCount = logicalIndices->size();
itemPositions->resize(indicesCount);
for (qsizetype currentLogicalSection = 0; currentLogicalSection < indicesCount; ++currentLogicalSection) {
- // shortcut, no need to calc anything more
- if (indicesCount == 1 || spanning) {
- (*itemPositions)[currentLogicalSection] = QStyleOptionViewItem::OnlyOne;
- continue;
- }
- const int headerSection = logicalIndices->at(currentLogicalSection);
// determine the viewItemPosition depending on the position of column 0
int nextLogicalSection = currentLogicalSection + 1 >= indicesCount
? logicalIndexAfterRight
@@ -1635,8 +1629,11 @@ void QTreeViewPrivate::calcLogicalIndices(
int prevLogicalSection = currentLogicalSection - 1 < 0
? logicalIndexBeforeLeft
: logicalIndices->at(currentLogicalSection - 1);
+ const int headerSection = logicalIndices->at(currentLogicalSection);
QStyleOptionViewItem::ViewItemPosition pos;
- if ((nextLogicalSection != 0 && prevLogicalSection == -1) || isTreePosition(headerSection))
+ if ((nextLogicalSection == -1 && prevLogicalSection == -1) || spanning) {
+ pos = QStyleOptionViewItem::OnlyOne;
+ } else if ((nextLogicalSection != 0 && prevLogicalSection == -1) || isTreePosition(headerSection))
pos = QStyleOptionViewItem::Beginning;
else if (nextLogicalSection == 0 || nextLogicalSection == -1)
pos = QStyleOptionViewItem::End;
diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp
index e9de82d2357..314d82fd64f 100644
--- a/src/widgets/kernel/qstandardgestures.cpp
+++ b/src/widgets/kernel/qstandardgestures.cpp
@@ -348,8 +348,14 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state,
result = QGestureRecognizer::Ignore;
break;
case QSwipeGesturePrivate::ThreePointsReached:
- result = (ev->touchPointStates() & QEventPoint::State::Pressed)
- ? QGestureRecognizer::CancelGesture : QGestureRecognizer::Ignore;
+ if (ev->touchPointStates() & QEventPoint::State::Pressed) {
+ result = QGestureRecognizer::CancelGesture;
+ } else if (d->verticalDirection != QSwipeGesture::NoDirection ||
+ d->horizontalDirection != QSwipeGesture::NoDirection) {
+ result = QGestureRecognizer::TriggerGesture;
+ } else {
+ result = QGestureRecognizer::Ignore;
+ }
break;
}
}
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
index ac50a5cdae7..e42fb4419a8 100644
--- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -3518,12 +3518,33 @@ void tst_QTreeView::styleOptionViewItem()
model.clear();
model.appendRow({ new QStandardItem("Hidden"),
new QStandardItem("OnlyOne Last") });
+ view.setModel(&model);
view.setColumnHidden(0, true);
view.setColumnHidden(1, false);
- view.setModel(&model);
delegate.count = 0;
QTRY_COMPARE_GE(delegate.count, 1);
+
+ // special case, four columns, only one is updated but
+ // calcLogicalIndices() returns the correct value
+ {
+ model.clear();
+ model.appendRow({ new QStandardItem("Hidden"),
+ new QStandardItem("Beginning Last"),
+ new QStandardItem("Middle Last"),
+ new QStandardItem("End Last") });
+ view.setColumnHidden(0, true);
+ delegate.count = 0;
+ QTRY_COMPARE_GE(delegate.count, 4);
+
+ // do not rely on paintEvent() as this might redraw a bigger
+ // rect than we expect
+ QList<int> logicalIndices;
+ QList<QStyleOptionViewItem::ViewItemPosition> itemPositions;
+ view.d_func()->calcLogicalIndices(&logicalIndices, &itemPositions, 3, 3);
+ QCOMPARE(itemPositions.size(), 1);
+ QCOMPARE(itemPositions.at(0), QStyleOptionViewItem::End);
+ }
}
class task174627_TreeView : public QTreeView
diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
index febb9e2c9dc..255bcaa5bec 100644
--- a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
+++ b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
@@ -9,11 +9,14 @@
#include <QtGui/QScreen>
#include <QtGui/QPointingDevice>
#include <QtCore/QList>
+#include <QtCore/QLoggingCategory>
#include <QtCore/QString>
#include <QtCore/QHash>
#include <QtCore/QDebug>
#include <memory>
+Q_LOGGING_CATEGORY(lcTests, "qt.widgets.tests")
+
class tst_QGestureRecognizer : public QObject
{
Q_OBJECT
@@ -60,14 +63,30 @@ public:
bool gestureReceived(Qt::GestureType gestureType) const
{ return m_receivedGestures.value(gestureType); }
-protected:
- bool event(QEvent * event) override;
+ void clearReceivedGestures();
-private:
- typedef QHash<Qt::GestureType, bool> GestureTypeHash;
- GestureTypeHash m_receivedGestures;
+ qreal lastSwipeAngle = 0;
+ QSwipeGesture::SwipeDirection lastHorizontalDirection = QSwipeGesture::NoDirection;
+ QSwipeGesture::SwipeDirection lastVerticalDirection = QSwipeGesture::NoDirection;
+ Qt::GestureState lastSwipeState = Qt::NoGesture;
+
+ protected:
+ bool event(QEvent *event) override;
+
+ private:
+ typedef QHash<Qt::GestureType, bool> GestureTypeHash;
+ GestureTypeHash m_receivedGestures;
};
+void TestWidget::clearReceivedGestures()
+{
+ m_receivedGestures.clear();
+ lastSwipeAngle = {};
+ lastHorizontalDirection = QSwipeGesture::NoDirection;
+ lastVerticalDirection = QSwipeGesture::NoDirection;
+ lastSwipeState = Qt::NoGesture;
+}
+
TestWidget::TestWidget(const GestureTypeVector &gestureTypes)
{
setAttribute(Qt::WA_AcceptTouchEvents);
@@ -95,8 +114,22 @@ bool TestWidget::event(QEvent * event)
it.value() = true;
}
}
- }
+ for (const QGesture *gesture : gestureEvent->activeGestures()) {
+ switch (gesture->gestureType()) {
+ case Qt::SwipeGesture: {
+ const auto *swipe = static_cast<const QSwipeGesture *>(gesture);
+ lastSwipeAngle = swipe->swipeAngle();
+ lastHorizontalDirection = swipe->horizontalDirection();
+ lastVerticalDirection = swipe->verticalDirection();
+ lastSwipeState = gesture->state();
+ break;
+ }
+ default:
+ break;
+ }
+ }
break;
+ }
default:
break;
}
@@ -241,10 +274,26 @@ enum SwipeSubTest {
void tst_QGestureRecognizer::swipeGesture_data()
{
QTest::addColumn<int>("swipeSubTest");
+ QTest::addColumn<QPoint>("moveDelta");
QTest::addColumn<bool>("gestureExpected");
- QTest::newRow("Line") << int(SwipeLineSubTest) << true;
- QTest::newRow("DirectionChange") << int(SwipeDirectionChangeSubTest) << false;
- QTest::newRow("SmallDirectionChange") << int(SwipeSmallDirectionChangeSubTest) << true;
+ QTest::addColumn<int>("expectedAngle");
+ QTest::addColumn<QSwipeGesture::SwipeDirection>("expectedHorizontalDirection");
+ QTest::addColumn<QSwipeGesture::SwipeDirection>("expectedVerticalDirection");
+
+ QTest::newRow("UpRight Line") << int(SwipeLineSubTest) << QPoint(42, -25)
+ << true << 30 << QSwipeGesture::Right << QSwipeGesture::Up;
+ QTest::newRow("DownRight Line") << int(SwipeLineSubTest) << QPoint(42, 25)
+ << true << 329 << QSwipeGesture::Right << QSwipeGesture::Down;
+ QTest::newRow("OutRight Line") << int(SwipeLineSubTest) << QPoint(42, 0)
+ << true << 360 << QSwipeGesture::Right << QSwipeGesture::NoDirection;
+ QTest::newRow("DownLeft Line") << int(SwipeLineSubTest) << QPoint(-42, 25)
+ << true << 211 << QSwipeGesture::Left << QSwipeGesture::Down;
+ QTest::newRow("Up Line") << int(SwipeLineSubTest) << QPoint(0, -25)
+ << true << 90 << QSwipeGesture::NoDirection << QSwipeGesture::Up;
+ QTest::newRow("DirectionChange") << int(SwipeDirectionChangeSubTest) << QPoint(42, 25)
+ << false << 0 << QSwipeGesture::NoDirection << QSwipeGesture::NoDirection;
+ QTest::newRow("SmallDirectionChange") << int(SwipeSmallDirectionChangeSubTest) << QPoint(42, -25)
+ << true << 359 << QSwipeGesture::Right << QSwipeGesture::Down;
}
void tst_QGestureRecognizer::swipeGesture()
@@ -252,7 +301,11 @@ void tst_QGestureRecognizer::swipeGesture()
enum { swipePoints = 3 };
QFETCH(int, swipeSubTest);
+ QFETCH(QPoint, moveDelta);
QFETCH(bool, gestureExpected);
+ QFETCH(int, expectedAngle);
+ QFETCH(QSwipeGesture::SwipeDirection, expectedHorizontalDirection);
+ QFETCH(QSwipeGesture::SwipeDirection, expectedVerticalDirection);
const Qt::GestureType gestureType = Qt::SwipeGesture;
TestWidget widget(GestureTypeVector(1, gestureType));
@@ -264,20 +317,27 @@ void tst_QGestureRecognizer::swipeGesture()
// Start a swipe sequence with 2 points (QTBUG-15768)
const QPoint fingerDistance(m_fingerDistance, m_fingerDistance);
QList<QPoint> points;
- for (int i = 0; i < swipePoints - 1; ++i)
+ for (int i = 1; i < swipePoints; ++i)
points.append(fingerDistance + i * fingerDistance);
QTest::QTouchEventWidgetSequence swipeSequence = QTest::touchEvent(&widget, m_touchDevice.get());
pressSequence(swipeSequence, points, &widget);
+ // Move a little: nothing happens
+ points[0] += {1, 1};
+ points[1] += {1, 1};
+ swipeSequence.move(0, points[0], &widget).move(1, points[1], &widget).commit();
+ QCoreApplication::processEvents();
+ QVERIFY(!widget.gestureReceived(gestureType));
+
// Press point #3
points.append(points.last() + fingerDistance);
swipeSequence.stationary(0).stationary(1).press(points.size() - 1, points.last(), &widget);
swipeSequence.commit();
Q_ASSERT(points.size() == swipePoints);
+ QCOMPARE(widget.lastSwipeState, Qt::NoGesture);
// Move.
- const QPoint moveDelta(60, 20);
switch (swipeSubTest) {
case SwipeLineSubTest:
linearSequence(5, moveDelta, swipeSequence, points, &widget);
@@ -294,15 +354,37 @@ void tst_QGestureRecognizer::swipeGesture()
}
break;
}
+ QCOMPARE(widget.lastSwipeState, Qt::GestureUpdated);
- releaseSequence(swipeSequence, points, &widget);
-
+ // release any point: the gesture ends
+ swipeSequence.release(0, points[0], &widget).commit();
if (gestureExpected) {
QTRY_VERIFY(widget.gestureReceived(gestureType));
+ qCDebug(lcTests) << "started @" << fingerDistance
+ << "; ended with angle" << widget.lastSwipeAngle
+ << "expected" << expectedAngle
+ << "dirns" << widget.lastHorizontalDirection << widget.lastVerticalDirection;
+ QCOMPARE(qRound(widget.lastSwipeAngle), expectedAngle);
+ QEXPECT_FAIL("Up Line", "90 degrees (up) should be NoDirection on horizontal axis", Continue);
+ QCOMPARE(widget.lastHorizontalDirection, expectedHorizontalDirection);
+ QEXPECT_FAIL("OutRight Line", "0 degrees (to the right) should be NoDirection on the vertical axis", Continue);
+ QCOMPARE(widget.lastVerticalDirection, expectedVerticalDirection);
+ QCOMPARE(widget.lastSwipeState, Qt::GestureFinished);
} else {
QCoreApplication::processEvents();
QVERIFY(!widget.gestureReceived(gestureType));
+ QCOMPARE(widget.lastSwipeState, Qt::GestureUpdated);
}
+
+ // move the others a little, then release: no further swipe (it needs 3 fingers)
+ widget.clearReceivedGestures();
+ points[1] += {1, 1};
+ points[2] += {1, 1};
+ swipeSequence.move(1, points[1], &widget).move(2, points[2], &widget).commit();
+ swipeSequence.release(1, points[1], &widget).release(2, points[2], &widget).commit();
+ QCoreApplication::processEvents();
+ QVERIFY(!widget.gestureReceived(gestureType));
+ QCOMPARE(widget.lastSwipeState, Qt::NoGesture);
}
void tst_QGestureRecognizer::touchReplay()