summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp24
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.h9
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp102
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h13
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp58
-rw-r--r--src/corelib/kernel/qwineventnotifier_p.h6
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;
};