diff options
Diffstat (limited to 'src/corelib/kernel/qeventdispatcher_win.cpp')
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win.cpp | 67 |
1 files changed, 41 insertions, 26 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 0952464f53..b7fe1557d3 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -53,6 +53,7 @@ #include "qcoreapplication_p.h" #include <private/qthread_p.h> #include <private/qmutexpool_p.h> +#include <private/qwineventnotifier_p.h> QT_BEGIN_NAMESPACE @@ -96,13 +97,14 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA QEventDispatcherWin32Private::QEventDispatcherWin32Private() : threadId(GetCurrentThreadId()), interrupt(false), closingDown(false), internalHwnd(0), getMessageHook(0), serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0), - wakeUps(0) - , activateNotifiersPosted(false) + wakeUps(0), activateNotifiersPosted(false), winEventNotifierActivatedEvent(NULL) { } QEventDispatcherWin32Private::~QEventDispatcherWin32Private() { + if (winEventNotifierActivatedEvent) + CloseHandle(winEventNotifierActivatedEvent); if (internalHwnd) DestroyWindow(internalHwnd); } @@ -537,12 +539,14 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) bool needWM_QT_SENDPOSTEDEVENTS = false; do { DWORD waitRet = 0; - HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1]; + DWORD nCount = 0; + HANDLE *pHandles = nullptr; + if (d->winEventNotifierActivatedEvent) { + nCount = 1; + pHandles = &d->winEventNotifierActivatedEvent; + } QVarLengthArray<MSG> processedTimers; while (!d->interrupt) { - DWORD nCount = d->winEventNotifierList.count(); - Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1); - MSG msg; bool haveMessage; @@ -584,8 +588,6 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) } if (!haveMessage) { // no message - check for signalled objects - for (int i=0; i<(int)nCount; i++) - pHandles[i] = d->winEventNotifierList.at(i)->handle(); waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, 0, QS_ALLINPUT, MWMO_ALERTABLE); if ((haveMessage = (waitRet == WAIT_OBJECT_0 + nCount))) { // a new message has arrived, process it @@ -626,7 +628,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) DispatchMessage(&msg); } } else if (waitRet - WAIT_OBJECT_0 < nCount) { - d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0)); + activateEventNotifiers(); } else { // nothing todo so break break; @@ -639,16 +641,11 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) && !d->interrupt && (flags & QEventLoop::WaitForMoreEvents)); if (canWait) { - DWORD nCount = d->winEventNotifierList.count(); - Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1); - for (int i=0; i<(int)nCount; i++) - pHandles[i] = d->winEventNotifierList.at(i)->handle(); - emit aboutToBlock(); waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE); emit awake(); if (waitRet - WAIT_OBJECT_0 < nCount) { - d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0)); + activateEventNotifiers(); retVal = true; } } @@ -906,12 +903,12 @@ bool QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier) if (d->winEventNotifierList.contains(notifier)) return true; - if (d->winEventNotifierList.count() >= MAXIMUM_WAIT_OBJECTS - 2) { - qWarning("QWinEventNotifier: Cannot have more than %d enabled at one time", MAXIMUM_WAIT_OBJECTS - 2); - return false; - } d->winEventNotifierList.append(notifier); - return true; + + if (!d->winEventNotifierActivatedEvent) + d->winEventNotifierActivatedEvent = CreateEvent(0, TRUE, FALSE, nullptr); + + return QWinEventNotifierPrivate::get(notifier)->registerWaitObject(); } void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier) @@ -927,17 +924,35 @@ void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier) Q_D(QEventDispatcherWin32); int i = d->winEventNotifierList.indexOf(notifier); - if (i != -1) - d->winEventNotifierList.takeAt(i); + if (i == -1) + return; + d->winEventNotifierList.takeAt(i); + QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier); + if (nd->waitHandle) + nd->unregisterWaitObject(); } void QEventDispatcherWin32::activateEventNotifiers() { Q_D(QEventDispatcherWin32); - //### this could break if events are removed/added in the activation - for (int i=0; i<d->winEventNotifierList.count(); i++) { - if (WaitForSingleObjectEx(d->winEventNotifierList.at(i)->handle(), 0, TRUE) == WAIT_OBJECT_0) - d->activateEventNotifier(d->winEventNotifierList.at(i)); + ResetEvent(d->winEventNotifierActivatedEvent); + + // Iterate backwards, because the notifier might remove itself on activate(). + for (int i = d->winEventNotifierList.count(); --i >= 0;) { + QWinEventNotifier *notifier = d->winEventNotifierList.at(i); + QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier); + if (WaitForSingleObject(nd->handleToEvent, 0) == WAIT_OBJECT_0) { + nd->unregisterWaitObject(); + d->activateEventNotifier(notifier); + } + } + + // Re-register the remaining activated notifiers. + for (int i = 0; i < d->winEventNotifierList.count(); ++i) { + QWinEventNotifier *notifier = d->winEventNotifierList.at(i); + QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier); + if (!nd->waitHandle) + nd->registerWaitObject(); } } |