diff options
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qabstracteventdispatcher.cpp | 24 | ||||
-rw-r--r-- | src/corelib/kernel/qabstracteventdispatcher.h | 9 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win.cpp | 102 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win_p.h | 13 | ||||
-rw-r--r-- | src/corelib/kernel/qwineventnotifier.cpp | 58 | ||||
-rw-r--r-- | src/corelib/kernel/qwineventnotifier_p.h | 6 |
6 files changed, 34 insertions, 178 deletions
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index b6947dc7dc..358a59d05b 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -460,30 +460,6 @@ bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, vo return false; } -/*! \fn bool QAbstractEventDispatcher::registerEventNotifier(QWinEventNotifier *notifier) - - This pure virtual method exists on windows only and has to be reimplemented by a Windows specific - event dispatcher implementation. \a notifier is the QWinEventNotifier instance to be registered. - - The method should return true if the registration of \a notifier was successful, otherwise false. - - QWinEventNotifier calls this method in it's constructor and there should never be a need to call this - method directly. - - \sa QWinEventNotifier, unregisterEventNotifier() -*/ - -/*! \fn bool QAbstractEventDispatcher::unregisterEventNotifier(QWinEventNotifier *notifier) - - This pure virtual method exists on windows only and has to be reimplemented by a Windows specific - event dispatcher implementation. \a notifier is the QWinEventNotifier instance to be unregistered. - - QWinEventNotifier calls this method in it's destructor and there should never be a need to call this - method directly. - - \sa QWinEventNotifier, registerEventNotifier() -*/ - /*! \fn void QAbstractEventDispatcher::awake() This signal is emitted after the event loop returns from a diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h index 9a0a049ed4..717fdc8984 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.h +++ b/src/corelib/kernel/qabstracteventdispatcher.h @@ -49,10 +49,6 @@ class QAbstractNativeEventFilter; class QAbstractEventDispatcherPrivate; class QSocketNotifier; -#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC) -class QWinEventNotifier; -#endif - class Q_CORE_EXPORT QAbstractEventDispatcher : public QObject { Q_OBJECT @@ -88,11 +84,6 @@ public: virtual int remainingTime(int timerId) = 0; -#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC) - virtual bool registerEventNotifier(QWinEventNotifier *notifier) = 0; - virtual void unregisterEventNotifier(QWinEventNotifier *notifier) = 0; -#endif - virtual void wakeUp() = 0; virtual void interrupt() = 0; diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 44487d57e2..1336238795 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -47,12 +47,10 @@ #include "qset.h" #include "qsocketnotifier.h" #include "qvarlengtharray.h" -#include "qwineventnotifier.h" #include "qelapsedtimer.h" #include "qcoreapplication_p.h" #include <private/qthread_p.h> -#include <private/qwineventnotifier_p.h> QT_BEGIN_NAMESPACE @@ -99,7 +97,7 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA QEventDispatcherWin32Private::QEventDispatcherWin32Private() : interrupt(false), internalHwnd(0), getMessageHook(0), sendPostedEventsTimerId(0), wakeUps(0), - activateNotifiersPosted(false), activateEventNotifiersPosted(false) + activateNotifiersPosted(false) { } @@ -109,12 +107,6 @@ QEventDispatcherWin32Private::~QEventDispatcherWin32Private() DestroyWindow(internalHwnd); } -void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen) -{ - QEvent event(QEvent::WinEventAct); - QCoreApplication::sendEvent(wen, &event); -} - // This function is called by a workerthread void WINAPI QT_WIN_CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/, DWORD_PTR user, DWORD_PTR /*reserved*/, DWORD_PTR /*reserved*/) { @@ -455,14 +447,6 @@ void QEventDispatcherWin32Private::postActivateSocketNotifiers() activateNotifiersPosted = PostMessage(internalHwnd, WM_QT_ACTIVATENOTIFIERS, 0, 0); } -void QEventDispatcherWin32Private::postActivateEventNotifiers() -{ - Q_Q(QEventDispatcherWin32); - - if (!activateEventNotifiersPosted.fetchAndStoreRelease(true)) - QCoreApplication::postEvent(q, new QEvent(QEvent::WinEventAct)); -} - QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent) : QEventDispatcherWin32(*new QEventDispatcherWin32Private, parent) { @@ -817,83 +801,6 @@ QEventDispatcherWin32::registeredTimers(QObject *object) const return list; } -bool QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier) -{ - Q_ASSERT(notifier); -#ifndef QT_NO_DEBUG - if (notifier->thread() != thread() || thread() != QThread::currentThread()) { - qWarning("QEventDispatcherWin32: event notifiers cannot be enabled from another thread"); - return false; - } -#endif - - Q_D(QEventDispatcherWin32); - - if (d->winEventNotifierList.contains(notifier)) - return true; - - d->winEventNotifierList.append(notifier); - d->winEventNotifierListModified = true; - - return QWinEventNotifierPrivate::get(notifier)->registerWaitObject(); -} - -void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier) -{ - Q_ASSERT(notifier); -#ifndef QT_NO_DEBUG - if (notifier->thread() != thread() || thread() != QThread::currentThread()) { - qWarning("QEventDispatcherWin32: event notifiers cannot be disabled from another thread"); - return; - } -#endif - doUnregisterEventNotifier(notifier); -} - -void QEventDispatcherWin32::doUnregisterEventNotifier(QWinEventNotifier *notifier) -{ - Q_D(QEventDispatcherWin32); - - int i = d->winEventNotifierList.indexOf(notifier); - if (i == -1) - return; - d->winEventNotifierList.takeAt(i); - d->winEventNotifierListModified = true; - QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier); - if (nd->waitHandle) - nd->unregisterWaitObject(); -} - -void QEventDispatcherWin32::activateEventNotifiers() -{ - Q_D(QEventDispatcherWin32); - - // Enable WM_QT_ACTIVATEWINEVENTS posting. - d->activateEventNotifiersPosted.fetchAndStoreAcquire(false); - - // Activate signaled notifiers. Our winEventNotifierList can be modified in activation slots. - do { - d->winEventNotifierListModified = false; - for (int i = 0; i < d->winEventNotifierList.count(); ++i) { - QWinEventNotifier *notifier = d->winEventNotifierList.at(i); - QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier); - if (nd->signaled.loadRelaxed()) { - nd->signaled.storeRelaxed(false); - nd->unregisterWaitObject(); - d->activateEventNotifier(notifier); - } - } - } while (d->winEventNotifierListModified); - - // 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(); - } -} - int QEventDispatcherWin32::remainingTime(int timerId) { #ifndef QT_NO_DEBUG @@ -958,10 +865,6 @@ void QEventDispatcherWin32::closingDown() doUnregisterSocketNotifier((*(d->sn_except.begin()))->obj); Q_ASSERT(d->active_fd.isEmpty()); - // clean up any eventnotifiers - while (!d->winEventNotifierList.isEmpty()) - doUnregisterEventNotifier(d->winEventNotifierList.first()); - // clean up any timers for (int i = 0; i < d->timerVec.count(); ++i) d->unregisterTimer(d->timerVec.at(i)); @@ -1009,9 +912,6 @@ bool QEventDispatcherWin32::event(QEvent *e) case QEvent::Timer: d->sendTimerEvent(static_cast<const QTimerEvent*>(e)->timerId()); break; - case QEvent::WinEventAct: - activateEventNotifiers(); - break; default: break; } diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index a5c063e062..4637185563 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -60,7 +60,6 @@ QT_BEGIN_NAMESPACE -class QWinEventNotifier; class QEventDispatcherWin32Private; // forward declaration @@ -86,10 +85,6 @@ public: bool unregisterTimers(QObject *object) override; QList<TimerInfo> registeredTimers(QObject *object) const override; - bool registerEventNotifier(QWinEventNotifier *notifier) override; - void unregisterEventNotifier(QWinEventNotifier *notifier) override; - void activateEventNotifiers(); - int remainingTime(int timerId) override; void wakeUp() override; @@ -106,7 +101,6 @@ protected: QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent = nullptr); virtual void sendPostedEvents(); void doUnregisterSocketNotifier(QSocketNotifier *notifier); - void doUnregisterEventNotifier(QWinEventNotifier *notifier); private: friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp); @@ -156,7 +150,6 @@ class Q_CORE_EXPORT QEventDispatcherWin32Private : public QAbstractEventDispatch public: QEventDispatcherWin32Private(); ~QEventDispatcherWin32Private(); - static QEventDispatcherWin32Private *get(QEventDispatcherWin32 *q) { return q->d_func(); } QAtomicInt interrupt; @@ -186,12 +179,6 @@ public: bool closingDown = false; - bool winEventNotifierListModified = false; - QAtomicInt activateEventNotifiersPosted; - QList<QWinEventNotifier *> winEventNotifierList; - void postActivateEventNotifiers(); - void activateEventNotifier(QWinEventNotifier * wen); - QList<MSG> queuedUserInputEvents; QList<MSG> queuedSocketEvents; }; diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index 5a3ad9ed5d..d3be82db58 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -39,10 +39,8 @@ #include "qwineventnotifier_p.h" -#include "qeventdispatcher_win_p.h" #include "qcoreapplication.h" - -#include <private/qthread_p.h> +#include "qthread.h" QT_BEGIN_NAMESPACE @@ -120,12 +118,8 @@ QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent) : QObject(*new QWinEventNotifierPrivate(hEvent, false), parent) { Q_D(QWinEventNotifier); - QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed(); - if (Q_UNLIKELY(!eventDispatcher)) { - qWarning("QWinEventNotifier: Can only be used with threads started with QThread"); - return; - } - eventDispatcher->registerEventNotifier(this); + + d->registerWaitObject(); d->enabled = true; } @@ -193,19 +187,20 @@ void QWinEventNotifier::setEnabled(bool enable) return; d->enabled = enable; - QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed(); - if (!eventDispatcher) // perhaps application is shutting down - return; if (Q_UNLIKELY(thread() != QThread::currentThread())) { qWarning("QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread"); return; } if (enable) { - d->signaled.storeRelaxed(false); - eventDispatcher->registerEventNotifier(this); - } else { - eventDispatcher->unregisterEventNotifier(this); + // It is possible that the notifier was disabled after an event was already + // posted. In that case we set a state that indicates that such an obsolete + // event shall be ignored. + d->winEventActPosted.testAndSetRelaxed(QWinEventNotifierPrivate::Posted, + QWinEventNotifierPrivate::IgnorePosted); + d->registerWaitObject(); + } else if (d->waitHandle != NULL) { + d->unregisterWaitObject(); } } @@ -225,28 +220,33 @@ bool QWinEventNotifier::event(QEvent * e) } QObject::event(e); // will activate filters if (e->type() == QEvent::WinEventAct) { - emit activated(d->handleToEvent, QPrivateSignal()); + // Emit notification, but only if the event has not been invalidated + // since by the notifier being disabled, even if it was re-enabled + // again. + if (d->winEventActPosted.fetchAndStoreRelaxed(QWinEventNotifierPrivate::NotPosted) + == QWinEventNotifierPrivate::Posted && d->enabled) { + d->unregisterWaitObject(); + + emit activated(d->handleToEvent, QPrivateSignal()); + + if (d->enabled && d->waitHandle == NULL) + d->registerWaitObject(); + } return true; } return false; } -static void CALLBACK wfsoCallback(void *context, BOOLEAN /*ignore*/) +void CALLBACK QWinEventNotifierPrivate::wfsoCallback(void *context, BOOLEAN /*ignore*/) { QWinEventNotifierPrivate *nd = reinterpret_cast<QWinEventNotifierPrivate *>(context); - QAbstractEventDispatcher *eventDispatcher = nd->threadData.loadRelaxed()->eventDispatcher.loadRelaxed(); - // Happens when Q(Core)Application is destroyed before QWinEventNotifier. - // https://bugreports.qt.io/browse/QTBUG-70214 - if (!eventDispatcher) { // perhaps application is shutting down - qWarning("QWinEventNotifier: no event dispatcher, application shutting down? Cannot deliver event."); - return; + // Do not post an event, if an event is already in the message queue. Note + // that an event that was previously invalidated will be reactivated. + if (nd->winEventActPosted.fetchAndStoreRelaxed(QWinEventNotifierPrivate::Posted) + == QWinEventNotifierPrivate::NotPosted) { + QCoreApplication::postEvent(nd->q_func(), new QEvent(QEvent::WinEventAct)); } - - QEventDispatcherWin32Private *edp = QEventDispatcherWin32Private::get( - static_cast<QEventDispatcherWin32 *>(eventDispatcher)); - nd->signaled.storeRelaxed(true); - edp->postActivateEventNotifiers(); } bool QWinEventNotifierPrivate::registerWaitObject() diff --git a/src/corelib/kernel/qwineventnotifier_p.h b/src/corelib/kernel/qwineventnotifier_p.h index f8f7cd8eff..da9d8ff9a0 100644 --- a/src/corelib/kernel/qwineventnotifier_p.h +++ b/src/corelib/kernel/qwineventnotifier_p.h @@ -68,13 +68,15 @@ public: QWinEventNotifierPrivate(HANDLE h, bool e) : handleToEvent(h), enabled(e) {} - static QWinEventNotifierPrivate *get(QWinEventNotifier *q) { return q->d_func(); } + static void CALLBACK wfsoCallback(void *context, BOOLEAN /*ignore*/); bool registerWaitObject(); void unregisterWaitObject(); HANDLE handleToEvent; HANDLE waitHandle = NULL; - QAtomicInt signaled; + + enum PostingState { NotPosted = 0, Posted, IgnorePosted }; + QAtomicInt winEventActPosted; bool enabled; }; |