diff options
-rw-r--r-- | src/corelib/animation/qabstractanimation.cpp | 146 | ||||
-rw-r--r-- | src/corelib/animation/qabstractanimation.h | 31 | ||||
-rw-r--r-- | src/corelib/animation/qabstractanimation_p.h | 48 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_mac.mm | 2 | ||||
-rw-r--r-- | src/gui/text/qfontengine_mac.mm | 2 | ||||
-rw-r--r-- | tests/auto/qpauseanimation/tst_qpauseanimation.cpp | 5 |
6 files changed, 216 insertions, 18 deletions
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 641b42b..9add36e 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -166,11 +166,12 @@ Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer) #endif QUnifiedTimer::QUnifiedTimer() : - QObject(), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), + QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), currentAnimationIdx(0), consistentTiming(false), slowMode(false), slowdownFactor(5.0f), isPauseTimerActive(false), runningLeafAnimations(0) { time.invalidate(); + driver = &defaultDriver; } @@ -247,14 +248,27 @@ void QUnifiedTimer::restartAnimationTimer() qDebug() << runningPauseAnimations; qDebug() << closestPauseAnimationTimeToFinish(); } + driver->stop(); animationTimer.start(closestTimeToFinish, this); isPauseTimerActive = true; - } else if (!animationTimer.isActive() || isPauseTimerActive) { - animationTimer.start(timingInterval, this); + } else if (!driver->isRunning() || isPauseTimerActive) { + driver->start(); isPauseTimerActive = false; } } +void QUnifiedTimer::setTimingInterval(int interval) +{ + timingInterval = interval; + + if (driver->isRunning() && !isPauseTimerActive) { + //we changed the timing interval + driver->stop(); + driver->start(); + } +} + + void QUnifiedTimer::timerEvent(QTimerEvent *event) { //in the case of consistent timing we make sure the orders in which events come is always the same @@ -369,6 +383,129 @@ int QUnifiedTimer::closestPauseAnimationTimeToFinish() return closestTimeToFinish; } +void QUnifiedTimer::installAnimationDriver(QAnimationDriver *d) +{ + if (driver->isRunning()) { + qWarning("QUnifiedTimer: Cannot change animation driver while animations are running"); + return; + } + + if (driver && driver != &defaultDriver) + delete driver; + + driver = d; +} + +/*! + \class QAnimationDriver + + \brief The QAnimationDriver class is used to exchange the mechanism that drives animations. + + The default animation system is driven by a timer that fires at regular intervals. + In some scenarios, it is better to drive the animation based on other synchronization + mechanisms, such as the vertical refresh rate of the screen. + */ + +QAnimationDriver::QAnimationDriver(QObject *parent) + : QObject(*(new QAnimationDriverPrivate), parent) +{ +} + +QAnimationDriver::QAnimationDriver(QAnimationDriverPrivate &dd, QObject *parent) + : QObject(dd, parent) +{ +} + + +/*! + Advances the animation based on the current time. This function should + be continuously called by the driver while the animation is running. + */ +void QAnimationDriver::advance() +{ + QUnifiedTimer *instance = QUnifiedTimer::instance(); + + // update current time on all top level animations + instance->updateAnimationsTime(); + instance->restartAnimationTimer(); +} + + +/*! + Installs this animation driver. The animation driver is thread local and + will only apply for the thread its installed in. + */ +void QAnimationDriver::install() +{ + QUnifiedTimer *timer = QUnifiedTimer::instance(true); + timer->installAnimationDriver(this); +} + +bool QAnimationDriver::isRunning() const +{ + return d_func()->running; +} + + +void QAnimationDriver::start() +{ + Q_D(QAnimationDriver); + if (!d->running) { + started(); + d->running = true; + } +} + + +void QAnimationDriver::stop() +{ + Q_D(QAnimationDriver); + if (d->running) { + stopped(); + d->running = false; + } +} + +/*! + \fn QAnimationDriver::started() + + This function is called by the animation framework to notify the driver + that it should start running. + */ + +/*! + \fn QAnimationDriver::stopped() + + This function is called by the animation framework to notify the driver + that it should stop running. + */ + +/*! + The default animation driver just spins the timer... + */ +QDefaultAnimationDriver::QDefaultAnimationDriver(QUnifiedTimer *timer) + : QAnimationDriver(0), m_unified_timer(timer) +{ +} + +void QDefaultAnimationDriver::timerEvent(QTimerEvent *e) +{ + Q_ASSERT(e->timerId() == m_timer.timerId()); + advance(); +} + +void QDefaultAnimationDriver::started() +{ + m_timer.start(m_unified_timer->timingInterval, this); +} + +void QDefaultAnimationDriver::stopped() +{ + m_timer.stop(); +} + + + void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) { Q_Q(QAbstractAnimation); @@ -794,6 +931,9 @@ void QAbstractAnimation::stop() { Q_D(QAbstractAnimation); + if (d->state == Stopped) + return; + d->setState(Stopped); } diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h index d3c0d0d..6abe8c1 100644 --- a/src/corelib/animation/qabstractanimation.h +++ b/src/corelib/animation/qabstractanimation.h @@ -54,6 +54,7 @@ QT_MODULE(Core) class QAnimationGroup; class QSequentialAnimationGroup; +class QAnimationDriver; class QAbstractAnimationPrivate; class Q_CORE_EXPORT QAbstractAnimation : public QObject @@ -132,6 +133,36 @@ private: Q_DECLARE_PRIVATE(QAbstractAnimation) }; +class QAnimationDriverPrivate; +class Q_CORE_EXPORT QAnimationDriver : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QAnimationDriver) + +public: + QAnimationDriver(QObject *parent); + + void advance(); + void install(); + + bool isRunning() const; + +protected: + virtual void started() = 0; + virtual void stopped() = 0; + + QAnimationDriver(QAnimationDriverPrivate &dd, QObject *parent = 0); + +private: + friend class QUnifiedTimer; + + void start(); + void stop(); +}; + + + + #endif //QT_NO_ANIMATION QT_END_NAMESPACE diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index d3d4098..bc3746d 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -58,6 +58,7 @@ #include <QtCore/qtimer.h> #include <QtCore/qelapsedtimer.h> #include <private/qobject_p.h> +#include <qabstractanimation.h> #ifdef Q_OS_WIN #include <qt_windows.h> @@ -114,6 +115,30 @@ private: Q_DECLARE_PUBLIC(QAbstractAnimation) }; + +class QUnifiedTimer; +class QDefaultAnimationDriver : public QAnimationDriver +{ + Q_OBJECT +public: + QDefaultAnimationDriver(QUnifiedTimer *timer); + void timerEvent(QTimerEvent *e); + + void started(); + void stopped(); + +private: + QBasicTimer m_timer; + QUnifiedTimer *m_unified_timer; +}; + +class Q_CORE_EXPORT QAnimationDriverPrivate : public QObjectPrivate +{ +public: + QAnimationDriverPrivate() : running(false) {} + bool running; +}; + typedef QElapsedTimer ElapsedTimer; class QUnifiedTimer : public QObject @@ -130,14 +155,7 @@ public: static void unregisterAnimation(QAbstractAnimation *animation); //defines the timing interval. Default is DEFAULT_TIMER_INTERVAL - void setTimingInterval(int interval) - { - timingInterval = interval; - if (animationTimer.isActive() && !isPauseTimerActive) { - //we changed the timing interval - animationTimer.start(timingInterval, this); - } - } + void setTimingInterval(int interval); /* this allows to have a consistent timer interval at each tick from the timer @@ -161,11 +179,20 @@ public: */ static void updateAnimationTimer(); + void installAnimationDriver(QAnimationDriver *driver); + + void restartAnimationTimer(); + void updateAnimationsTime(); + protected: void timerEvent(QTimerEvent *); private: - // timer used for all active (running) animations + friend class QDefaultAnimationDriver; + + QAnimationDriver *driver; + QDefaultAnimationDriver defaultDriver; + QBasicTimer animationTimer; // timer used to delay the check if we should start/stop the animation timer QBasicTimer startStopAnimationTimer; @@ -195,9 +222,6 @@ private: void registerRunningAnimation(QAbstractAnimation *animation); void unregisterRunningAnimation(QAbstractAnimation *animation); - void restartAnimationTimer(); - - void updateAnimationsTime(); int closestPauseAnimationTimeToFinish(); }; diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index e5364d0..3aafeb4 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -549,7 +549,7 @@ void qt_mac_update_os_settings() FontMap("QTipLabel", kThemeSmallSystemFont), FontMap("QLabel", kThemeSystemFont), FontMap("QToolButton", kThemeSmallSystemFont), - FontMap("QMenuItem", kThemeMenuItemCmdKeyFont), // It doesn't exist, but its unique. + FontMap("QMenuItem", kThemeMenuItemFont), // It doesn't exist, but its unique. FontMap("QComboLineEdit", kThemeViewsFont), // It doesn't exist, but its unique. FontMap("QSmallFont", kThemeSmallSystemFont), // It doesn't exist, but its unique. FontMap("QMiniFont", kThemeMiniSystemFont), // It doesn't exist, but its unique. diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 7efb1cc..51e18ec 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -694,7 +694,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition CGContextSetFont(ctx, cgFont); qreal pos_x = -br.x.toReal() + subPixelPosition.toReal(); - qreal pos_y = im.height()+br.y.toReal(); + qreal pos_y = im.height() + br.y.toReal() - 1; CGContextSetTextPosition(ctx, pos_x, pos_y); CGSize advance; diff --git a/tests/auto/qpauseanimation/tst_qpauseanimation.cpp b/tests/auto/qpauseanimation/tst_qpauseanimation.cpp index 605cee6..378eb1c 100644 --- a/tests/auto/qpauseanimation/tst_qpauseanimation.cpp +++ b/tests/auto/qpauseanimation/tst_qpauseanimation.cpp @@ -394,7 +394,10 @@ void tst_QPauseAnimation::multipleSequentialGroups() QVERIFY(subgroup3.state() == QAbstractAnimation::Running); QVERIFY(subgroup4.state() == QAbstractAnimation::Running); - QTest::qWait(group.totalDuration() + 100); + // This is a pretty long animation so it tends to get rather out of sync + // when using the consistent timer, so run for an extra half second for good + // measure... + QTest::qWait(group.totalDuration() + 500); #ifdef Q_OS_WIN if (group.state() != QAbstractAnimation::Stopped) |