src/corelib/kernel/qeventdispatcher_win.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    61 extern uint qGlobalPostedEventsCount();
    61 extern uint qGlobalPostedEventsCount();
    62 
    62 
    63 #ifndef TIME_KILL_SYNCHRONOUS
    63 #ifndef TIME_KILL_SYNCHRONOUS
    64 #  define TIME_KILL_SYNCHRONOUS 0x0100
    64 #  define TIME_KILL_SYNCHRONOUS 0x0100
    65 #endif
    65 #endif
       
    66 
       
    67 #ifndef QS_RAWINPUT
       
    68 #  define QS_RAWINPUT 0x0400
       
    69 #endif
       
    70 
       
    71 enum {
       
    72     WM_QT_SOCKETNOTIFIER = WM_USER,
       
    73     WM_QT_SENDPOSTEDEVENTS = WM_USER + 1,
       
    74     SendPostedEventsTimerId = ~1u
       
    75 };
    66 
    76 
    67 #if defined(Q_OS_WINCE)
    77 #if defined(Q_OS_WINCE)
    68 QT_BEGIN_INCLUDE_NAMESPACE
    78 QT_BEGIN_INCLUDE_NAMESPACE
    69 #include <winsock.h>
    79 #include <winsock.h>
    70 // Asynchronous Winsocks ------------------------------------------
    80 // Asynchronous Winsocks ------------------------------------------
   324 
   334 
   325     bool interrupt;
   335     bool interrupt;
   326 
   336 
   327     // internal window handle used for socketnotifiers/timers/etc
   337     // internal window handle used for socketnotifiers/timers/etc
   328     HWND internalHwnd;
   338     HWND internalHwnd;
       
   339     HHOOK getMessageHook;
       
   340 
       
   341     // for controlling when to send posted events
       
   342     QAtomicInt serialNumber;
       
   343     int lastSerialNumber;
       
   344     QAtomicInt wakeUps;
   329 
   345 
   330     // timers
   346     // timers
   331     WinTimerVec timerVec;
   347     WinTimerVec timerVec;
   332     WinTimerDict timerDict;
   348     WinTimerDict timerDict;
   333     void registerTimer(WinTimerInfo *t);
   349     void registerTimer(WinTimerInfo *t);
   338     QSNDict sn_read;
   354     QSNDict sn_read;
   339     QSNDict sn_write;
   355     QSNDict sn_write;
   340     QSNDict sn_except;
   356     QSNDict sn_except;
   341     void doWsaAsyncSelect(int socket);
   357     void doWsaAsyncSelect(int socket);
   342 
   358 
   343     // event notifier
       
   344     QWinEventNotifier wakeUpNotifier;
       
   345 
       
   346     QList<QWinEventNotifier *> winEventNotifierList;
   359     QList<QWinEventNotifier *> winEventNotifierList;
   347     void activateEventNotifier(QWinEventNotifier * wen);
   360     void activateEventNotifier(QWinEventNotifier * wen);
   348 
   361 
   349     QList<MSG> queuedUserInputEvents;
   362     QList<MSG> queuedUserInputEvents;
   350     QList<MSG> queuedSocketEvents;
   363     QList<MSG> queuedSocketEvents;
   351 };
   364 };
   352 
   365 
   353 QEventDispatcherWin32Private::QEventDispatcherWin32Private()
   366 QEventDispatcherWin32Private::QEventDispatcherWin32Private()
   354     : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0)
   367     : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0), getMessageHook(0), serialNumber(0), lastSerialNumber(0), wakeUps(0)
   355 {
   368 {
   356     resolveTimerAPI();
   369     resolveTimerAPI();
   357 
       
   358     wakeUpNotifier.setHandle(CreateEvent(0, FALSE, FALSE, 0));
       
   359     if (!wakeUpNotifier.handle())
       
   360         qWarning("QEventDispatcher: Creating QEventDispatcherWin32Private wakeup event failed");
       
   361 }
   370 }
   362 
   371 
   363 QEventDispatcherWin32Private::~QEventDispatcherWin32Private()
   372 QEventDispatcherWin32Private::~QEventDispatcherWin32Private()
   364 {
   373 {
   365     wakeUpNotifier.setEnabled(false);
       
   366     CloseHandle(wakeUpNotifier.handle());
       
   367     if (internalHwnd)
   374     if (internalHwnd)
   368         DestroyWindow(internalHwnd);
   375         DestroyWindow(internalHwnd);
   369     QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc));
   376     QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc));
   370     UnregisterClass((wchar_t*)className.utf16(), qWinAppInst());
   377     UnregisterClass((wchar_t*)className.utf16(), qWinAppInst());
   371 }
   378 }
   406     QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId));
   413     QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId));
   407 }
   414 }
   408 
   415 
   409 LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
   416 LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
   410 {
   417 {
   411     if (message == WM_NCCREATE) {
   418     if (message == WM_NCCREATE)
   412             return true;
   419         return true;
   413     } else if (message == WM_USER) {
   420 
   414 
   421     MSG msg;
       
   422     msg.hwnd = hwnd;
       
   423     msg.message = message;
       
   424     msg.wParam = wp;
       
   425     msg.lParam = lp;
       
   426     QCoreApplication *app = QCoreApplication::instance();
       
   427     long result;
       
   428     if (!app) {
       
   429         if (message == WM_TIMER)
       
   430             KillTimer(hwnd, wp);
       
   431         return 0;
       
   432     } else if (app->filterEvent(&msg, &result)) {
       
   433         return result;
       
   434     }
       
   435 
       
   436 #ifdef GWLP_USERDATA
       
   437     QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
       
   438 #else
       
   439     QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA);
       
   440 #endif
       
   441     QEventDispatcherWin32Private *d = 0;
       
   442     if (q != 0)
       
   443         d = q->d_func();
       
   444 
       
   445     if (message == WM_QT_SOCKETNOTIFIER) {
   415         // socket notifier message
   446         // socket notifier message
   416         MSG msg;
       
   417         msg.hwnd = hwnd;
       
   418         msg.message = message;
       
   419         msg.wParam = wp;
       
   420         msg.lParam = lp;
       
   421 
       
   422         QCoreApplication *app = QCoreApplication::instance();
       
   423         long result;
       
   424         if (app && app->filterEvent(&msg, &result))
       
   425             return result;
       
   426 
       
   427         int type = -1;
   447         int type = -1;
   428         switch (WSAGETSELECTEVENT(lp)) {
   448         switch (WSAGETSELECTEVENT(lp)) {
   429         case FD_READ:
   449         case FD_READ:
   430         case FD_CLOSE:
   450         case FD_CLOSE:
   431         case FD_ACCEPT:
   451         case FD_ACCEPT:
   438         case FD_OOB:
   458         case FD_OOB:
   439             type = 2;
   459             type = 2;
   440             break;
   460             break;
   441         }
   461         }
   442         if (type >= 0) {
   462         if (type >= 0) {
   443 
   463             Q_ASSERT(d != 0);
   444     #ifdef GWLP_USERDATA
   464             QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
   445             QEventDispatcherWin32 *eventDispatcher =
   465             QSNDict *dict = sn_vec[type];
   446                 (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
   466 
   447     #else
   467             QSockNot *sn = dict ? dict->value(wp) : 0;
   448             QEventDispatcherWin32 *eventDispatcher =
   468             if (sn) {
   449                 (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA);
   469                 QEvent event(QEvent::SockAct);
   450     #endif
   470                 QCoreApplication::sendEvent(sn->obj, &event);
   451             if (eventDispatcher) {
   471             }
   452                 QEventDispatcherWin32Private *d = eventDispatcher->d_func();
   472         }
   453                 QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
   473         return 0;
   454                 QSNDict *dict = sn_vec[type];
   474     } else if (message == WM_TIMER) {    
   455 
   475         Q_ASSERT(d != 0);
   456                 QSockNot *sn = dict ? dict->value(wp) : 0;
   476         d->sendTimerEvent(wp);
   457                 if (sn) {
   477         return 0;
   458                     QEvent event(QEvent::SockAct);
   478     } else if (message == WM_QT_SENDPOSTEDEVENTS) {
   459                     QCoreApplication::sendEvent(sn->obj, &event);
   479         int localSerialNumber = d->serialNumber;
       
   480         if (localSerialNumber != d->lastSerialNumber) {
       
   481             d->lastSerialNumber = localSerialNumber;
       
   482             QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
       
   483         }
       
   484         return 0;
       
   485     }
       
   486 
       
   487     return DefWindowProc(hwnd, message, wp, lp);
       
   488 }
       
   489 
       
   490 LRESULT CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp)
       
   491 {
       
   492     if (wp == PM_REMOVE) {
       
   493         QEventDispatcherWin32 *q = qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
       
   494         Q_ASSERT(q != 0);
       
   495         if (q) {
       
   496             QEventDispatcherWin32Private *d = q->d_func();
       
   497             int localSerialNumber = d->serialNumber;
       
   498             if (HIWORD(GetQueueStatus(QS_INPUT | QS_RAWINPUT | QS_TIMER)) == 0) {
       
   499                 // no more input or timer events in the message queue, we can allow posted events to be
       
   500                 // sent now
       
   501                 (void) d->wakeUps.fetchAndStoreRelease(0);
       
   502                 MSG *msg = (MSG *) lp;
       
   503                 if (localSerialNumber != d->lastSerialNumber
       
   504                     // if this message IS the one that triggers sendPostedEvents(), no need to post it again
       
   505                     && msg->hwnd != d->internalHwnd
       
   506                     && msg->message != WM_QT_SENDPOSTEDEVENTS) {
       
   507                     PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
   460                 }
   508                 }
   461             }
   509             }
   462         }
   510         }
   463         return 0;
   511     }
   464 
   512 #ifdef Q_OS_WINCE
   465     } else if (message == WM_TIMER) {
   513     return 0;
   466 
   514 #else
   467         MSG msg;
   515     return CallNextHookEx(0, code, wp, lp);
   468         msg.hwnd = hwnd;
   516 #endif
   469         msg.message = message;
       
   470         msg.wParam = wp;
       
   471         msg.lParam = lp;
       
   472 
       
   473         QCoreApplication *app = QCoreApplication::instance();
       
   474         Q_ASSERT_X(app, "qt_interal_proc", "Timer fired, but no QCoreApplication");
       
   475         if (!app) {
       
   476             KillTimer(hwnd, wp);
       
   477             return 0;
       
   478         }
       
   479 
       
   480         long result;
       
   481         if (app->filterEvent(&msg, &result))
       
   482             return result;
       
   483 
       
   484         QEventDispatcherWin32 *eventDispatcher =
       
   485             qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
       
   486         Q_ASSERT(eventDispatcher != 0);
       
   487         QEventDispatcherWin32Private *d = eventDispatcher->d_func();
       
   488         d->sendTimerEvent(wp);
       
   489         return 0;
       
   490     }
       
   491 
       
   492     return  DefWindowProc(hwnd, message, wp, lp);
       
   493 }
   517 }
   494 
   518 
   495 static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
   519 static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
   496 {
   520 {
   497     // make sure that multiple Qt's can coexist in the same process
   521     // make sure that multiple Qt's can coexist in the same process
   517                             0,                 // parent
   541                             0,                 // parent
   518                             0,                 // menu handle
   542                             0,                 // menu handle
   519                             qWinAppInst(),     // application
   543                             qWinAppInst(),     // application
   520                             0);                // windows creation data.
   544                             0);                // windows creation data.
   521 
   545 
       
   546     if (!wnd) {
       
   547         qWarning("QEventDispatcher: Failed to create QEventDispatcherWin32 internal window: %d\n", (int)GetLastError());
       
   548     }
       
   549 
   522 #ifdef GWLP_USERDATA
   550 #ifdef GWLP_USERDATA
   523     SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher);
   551     SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher);
   524 #else
   552 #else
   525     SetWindowLong(wnd, GWL_USERDATA, (LONG)eventDispatcher);
   553     SetWindowLong(wnd, GWL_USERDATA, (LONG)eventDispatcher);
   526 #endif
   554 #endif
   527 
   555 
   528     if (!wnd) {
       
   529         qWarning("QEventDispatcher: Failed to create QEventDispatcherWin32 internal window: %d\n", (int)GetLastError());
       
   530     }
       
   531     return wnd;
   556     return wnd;
   532 }
   557 }
   533 
   558 
   534 void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
   559 void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
   535 {
   560 {
   536     Q_ASSERT(internalHwnd);
   561     Q_ASSERT(internalHwnd);
   537 
   562 
   538     Q_Q(QEventDispatcherWin32);
   563     Q_Q(QEventDispatcherWin32);
   539 
   564 
   540     int ok = 0;
   565     int ok = 0;
   541 
   566     if (t->interval > 20 || !t->interval || !qtimeSetEvent) {
   542     //in the animation api, we delay the start of the animation
       
   543     //for the dock widgets, we need to use a system timer because dragging a native window
       
   544     //makes Windows start its own event loop.
       
   545     //So if this threshold changes, please change STARTSTOP_TIMER_DELAY in qabstractanimation.cpp accordingly.
       
   546     if (t->interval > 15 || !t->interval || !qtimeSetEvent) {
       
   547         ok = 1;
   567         ok = 1;
   548         if (!t->interval)  // optimization for single-shot-zero-timer
   568         if (!t->interval)  // optimization for single-shot-zero-timer
   549             QCoreApplication::postEvent(q, new QZeroTimerEvent(t->timerId));
   569             QCoreApplication::postEvent(q, new QZeroTimerEvent(t->timerId));
   550         else
   570         else
   551             ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
   571             ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
   606         sn_event |= FD_WRITE | FD_CONNECT;
   626         sn_event |= FD_WRITE | FD_CONNECT;
   607     if (sn_except.contains(socket))
   627     if (sn_except.contains(socket))
   608         sn_event |= FD_OOB;
   628         sn_event |= FD_OOB;
   609     // BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0
   629     // BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0
   610     // This is a BoundsChecker bug and not a Qt bug
   630     // This is a BoundsChecker bug and not a Qt bug
   611     WSAAsyncSelect(socket, internalHwnd, sn_event ? WM_USER : 0, sn_event);
   631     WSAAsyncSelect(socket, internalHwnd, sn_event ? WM_QT_SOCKETNOTIFIER : 0, sn_event);
   612 }
   632 }
   613 
   633 
   614 void QEventDispatcherWin32::createInternalHwnd()
   634 void QEventDispatcherWin32::createInternalHwnd()
   615 {
   635 {
   616     Q_D(QEventDispatcherWin32);
   636     Q_D(QEventDispatcherWin32);
   617 
   637 
   618     Q_ASSERT(!d->internalHwnd);
   638     Q_ASSERT(!d->internalHwnd);
   619     if (d->internalHwnd)
   639     if (d->internalHwnd)
   620         return;
   640         return;
   621     d->internalHwnd = qt_create_internal_window(this);
   641     d->internalHwnd = qt_create_internal_window(this);
       
   642 
       
   643 #ifndef Q_OS_WINCE
       
   644     // setup GetMessage hook needed to drive our posted events
       
   645     d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId());
       
   646     if (!d->getMessageHook) {
       
   647         qFatal("Qt: INTERNALL ERROR: failed to install GetMessage hook");
       
   648     }
       
   649 #endif
   622 
   650 
   623     // register all socket notifiers
   651     // register all socket notifiers
   624     QList<int> sockets = (d->sn_read.keys().toSet()
   652     QList<int> sockets = (d->sn_read.keys().toSet()
   625                           + d->sn_write.keys().toSet()
   653                           + d->sn_write.keys().toSet()
   626                           + d->sn_except.keys().toSet()).toList();
   654                           + d->sn_except.keys().toSet()).toList();
   628         d->doWsaAsyncSelect(sockets.at(i));
   656         d->doWsaAsyncSelect(sockets.at(i));
   629 
   657 
   630     // start all normal timers
   658     // start all normal timers
   631     for (int i = 0; i < d->timerVec.count(); ++i)
   659     for (int i = 0; i < d->timerVec.count(); ++i)
   632         d->registerTimer(d->timerVec.at(i));
   660         d->registerTimer(d->timerVec.at(i));
       
   661 
       
   662     // trigger a call to sendPostedEvents()
       
   663     wakeUp();
   633 }
   664 }
   634 
   665 
   635 QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent)
   666 QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent)
   636     : QAbstractEventDispatcher(*new QEventDispatcherWin32Private, parent)
   667     : QAbstractEventDispatcher(*new QEventDispatcherWin32Private, parent)
   637 {
   668 {
   651     d->interrupt = false;
   682     d->interrupt = false;
   652     emit awake();
   683     emit awake();
   653 
   684 
   654     bool canWait;
   685     bool canWait;
   655     bool retVal = false;
   686     bool retVal = false;
       
   687     bool seenWM_QT_SENDPOSTEDEVENTS = false;
       
   688     bool needWM_QT_SENDPOSTEDEVENTS = false;
   656     do {
   689     do {
   657         QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
       
   658 
       
   659         DWORD waitRet = 0;
   690         DWORD waitRet = 0;
   660         HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1];
   691         HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1];
   661         QVarLengthArray<MSG> processedTimers;
   692         QVarLengthArray<MSG> processedTimers;
   662         while (!d->interrupt) {
   693         while (!d->interrupt) {
   663             DWORD nCount = d->winEventNotifierList.count();
   694             DWORD nCount = d->winEventNotifierList.count();
   687                     // queue user input events for later processing
   718                     // queue user input events for later processing
   688                     haveMessage = false;
   719                     haveMessage = false;
   689                     d->queuedUserInputEvents.append(msg);
   720                     d->queuedUserInputEvents.append(msg);
   690                 }
   721                 }
   691                 if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers)
   722                 if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers)
   692                     && (msg.message == WM_USER && msg.hwnd == d->internalHwnd)) {
   723                     && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
   693                     // queue socket events for later processing
   724                     // queue socket events for later processing
   694                     haveMessage = false;
   725                     haveMessage = false;
   695                     d->queuedSocketEvents.append(msg);
   726                     d->queuedSocketEvents.append(msg);
   696                 }
   727                 }
   697             }
   728             }
   704                     // a new message has arrived, process it
   735                     // a new message has arrived, process it
   705                     continue;
   736                     continue;
   706                 }
   737                 }
   707             }
   738             }
   708             if (haveMessage) {
   739             if (haveMessage) {
   709                 if (msg.message == WM_TIMER) {
   740 #ifdef Q_OS_WINCE
       
   741                 // WinCE doesn't support hooks at all, so we have to call this by hand :(
       
   742                 (void) qt_GetMessageHook(0, PM_REMOVE, (LPARAM) &msg);
       
   743 #endif
       
   744 
       
   745                 if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
       
   746                     if (seenWM_QT_SENDPOSTEDEVENTS) {
       
   747                         needWM_QT_SENDPOSTEDEVENTS = true;
       
   748                         continue;
       
   749                     }
       
   750                     seenWM_QT_SENDPOSTEDEVENTS = true;
       
   751                 } else if (msg.message == WM_TIMER) {
   710                     // avoid live-lock by keeping track of the timers we've already sent
   752                     // avoid live-lock by keeping track of the timers we've already sent
   711                     bool found = false;
   753                     bool found = false;
   712                     for (int i = 0; !found && i < processedTimers.count(); ++i) {
   754                     for (int i = 0; !found && i < processedTimers.count(); ++i) {
   713                         const MSG processed = processedTimers.constData()[i];
   755                         const MSG processed = processedTimers.constData()[i];
   714                         found = (processed.wParam == msg.wParam && processed.hwnd == msg.hwnd && processed.lParam == msg.lParam);
   756                         found = (processed.wParam == msg.wParam && processed.hwnd == msg.hwnd && processed.lParam == msg.lParam);
   734             }
   776             }
   735             retVal = true;
   777             retVal = true;
   736         }
   778         }
   737 
   779 
   738         // still nothing - wait for message or signalled objects
   780         // still nothing - wait for message or signalled objects
   739         QThreadData *data = d->threadData;
       
   740         canWait = (!retVal
   781         canWait = (!retVal
   741                    && data->canWait
       
   742                    && !d->interrupt
   782                    && !d->interrupt
   743                    && (flags & QEventLoop::WaitForMoreEvents));
   783                    && (flags & QEventLoop::WaitForMoreEvents));
   744         if (canWait) {
   784         if (canWait) {
   745             DWORD nCount = d->winEventNotifierList.count();
   785             DWORD nCount = d->winEventNotifierList.count();
   746             Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);
   786             Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);
   754                 d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
   794                 d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
   755                 retVal = true;
   795                 retVal = true;
   756             }
   796             }
   757         }
   797         }
   758     } while (canWait);
   798     } while (canWait);
       
   799 
       
   800     if (!seenWM_QT_SENDPOSTEDEVENTS && (flags & QEventLoop::EventLoopExec) == 0) {
       
   801         // when called "manually", always send posted events
       
   802         QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
       
   803     }
       
   804 
       
   805     if (needWM_QT_SENDPOSTEDEVENTS)
       
   806         PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
   759 
   807 
   760     return retVal;
   808     return retVal;
   761 }
   809 }
   762 
   810 
   763 bool QEventDispatcherWin32::hasPendingEvents()
   811 bool QEventDispatcherWin32::hasPendingEvents()
   988 }
  1036 }
   989 
  1037 
   990 void QEventDispatcherWin32::wakeUp()
  1038 void QEventDispatcherWin32::wakeUp()
   991 {
  1039 {
   992     Q_D(QEventDispatcherWin32);
  1040     Q_D(QEventDispatcherWin32);
   993     SetEvent(d->wakeUpNotifier.handle());
  1041     d->serialNumber.ref();
       
  1042     if (d->internalHwnd && d->wakeUps.testAndSetAcquire(0, 1)) {
       
  1043         // post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending
       
  1044         PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
       
  1045     }
   994 }
  1046 }
   995 
  1047 
   996 void QEventDispatcherWin32::interrupt()
  1048 void QEventDispatcherWin32::interrupt()
   997 {
  1049 {
   998     Q_D(QEventDispatcherWin32);
  1050     Q_D(QEventDispatcherWin32);
  1001 }
  1053 }
  1002 
  1054 
  1003 void QEventDispatcherWin32::flush()
  1055 void QEventDispatcherWin32::flush()
  1004 { }
  1056 { }
  1005 
  1057 
  1006 
       
  1007 void QEventDispatcherWin32::startingUp()
  1058 void QEventDispatcherWin32::startingUp()
  1008 {
  1059 { }
  1009     Q_D(QEventDispatcherWin32);
       
  1010 
       
  1011     if (d->wakeUpNotifier.handle()) d->wakeUpNotifier.setEnabled(true);
       
  1012 }
       
  1013 
  1060 
  1014 void QEventDispatcherWin32::closingDown()
  1061 void QEventDispatcherWin32::closingDown()
  1015 {
  1062 {
  1016     Q_D(QEventDispatcherWin32);
  1063     Q_D(QEventDispatcherWin32);
  1017 
  1064 
  1026     // clean up any timers
  1073     // clean up any timers
  1027     for (int i = 0; i < d->timerVec.count(); ++i)
  1074     for (int i = 0; i < d->timerVec.count(); ++i)
  1028         d->unregisterTimer(d->timerVec.at(i), true);
  1075         d->unregisterTimer(d->timerVec.at(i), true);
  1029     d->timerVec.clear();
  1076     d->timerVec.clear();
  1030     d->timerDict.clear();
  1077     d->timerDict.clear();
       
  1078 
       
  1079 #ifndef Q_OS_WINCE
       
  1080     if (d->getMessageHook)
       
  1081         UnhookWindowsHookEx(d->getMessageHook);
       
  1082     d->getMessageHook = 0;
       
  1083 #endif
  1031 }
  1084 }
  1032 
  1085 
  1033 bool QEventDispatcherWin32::event(QEvent *e)
  1086 bool QEventDispatcherWin32::event(QEvent *e)
  1034 {
  1087 {
  1035     Q_D(QEventDispatcherWin32);
  1088     Q_D(QEventDispatcherWin32);