Fix tst_gestures flakiness on XCB

X11 spawns painting threads and sends an expose event at the same time.
While the worker is still paining, QXcbScreen::topLevelAt() may not
find the window, even if it reports being exposed.

Wait until windows are exposed and painted.
Remove workaround to intercept warnings about undeliverable gestures.
Remove qWait() antipattern.

Fixes: QTBUG-130811
Fixes: QTBUG-84258
Fixes: QTBUG-69648
Fixes: QTBUG-67393
Fixes: QTBUG-67392
Fixes: QTBUG-67389
Fixes: QTBUG-68861
Fixes: QTBUG-70224
Fixes: QTBUG-70223
Fixes: QTBUG-67395
Fixes: QTBUG-70227
Fixes: QTBUG-70226
Fixes: QTBUG-70209
Fixes: QTBUG-70153
Pick-to: 6.5
Change-Id: Id126fe884ba360551425f3e2b29674f5b9419fff
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 705bac063cc5ec535ff5467a208d5653555ae8f9)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Axel Spoerl 2024-11-14 11:00:28 +01:00 committed by Qt Cherry-pick Bot
parent d0ff36878d
commit d952be28ff

View File

@ -322,6 +322,7 @@ private slots:
void testReuseCanceledGestures(); void testReuseCanceledGestures();
void bug_13501_gesture_not_accepted(); void bug_13501_gesture_not_accepted();
private: private:
bool waitForWindowPainted(QWidget *wid) const;
QPoint m_availableTopLeft; QPoint m_availableTopLeft;
}; };
@ -347,30 +348,34 @@ void tst_Gestures::cleanup()
QGestureRecognizer::unregisterRecognizer(CustomGesture::GestureType); QGestureRecognizer::unregisterRecognizer(CustomGesture::GestureType);
} }
static QtMessageHandler originalMessageHandler = nullptr; bool tst_Gestures::waitForWindowPainted(QWidget *wid) const
static bool skipCustomGesture = false;
static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &text)
{ {
if (type == QtMsgType::QtWarningMsg && text == "QGestureManager::deliverEvent: could not find the target for gesture") #ifdef Q_OS_LINUX
skipCustomGesture = true; if (!QTest::qWaitForWindowExposed(wid))
originalMessageHandler(type, context, text); return false;
if (!QGuiApplication::platformName().contains("xcb"))
return true;
return QTest::qWaitFor([wid]{ return QApplication::topLevelAt(wid->geometry().center()) == wid; });
#else
return QTest::qWaitForWindowExposed(wid);
#endif
} }
#define CHECK_EXPOSED(widget) QVERIFY(waitForWindowPainted(widget))
void tst_Gestures::customGesture() void tst_Gestures::customGesture()
{ {
originalMessageHandler = qInstallMessageHandler(messageHandler);
auto guard = qScopeGuard([](){ qInstallMessageHandler(originalMessageHandler); });
GestureWidget widget; GestureWidget widget;
widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
widget.show(); widget.show();
QVERIFY(QTest::qWaitForWindowActive(&widget)); CHECK_EXPOSED(&widget);
CustomEvent event; CustomEvent event;
event.hotSpot = widget.mapToGlobal(QPoint(5,5)); event.hotSpot = widget.mapToGlobal(QPoint(5,5));
event.hasHotSpot = true; event.hasHotSpot = true;
sendCustomGesture(&event, &widget); sendCustomGesture(&event, &widget);
if (skipCustomGesture)
QSKIP("QApplication unable to access test widget.");
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
@ -412,11 +417,10 @@ void tst_Gestures::autoCancelingGestures()
QApplication::sendEvent(&widget, &ev); QApplication::sendEvent(&widget, &ev);
} }
// wait long enough so the gesture manager will cancel the gesture // wait long enough so the gesture manager will cancel the gesture
QTest::qWait(5000); QTRY_COMPARE(widget.customEventsReceived, CustomGesture::SerialStartedThreshold - CustomGesture::SerialMaybeThreshold);
QCOMPARE(widget.customEventsReceived, CustomGesture::SerialStartedThreshold - CustomGesture::SerialMaybeThreshold); QTRY_COMPARE(widget.gestureEventsReceived, 0);
QCOMPARE(widget.gestureEventsReceived, 0); QTRY_COMPARE(widget.gestureOverrideEventsReceived, 0);
QCOMPARE(widget.gestureOverrideEventsReceived, 0); QTRY_COMPARE(widget.events.all.size(), 0);
QCOMPARE(widget.events.all.size(), 0);
} }
void tst_Gestures::gestureOverChild() void tst_Gestures::gestureOverChild()
@ -837,7 +841,7 @@ void tst_Gestures::graphicsItemGesture()
item->setPos(100, 100); item->setPos(100, 100);
view.show(); view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view)); CHECK_EXPOSED(&view);
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
item->grabGesture(CustomGesture::GestureType); item->grabGesture(CustomGesture::GestureType);
@ -900,7 +904,7 @@ void tst_Gestures::graphicsView()
item->setPos(100, 100); item->setPos(100, 100);
view.show(); view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view)); CHECK_EXPOSED(&view);
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
item->grabGesture(CustomGesture::GestureType); item->grabGesture(CustomGesture::GestureType);
@ -977,7 +981,7 @@ void tst_Gestures::graphicsItemTreeGesture()
item1_child2->setParentItem(item1); item1_child2->setParentItem(item1);
view.show(); view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view)); CHECK_EXPOSED(&view);
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
item1->grabGesture(CustomGesture::GestureType); item1->grabGesture(CustomGesture::GestureType);
@ -1035,7 +1039,7 @@ void tst_Gestures::explicitGraphicsObjectTarget()
item2_child1->setPos(10, 10); item2_child1->setPos(10, 10);
view.show(); view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view)); CHECK_EXPOSED(&view);
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
item1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); item1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
@ -1094,7 +1098,7 @@ void tst_Gestures::gestureOverChildGraphicsItem()
item2_child1->setPos(0, 0); item2_child1->setPos(0, 0);
view.show(); view.show();
QTRY_VERIFY(QTest::qWaitForWindowExposed(&view)); CHECK_EXPOSED(&view);
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
item1->grabGesture(CustomGesture::GestureType); item1->grabGesture(CustomGesture::GestureType);
@ -1395,7 +1399,7 @@ void tst_Gestures::testMapToScene()
item0->setPos(14, 16); item0->setPos(14, 16);
view.show(); // need to show to give it a global coordinate view.show(); // need to show to give it a global coordinate
QVERIFY(QTest::qWaitForWindowExposed(&view)); CHECK_EXPOSED(&view);
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
QPoint origin = view.mapToGlobal(QPoint()); QPoint origin = view.mapToGlobal(QPoint());
@ -1524,7 +1528,7 @@ void tst_Gestures::autoCancelGestures()
parent.grabGesture(CustomGesture::GestureType); parent.grabGesture(CustomGesture::GestureType);
child->grabGesture(secondGesture); child->grabGesture(secondGesture);
parent.show(); parent.show();
QVERIFY(QTest::qWaitForWindowExposed(&parent)); CHECK_EXPOSED(&parent);
/* /*
An event is sent to both the child and the parent, when the child gets it a gesture is triggered An event is sent to both the child and the parent, when the child gets it a gesture is triggered
@ -1588,7 +1592,7 @@ void tst_Gestures::autoCancelGestures2()
child->grabGesture(secondGesture); child->grabGesture(secondGesture);
view.show(); view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view)); CHECK_EXPOSED(&view);
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
CustomEvent event; CustomEvent event;
@ -1635,7 +1639,7 @@ void tst_Gestures::graphicsViewParentPropagation()
item1_c1_c1->setPos(0, 0); item1_c1_c1->setPos(0, 0);
view.show(); view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view)); CHECK_EXPOSED(&view);
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
item0->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent); item0->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
@ -1706,8 +1710,8 @@ void tst_Gestures::panelPropagation()
item1_child1_child1->setZValue(10); item1_child1_child1->setZValue(10);
view.show(); view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
CHECK_EXPOSED(&view);
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
@ -1818,8 +1822,8 @@ void tst_Gestures::panelStacksBehindParent()
panel->setZValue(5); panel->setZValue(5);
view.show(); view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
CHECK_EXPOSED(&view);
static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
@ -1927,7 +1931,7 @@ void tst_Gestures::deleteGestureTargetItem()
items.insert(item2->objectName(), item2); items.insert(item2->objectName(), item2);
view.show(); view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view)); CHECK_EXPOSED(&view);
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
if (propagateUpdateGesture) if (propagateUpdateGesture)
@ -1972,7 +1976,7 @@ void tst_Gestures::viewportCoordinates()
scene.addItem(item1); scene.addItem(item1);
view.show(); view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view)); CHECK_EXPOSED(&view);
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
CustomEvent event; CustomEvent event;
@ -2010,7 +2014,7 @@ void tst_Gestures::partialGesturePropagation()
scene.addItem(item4); scene.addItem(item4);
view.show(); view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view)); CHECK_EXPOSED(&view);
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
item1->ignoredUpdatedGestures << CustomGesture::GestureType; item1->ignoredUpdatedGestures << CustomGesture::GestureType;
@ -2233,7 +2237,7 @@ void tst_Gestures::testReuseCanceledGestures()
gv->viewport()->grabGesture(tapGestureTypeId); gv->viewport()->grabGesture(tapGestureTypeId);
mw.show(); mw.show();
QVERIFY(QTest::qWaitForWindowExposed(&mw)); CHECK_EXPOSED(&mw);
QPoint targetPos(gv->mapFromScene(target->mapToScene(target->rect().center()))); QPoint targetPos(gv->mapFromScene(target->mapToScene(target->rect().center())));
targetPos = gv->viewport()->mapFromParent(targetPos); targetPos = gv->viewport()->mapFromParent(targetPos);
@ -2287,7 +2291,7 @@ void tst_Gestures::conflictingGesturesInGraphicsView()
view.setWindowFlags(Qt::X11BypassWindowManagerHint); view.setWindowFlags(Qt::X11BypassWindowManagerHint);
view.show(); view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view)); CHECK_EXPOSED(&view);
view.ensureVisible(scene.sceneRect()); view.ensureVisible(scene.sceneRect());
const QRectF gestureRect(0, 0, view.width() * 0.9, view.height() * 0.9); const QRectF gestureRect(0, 0, view.width() * 0.9, view.height() * 0.9);
@ -2366,11 +2370,12 @@ void tst_Gestures::bug_13501_gesture_not_accepted()
NoConsumeWidgetBug13501 w; NoConsumeWidgetBug13501 w;
w.grabGesture(Qt::TapGesture); w.grabGesture(Qt::TapGesture);
w.show(); w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w)); CHECK_EXPOSED(&w);
//QTest::mousePress(&ignoreEvent, Qt::LeftButton); //QTest::mousePress(&ignoreEvent, Qt::LeftButton);
QPointingDevice *device = QTest::createTouchDevice(); QPointingDevice *device = QTest::createTouchDevice();
QTest::touchEvent(&w, device).press(0, QPoint(10, 10), &w); QTest::touchEvent(&w, device).press(0, QPoint(10, 10), &w);
} }
#undef CHECK_EXPOSED
QTEST_MAIN(tst_Gestures) QTEST_MAIN(tst_Gestures)
#include "tst_gestures.moc" #include "tst_gestures.moc"