diff options
-rw-r--r-- | src/corelib/animation/qabstractanimation.cpp | 12 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win.cpp | 180 | ||||
-rw-r--r-- | src/gui/kernel/qapplication.cpp | 3 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_p.h | 3 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_win.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qbackingstore.cpp | 12 |
6 files changed, 96 insertions, 116 deletions
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index c775a00..df8b548 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -157,19 +157,7 @@ #ifndef QT_NO_ANIMATION #define DEFAULT_TIMER_INTERVAL 16 - -#ifdef Q_WS_WIN - /// Fix for Qt 4.7 - //on windows if you're currently dragging a widget an inner eventloop was started by the system - //to make sure that this timer is getting fired, we need to make sure to use the system timers - //that will send a WM_TIMER event. We do that by settings the timer interval to 11 - //It is 16 because QEventDispatcherWin32Private::registerTimer specifically checks if the interval - //is greater than 11 to determine if it should use a system timer (or the multimedia timer). -#define STARTSTOP_TIMER_DELAY 16 -#else #define STARTSTOP_TIMER_DELAY 0 -#endif - QT_BEGIN_NAMESPACE diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 1e6402f..df4c02d 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -64,6 +64,15 @@ extern uint qGlobalPostedEventsCount(); # define TIME_KILL_SYNCHRONOUS 0x0100 #endif +#ifndef QS_RAWINPUT +# define QS_RAWINPUT 0x0400 +#endif + +enum { + WM_QT_SOCKETNOTIFIER = WM_USER, + WM_QT_SENDPOSTEDEVENTS = WM_USER + 1 +}; + #if defined(Q_OS_WINCE) QT_BEGIN_INCLUDE_NAMESPACE #include <winsock.h> @@ -327,6 +336,11 @@ public: // internal window handle used for socketnotifiers/timers/etc HWND internalHwnd; + // for controlling when to send posted events + QAtomicInt serialNumber; + int lastSerialNumber; + QAtomicInt wakeUps; + // timers WinTimerVec timerVec; WinTimerDict timerDict; @@ -340,9 +354,6 @@ public: QSNDict sn_except; void doWsaAsyncSelect(int socket); - // event notifier - QWinEventNotifier wakeUpNotifier; - QList<QWinEventNotifier *> winEventNotifierList; void activateEventNotifier(QWinEventNotifier * wen); @@ -351,19 +362,13 @@ public: }; QEventDispatcherWin32Private::QEventDispatcherWin32Private() - : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0) + : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0), serialNumber(0), lastSerialNumber(0), wakeUps(0) { resolveTimerAPI(); - - wakeUpNotifier.setHandle(CreateEvent(0, FALSE, FALSE, 0)); - if (!wakeUpNotifier.handle()) - qWarning("QEventDispatcher: Creating QEventDispatcherWin32Private wakeup event failed"); } QEventDispatcherWin32Private::~QEventDispatcherWin32Private() { - wakeUpNotifier.setEnabled(false); - CloseHandle(wakeUpNotifier.handle()); if (internalHwnd) DestroyWindow(internalHwnd); QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc)); @@ -408,22 +413,35 @@ void WINAPI CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/, DWORD_P LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) { - if (message == WM_NCCREATE) { - return true; - } else if (message == WM_USER) { + if (message == WM_NCCREATE) + return true; - // socket notifier message - MSG msg; - msg.hwnd = hwnd; - msg.message = message; - msg.wParam = wp; - msg.lParam = lp; + MSG msg; + msg.hwnd = hwnd; + msg.message = message; + msg.wParam = wp; + msg.lParam = lp; + QCoreApplication *app = QCoreApplication::instance(); + long result; + if (!app) { + if (message == WM_TIMER) + KillTimer(hwnd, wp); + return 0; + } else if (app->filterEvent(&msg, &result)) { + return result; + } - QCoreApplication *app = QCoreApplication::instance(); - long result; - if (app && app->filterEvent(&msg, &result)) - return result; +#ifdef GWLP_USERDATA + QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA); +#else + QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA); +#endif + QEventDispatcherWin32Private *d = 0; + if (q != 0) + d = q->d_func(); + if (message == WM_QT_SOCKETNOTIFIER) { + // socket notifier message int type = -1; switch (WSAGETSELECTEVENT(lp)) { case FD_READ: @@ -440,56 +458,50 @@ LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) break; } if (type >= 0) { - - #ifdef GWLP_USERDATA - QEventDispatcherWin32 *eventDispatcher = - (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA); - #else - QEventDispatcherWin32 *eventDispatcher = - (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA); - #endif - if (eventDispatcher) { - QEventDispatcherWin32Private *d = eventDispatcher->d_func(); - QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except }; - QSNDict *dict = sn_vec[type]; - - QSockNot *sn = dict ? dict->value(wp) : 0; - if (sn) { - QEvent event(QEvent::SockAct); - QCoreApplication::sendEvent(sn->obj, &event); - } + Q_ASSERT(d != 0); + QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except }; + QSNDict *dict = sn_vec[type]; + + QSockNot *sn = dict ? dict->value(wp) : 0; + if (sn) { + QEvent event(QEvent::SockAct); + QCoreApplication::sendEvent(sn->obj, &event); } } return 0; - - } else if (message == WM_TIMER) { - - MSG msg; - msg.hwnd = hwnd; - msg.message = message; - msg.wParam = wp; - msg.lParam = lp; - - QCoreApplication *app = QCoreApplication::instance(); - Q_ASSERT_X(app, "qt_interal_proc", "Timer fired, but no QCoreApplication"); - if (!app) { - KillTimer(hwnd, wp); - return 0; + } else if (message == WM_TIMER) { + if (wp == ~0u) { + KillTimer(d->internalHwnd, wp); + int localSerialNumber = d->serialNumber; + (void) d->wakeUps.fetchAndStoreRelease(0); + if (localSerialNumber != d->lastSerialNumber) { + PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0); + } + } else { + Q_ASSERT(d != 0); + d->sendTimerEvent(wp); + } + return 0; + } else if (message == WM_QT_SENDPOSTEDEVENTS) { + int localSerialNumber = d->serialNumber; + + if (GetQueueStatus(QS_INPUT | QS_RAWINPUT | QS_TIMER) != 0) { + // delay the next pass of sendPostedEvents() until we get the special + // WM_TIMER, which allows all pending Windows messages to be processed + SetTimer(d->internalHwnd, ~0u, 0, 0); + } else { + // nothing pending in the queue, let sendPostedEvents go through + d->wakeUps.fetchAndStoreRelease(0); } - long result; - if (app->filterEvent(&msg, &result)) - return result; - - QEventDispatcherWin32 *eventDispatcher = - qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance()); - Q_ASSERT(eventDispatcher != 0); - QEventDispatcherWin32Private *d = eventDispatcher->d_func(); - d->sendTimerEvent(wp); + if (localSerialNumber != d->lastSerialNumber) { + d->lastSerialNumber = localSerialNumber; + QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData); + } return 0; } - return DefWindowProc(hwnd, message, wp, lp); + return DefWindowProc(hwnd, message, wp, lp); } static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher) @@ -538,11 +550,6 @@ void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t) Q_Q(QEventDispatcherWin32); int ok = 0; - - //in the animation api, we delay the start of the animation - //for the dock widgets, we need to use a system timer because dragging a native window - //makes Windows start its own event loop. - //So if this threshold changes, please change STARTSTOP_TIMER_DELAY in qabstractanimation.cpp accordingly. if (t->interval > 15 || !t->interval || !qtimeSetEvent) { ok = 1; if (!t->interval) // optimization for single-shot-zero-timer @@ -608,7 +615,7 @@ void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket) sn_event |= FD_OOB; // BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0 // This is a BoundsChecker bug and not a Qt bug - WSAAsyncSelect(socket, internalHwnd, sn_event ? WM_USER : 0, sn_event); + WSAAsyncSelect(socket, internalHwnd, sn_event ? WM_QT_SOCKETNOTIFIER : 0, sn_event); } void QEventDispatcherWin32::createInternalHwnd() @@ -630,6 +637,9 @@ void QEventDispatcherWin32::createInternalHwnd() // start all normal timers for (int i = 0; i < d->timerVec.count(); ++i) d->registerTimer(d->timerVec.at(i)); + + // trigger a call to sendPostedEvents() + wakeUp(); } QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent) @@ -654,11 +664,10 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) bool canWait; bool retVal = false; do { - QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData); - DWORD waitRet = 0; HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1]; QVarLengthArray<MSG> processedTimers; + bool seenWM_QT_SENDPOSTEDEVENTS = false; while (!d->interrupt) { DWORD nCount = d->winEventNotifierList.count(); Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1); @@ -689,7 +698,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) d->queuedUserInputEvents.append(msg); } if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers) - && (msg.message == WM_USER && msg.hwnd == d->internalHwnd)) { + && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) { // queue socket events for later processing haveMessage = false; d->queuedSocketEvents.append(msg); @@ -706,7 +715,13 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) } } if (haveMessage) { - if (msg.message == WM_TIMER) { + if (msg.message == WM_QT_SENDPOSTEDEVENTS && !(flags & QEventLoop::EventLoopExec)) { + if (seenWM_QT_SENDPOSTEDEVENTS) { + PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0); + break; + } + seenWM_QT_SENDPOSTEDEVENTS = true; + } else if (msg.message == WM_TIMER) { // avoid live-lock by keeping track of the timers we've already sent bool found = false; for (int i = 0; !found && i < processedTimers.count(); ++i) { @@ -736,9 +751,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) } // still nothing - wait for message or signalled objects - QThreadData *data = d->threadData; canWait = (!retVal - && data->canWait && !d->interrupt && (flags & QEventLoop::WaitForMoreEvents)); if (canWait) { @@ -990,7 +1003,11 @@ void QEventDispatcherWin32::activateEventNotifiers() void QEventDispatcherWin32::wakeUp() { Q_D(QEventDispatcherWin32); - SetEvent(d->wakeUpNotifier.handle()); + d->serialNumber.ref(); + if (d->internalHwnd && d->wakeUps.testAndSetAcquire(0, 1)) { + // post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending + PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0); + } } void QEventDispatcherWin32::interrupt() @@ -1003,13 +1020,8 @@ void QEventDispatcherWin32::interrupt() void QEventDispatcherWin32::flush() { } - void QEventDispatcherWin32::startingUp() -{ - Q_D(QEventDispatcherWin32); - - if (d->wakeUpNotifier.handle()) d->wakeUpNotifier.setEnabled(true); -} +{ } void QEventDispatcherWin32::closingDown() { diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index f48c551..9658f5e 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -474,9 +474,6 @@ bool QApplicationPrivate::fade_tooltip = false; bool QApplicationPrivate::animate_toolbox = false; bool QApplicationPrivate::widgetCount = false; bool QApplicationPrivate::load_testability = false; -#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) -bool QApplicationPrivate::inSizeMove = false; -#endif #ifdef QT_KEYPAD_NAVIGATION # ifdef Q_OS_SYMBIAN Qt::NavigationMode QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional; diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 65f61e9..0fa7269 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -441,9 +441,6 @@ public: #ifdef Q_WS_MAC static bool native_modal_dialog_active; #endif -#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) - static bool inSizeMove; -#endif static void setSystemPalette(const QPalette &pal); static void setPalette_helper(const QPalette &palette, const char* className, bool clearWidgetPaletteHash); diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 5bb25fa..522f1ac 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -1916,11 +1916,9 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam #ifndef Q_WS_WINCE case WM_ENTERSIZEMOVE: autoCaptureWnd = hwnd; - QApplicationPrivate::inSizeMove = true; break; case WM_EXITSIZEMOVE: autoCaptureWnd = 0; - QApplicationPrivate::inSizeMove = false; break; #endif case WM_MOVE: // move window diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 7c07df8..7facd91 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -497,18 +497,6 @@ static inline void sendUpdateRequest(QWidget *widget, bool updateImmediately) if (!widget) return; -#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) - if (QApplicationPrivate::inSizeMove && widget->internalWinId() && !updateImmediately - && !widget->testAttribute(Qt::WA_DontShowOnScreen)) { - // Tell Windows to send us a paint event if we're in WM_SIZE/WM_MOVE; posted events - // are blocked until the mouse button is released. See task 146849. - const QRegion rgn(qt_dirtyRegion(widget)); - InvalidateRgn(widget->internalWinId(), rgn.handle(), false); - qt_widget_private(widget)->dirty = QRegion(); - return; - } -#endif - if (updateImmediately) { QEvent event(QEvent::UpdateRequest); QApplication::sendEvent(widget, &event); |