Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwineventnotifier.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include "qcoreapplication.h"
7#include "qthread.h"
8#include <QPointer>
9
11
67QWinEventNotifier::QWinEventNotifier(QObject *parent)
68 : QObject(*new QWinEventNotifierPrivate, parent)
69{}
70
82QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent)
83 : QObject(*new QWinEventNotifierPrivate(hEvent, false), parent)
84{
85 setEnabled(true);
86}
87
92QWinEventNotifier::~QWinEventNotifier()
93{
94 setEnabled(false);
95}
96
107void QWinEventNotifier::setHandle(HANDLE hEvent)
108{
110 setEnabled(false);
111 d->handleToEvent = hEvent;
112}
113
120HANDLE QWinEventNotifier::handle() const
121{
122 Q_D(const QWinEventNotifier);
123 return d->handleToEvent;
124}
125
132bool QWinEventNotifier::isEnabled() const
133{
134 Q_D(const QWinEventNotifier);
135 return d->enabled;
136}
137
145void QWinEventNotifier::setEnabled(bool enable)
146{
148 if (d->enabled == enable) // no change
149 return;
150 d->enabled = enable;
151
152 if (Q_UNLIKELY(thread() != QThread::currentThread())) {
153 qWarning("QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread");
154 return;
155 }
156
157 if (enable) {
158 // It is possible that the notifier was disabled after an event was already
159 // posted. In that case we set a state that indicates that such an obsolete
160 // event shall be ignored.
161 d->winEventActPosted.testAndSetRelaxed(QWinEventNotifierPrivate::Posted,
163 // The notifier can't be registered, if 'enabled' flag was false.
164 // The code in the else branch ensures that.
165 Q_ASSERT(!d->registered);
166 SetThreadpoolWait(d->waitObject, d->handleToEvent, NULL);
167 d->registered = true;
168 } else if (d->registered) {
169 // Stop waiting for an event. However, there may be a callback queued
170 // already after the call.
171 SetThreadpoolWait(d->waitObject, NULL, NULL);
172 // So, to avoid a race condition after a possible call to
173 // setEnabled(true), wait for a possibly outstanding callback
174 // to complete.
175 WaitForThreadpoolWaitCallbacks(d->waitObject, TRUE);
176 d->registered = false;
177 }
178}
179
184bool QWinEventNotifier::event(QEvent * e)
185{
187
188 switch (e->type()) {
190 if (d->enabled) {
192 Q_ARG(bool, true));
193 setEnabled(false);
194 }
195 break;
197 // Emit notification, but only if the event has not been invalidated
198 // since by the notifier being disabled, even if it was re-enabled
199 // again.
200 if (d->winEventActPosted.fetchAndStoreRelaxed(QWinEventNotifierPrivate::NotPosted)
201 == QWinEventNotifierPrivate::Posted && d->enabled) {
202 // Clear the flag, as the wait object is implicitly unregistered
203 // when the callback is queued.
204 d->registered = false;
205
206 QPointer<QWinEventNotifier> alive(this);
207 emit activated(d->handleToEvent, QPrivateSignal());
208
209 if (alive && d->enabled && !d->registered) {
210 SetThreadpoolWait(d->waitObject, d->handleToEvent, NULL);
211 d->registered = true;
212 }
213 }
214 return true;
215 default:
216 break;
217 }
218 return QObject::event(e);
219}
220
222 : handleToEvent(h), enabled(e), registered(false)
223{
224 waitObject = CreateThreadpoolWait(waitCallback, this, NULL);
225 if (waitObject == NULL)
226 qErrnoWarning("QWinEventNotifier:: CreateThreadpollWait failed.");
227}
228
233
234void QWinEventNotifierPrivate::waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context,
235 PTP_WAIT wait, TP_WAIT_RESULT waitResult)
236{
237 Q_UNUSED(instance);
238 Q_UNUSED(wait);
239 Q_UNUSED(waitResult);
241
242 // Do not post an event, if an event is already in the message queue. Note
243 // that an event that was previously invalidated will be reactivated.
244 if (nd->winEventActPosted.fetchAndStoreRelaxed(QWinEventNotifierPrivate::Posted)
247 }
248}
249
251
252#include "moc_qwineventnotifier.cpp"
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
\inmodule QtCore
Definition qcoreevent.h:45
@ WinEventAct
Definition qcoreevent.h:99
@ ThreadChange
Definition qcoreevent.h:82
Type type() const
Returns the event type.
Definition qcoreevent.h:304
\inmodule QtCore
Definition qobject.h:103
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition qobject.cpp:1389
static QThread * currentThread()
Definition qthread.cpp:1039
static void CALLBACK waitCallback(PTP_CALLBACK_INSTANCE instance, PVOID context, PTP_WAIT wait, TP_WAIT_RESULT waitResult)
\inmodule QtCore
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
void * HANDLE
@ QueuedConnection
static void * context
#define Q_UNLIKELY(x)
#define qWarning
Definition qlogging.h:166
#define Q_ARG(Type, data)
Definition qobjectdefs.h:63
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLboolean enable
GLfloat GLfloat GLfloat GLfloat h
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define emit
#define Q_UNUSED(x)
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...