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
qeventdispatcher_win.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
6
7#include "qcoreapplication.h"
8#include <private/qsystemlibrary_p.h>
10#include "qset.h"
11#include "qsocketnotifier.h"
12#include "qvarlengtharray.h"
13
14#include "qelapsedtimer.h"
15#include "qcoreapplication_p.h"
16#include <private/qthread_p.h>
17
19
20#ifndef TIME_KILL_SYNCHRONOUS
21# define TIME_KILL_SYNCHRONOUS 0x0100
22#endif
23
24#ifndef QS_RAWINPUT
25# define QS_RAWINPUT 0x0400
26#endif
27
28#ifndef WM_TOUCH
29# define WM_TOUCH 0x0240
30#endif
31#ifndef QT_NO_GESTURES
32#ifndef WM_GESTURE
33# define WM_GESTURE 0x0119
34#endif
35#ifndef WM_GESTURENOTIFY
36# define WM_GESTURENOTIFY 0x011A
37#endif
38#endif // QT_NO_GESTURES
39
40enum {
43 WM_QT_ACTIVATENOTIFIERS = WM_USER + 2
44};
45
46enum {
48};
49
51
52#if !defined(DWORD_PTR) && !defined(Q_OS_WIN64)
53#define DWORD_PTR DWORD
54#endif
55
56LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
57
59{
60 using namespace std::chrono;
61 auto t = duration_cast<milliseconds>(steady_clock::now().time_since_epoch());
62 return t.count();
63}
64
70}
71
77
78// This function is called by a workerthread
79void WINAPI QT_WIN_CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/, DWORD_PTR user, DWORD_PTR /*reserved*/, DWORD_PTR /*reserved*/)
80{
81 if (!timerId) // sanity check
82 return;
83 auto t = reinterpret_cast<WinTimerInfo*>(user);
84 Q_ASSERT(t);
85 QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId));
86}
87
88LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
89{
90 if (message == WM_NCCREATE)
91 return true;
92
93 MSG msg;
94 msg.hwnd = hwnd;
95 msg.message = message;
96 msg.wParam = wp;
97 msg.lParam = lp;
100 if (!dispatcher) {
101 if (message == WM_TIMER)
102 KillTimer(hwnd, wp);
103 return 0;
104 }
105 if (dispatcher->filterNativeEvent(QByteArrayLiteral("windows_dispatcher_MSG"), &msg, &result))
106 return result;
107
108 auto q = reinterpret_cast<QEventDispatcherWin32 *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
110 if (q != nullptr)
111 d = q->d_func();
112
113 switch (message) {
115 // socket notifier message
116 int type = -1;
117 switch (WSAGETSELECTEVENT(lp)) {
118 case FD_READ:
119 case FD_ACCEPT:
120 type = 0;
121 break;
122 case FD_WRITE:
123 case FD_CONNECT:
124 type = 1;
125 break;
126 case FD_OOB:
127 type = 2;
128 break;
129 case FD_CLOSE:
130 type = 3;
131 break;
132 }
133 if (type >= 0) {
134 Q_ASSERT(d != nullptr);
135 QSNDict *sn_vec[4] = { &d->sn_read, &d->sn_write, &d->sn_except, &d->sn_read };
136 QSNDict *dict = sn_vec[type];
137
138 QSockNot *sn = dict ? dict->value(qintptr(wp)) : 0;
139 if (sn == nullptr) {
140 d->postActivateSocketNotifiers();
141 } else {
142 Q_ASSERT(d->active_fd.contains(sn->fd));
143 QSockFd &sd = d->active_fd[sn->fd];
144 if (sd.selected) {
145 Q_ASSERT(sd.mask == 0);
146 d->doWsaAsyncSelect(sn->fd, 0);
147 sd.selected = false;
148 }
149 d->postActivateSocketNotifiers();
150
151 // Ignore the message if a notification with the same type was
152 // received previously. Suppressed message is definitely spurious.
153 const long eventCode = WSAGETSELECTEVENT(lp);
154 if ((sd.mask & eventCode) != eventCode) {
155 sd.mask |= eventCode;
158 }
159 }
160 }
161 return 0;
162 }
164 Q_ASSERT(d != nullptr);
165
166 // Postpone activation if we have unhandled socket notifier messages
167 // in the queue. WM_QT_ACTIVATENOTIFIERS will be posted again as a result of
168 // event processing.
169 MSG msg;
170 if (!PeekMessage(&msg, d->internalHwnd,
172 && d->queuedSocketEvents.isEmpty()) {
173 // register all socket notifiers
174 for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end();
175 it != end; ++it) {
176 QSockFd &sd = it.value();
177 if (!sd.selected) {
178 d->doWsaAsyncSelect(it.key(), sd.event);
179 // allow any event to be accepted
180 sd.mask = 0;
181 sd.selected = true;
182 }
183 }
184 }
185 d->activateNotifiersPosted = false;
186 return 0;
187 }
188 case WM_TIMER:
189 Q_ASSERT(d != nullptr);
190
191 if (wp == d->sendPostedEventsTimerId)
192 q->sendPostedEvents();
193 else
194 d->sendTimerEvent(wp);
195 return 0;
197 Q_ASSERT(d != nullptr);
198
199 // We send posted events manually, if the window procedure was invoked
200 // by the foreign event loop (e.g. from the native modal dialog).
201 // Skip sending, if the message queue is not empty.
202 // sendPostedEventsTimer will deliver posted events later.
203 static const UINT mask = QS_ALLEVENTS;
204 if (HIWORD(GetQueueStatus(mask)) == 0)
205 q->sendPostedEvents();
206 else
207 d->startPostedEventsTimer();
208 return 0;
209 } // switch (message)
210
211 return DefWindowProc(hwnd, message, wp, lp);
212}
213
215{
216 // we received WM_QT_SENDPOSTEDEVENTS, so allow posting it again
218 if (sendPostedEventsTimerId == 0) {
219 // Start a timer to deliver posted events when the message queue is emptied.
221 USER_TIMER_MINIMUM, NULL);
222 }
223}
224
225// Provide class name and atom for the message window used by
226// QEventDispatcherWin32Private via Q_GLOBAL_STATIC shared between threads.
235
237 : atom(0), className(0)
238{
239 // make sure that multiple Qt's can coexist in the same process
240 const QString qClassName = QStringLiteral("QEventDispatcherWin32_Internal_Widget")
242 className = new wchar_t[qClassName.size() + 1];
243 qClassName.toWCharArray(className);
244 className[qClassName.size()] = 0;
245
246 WNDCLASS wc;
247 wc.style = 0;
248 wc.lpfnWndProc = qt_internal_proc;
249 wc.cbClsExtra = 0;
250 wc.cbWndExtra = 0;
251 wc.hInstance = GetModuleHandle(0);
252 wc.hIcon = 0;
253 wc.hCursor = 0;
254 wc.hbrBackground = 0;
255 wc.lpszMenuName = NULL;
256 wc.lpszClassName = className;
257 atom = RegisterClass(&wc);
258 if (!atom) {
259 qErrnoWarning("%ls RegisterClass() failed", qUtf16Printable(qClassName));
260 delete [] className;
261 className = 0;
262 }
263}
264
266{
267 if (className) {
268 UnregisterClass(className, GetModuleHandle(0));
269 delete [] className;
270 }
271}
272
273Q_GLOBAL_STATIC(QWindowsMessageWindowClassContext, qWindowsMessageWindowClassContext)
274
275static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
276{
277 QWindowsMessageWindowClassContext *ctx = qWindowsMessageWindowClassContext();
278 if (!ctx->atom)
279 return 0;
280 HWND wnd = CreateWindow(ctx->className, // classname
281 ctx->className, // window name
282 0, // style
283 0, 0, 0, 0, // geometry
284 HWND_MESSAGE, // parent
285 0, // menu handle
286 GetModuleHandle(0), // application
287 0); // windows creation data.
288
289 if (!wnd) {
290 qErrnoWarning("CreateWindow() for QEventDispatcherWin32 internal window failed");
291 return 0;
292 }
293
294 SetWindowLongPtr(wnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(eventDispatcher));
295
296 return wnd;
297}
298
300{
301 uint interval = t->interval;
302 ULONG tolerance = TIMERV_DEFAULT_COALESCING;
303 switch (t->timerType) {
304 case Qt::PreciseTimer:
305 // high precision timer is based on millisecond precision
306 // so no adjustment is necessary
307 break;
308
309 case Qt::CoarseTimer:
310 // this timer has up to 5% coarseness
311 // so our boundaries are 20 ms and 20 s
312 // below 20 ms, 5% inaccuracy is below 1 ms, so we convert to high precision
313 // above 20 s, 5% inaccuracy is above 1 s, so we convert to VeryCoarseTimer
314 if (interval >= 20000) {
315 t->timerType = Qt::VeryCoarseTimer;
316 } else if (interval <= 20) {
317 // no adjustment necessary
318 t->timerType = Qt::PreciseTimer;
319 break;
320 } else {
321 tolerance = interval / 20;
322 break;
323 }
326 // the very coarse timer is based on full second precision,
327 // so we round to closest second (but never to zero)
328 tolerance = 1000;
329 if (interval < 1000)
330 interval = 1000;
331 else
332 interval = (interval + 500) / 1000 * 1000;
333 currentTime = currentTime / 1000 * 1000;
334 break;
335 }
336
337 t->interval = interval;
338 t->timeout = currentTime + interval;
339 return tolerance;
340}
341
343{
345
347
348 bool ok = false;
349 ULONG tolerance = calculateNextTimeout(t, qt_msectime());
350 uint interval = t->interval;
351 if (interval == 0u) {
352 // optimization for single-shot-zero-timer
354 ok = true;
355 } else if (tolerance == TIMERV_DEFAULT_COALESCING) {
356 // 3/2016: Although MSDN states timeSetEvent() is deprecated, the function
357 // is still deemed to be the most reliable precision timer.
358 t->fastTimerId = timeSetEvent(interval, 1, qt_fast_timer_proc, DWORD_PTR(t),
359 TIME_CALLBACK_FUNCTION | TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
360 ok = t->fastTimerId;
361 }
362
363 if (!ok) {
364 // user normal timers for (Very)CoarseTimers, or if no more multimedia timers available
365 ok = SetCoalescableTimer(internalHwnd, t->timerId, interval, nullptr, tolerance);
366 }
367 if (!ok)
368 ok = SetTimer(internalHwnd, t->timerId, interval, nullptr);
369
370 if (!ok)
371 qErrnoWarning("QEventDispatcherWin32::registerTimer: Failed to create a timer");
372}
373
375{
376 if (t->interval == 0) {
377 QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
378 } else if (t->fastTimerId != 0) {
379 timeKillEvent(t->fastTimerId);
380 QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
381 } else {
382 KillTimer(internalHwnd, t->timerId);
383 }
384 t->timerId = -1;
385 if (!t->inTimerEvent)
386 delete t;
387}
388
390{
391 WinTimerInfo *t = timerDict.value(timerId);
392 if (t && !t->inTimerEvent) {
393 // send event, but don't allow it to recurse
394 t->inTimerEvent = true;
395
396 // recalculate next emission
398
399 QTimerEvent e(t->timerId);
401
402 // timer could have been removed
403 if (t->timerId == -1) {
404 delete t;
405 } else {
406 t->inTimerEvent = false;
407 }
408 }
409}
410
412{
414 // BoundsChecker may emit a warning for WSAAsyncSelect when event == 0
415 // This is a BoundsChecker bug and not a Qt bug
416 WSAAsyncSelect(socket, internalHwnd, event ? int(WM_QT_SOCKETNOTIFIER) : 0, event);
417}
418
424
429
437
441
443{
444 return (message >= WM_KEYFIRST && message <= WM_KEYLAST)
445 || (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST)
448 || message == WM_TOUCH
449#ifndef QT_NO_GESTURES
450 || message == WM_GESTURE
452#endif
453// Pointer input: Exclude WM_NCPOINTERUPDATE .. WM_POINTERROUTEDRELEASED
454 || (message >= 0x0241 && message <= 0x0253)
455 || message == WM_CLOSE;
456}
457
458bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
459{
461
462 // We don't know _when_ the interrupt occurred so we have to honor it.
463 const bool wasInterrupted = d->interrupt.fetchAndStoreRelaxed(false);
464 emit awake();
465
466 // To prevent livelocks, send posted events once per iteration.
467 // QCoreApplication::sendPostedEvents() takes care about recursions.
469
470 if (wasInterrupted)
471 return false;
472
473 auto threadData = d->threadData.loadRelaxed();
474 bool canWait;
475 bool retVal = false;
476 do {
477 QVarLengthArray<MSG> processedTimers;
478 while (!d->interrupt.loadRelaxed()) {
479 MSG msg;
480
481 if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) {
482 // process queued user input events
483 msg = d->queuedUserInputEvents.takeFirst();
484 } else if (!(flags & QEventLoop::ExcludeSocketNotifiers) && !d->queuedSocketEvents.isEmpty()) {
485 // process queued socket events
486 msg = d->queuedSocketEvents.takeFirst();
487 } else if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
489 && isUserInputMessage(msg.message)) {
490 // queue user input events for later processing
491 d->queuedUserInputEvents.append(msg);
492 continue;
493 }
495 && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
496 // queue socket events for later processing
497 d->queuedSocketEvents.append(msg);
498 continue;
499 }
500 } else if (MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, MWMO_ALERTABLE)
501 == WAIT_OBJECT_0) {
502 // a new message has arrived, process it
503 continue;
504 } else {
505 // nothing to do, so break
506 break;
507 }
508
509 if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
510 d->startPostedEventsTimer();
511 // Set result to 'true' because the message was sent by wakeUp().
512 retVal = true;
513 continue;
514 }
515 if (msg.message == WM_TIMER) {
516 // Skip timer event intended for use inside foreign loop.
517 if (d->internalHwnd == msg.hwnd && msg.wParam == d->sendPostedEventsTimerId)
518 continue;
519
520 // avoid live-lock by keeping track of the timers we've already sent
521 bool found = false;
522 for (int i = 0; !found && i < processedTimers.count(); ++i) {
523 const MSG processed = processedTimers.constData()[i];
524 found = (processed.wParam == msg.wParam && processed.hwnd == msg.hwnd && processed.lParam == msg.lParam);
525 }
526 if (found)
527 continue;
528 processedTimers.append(msg);
529 } else if (msg.message == WM_QUIT) {
532 return false;
533 }
534
535 if (!filterNativeEvent(QByteArrayLiteral("windows_generic_MSG"), &msg, 0)) {
536 TranslateMessage(&msg);
537 DispatchMessage(&msg);
538 }
539 retVal = true;
540 }
541
542 // wait for message
543 canWait = (!retVal
544 && !d->interrupt.loadRelaxed()
546 && threadData->canWaitLocked());
547 if (canWait) {
549 MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
550 emit awake();
551 }
552 } while (canWait);
553
554 return retVal;
555}
556
558{
560 qintptr sockfd = notifier->socket();
561 int type = notifier->type();
562#ifndef QT_NO_DEBUG
563 if (sockfd < 0) {
564 qWarning("QEventDispatcherWin32::registerSocketNotifier: invalid socket identifier");
565 return;
566 }
567 if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
568 qWarning("QEventDispatcherWin32: socket notifiers cannot be enabled from another thread");
569 return;
570 }
571#endif
572
574 QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
575 QSNDict *dict = sn_vec[type];
576
577 if (QCoreApplication::closingDown()) // ### d->exitloop?
578 return; // after sn_cleanup, don't reinitialize.
579
580 if (dict->contains(sockfd)) {
581 const char *t[] = { "Read", "Write", "Exception" };
582 /* Variable "socket" below is a function pointer. */
583 qWarning("QSocketNotifier: Multiple socket notifiers for "
584 "same socket %" PRIdQINTPTR " and type %s", sockfd, t[type]);
585 }
586
587 QSockNot *sn = new QSockNot;
588 sn->obj = notifier;
589 sn->fd = sockfd;
590 dict->insert(sn->fd, sn);
591
592 long event = 0;
593 if (d->sn_read.contains(sockfd))
594 event |= FD_READ | FD_CLOSE | FD_ACCEPT;
595 if (d->sn_write.contains(sockfd))
596 event |= FD_WRITE | FD_CONNECT;
597 if (d->sn_except.contains(sockfd))
598 event |= FD_OOB;
599
600 QSFDict::iterator it = d->active_fd.find(sockfd);
601 if (it != d->active_fd.end()) {
602 QSockFd &sd = it.value();
603 if (sd.selected) {
604 d->doWsaAsyncSelect(sockfd, 0);
605 sd.selected = false;
606 }
607 sd.event |= event;
608 } else {
609 // Although WSAAsyncSelect(..., 0), which is called from
610 // unregisterSocketNotifier(), immediately disables event message
611 // posting for the socket, it is possible that messages could be
612 // waiting in the application message queue even if the socket was
613 // closed. Also, some events could be implicitly re-enabled due
614 // to system calls. Ignore these superfluous events until all
615 // pending notifications have been suppressed. Next activation of
616 // socket notifiers will reset the mask.
617 d->active_fd.insert(sockfd, QSockFd(event, FD_READ | FD_CLOSE | FD_ACCEPT | FD_WRITE
618 | FD_CONNECT | FD_OOB));
619 }
620
621 d->postActivateSocketNotifiers();
622}
623
625{
627#ifndef QT_NO_DEBUG
628 qintptr sockfd = notifier->socket();
629 if (sockfd < 0) {
630 qWarning("QEventDispatcherWin32::unregisterSocketNotifier: invalid socket identifier");
631 return;
632 }
633 if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
634 qWarning("QEventDispatcherWin32: socket notifiers cannot be disabled from another thread");
635 return;
636 }
637#endif
639}
640
642{
644 int type = notifier->type();
645 qintptr sockfd = notifier->socket();
646 Q_ASSERT(sockfd >= 0);
647
648 QSFDict::iterator it = d->active_fd.find(sockfd);
649 if (it != d->active_fd.end()) {
650 QSockFd &sd = it.value();
651 if (sd.selected)
652 d->doWsaAsyncSelect(sockfd, 0);
653 const long event[3] = { FD_READ | FD_CLOSE | FD_ACCEPT, FD_WRITE | FD_CONNECT, FD_OOB };
654 sd.event ^= event[type];
655 if (sd.event == 0) {
656 d->active_fd.erase(it);
657 } else if (sd.selected) {
658 sd.selected = false;
659 d->postActivateSocketNotifiers();
660 }
661 }
662
663 QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
664 QSNDict *dict = sn_vec[type];
665 QSockNot *sn = dict->value(sockfd);
666 if (!sn)
667 return;
668
669 dict->remove(sockfd);
670 delete sn;
671}
672
673void QEventDispatcherWin32::registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object)
674{
675#ifndef QT_NO_DEBUG
676 if (timerId < 1 || interval < 0 || !object) {
677 qWarning("QEventDispatcherWin32::registerTimer: invalid arguments");
678 return;
679 }
680 if (object->thread() != thread() || thread() != QThread::currentThread()) {
681 qWarning("QEventDispatcherWin32::registerTimer: timers cannot be started from another thread");
682 return;
683 }
684#endif
685
687
688 // exiting ... do not register new timers
689 // (QCoreApplication::closingDown() is set too late to be used here)
690 if (d->closingDown)
691 return;
692
694 t->dispatcher = this;
695 t->timerId = timerId;
696 t->interval = interval;
697 t->timerType = timerType;
698 t->obj = object;
699 t->inTimerEvent = false;
700 t->fastTimerId = 0;
701
702 d->registerTimer(t);
703
704 d->timerDict.insert(t->timerId, t); // store timers in dict
705}
706
708{
709#ifndef QT_NO_DEBUG
710 if (timerId < 1) {
711 qWarning("QEventDispatcherWin32::unregisterTimer: invalid argument");
712 return false;
713 }
714 if (thread() != QThread::currentThread()) {
715 qWarning("QEventDispatcherWin32::unregisterTimer: timers cannot be stopped from another thread");
716 return false;
717 }
718#endif
719
721
722 WinTimerInfo *t = d->timerDict.take(timerId);
723 if (!t)
724 return false;
725
726 d->unregisterTimer(t);
727 return true;
728}
729
731{
732#ifndef QT_NO_DEBUG
733 if (!object) {
734 qWarning("QEventDispatcherWin32::unregisterTimers: invalid argument");
735 return false;
736 }
737 if (object->thread() != thread() || thread() != QThread::currentThread()) {
738 qWarning("QEventDispatcherWin32::unregisterTimers: timers cannot be stopped from another thread");
739 return false;
740 }
741#endif
742
744 if (d->timerDict.isEmpty())
745 return false;
746
747 auto it = d->timerDict.begin();
748 while (it != d->timerDict.end()) {
749 WinTimerInfo *t = it.value();
750 Q_ASSERT(t);
751 if (t->obj == object) {
752 it = d->timerDict.erase(it);
753 d->unregisterTimer(t);
754 } else {
755 ++it;
756 }
757 }
758 return true;
759}
760
761QList<QEventDispatcherWin32::TimerInfo>
763{
764#ifndef QT_NO_DEBUG
765 if (!object) {
766 qWarning("QEventDispatcherWin32:registeredTimers: invalid argument");
767 return QList<TimerInfo>();
768 }
769#endif
770
771 Q_D(const QEventDispatcherWin32);
772 QList<TimerInfo> list;
773 for (WinTimerInfo *t : std::as_const(d->timerDict)) {
774 Q_ASSERT(t);
775 if (t->obj == object)
776 list << TimerInfo(t->timerId, t->interval, t->timerType);
777 }
778 return list;
779}
780
782{
783#ifndef QT_NO_DEBUG
784 if (timerId < 1) {
785 qWarning("QEventDispatcherWin32::remainingTime: invalid argument");
786 return -1;
787 }
788#endif
789
791
793
794 WinTimerInfo *t = d->timerDict.value(timerId);
795 if (t) {
796 // timer found, return time to wait
797 return t->timeout > currentTime ? t->timeout - currentTime : 0;
798 }
799
800#ifndef QT_NO_DEBUG
801 qWarning("QEventDispatcherWin32::remainingTime: timer id %d not found", timerId);
802#endif
803
804 return -1;
805}
806
808{
810 if (d->wakeUps.testAndSetRelaxed(0, 1)) {
811 // post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending
812 if (!PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0))
813 qErrnoWarning("QEventDispatcherWin32::wakeUp: Failed to post a message");
814 }
815}
816
818{
820 d->interrupt.storeRelaxed(true);
821 wakeUp();
822}
823
826
828{
830
831 // clean up any socketnotifiers
832 while (!d->sn_read.isEmpty())
833 doUnregisterSocketNotifier((*(d->sn_read.begin()))->obj);
834 while (!d->sn_write.isEmpty())
835 doUnregisterSocketNotifier((*(d->sn_write.begin()))->obj);
836 while (!d->sn_except.isEmpty())
837 doUnregisterSocketNotifier((*(d->sn_except.begin()))->obj);
838 Q_ASSERT(d->active_fd.isEmpty());
839
840 // clean up any timers
841 for (WinTimerInfo *t : std::as_const(d->timerDict))
842 d->unregisterTimer(t);
843 d->timerDict.clear();
844
845 d->closingDown = true;
846
847 if (d->sendPostedEventsTimerId != 0)
848 KillTimer(d->internalHwnd, d->sendPostedEventsTimerId);
849 d->sendPostedEventsTimerId = 0;
850}
851
853{
855 switch (e->type()) {
857 QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
858 WinTimerInfo *t = d->timerDict.value(zte->timerId());
859 if (t) {
860 t->inTimerEvent = true;
861
862 QTimerEvent te(zte->timerId());
864
865 // timer could have been removed
866 if (t->timerId == -1) {
867 delete t;
868 } else {
869 if (t->interval == 0 && t->inTimerEvent) {
870 // post the next zero timer event as long as the timer was not restarted
871 QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId()));
872 }
873
874 t->inTimerEvent = false;
875 }
876 }
877 return true;
878 }
879 case QEvent::Timer:
880 d->sendTimerEvent(static_cast<const QTimerEvent*>(e)->timerId());
881 break;
882 default:
883 break;
884 }
886}
887
889{
891
892 if (d->sendPostedEventsTimerId != 0)
893 KillTimer(d->internalHwnd, d->sendPostedEventsTimerId);
894 d->sendPostedEventsTimerId = 0;
895
896 // Allow posting WM_QT_SENDPOSTEDEVENTS message.
897 d->wakeUps.storeRelaxed(0);
898
899 QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData.loadRelaxed());
900}
901
903{
904 return d_func()->internalHwnd;
905}
906
908
909#include "moc_qeventdispatcher_win_p.cpp"
DarwinBluetooth::LECBManagerNotifier * notifier
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
Returns a pointer to the event dispatcher object for the specified thread.
void aboutToBlock()
This signal is emitted before the event loop calls a function that could block.
bool filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result)
Sends message through the event filters that were set by installNativeEventFilter().
void awake()
This signal is emitted after the event loop returns from a function that could block.
void storeRelaxed(T newValue) noexcept
static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data)
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
static bool closingDown()
Returns true if the application objects are being destroyed; otherwise returns false.
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
void doWsaAsyncSelect(qintptr socket, long event)
void interrupt() override
Interrupts event dispatching.
bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags) override
Processes pending events that match flags until there are no more events to process.
bool unregisterTimer(int timerId) override
QList< TimerInfo > registeredTimers(QObject *object) const override
QEventDispatcherWin32(QObject *parent=nullptr)
bool unregisterTimers(QObject *object) override
Unregisters all the timers associated with the given object.
void wakeUp() override
\threadsafe
int remainingTime(int timerId) override
void doUnregisterSocketNotifier(QSocketNotifier *notifier)
void registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object) override
void registerSocketNotifier(QSocketNotifier *notifier) override
Registers notifier with the event loop.
void unregisterSocketNotifier(QSocketNotifier *notifier) override
Unregisters notifier from the event dispatcher.
bool event(QEvent *e) override
This virtual function receives events to an object and should return true if the event e was recogniz...
@ ExcludeSocketNotifiers
Definition qeventloop.h:28
@ WaitForMoreEvents
Definition qeventloop.h:29
@ ExcludeUserInputEvents
Definition qeventloop.h:27
\inmodule QtCore
Definition qcoreevent.h:45
@ SockClose
Definition qcoreevent.h:268
@ SockAct
Definition qcoreevent.h:98
@ ZeroTimerEvent
Definition qcoreevent.h:187
Type type() const
Returns the event type.
Definition qcoreevent.h:304
friend class iterator
Definition qhash.h:1142
T value(const Key &key) const noexcept
Definition qhash.h:1054
\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
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1598
iterator begin()
Definition qset.h:136
iterator end()
Definition qset.h:140
iterator erase(const_iterator i)
Definition qset.h:145
iterator find(const T &value)
Definition qset.h:159
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
static QThread * currentThread()
Definition qthread.cpp:1039
\inmodule QtCore
Definition qcoreevent.h:366
EGLContext ctx
QSet< QString >::iterator it
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
TimerType
@ CoarseTimer
@ VeryCoarseTimer
@ PreciseTimer
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
#define Q_FALLTHROUGH()
static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
static quint64 qt_msectime()
#define TIME_KILL_SYNCHRONOUS
@ SendPostedEventsTimerId
#define WM_GESTURE
#define WM_GESTURENOTIFY
void WINAPI QT_WIN_CALLBACK qt_fast_timer_proc(uint timerId, uint, DWORD_PTR user, DWORD_PTR, DWORD_PTR)
@ WM_QT_SENDPOSTEDEVENTS
@ WM_QT_ACTIVATENOTIFIERS
@ WM_QT_SOCKETNOTIFIER
#define DWORD_PTR
#define WM_TOUCH
static bool isUserInputMessage(UINT message)
static ULONG calculateNextTimeout(WinTimerInfo *t, quint64 currentTime)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qWarning
Definition qlogging.h:166
GLuint GLuint end
GLuint object
[3]
GLenum type
GLbitfield flags
GLuint GLsizei const GLchar * message
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
struct _cl_event * event
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qUtf16Printable(string)
Definition qstring.h:1543
#define QStringLiteral(str)
#define WM_MOUSEHWHEEL
Definition qt_windows.h:80
#define WM_MOUSEWHEEL
Definition qt_windows.h:77
#define emit
size_t quintptr
Definition qtypes.h:167
unsigned long long quint64
Definition qtypes.h:61
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
ptrdiff_t qintptr
Definition qtypes.h:166
#define PRIdQINTPTR
Definition qtypes.h:175
static double currentTime()
struct tagMSG MSG
const char className[16]
[1]
Definition qwizard.cpp:100
QList< int > list
[14]
QTcpSocket * socket
[1]
QSocketNotifier * obj