diff options
author | Alex Trotsenko <alex1973tr@gmail.com> | 2019-11-16 20:39:20 +0200 |
---|---|---|
committer | Alex Trotsenko <alex1973tr@gmail.com> | 2020-07-29 18:34:34 +0300 |
commit | 8969070cfdeab4502a693bdf46a572cbea50bab3 (patch) | |
tree | 32b145683044e02725a16cb6adba57d7d4346643 /tests | |
parent | 9d55d6b45bfc1f4e3c603bcc95f694ebe3a9206f (diff) |
QEventDispatcherWin32: redesign event notifiers activation
The previous implementation multiplexed callback-based event
notification into a single proxy event (cf. 85403d0af), which was
in turn object-waited for (this was the case since the beginning
of public qt history). It makes more sense to multiplex into a
posted message, because that also works with foreign event loops
that do not know anything about our event objects.
Task-number: QTBUG-64443
Change-Id: I97945ac8b5d7c8582701077134c0aef4f3b5a18f
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp b/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp index 5fd7079a6a..6f2ed47b72 100644 --- a/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp +++ b/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp @@ -37,6 +37,7 @@ #include <QtNetwork/qtcpsocket.h> #include <QtCore/qelapsedtimer.h> #include <QtCore/qtimer.h> +#include <QtCore/qwineventnotifier.h> #include <QtCore/qt_windows.h> @@ -50,6 +51,8 @@ class tst_NoQtEventLoop : public QObject private slots: void consumeMouseEvents(); void consumeSocketEvents(); + void consumeWinEvents_data(); + void consumeWinEvents(); void deliverEventsInLivelock(); void postingWithNoYieldFlag(); }; @@ -314,6 +317,86 @@ void tst_NoQtEventLoop::consumeSocketEvents() QVERIFY(server.hasPendingConnections()); } +void tst_NoQtEventLoop::consumeWinEvents_data() +{ + QTest::addColumn<bool>("peeking"); + QTest::addColumn<bool>("nestedLoops"); + QTest::addColumn<bool>("nativeMainLoop"); + + QTest::newRow("PeekMessage, single loop") << true << false << true; + QTest::newRow("GetMessage, single loop") << false << false << true; + + QTest::newRow("PeekMessage, nested loops") << true << true << true; + QTest::newRow("GetMessage, nested loops") << false << true << true; + QTest::newRow("PeekMessage, nested loops, Qt main loop") << true << true << false; + QTest::newRow("GetMessage, nested loops, Qt main loop") << false << true << false; +} + +void tst_NoQtEventLoop::consumeWinEvents() +{ + QFETCH(bool, peeking); + QFETCH(bool, nestedLoops); + QFETCH(bool, nativeMainLoop); + int argc = 1; + char *argv[] = { const_cast<char *>("test"), 0 }; + QGuiApplication app(argc, argv); + + HANDLE winEvent = ::CreateEvent(0, FALSE, FALSE, 0); + QVERIFY(winEvent != NULL); + bool notifierActivated = false; + QWinEventNotifier notifier(winEvent); + connect(¬ifier, &QWinEventNotifier::activated, [¬ifierActivated]() { + notifierActivated = true; + }); + + bool timeExpired = false; + QTimer expiredTimer; + connect(&expiredTimer, &QTimer::timeout, [&timeExpired]() { + timeExpired = true; + }); + expiredTimer.start(3000); + + auto runNativeEventLoop = [&timeExpired, ¬ifierActivated, peeking]() -> void { + MSG msg; + while (!(timeExpired || notifierActivated)) { + if (peeking) { + if (!::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + QThread::msleep(100); + continue; + } + } else { + if (::GetMessage(&msg, NULL, 0, 0) <= 0) + break; + } + + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + }; + + QTimer::singleShot(0, [winEvent, nestedLoops, runNativeEventLoop]() { + ::SetEvent(winEvent); + if (nestedLoops) + runNativeEventLoop(); + }); + + // Exec main message loop + if (nativeMainLoop) { + runNativeEventLoop(); + } else { + QEventLoop loop; + connect(¬ifier, &QWinEventNotifier::activated, + &loop, &QEventLoop::quit); + connect(&expiredTimer, &QTimer::timeout, + &loop, &QEventLoop::quit); + + loop.exec(); + } + + QVERIFY(notifierActivated); + QVERIFY(!timeExpired); +} + void tst_NoQtEventLoop::deliverEventsInLivelock() { int argc = 1; |