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