From 7199498fb9cbfb5afc043ddb0e630c8ffad5240b Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Tue, 7 Mar 2023 14:44:14 +0100 Subject: [PATCH] QPushButton: use QMenu::popup instead of exec to show menu QMenu::exec opens a blocking loop, which is problematic for webassembly. Replace with QMenu::popup, and reset the down-state of the button when the menu is about to hide. QMenu emits aboutToHide immediately before existing the event loop in the hideEvent override, so the timing is the same. Change-Id: Iccb418d10fcb25f6ad1f73f9cdce6ea6581bd73b Reviewed-by: Qt CI Bot Reviewed-by: Richard Moe Gustavsen --- src/widgets/widgets/qpushbutton.cpp | 11 ++++------- tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp | 8 ++++++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp index ec882db1756..74ec79fae2c 100644 --- a/src/widgets/widgets/qpushbutton.cpp +++ b/src/widgets/widgets/qpushbutton.cpp @@ -575,17 +575,14 @@ void QPushButtonPrivate::_q_popupPressed() QPoint menuPos = adjustedMenuPosition(); - QPointer guard(q); - QMenuPrivate::get(menu)->causedPopup.widget = guard; + QMenuPrivate::get(menu)->causedPopup.widget = q; //Because of a delay in menu effects, we must keep track of the //menu visibility to avoid flicker on button release menuOpen = true; - menu->exec(menuPos); - if (guard) { - menuOpen = false; - q->setDown(false); - } + QObject::connect(menu, &QMenu::aboutToHide, + q, [q]{ q->setDown(false); }, Qt::SingleShotConnection); + menu->popup(menuPos); } QPoint QPushButtonPrivate::adjustedMenuPosition() diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index 73cdbe87fe2..fb0058e3fe3 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -1143,14 +1143,18 @@ void tst_QMenu::pushButtonPopulateOnAboutToShow() QSKIP("Your window manager won't allow a window against the bottom of the screen"); } - QTimer::singleShot(300, buttonMenu, SLOT(hide())); QTest::mouseClick(&b, Qt::LeftButton, Qt::NoModifier, b.rect().center()); + QVERIFY(QTest::qWaitForWindowExposed(buttonMenu)); + QTest::qWait(300); + buttonMenu->hide(); QVERIFY2(!buttonMenu->geometry().intersects(b.geometry()), msgGeometryIntersects(buttonMenu->geometry(), b.geometry())); // note: we're assuming that, if we previously got the desired geometry, we'll get it here too b.move(10, screen.bottom()-buttonMenu->height()-5); - QTimer::singleShot(300, buttonMenu, SLOT(hide())); QTest::mouseClick(&b, Qt::LeftButton, Qt::NoModifier, b.rect().center()); + QVERIFY(QTest::qWaitForWindowExposed(buttonMenu)); + QTest::qWait(300); + buttonMenu->hide(); QVERIFY2(!buttonMenu->geometry().intersects(b.geometry()), msgGeometryIntersects(buttonMenu->geometry(), b.geometry())); }