diff options
author | Bernd Weimer <bweimer@rim.com> | 2012-10-19 08:43:32 (GMT) |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-10-30 16:35:27 (GMT) |
commit | 7301665b57745a0b6d7b551834d603c6aa275b8c (patch) | |
tree | 45c166d8ee72c0214c03fbff03d8221149adc88b | |
parent | 2d487381e8537024bbb10b03d324cea6b6060185 (diff) | |
download | Qt-7301665b57745a0b6d7b551834d603c6aa275b8c.zip Qt-7301665b57745a0b6d7b551834d603c6aa275b8c.tar.gz Qt-7301665b57745a0b6d7b551834d603c6aa275b8c.tar.bz2 |
Blackberry: Fix for slowness of touch move events
In the event dispatcher native events will be processed in a tight
loop to drain the queue. IO events and timers will be postponed.
Backported from c4b2d77f40a42a67480bb49aa63b0953c80c024a
Change-Id: Iaf408425000e7fd6fdbf0992bbf927d03a650581
Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com>
Reviewed-by: Kevin Krammer <kevin.krammer@kdab.com>
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com>
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_blackberry.cpp | 106 |
1 files changed, 46 insertions, 60 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp index 3c00e91..366bacb 100644 --- a/src/corelib/kernel/qeventdispatcher_blackberry.cpp +++ b/src/corelib/kernel/qeventdispatcher_blackberry.cpp @@ -43,7 +43,6 @@ #include "qsocketnotifier.h" #include "qdebug.h" #include "qelapsedtimer.h" -#include "qthread.h" #include <bps/bps.h> #include <bps/event.h> @@ -244,28 +243,6 @@ void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notif } } -static inline bool updateTimeout(int *timeout, const struct timeval &start) -{ - // A timeout of -1 means we should block indefinitely. If we get here, we got woken up by a - // non-IO BPS event, and that event has been processed already. This means we can go back and - // block in bps_get_event(). - // Note that processing the BPS event might have triggered a wakeup, in that case we get a - // IO event in the next bps_get_event() right away. - if (*timeout == -1) - return true; - - if (Q_UNLIKELY(!QElapsedTimer::isMonotonic())) { - // we cannot recalculate the timeout without a monotonic clock as the time may have changed - return false; - } - - // clock source is monotonic, so we can recalculate how much timeout is left - timeval t2 = qt_gettime(); - int elapsed = (t2.tv_sec * 1000 + t2.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); - *timeout -= elapsed; - return *timeout >= 0; -} - int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timeval *timeout) { @@ -292,63 +269,72 @@ int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writef FD_ZERO(exceptfds); // Convert timeout to milliseconds - int timeout_bps = -1; + int timeoutTotal = -1; if (timeout) - timeout_bps = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); + timeoutTotal = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); + + int timeoutLeft = timeoutTotal; - bool hasProcessedEventsOnce = false; bps_event_t *event = 0; + unsigned int eventCount = 0; // This loop exists such that we can drain the bps event queue of all native events // more efficiently than if we were to return control to Qt after each event. This // is important for handling touch events which can come in rapidly. forever { - Q_ASSERT(!hasProcessedEventsOnce || event); - - // Only emit the awake() and aboutToBlock() signals in the second iteration. For the first - // iteration, the UNIX event dispatcher will have taken care of that already. - if (hasProcessedEventsOnce) - emit awake(); - - // Filtering the native event should happen between the awake() and aboutToBlock() signal - // emissions. The calls awake() - filterNativeEvent() - aboutToBlock() - bps_get_event() - // need not to be interrupted by a break or return statement. - // - // Because of this, the native event is actually processed one loop iteration - // after it was retrieved with bps_get_event(). - if (event) - filterEvent((void*)event); - - if (hasProcessedEventsOnce) - emit aboutToBlock(); + // Only emit the awake() and aboutToBlock() signals in the second iteration. For the + // first iteration, the UNIX event dispatcher will have taken care of that already. + // Also native events are actually processed one loop iteration after they were + // retrieved with bps_get_event(). + + // Filtering the native event should happen between the awake() and aboutToBlock() + // signal emissions. The calls awake() - filterNativeEvent() - aboutToBlock() - + // bps_get_event() need not to be interrupted by a break or return statement. + if (eventCount > 0) { + if (event) { + emit awake(); + filterEvent(static_cast<void*>(event)); + emit aboutToBlock(); + } + + // Update the timeout + // Clock source is monotonic, so we can recalculate how much timeout is left + if (timeoutTotal != -1) { + timeval t2 = qt_gettime(); + timeoutLeft = timeoutTotal - ((t2.tv_sec * 1000 + t2.tv_usec / 1000) + - (startTime.tv_sec * 1000 + startTime.tv_usec / 1000)); + if (timeoutLeft < 0) + timeoutLeft = 0; + } + } // Wait for event or file to be ready event = 0; - const int result = bps_get_event(&event, timeout_bps); + const int result = bps_get_event(&event, timeoutLeft); if (result != BPS_SUCCESS) qWarning("QEventDispatcherBlackberry::select: bps_get_event() failed"); - // In the case of !event, we break out of the loop to let Qt process the timers - // that are now ready (since timeout has expired). - // In the case of bpsIOReadyDomain, we break out to let Qt process the FDs that - // are ready. If we do not do this activation of QSocketNotifiers etc would be - // delayed. - if (!event || bps_event_get_domain(event) == bpsIOReadyDomain) - break; + if (!event) // In case of !event, we break out of the loop to let Qt process the timers + break; // (since timeout has expired) and socket notifiers that are now ready. - // Update the timeout. If this fails we have exceeded our alloted time or the system - // clock has changed time and we cannot calculate a new timeout so we bail out. - if (!updateTimeout(&timeout_bps, startTime)) { + if (bps_event_get_domain(event) == bpsIOReadyDomain) { + timeoutTotal = 0; // in order to immediately drain the event queue of native events + event = 0; // (especially touch move events) we don't break out here + } - // No more loop iteration, so we need to filter the event here. - filterEvent((void*)event); + ++eventCount; + + // Make sure we are not trapped in this loop due to continuous native events + // also we cannot recalculate the timeout without a monotonic clock as the time may have changed + const unsigned int maximumEventCount = 12; + if (Q_UNLIKELY((eventCount > maximumEventCount && timeoutLeft == 0) + || !QElapsedTimer::isMonotonic())) { + if (event) + filterEvent(static_cast<void*>(event)); break; } - - hasProcessedEventsOnce = true; } - // the number of bits set in the file sets return d->ioData->count; } |