diff --git a/src/qml/animations/qabstractanimationjob.cpp b/src/qml/animations/qabstractanimationjob.cpp
index 343338c661c5fe0083e4f465c5fba0806cf966a6..da961763ede1f8f17edb757d130180b72078a610 100644
--- a/src/qml/animations/qabstractanimationjob.cpp
+++ b/src/qml/animations/qabstractanimationjob.cpp
@@ -277,6 +277,8 @@ QAbstractAnimationJob::QAbstractAnimationJob()
     , m_isGroup(false)
     , m_disableUserControl(false)
     , m_hasCurrentTimeChangeListeners(false)
+    , m_isRenderThreadJob(false)
+    , m_isRenderThreadProxy(false)
 
 {
 }
diff --git a/src/qml/animations/qabstractanimationjob_p.h b/src/qml/animations/qabstractanimationjob_p.h
index abf3cd6df6060b8f09f6c3c4a56f728a6ee7fb2e..95a238405cfd0ac6ddd2b7fd5265dc03560c7216 100644
--- a/src/qml/animations/qabstractanimationjob_p.h
+++ b/src/qml/animations/qabstractanimationjob_p.h
@@ -113,6 +113,10 @@ public:
     QAbstractAnimationJob *nextSibling() const { return m_nextSibling; }
     QAbstractAnimationJob *previousSibling() const { return m_previousSibling; }
 
+    bool isGroup() const { return m_isGroup; }
+    bool isRenderThreadJob() const { return m_isRenderThreadJob; }
+    bool isRenderThreadProxy() const { return m_isRenderThreadProxy; }
+
 protected:
     virtual void updateCurrentTime(int) {}
     virtual void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState);
@@ -157,6 +161,8 @@ protected:
     bool m_isGroup:1;
     bool m_disableUserControl:1;
     bool m_hasCurrentTimeChangeListeners:1;
+    bool m_isRenderThreadJob:1;
+    bool m_isRenderThreadProxy:1;
 
     friend class QQmlAnimationTimer;
     friend class QAnimationGroupJob;
diff --git a/src/quick/doc/snippets/qml/animators.qml b/src/quick/doc/snippets/qml/animators.qml
new file mode 100644
index 0000000000000000000000000000000000000000..4b9e4f425089c40b136ae6247554890d290f62a3
--- /dev/null
+++ b/src/quick/doc/snippets/qml/animators.qml
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+**     of its contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+
+Rectangle {
+
+    width: 320
+    height: 480
+
+    color: "steelblue"
+
+    Grid {
+        anchors.fill: parent
+        anchors.margins: 20
+        columnSpacing: 30
+        rowSpacing: 30
+        columns: 4
+        rows: 4
+
+        property real cellWidth: (width - (columns - 1) * columnSpacing) / columns;
+        property real cellHeight: (height - (rows - 1) * rowSpacing) / rows;
+
+        Item {
+            width: parent.cellWidth
+            height: parent.cellHeight
+//! [x on]
+Rectangle {
+    width: 50
+    height: 50
+    color: "lightsteelblue"
+    XAnimator on x {
+        from: 10;
+        to: 0;
+        duration: 1000
+    }
+}
+//! [x on]
+        }
+        Item {
+            width: parent.cellWidth
+            height: parent.cellHeight
+//! [x target]
+Rectangle {
+    id: xmovingBox
+    width: 50
+    height: 50
+    color: "lightsteelblue"
+    XAnimator {
+        target: xmovingBox;
+        from: 10;
+        to: 0;
+        duration: 1000
+        running: true
+    }
+}
+//! [x target]
+    }
+    Item {
+        width: parent.cellWidth
+        height: parent.cellHeight
+//! [y on]
+Rectangle {
+    width: 50
+    height: 50
+    color: "lightsteelblue"
+    YAnimator on y {
+        from: 10;
+        to: 0;
+        duration: 1000
+    }
+}
+//! [y on]
+    }
+    Item {
+        width: parent.cellWidth
+        height: parent.cellHeight
+//! [y target]
+Rectangle {
+    id: ymovingBox
+    width: 50
+    height: 50
+    color: "lightsteelblue"
+    YAnimator {
+        target: ymovingBox;
+        from: 10;
+        to: 0;
+        duration: 1000
+        running: true
+    }
+}
+//! [y target]
+    }
+//! [rotation on]
+Rectangle {
+    width: 50
+    height: 50
+    color: "lightsteelblue"
+    RotationAnimator on rotation {
+        from: 0;
+        to: 360;
+        duration: 1000
+    }
+}
+//! [rotation on]
+//! [rotation target]
+Rectangle {
+    id: rotatingBox
+    width: 50
+    height: 50
+    color: "lightsteelblue"
+    RotationAnimator {
+        target: rotatingBox;
+        from: 0;
+        to: 360;
+        duration: 1000
+        running: true
+    }
+}
+//! [rotation target]
+//! [scale on]
+Rectangle {
+    width: 50
+    height: 50
+    color: "lightsteelblue"
+    ScaleAnimator on scale {
+        from: 0.5;
+        to: 1;
+        duration: 1000
+    }
+}
+//! [scale on]
+//! [scale target]
+Rectangle {
+    id: scalingBox
+    width: 50
+    height: 50
+    color: "lightsteelblue"
+    ScaleAnimator {
+        target: scalingBox;
+        from: 0.5;
+        to: 1;
+        duration: 1000
+        running: true
+    }
+}
+//! [scale target]
+//! [opacity on]
+Rectangle {
+    width: 50
+    height: 50
+    color: "lightsteelblue"
+    OpacityAnimator on opacity{
+        from: 0;
+        to: 1;
+        duration: 1000
+    }
+}
+//! [opacity on]
+//! [opacity target]
+Rectangle {
+    id: opacityBox
+    width: 50
+    height: 50
+    color: "lightsteelblue"
+    OpacityAnimator {
+        target: opacityBox;
+        from: 0;
+        to: 1;
+        duration: 1000
+        running: true
+    }
+}
+//! [opacity target]
+//![shaderon]
+ShaderEffect {
+    width: 50
+    height: 50
+    property variant t;
+    UniformAnimator on t {
+        from: 0
+        to: 1
+        duration: 1000
+    }
+    fragmentShader:
+    "
+        uniform lowp float t;
+        varying highp vec2 qt_TexCoord0;
+        void main() {
+            lowp float c = qt_TexCoord0.y;
+            gl_FragColor = vec4(c * t, 0, 0, 1);
+        }
+    "
+}
+//![shaderon]
+//![shader target]
+ShaderEffect {
+    id: shader
+    width: 50
+    height: 50
+    property variant t;
+    UniformAnimator {
+        target: shader
+        uniform: "t"
+        from: 0
+        to: 1
+        duration: 1000
+        running: true
+    }
+    fragmentShader:
+    "
+        uniform lowp float t;
+        varying highp vec2 qt_TexCoord0;
+        void main() {
+            lowp float c = qt_TexCoord0.y;
+            gl_FragColor = vec4(0, 0, c * t, 1);
+        }
+    "
+}
+//![shader target]
+//![mixed]
+Rectangle {
+    id: mixBox
+    width: 50
+    height: 50
+    ParallelAnimation {
+        ColorAnimation {
+            target: mixBox
+            property: "color"
+            from: "forestgreen"
+            to: "lightsteelblue";
+            duration: 1000
+        }
+        ScaleAnimator {
+            target: mixBox
+            from: 2
+            to: 1
+            duration: 1000
+        }
+        running: true
+    }
+}
+//! [mixed]
+    }
+}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 5b4145e23556d5f09fb2a72681eaa809e87986ea..923b7605e1820e4e19e6f4a137ed3cb3d006d128 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -53,6 +53,7 @@
 #include <QtQuick/private/qsgflashnode_p.h>
 
 #include <private/qsgrenderloop_p.h>
+#include <private/qquickanimatorcontroller_p.h>
 
 #include <private/qguiapplication_p.h>
 #include <QtGui/QInputMethod>
@@ -319,6 +320,8 @@ void QQuickWindowPrivate::syncSceneGraph()
     QML_MEMORY_SCOPE_STRING("SceneGraph");
     Q_Q(QQuickWindow);
 
+    animationController->beforeNodeSync();
+
     emit q->beforeSynchronizing();
     if (!renderer) {
         forceUpdate(contentItem);
@@ -331,6 +334,8 @@ void QQuickWindowPrivate::syncSceneGraph()
 
     updateDirtyNodes();
 
+    animationController->afterNodeSync();
+
     // Copy the current state of clearing from window into renderer.
     renderer->setClearColor(clearColor);
     QSGRenderer::ClearMode mode = QSGRenderer::ClearStencilBuffer | QSGRenderer::ClearDepthBuffer;
@@ -344,6 +349,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size)
 {
     QML_MEMORY_SCOPE_STRING("SceneGraph");
     Q_Q(QQuickWindow);
+    animationController->advance();
     emit q->beforeRendering();
     int fboId = 0;
     const qreal devicePixelRatio = q->devicePixelRatio();
@@ -414,6 +420,9 @@ void QQuickWindowPrivate::init(QQuickWindow *c)
     q->setSurfaceType(QWindow::OpenGLSurface);
     q->setFormat(context->defaultSurfaceFormat());
 
+    animationController = new QQuickAnimatorController();
+    animationController->window = q;
+
     QObject::connect(context, SIGNAL(initialized()), q, SIGNAL(sceneGraphInitialized()), Qt::DirectConnection);
     QObject::connect(context, SIGNAL(invalidated()), q, SIGNAL(sceneGraphInvalidated()), Qt::DirectConnection);
     QObject::connect(context, SIGNAL(invalidated()), q, SLOT(cleanupSceneGraph()), Qt::DirectConnection);
@@ -990,6 +999,7 @@ QQuickWindow::~QQuickWindow()
 {
     Q_D(QQuickWindow);
 
+    d->animationController->deleteLater();
     d->windowManager->windowDestroyed(this);
 
     QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index e29ceb521ffd4f9d51081b0b461eeed469796bad..c656eacce730c3eaf8376a10afa1ab2f2b0fcce4 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -71,6 +71,7 @@ QT_BEGIN_NAMESPACE
 
 //Make it easy to identify and customize the root item if needed
 
+class QQuickAnimatorController;
 class QSGRenderLoop;
 class QQuickDragGrabber;
 
@@ -197,6 +198,7 @@ public:
     QSGRenderer *renderer;
 
     QSGRenderLoop *windowManager;
+    QQuickAnimatorController *animationController;
 
     QColor clearColor;
 
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index e099d94a53cf9b2960e8992f21496435d6de8c67..890f5793159e19f16bf69c7a6fe002a8afffda36 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -124,6 +124,18 @@ public:
     bool eventPending;
 };
 
+bool QSGRenderLoop::useConsistentTiming()
+{
+    bool bufferQueuing = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::BufferQueueingOpenGL);
+    // Enable fixed animation steps...
+    QByteArray fixed = qgetenv("QSG_FIXED_ANIMATION_STEP");
+    bool fixedAnimationSteps = bufferQueuing;
+    if (fixed == "no")
+        fixedAnimationSteps = false;
+    else if (fixed.length())
+        fixedAnimationSteps = true;
+    return fixedAnimationSteps;
+}
 
 QSGRenderLoop *QSGRenderLoop::instance()
 {
@@ -131,16 +143,7 @@ QSGRenderLoop *QSGRenderLoop::instance()
 
         s_instance = QSGContext::createWindowManager();
 
-        bool bufferQueuing = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::BufferQueueingOpenGL);
-
-        // Enable fixed animation steps...
-        QByteArray fixed = qgetenv("QML_FIXED_ANIMATION_STEP");
-        bool fixedAnimationSteps = bufferQueuing;
-        if (fixed == "no")
-            fixedAnimationSteps = false;
-        else if (fixed.length())
-            fixedAnimationSteps = true;
-        if (fixedAnimationSteps)
+        if (useConsistentTiming())
             QUnifiedTimer::instance(true)->setConsistentTiming(true);
 
         if (!s_instance) {
diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h
index 1e9a645cf4f2b2e72f4e3f89c1bf37feec849382..99b3ab677d458aae3da962b5195fabaf99d422bd 100644
--- a/src/quick/scenegraph/qsgrenderloop_p.h
+++ b/src/quick/scenegraph/qsgrenderloop_p.h
@@ -79,6 +79,8 @@ public:
     static QSGRenderLoop *instance();
     static void setInstance(QSGRenderLoop *instance);
 
+    static bool useConsistentTiming();
+
     virtual bool interleaveIncubation() const { return false; }
 
 Q_SIGNALS:
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index ba7bdbb2f479995eff7440be8ad438a37f6c20d0..88bc013306f739f87ab844cbcf941afadfc8ca12 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -55,6 +55,7 @@
 #include <QtQuick/private/qsgrenderer_p.h>
 
 #include "qsgthreadedrenderloop_p.h"
+#include <private/qquickanimatorcontroller_p.h>
 
 #include <private/qqmlprofilerservice_p.h>
 
@@ -329,8 +330,6 @@ public:
     QOpenGLContext *gl;
     QSGContext *sg;
 
-    QEventLoop eventLoop;
-
     uint pendingUpdate;
     uint sleeping;
     uint syncResultedInChanges;
@@ -861,6 +860,10 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
             m_thread->gl = ctx;
         }
 
+        QQuickAnimatorController *controller = QQuickWindowPrivate::get(window)->animationController;
+        if (controller->thread() != m_thread)
+            controller->moveToThread(m_thread);
+
         m_thread->start();
 
     } else {
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index c05b254b516cd0ac1e0e253bd86b0765df8dca97..904842b91e39a1b6a6279ac97836d88b6ec18d35 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -42,6 +42,8 @@
 #include "qquickanimation_p.h"
 #include "qquickanimation_p_p.h"
 
+#include "qquickanimatorjob_p.h"
+
 #include <private/qquickstatechangescript_p.h>
 #include <private/qqmlcontext_p.h>
 
@@ -171,8 +173,11 @@ void QQuickAbstractAnimationPrivate::commence()
         delete oldInstance;
 
     if (animationInstance) {
-        if (oldInstance != animationInstance)
+        if (oldInstance != animationInstance) {
+            if (q->threadingModel() == QQuickAbstractAnimation::RenderThread)
+                animationInstance = new QQuickAnimatorProxyJob(animationInstance, q);
             animationInstance->addAnimationChangeListener(this, QAbstractAnimationJob::Completion);
+        }
         animationInstance->start();
         if (animationInstance->isStopped()) {
             running = false;
@@ -643,6 +648,11 @@ void QQuickAbstractAnimationPrivate::animationFinished(QAbstractAnimationJob*)
     }
 }
 
+QQuickAbstractAnimation::ThreadingModel QQuickAbstractAnimation::threadingModel() const
+{
+    return GuiThread;
+}
+
 /*!
     \qmltype PauseAnimation
     \instantiates QQuickPauseAnimation
@@ -1713,6 +1723,21 @@ QQuickSequentialAnimation::~QQuickSequentialAnimation()
 {
 }
 
+QQuickAbstractAnimation::ThreadingModel QQuickSequentialAnimation::threadingModel() const
+{
+    Q_D(const QQuickAnimationGroup);
+
+    ThreadingModel style = AnyThread;
+    for (int i=0; i<d->animations.size(); ++i) {
+        ThreadingModel ces = d->animations.at(i)->threadingModel();
+        if (ces == GuiThread)
+            return GuiThread;
+        else if (ces == RenderThread)
+            style = RenderThread;
+    }
+    return style;
+}
+
 QAbstractAnimationJob* QQuickSequentialAnimation::transition(QQuickStateActions &actions,
                                     QQmlProperties &modified,
                                     TransitionDirection direction,
@@ -1729,14 +1754,19 @@ QAbstractAnimationJob* QQuickSequentialAnimation::transition(QQuickStateActions
         from = d->animations.count() - 1;
     }
 
+    ThreadingModel execution = threadingModel();
+
     bool valid = d->defaultProperty.isValid();
     QAbstractAnimationJob* anim;
     for (int ii = from; ii < d->animations.count() && ii >= 0; ii += inc) {
         if (valid)
             d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
         anim = d->animations.at(ii)->transition(actions, modified, direction, defaultTarget);
-        if (anim)
+        if (anim) {
+            if (d->animations.at(ii)->threadingModel() == RenderThread && execution != RenderThread)
+                anim = new QQuickAnimatorProxyJob(anim, this);
             inc == -1 ? ag->prependAnimation(anim) : ag->appendAnimation(anim);
+        }
     }
 
     return initInstance(ag);
@@ -1782,6 +1812,23 @@ QQuickParallelAnimation::~QQuickParallelAnimation()
 {
 }
 
+QQuickAbstractAnimation::ThreadingModel QQuickParallelAnimation::threadingModel() const
+{
+    Q_D(const QQuickAnimationGroup);
+
+    ThreadingModel style = AnyThread;
+    for (int i=0; i<d->animations.size(); ++i) {
+        ThreadingModel ces = d->animations.at(i)->threadingModel();
+        if (ces == GuiThread)
+            return GuiThread;
+        else if (ces == RenderThread)
+            style = RenderThread;
+    }
+    return style;
+}
+
+
+
 QAbstractAnimationJob* QQuickParallelAnimation::transition(QQuickStateActions &actions,
                                       QQmlProperties &modified,
                                       TransitionDirection direction,
@@ -1790,14 +1837,19 @@ QAbstractAnimationJob* QQuickParallelAnimation::transition(QQuickStateActions &a
     Q_D(QQuickAnimationGroup);
     QParallelAnimationGroupJob *ag = new QParallelAnimationGroupJob;
 
+    ThreadingModel style = threadingModel();
+
     bool valid = d->defaultProperty.isValid();
     QAbstractAnimationJob* anim;
     for (int ii = 0; ii < d->animations.count(); ++ii) {
         if (valid)
             d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
         anim = d->animations.at(ii)->transition(actions, modified, direction, defaultTarget);
-        if (anim)
+        if (anim) {
+            if (d->animations.at(ii)->threadingModel() == RenderThread && style != RenderThread)
+                anim = new QQuickAnimatorProxyJob(anim, this);
             ag->appendAnimation(anim);
+        }
     }
     return initInstance(ag);
 }
@@ -2034,6 +2086,8 @@ void QQuickPropertyAnimation::setTo(const QVariant &t)
     \qmlproperty real QtQuick2::PropertyAnimation::easing.overshoot
     \qmlproperty real QtQuick2::PropertyAnimation::easing.period
     \qmlproperty list<real> QtQuick2::PropertyAnimation::easing.bezierCurve
+
+//! propertyanimation.easing
     \brief Specifies the easing curve used for the animation
 
     To specify an easing curve you need to specify at least the type. For some curves you can also specify
@@ -2235,6 +2289,7 @@ void QQuickPropertyAnimation::setTo(const QVariant &t)
 
     See the \l {qml/animation/easing}{easing} example for a demonstration of
     the different easing settings.
+//! propertyanimation.easing
 */
 QEasingCurve QQuickPropertyAnimation::easing() const
 {
diff --git a/src/quick/util/qquickanimation_p.h b/src/quick/util/qquickanimation_p.h
index 82d1ba269e9f11cafa8ac4c6aceb86c7e57b1a00..8851bed9696a0c83741149f3a30b32dfac8d8018 100644
--- a/src/quick/util/qquickanimation_p.h
+++ b/src/quick/util/qquickanimation_p.h
@@ -73,6 +73,12 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAbstractAnimation : public QObject, public QQ
     Q_CLASSINFO("DefaultMethod", "start()")
 
 public:
+    enum ThreadingModel  {
+        GuiThread,
+        RenderThread,
+        AnyThread
+    };
+
     QQuickAbstractAnimation(QObject *parent=0);
     virtual ~QQuickAbstractAnimation();
 
@@ -102,6 +108,8 @@ public:
     void classBegin();
     void componentComplete();
 
+    virtual ThreadingModel threadingModel() const;
+
 Q_SIGNALS:
     void started();
     void stopped();
@@ -421,6 +429,7 @@ public:
     virtual ~QQuickSequentialAnimation();
 
 protected:
+    virtual ThreadingModel threadingModel() const;
     virtual QAbstractAnimationJob* transition(QQuickStateActions &actions,
                             QQmlProperties &modified,
                             TransitionDirection direction,
@@ -437,6 +446,7 @@ public:
     virtual ~QQuickParallelAnimation();
 
 protected:
+    virtual ThreadingModel threadingModel() const;
     virtual QAbstractAnimationJob* transition(QQuickStateActions &actions,
                             QQmlProperties &modified,
                             TransitionDirection direction,
diff --git a/src/quick/util/qquickanimationcontroller.cpp b/src/quick/util/qquickanimationcontroller.cpp
index dd9ced4bd9b0aa683e326057922d965f19515f34..caf1408bb352205562920df883a7ebdad63cb315 100644
--- a/src/quick/util/qquickanimationcontroller.cpp
+++ b/src/quick/util/qquickanimationcontroller.cpp
@@ -3,7 +3,7 @@
 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 ** Contact: http://www.qt-project.org/legal
 **
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
 ** Commercial License Usage
diff --git a/src/quick/util/qquickanimationcontroller_p.h b/src/quick/util/qquickanimationcontroller_p.h
index 5286e7753494c7545fd2518570d1becb88717918..b11a602f327ef003444bcbc6337f09ad97cd0b25 100644
--- a/src/quick/util/qquickanimationcontroller_p.h
+++ b/src/quick/util/qquickanimationcontroller_p.h
@@ -3,7 +3,7 @@
 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 ** Contact: http://www.qt-project.org/legal
 **
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the QtQuick module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
 ** Commercial License Usage
diff --git a/src/quick/util/qquickanimator.cpp b/src/quick/util/qquickanimator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c6f9f20aae589dd839b75f38be27666c1f1233af
--- /dev/null
+++ b/src/quick/util/qquickanimator.cpp
@@ -0,0 +1,565 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickanimator_p_p.h"
+#include "qquickanimatorjob_p.h"
+
+#include <private/qquickitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+    \qmltype Animator
+    \instantiates QQuickAnimator
+    \inqmlmodule QtQuick 2
+    \since QtQuick 2.2
+    \ingroup qtquick-transitions-animations
+    \brief Is the base of all QML animators.
+
+    Animator types are a special type of animation which operate
+    directly on Qt Quick's scene graph, rather than the QML objects and their
+    properties like regular Animation types do. This has the benefit that
+    Animator based animations can animate on the \l
+    {Threaded Render Loop}{scene graph's rendering thread} even when the
+    UI thread is blocked.
+
+    The value of the QML property will be updated after the animation has
+    finished. The property is not updated while the animation is running.
+
+    The Animator types can be used just like any other Animation type.
+
+    \snippet qml/animators.qml mixed
+
+    If all sub-animations of ParallelAnimation and SequentialAnimation
+    are Animator types, the ParallelAnimation and SequentialAnimation will
+    also be treated as an Animator and be run on the scene graph's rendering
+    thread when possible.
+
+    The Animator type cannot be used directly in a QML file. It exists
+    to provide a set of common properties and methods, available across all the
+    other animator types that inherit from it. Attempting to use the Animator
+    type directly will result in an error.
+ */
+
+QQuickAnimator::QQuickAnimator(QQuickAnimatorPrivate &dd, QObject *parent)
+    : QQuickAbstractAnimation(dd, parent)
+{
+}
+
+QQuickAnimator::QQuickAnimator(QObject *parent)
+    : QQuickAbstractAnimation(*new QQuickAnimatorPrivate, parent)
+{
+}
+
+/*!
+   \qmlproperty QtQuick2::Item QtQuick2::Animator::target
+
+   This property holds the target item of the animator.
+
+   \note Animator targets must be Item based types.
+ */
+
+void QQuickAnimator::setTargetItem(QQuickItem *target)
+{
+    Q_D(QQuickAnimator);
+    if (target == d->target)
+        return;
+    d->target = target;
+    Q_EMIT targetItemChanged(d->target);
+}
+
+QQuickItem *QQuickAnimator::targetItem() const
+{
+    Q_D(const QQuickAnimator);
+    return d->target;
+}
+
+/*!
+    \qmlproperty int QtQuick2::Animator::duration
+    This property holds the duration of the animation in milliseconds.
+
+    The default value is 250.
+*/
+void QQuickAnimator::setDuration(int duration)
+{
+    Q_D(QQuickAnimator);
+    if (duration == d->duration)
+        return;
+    d->duration = duration;
+    Q_EMIT durationChanged(duration);
+}
+
+int QQuickAnimator::duration() const
+{
+    Q_D(const QQuickAnimator);
+    return d->duration;
+}
+
+/*!
+    \qmlpropertygroup QtQuick2::Animator::easing
+    \qmlproperty enumeration QtQuick2::Animator::easing.type
+    \qmlproperty real QtQuick2::Animator::easing.amplitude
+    \qmlproperty real QtQuick2::Animator::easing.overshoot
+    \qmlproperty real QtQuick2::Animator::easing.period
+    \qmlproperty list<real> QtQuick2::Animator::easing.bezierCurve
+    \include qquickanimation.cpp propertyanimation.easing
+*/
+
+void QQuickAnimator::setEasing(const QEasingCurve &easing)
+{
+    Q_D(QQuickAnimator);
+    if (easing == d->easing)
+        return;
+    d->easing = easing;
+    Q_EMIT easingChanged(d->easing);
+}
+
+QEasingCurve QQuickAnimator::easing() const
+{
+    Q_D(const QQuickAnimator);
+    return d->easing;
+}
+
+/*!
+    \qmlproperty real QtQuick2::Animator::to
+    This property holds the end value for the animation.
+
+    If the Animator is defined within a \l Transition or \l Behavior,
+    this value defaults to the value defined in the end state of the
+    \l Transition, or the value of the property change that triggered the
+    \l Behavior.
+ */
+
+void QQuickAnimator::setTo(qreal to)
+{
+    Q_D(QQuickAnimator);
+    if (to == d->to)
+        return;
+    d->isToDefined = true;
+    d->to = to;
+    Q_EMIT toChanged(d->to);
+}
+
+qreal QQuickAnimator::to() const
+{
+    Q_D(const QQuickAnimator);
+    return d->to;
+}
+
+/*!
+    \qmlproperty real QtQuick2::Animator::from
+    This property holds the starting value for the animation.
+
+    If the Animator is defined within a \l Transition or \l Behavior,
+    this value defaults to the value defined in the starting state of the
+    \l Transition, or the current value of the property at the moment the
+    \l Behavior is triggered.
+
+    \sa {Animation and Transitions in Qt Quick}
+*/
+
+void QQuickAnimator::setFrom(qreal from)
+{
+    Q_D(QQuickAnimator);
+    if (from == d->from)
+        return;
+    d->isFromDefined = true;
+    d->from = from;
+    Q_EMIT fromChanged(d->from);
+}
+
+qreal QQuickAnimator::from() const
+{
+    Q_D(const QQuickAnimator);
+    return d->from;
+}
+
+void QQuickAnimatorPrivate::apply(QQuickAnimatorJob *job,
+                                     const QString &propertyName,
+                                     QQuickStateActions &actions,
+                                     QQmlProperties &modified)
+{
+
+    if (actions.size()) {
+        for (int i=0; i<actions.size(); ++i) {
+            QQuickAction &action = actions[i];
+            if (action.property.name() != propertyName)
+                continue;
+            modified << action.property;
+
+            job->setTarget(qobject_cast<QQuickItem *>(action.property.object()));
+
+            if (isFromDefined)
+                job->setFrom(from);
+            else if (action.fromValue.isValid())
+                job->setFrom(action.fromValue.toReal());
+            else
+                job->setFrom(action.property.read().toReal());
+
+            if (isToDefined)
+                job->setTo(to);
+            else if (action.toValue.isValid())
+                job->setTo(action.toValue.toReal());
+            else
+                job->setTo(action.property.read().toReal());
+
+            // This magic line is in sync with what PropertyAnimation does
+            // and prevents the animation to end up in the "completeList"
+            // which forces action.toValue to be written directly to
+            // the item when a transition is cancelled.
+            action.fromValue = action.toValue;
+       }
+    } else {
+        job->setTarget(target);
+        job->setFrom(from);
+        job->setTo(to);
+    }
+
+    if (!job->target() && defaultProperty.object())
+        job->setTarget(qobject_cast<QQuickItem *>(defaultProperty.object()));
+
+    job->setDuration(duration);
+    job->setLoopCount(loopCount);
+    job->setEasingCurve(easing);
+}
+
+QAbstractAnimationJob *QQuickAnimator::transition(QQuickStateActions &actions,
+                                                  QQmlProperties &modified,
+                                                  TransitionDirection,
+                                                  QObject *)
+{
+    Q_D(QQuickAnimator);
+
+    if (d->defaultProperty.isValid() && propertyName() != d->defaultProperty.name()) {
+        qDebug() << Q_FUNC_INFO << "property name conflict...";
+        return 0;
+    }
+
+    QQuickAnimatorJob *job = createJob();
+    if (!job)
+        return 0;
+
+    d->apply(job, propertyName(), actions, modified);
+
+    if (!job->target()) {
+        delete job;
+        return 0;
+    }
+
+    return job;
+}
+
+/*!
+    \qmltype XAnimator
+    \instantiates QQuickXAnimator
+    \inqmlmodule QtQuick 2
+    \since QtQuick 2.2
+    \ingroup qtquick-transitions-animations
+    \brief The XAnimator type animates the x position of an Item.
+
+    \l{Animator} types are different from normal Animation types. When
+    using an Animator, the animation can be run in the render thread
+    and the property value will jump to the end when the animation is
+    complete.
+
+    The value of Item::x is updated after the animation has finished.
+
+    The following snippet shows how to use a XAnimator together
+    with a Rectangle item.
+
+    \snippet qml/animators.qml x target
+
+    It is also possible to use the \c on keyword to tie the
+    XAnimator directly to an Item instance.
+
+    \snippet qml/animators.qml x on
+
+
+ */
+
+QQuickXAnimator::QQuickXAnimator(QObject *parent) : QQuickAnimator(parent) {}
+
+QQuickAnimatorJob *QQuickXAnimator::createJob() const { return new QQuickXAnimatorJob(); }
+
+/*!
+    \qmltype YAnimator
+    \instantiates QQuickYAnimator
+    \inqmlmodule QtQuick 2
+    \since QtQuick 2.2
+    \ingroup qtquick-transitions-animations
+    \brief The YAnimator type animates the y position of an Item.
+
+    \l{Animator} types are different from normal Animation types. When
+    using an Animator, the animation can be run in the render thread
+    and the property value will jump to the end when the animation is
+    complete.
+
+    The value of Item::y is updated after the animation has finished.
+
+    The following snippet shows how to use a YAnimator together
+    with a Rectangle item.
+
+    \snippet qml/animators.qml y target
+
+    It is also possible to use the \c on keyword to tie the
+    YAnimator directly to an Item instance.
+
+    \snippet qml/animators.qml y on
+
+
+ */
+
+QQuickYAnimator::QQuickYAnimator(QObject *parent) : QQuickAnimator(parent) {}
+
+QQuickAnimatorJob *QQuickYAnimator::createJob() const { return new QQuickYAnimatorJob(); }
+
+/*!
+    \qmltype ScaleAnimator
+    \instantiates QQuickScaleAnimator
+    \inqmlmodule QtQuick 2
+    \since QtQuick 2.2
+    \ingroup qtquick-transitions-animations
+    \brief The ScaleAnimator type animates the scale factor of an Item.
+
+    \l{Animator} types are different from normal Animation types. When
+    using an Animator, the animation can be run in the render thread
+    and the property value will jump to the end when the animation is
+    complete.
+
+    The value of Item::scale is updated after the animation has finished.
+
+    The following snippet shows how to use a ScaleAnimator together
+    with a Rectangle item.
+
+    \snippet qml/animators.qml scale target
+
+    It is also possible to use the \c on keyword to tie the
+    ScaleAnimator directly to an Item instance.
+
+    \snippet qml/animators.qml scale on
+
+    \sa Item::transformOrigin, RotationAnimator
+ */
+
+QQuickScaleAnimator::QQuickScaleAnimator(QObject *parent) : QQuickAnimator(parent) {}
+
+QQuickAnimatorJob *QQuickScaleAnimator::createJob() const { return new QQuickScaleAnimatorJob(); }
+
+/*!
+    \qmltype OpacityAnimator
+    \instantiates QQuickOpacityAnimator
+    \inqmlmodule QtQuick 2
+    \since QtQuick 2.2
+    \ingroup qtquick-transitions-animations
+    \brief The OpacityAnimator type animates the opacity of an Item.
+
+    \l{Animator} types are different from normal Animation types. When
+    using an Animator, the animation can be run in the render thread
+    and the property value will jump to the end when the animation is
+    complete.
+
+    The value of Item::opacity is updated after the animation has finished.
+
+    The following snippet shows how to use a OpacityAnimator together
+    with a Rectangle item.
+
+    \snippet qml/animators.qml opacity target
+
+    It is also possible to use the \c on keyword to tie the
+    OpacityAnimator directly to an Item instance.
+
+    \snippet qml/animators.qml opacity on
+
+ */
+
+QQuickOpacityAnimator::QQuickOpacityAnimator(QObject *parent) : QQuickAnimator(parent) {}
+
+QQuickAnimatorJob *QQuickOpacityAnimator::createJob() const { return new QQuickOpacityAnimatorJob(); }
+
+/*!
+    \qmltype RotationAnimator
+    \instantiates QQuickRotationAnimator
+    \inqmlmodule QtQuick 2
+    \since QtQuick 2.2
+    \ingroup qtquick-transitions-animations
+    \brief The RotationAnimator type animates the rotation of an Item.
+
+    \l{Animator} types are different from normal Animation types. When
+    using an Animator, the animation can be run in the render thread
+    and the property value will jump to the end when the animation is
+    complete.
+
+    The value of Item::rotation is updated after the animation has finished.
+
+    The following snippet shows how to use a RotationAnimator together
+    with a Rectangle item.
+
+    \snippet qml/animators.qml rotation target
+
+    It is also possible to use the \c on keyword to tie the
+    RotationAnimator directly to the \c rotation property of an Item
+    instance.
+
+    \snippet qml/animators.qml rotation on
+
+    \sa Item::transformOrigin, ScaleAnimator
+ */
+
+QQuickRotationAnimator::QQuickRotationAnimator(QObject *parent)
+    : QQuickAnimator(*new QQuickRotationAnimatorPrivate, parent)
+{
+}
+
+QQuickAnimatorJob *QQuickRotationAnimator::createJob() const {
+    Q_D(const QQuickRotationAnimator);
+    QQuickRotationAnimatorJob *job = new QQuickRotationAnimatorJob();
+    job->setDirection(d->direction);
+    return job;
+}
+
+/*!
+    \qmlproperty enumeration QtQuick2::RotationAnimator::direction
+    This property holds the direction of the rotation.
+
+    Possible values are:
+
+    \list
+    \li RotationAnimator.Numerical (default) - Rotate by linearly interpolating between the two numbers.
+           A rotation from 10 to 350 will rotate 340 degrees clockwise.
+    \li RotationAnimator.Clockwise - Rotate clockwise between the two values
+    \li RotationAnimator.Counterclockwise - Rotate counterclockwise between the two values
+    \li RotationAnimator.Shortest - Rotate in the direction that produces the shortest animation path.
+           A rotation from 10 to 350 will rotate 20 degrees counterclockwise.
+    \endlist
+*/
+void QQuickRotationAnimator::setDirection(RotationDirection dir)
+{
+    Q_D(QQuickRotationAnimator);
+    if (d->direction == dir)
+        return;
+    d->direction = dir;
+    Q_EMIT directionChanged(d->direction);
+}
+
+QQuickRotationAnimator::RotationDirection QQuickRotationAnimator::direction() const
+{
+    Q_D(const QQuickRotationAnimator);
+    return d->direction;
+}
+
+/*!
+    \qmltype UniformAnimator
+    \instantiates QQuickUniformAnimator
+    \inqmlmodule QtQuick 2
+    \since QtQuick 2.2
+    \ingroup qtquick-transitions-animations
+    \brief The UniformAnimator type animates a uniform of a ShaderEffect.
+
+    \l{Animator} types are different from normal Animation types. When
+    using an Animator, the animation can be run in the render thread
+    and the property value will jump to the end when the animation is
+    complete.
+
+    The value of the QML property defining the uniform is updated after
+    the animation has finished.
+
+    The following snippet shows how to use a UniformAnimator together
+    with a ShaderEffect item.
+
+    \snippet qml/animators.qml shader target
+
+    It is also possible to use the \c on keyword to tie the
+    UniformAnimator directly to a uniform of a ShaderEffect
+    instance.
+
+    \snippet qml/animators.qml shader on
+
+    \sa ShaderEffect, ShaderEffectSource
+ */
+
+QQuickUniformAnimator::QQuickUniformAnimator(QObject *parent)
+    : QQuickAnimator(*new QQuickUniformAnimatorPrivate, parent)
+{
+}
+
+/*!
+   \qmlproperty string QtQuick2::UniformAnimator::uniform
+   This property holds the name of the uniform to animate.
+
+   The value of the uniform must correspond to both a property
+   on the target ShaderEffect and must be a uniform of type
+   \c float in the fragment or vertex shader.
+ */
+void QQuickUniformAnimator::setUniform(const QString &uniform)
+{
+    Q_D(QQuickUniformAnimator);
+    if (d->uniform == uniform)
+        return;
+    d->uniform = uniform;
+    Q_EMIT uniformChanged(d->uniform);
+}
+
+QString QQuickUniformAnimator::uniform() const
+{
+    Q_D(const QQuickUniformAnimator);
+    return d->uniform;
+}
+
+QString QQuickUniformAnimator::propertyName() const
+{
+    Q_D(const QQuickUniformAnimator);
+    if (!d->uniform.isEmpty())
+        return d->uniform;
+    return d->defaultProperty.name();
+}
+
+QQuickAnimatorJob *QQuickUniformAnimator::createJob() const
+{
+    QString u = propertyName();
+    if (u.isEmpty())
+        return 0;
+
+    QQuickUniformAnimatorJob *job = new QQuickUniformAnimatorJob();
+    job->setUniform(u.toLatin1());
+    return job;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/util/qquickanimator_p.h b/src/quick/util/qquickanimator_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..e5916c624c9088e6cb0912e64f02c40197be20a1
--- /dev/null
+++ b/src/quick/util/qquickanimator_p.h
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKANIMATOR_P_H
+#define QQUICKANIMATOR_P_H
+
+#include "qquickanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItem;
+
+class QQuickAnimatorJob;
+class QQuickAnimatorPrivate;
+class Q_QUICK_PRIVATE_EXPORT QQuickAnimator : public QQuickAbstractAnimation
+{
+    Q_OBJECT
+    Q_DECLARE_PRIVATE(QQuickAnimator)
+    Q_PROPERTY(QQuickItem *target READ targetItem WRITE setTargetItem NOTIFY targetItemChanged)
+    Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
+    Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+    Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged)
+    Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged)
+
+public:
+    QQuickItem *targetItem() const;
+    void setTargetItem(QQuickItem *target);
+
+    int duration() const;
+    void setDuration(int duration);
+
+    QEasingCurve easing() const;
+    void setEasing(const QEasingCurve & easing);
+
+    qreal to() const;
+    void setTo(qreal to);
+
+    qreal from() const;
+    void setFrom(qreal from);
+
+protected:
+    ThreadingModel threadingModel() const { return RenderThread; }
+    virtual QQuickAnimatorJob *createJob() const = 0;
+    virtual QString propertyName() const = 0;
+    QAbstractAnimationJob *transition(QQuickStateActions &actions,
+                                      QQmlProperties &modified,
+                                      TransitionDirection,
+                                      QObject *);
+
+    QQuickAnimator(QQuickAnimatorPrivate &dd, QObject *parent = 0);
+    QQuickAnimator(QObject *parent = 0);
+
+Q_SIGNALS:
+    void targetItemChanged(QQuickItem *);
+    void durationChanged(int duration);
+    void easingChanged(const QEasingCurve &curve);
+    void toChanged(qreal to);
+    void fromChanged(qreal from);
+};
+
+class QQuickScaleAnimatorPrivate;
+class Q_QUICK_PRIVATE_EXPORT QQuickScaleAnimator : public QQuickAnimator
+{
+    Q_OBJECT
+public:
+    QQuickScaleAnimator(QObject *parent = 0);
+protected:
+    QQuickAnimatorJob *createJob() const;
+    QString propertyName() const { return QStringLiteral("scale"); }
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickXAnimator : public QQuickAnimator
+{
+    Q_OBJECT
+public:
+    QQuickXAnimator(QObject *parent = 0);
+protected:
+    QQuickAnimatorJob *createJob() const;
+    QString propertyName() const{ return QStringLiteral("x"); }
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickYAnimator : public QQuickAnimator
+{
+    Q_OBJECT
+public:
+    QQuickYAnimator(QObject *parent = 0);
+protected:
+    QQuickAnimatorJob *createJob() const;
+    QString propertyName() const { return QStringLiteral("y"); }
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickOpacityAnimator : public QQuickAnimator
+{
+    Q_OBJECT
+public:
+    QQuickOpacityAnimator(QObject *parent = 0);
+protected:
+    QQuickAnimatorJob *createJob() const;
+    QString propertyName() const { return QStringLiteral("opacity"); }
+};
+
+class QQuickRotationAnimatorPrivate;
+class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimator : public QQuickAnimator
+{
+    Q_OBJECT
+    Q_DECLARE_PRIVATE(QQuickRotationAnimator)
+    Q_PROPERTY(RotationDirection direction READ direction WRITE setDirection NOTIFY directionChanged)
+
+    Q_ENUMS(RotationDirection)
+
+public:
+    enum RotationDirection { Numerical, Shortest, Clockwise, Counterclockwise };
+
+    QQuickRotationAnimator(QObject *parent = 0);
+
+    void setDirection(RotationDirection dir);
+    RotationDirection direction() const;
+
+Q_SIGNALS:
+    void directionChanged(RotationDirection dir);
+
+protected:
+    QQuickAnimatorJob *createJob() const;
+    QString propertyName() const { return QStringLiteral("rotation"); }
+};
+
+class QQuickUniformAnimatorPrivate;
+class Q_QUICK_PRIVATE_EXPORT QQuickUniformAnimator : public QQuickAnimator
+{
+    Q_OBJECT
+    Q_DECLARE_PRIVATE(QQuickUniformAnimator)
+    Q_PROPERTY(QString uniform READ uniform WRITE setUniform NOTIFY uniformChanged)
+
+public:
+    QQuickUniformAnimator(QObject *parent = 0);
+
+    QString uniform() const;
+    void setUniform(const QString &);
+
+Q_SIGNALS:
+    void uniformChanged(const QString &);
+
+protected:
+    QQuickAnimatorJob *createJob() const;
+    QString propertyName() const;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickAnimator)
+QML_DECLARE_TYPE(QQuickXAnimator)
+QML_DECLARE_TYPE(QQuickYAnimator)
+QML_DECLARE_TYPE(QQuickScaleAnimator)
+QML_DECLARE_TYPE(QQuickRotationAnimator)
+QML_DECLARE_TYPE(QQuickOpacityAnimator)
+QML_DECLARE_TYPE(QQuickUniformAnimator)
+
+#endif // QQUICKANIMATOR_P_H
diff --git a/src/quick/util/qquickanimator_p_p.h b/src/quick/util/qquickanimator_p_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..cc25496a8ffd760cbe8722d65219a2a253d09e57
--- /dev/null
+++ b/src/quick/util/qquickanimator_p_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKANIMATOR_P_P_H
+#define QQUICKANIMATOR_P_P_H
+
+#include "qquickanimator_p.h"
+#include "qquickanimation_p_p.h"
+#include <QtQuick/qquickitem.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickAnimatorJob;
+
+class QQuickAnimatorPrivate : public QQuickAbstractAnimationPrivate
+{
+    Q_DECLARE_PUBLIC(QQuickAnimator)
+public:
+    QQuickAnimatorPrivate()
+        : target(0)
+        , duration(250)
+        , from(0)
+        , to(0)
+        , isFromDefined(false)
+        , isToDefined(false)
+    {
+    }
+
+    QPointer<QQuickItem> target;
+    int duration;
+    QEasingCurve easing;
+    qreal from;
+    qreal to;
+
+    uint isFromDefined : 1;
+    uint isToDefined : 1;
+
+    void apply(QQuickAnimatorJob *job, const QString &propertyName, QQuickStateActions &actions, QQmlProperties &modified);
+};
+
+class QQuickRotationAnimatorPrivate : public QQuickAnimatorPrivate
+{
+public:
+    QQuickRotationAnimatorPrivate()
+        : direction(QQuickRotationAnimator::Numerical)
+    {
+    }
+    QQuickRotationAnimator::RotationDirection direction;
+};
+
+class QQuickUniformAnimatorPrivate : public QQuickAnimatorPrivate
+{
+public:
+    QString uniform;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKANIMATOR_P_P_H
diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..73d2882c052e5e6cc1f19117744ce8fb9cb9d5ea
--- /dev/null
+++ b/src/quick/util/qquickanimatorcontroller.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickanimatorcontroller_p.h"
+
+#include <private/qquickwindow_p.h>
+#include <private/qsgrenderloop_p.h>
+
+#include <private/qanimationgroupjob_p.h>
+
+#include <QtGui/qscreen.h>
+
+QT_BEGIN_NAMESPACE
+
+QQuickAnimatorController::QQuickAnimatorController()
+    : window(0)
+    , driver(0)
+{
+}
+
+QQuickAnimatorController::~QQuickAnimatorController()
+{
+    qDeleteAll(activeRootAnimations);
+}
+
+void QQuickAnimatorController::advance()
+{
+    if (driver && driver->isRunning()) {
+        // This lock is to prevent conflicts with syncBackCurrentValues
+        mutex.lock();
+        driver->advance();
+        mutex.unlock();
+    }
+
+    // The animation system uses a chain of queued connections to
+    // start the animation driver and these won't get delievered until,
+    // at best, after this frame. We need to track if animations
+    // are running here so we can keep on rendering in that case.
+    bool running = driver && driver->isRunning();
+    for (QSet<QAbstractAnimationJob *>::const_iterator it = activeRootAnimations.constBegin();
+         !running && it != activeRootAnimations.constEnd(); ++it) {
+        if ((*it)->isRunning())
+            running = true;
+    }
+
+    for (QSet<QQuickAnimatorJob *>::const_iterator it = activeLeafAnimations.constBegin();
+         it != activeLeafAnimations.constEnd(); ++it) {
+        if ((*it)->isTransform()) {
+            QQuickTransformAnimatorJob *xform = static_cast<QQuickTransformAnimatorJob *>(*it);
+            xform->transformHelper()->apply();
+        }
+    }
+
+    if (running)
+        window->update();
+}
+
+static void qquick_initialize_helper(QAbstractAnimationJob *job, QQuickAnimatorController *c)
+{
+    if (job->isRenderThreadJob()) {
+        QQuickAnimatorJob *j = static_cast<QQuickAnimatorJob *>(job);
+        j->initialize(c);
+    } else if (job->isGroup()) {
+        QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job);
+        for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling())
+            qquick_initialize_helper(a, c);
+    }
+}
+
+void QQuickAnimatorController::beforeNodeSync()
+{
+    if (!driver && window->thread() != window->openglContext()->thread()) {
+        driver = QQuickWindowPrivate::get(window)->context->createAnimationDriver(this);
+        connect(driver, SIGNAL(started()), this, SLOT(animationsStarted()), Qt::DirectConnection);
+        connect(driver, SIGNAL(stopped()), this, SLOT(animationsStopped()), Qt::DirectConnection);
+        driver->install();
+
+        QUnifiedTimer::instance(true)->setConsistentTiming(QSGRenderLoop::useConsistentTiming());
+    }
+
+    // Force a render pass if we are adding new animations
+    // so that advance will be called..
+    if (starting.size())
+        window->update();
+
+    for (int i=0; i<starting.size(); ++i) {
+        QAbstractAnimationJob *job = starting.at(i);
+        qquick_initialize_helper(job, this);
+        job->addAnimationChangeListener(this, QAbstractAnimationJob::StateChange);
+        job->start();
+    }
+    starting.clear();
+
+    for (QSet<QQuickAnimatorJob *>::const_iterator it = activeLeafAnimations.constBegin();
+         it != activeLeafAnimations.constEnd(); ++it) {
+        if ((*it)->isTransform()) {
+            QQuickTransformAnimatorJob *xform = static_cast<QQuickTransformAnimatorJob *>(*it);
+            xform->transformHelper()->sync();
+        }
+    }
+}
+
+void QQuickAnimatorController::afterNodeSync()
+{
+    for (QSet<QQuickAnimatorJob *>::const_iterator it = activeLeafAnimations.constBegin();
+         it != activeLeafAnimations.constEnd(); ++it) {
+        if ((*it)->isUniform()) {
+            QQuickUniformAnimatorJob *job = static_cast<QQuickUniformAnimatorJob *>(*it);
+            job->afterNodeSync();
+        }
+    }
+}
+
+
+void QQuickAnimatorController::startAnimation(QAbstractAnimationJob *job)
+{
+    mutex.lock();
+    starting << job;
+    mutex.unlock();
+}
+
+void QQuickAnimatorController::animationsStopped()
+{
+}
+
+void QQuickAnimatorController::animationsStarted()
+{
+    window->update();
+}
+
+void QQuickAnimatorController::animationStateChanged(QAbstractAnimationJob *job,
+                                                     QAbstractAnimationJob::State newState,
+                                                     QAbstractAnimationJob::State)
+{
+    if (newState == QAbstractAnimationJob::Running)
+        activeRootAnimations << job;
+    else
+        activeRootAnimations.remove(job);
+}
+
+bool QQuickAnimatorController::event(QEvent *e)
+{
+     if ((int) e->type() == StopAnimation) {
+        QAbstractAnimationJob *job = static_cast<Event *>(e)->job;
+        mutex.lock();
+        starting.removeOne(job);
+        mutex.unlock();
+        job->stop();
+        return true;
+
+    } else if ((uint) e->type() == DeleteAnimation) {
+        QAbstractAnimationJob *job = static_cast<Event *>(e)->job;
+        mutex.lock();
+        starting.removeOne(job);
+        mutex.unlock();
+        job->stop();
+        delete job;
+        return true;
+    }
+
+    return QObject::event(e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/util/qquickanimatorcontroller_p.h b/src/quick/util/qquickanimatorcontroller_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..1c79e3c493c9559001a3eef9c0d7c0d988ee2515
--- /dev/null
+++ b/src/quick/util/qquickanimatorcontroller_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKANIMATORCONTROLLER_P_H
+#define QQUICKANIMATORCONTROLLER_P_H
+
+#include "qquickanimatorjob_p.h"
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qquickitem.h>
+
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickAnimatorController : public QObject, public QAnimationJobChangeListener
+{
+    Q_OBJECT
+
+public:
+
+    enum EventType {
+        // GUI to RT events
+        StartAnimation = QEvent::User + 1,
+        StopAnimation,
+        DeleteAnimation,
+
+        // RT back to GUI events
+        AnimationFinished
+    };
+
+    class Event : public QEvent {
+    public:
+        Event(QAbstractAnimationJob *j, EventType type)
+            : QEvent(QEvent::Type(type))
+            , job(j)
+        {
+        }
+        QAbstractAnimationJob *job;
+    };
+
+    QQuickAnimatorController();
+    ~QQuickAnimatorController();
+
+    void advance();
+    void beforeNodeSync();
+    void afterNodeSync();
+
+    bool event(QEvent *);
+
+    void startAnimation(QAbstractAnimationJob *job);
+
+    void animationStateChanged(QAbstractAnimationJob *job,
+                               QAbstractAnimationJob::State newState,
+                               QAbstractAnimationJob::State oldState);
+
+public Q_SLOTS:
+    void animationsStarted();
+    void animationsStopped();
+
+public:
+    QList<QAbstractAnimationJob *> starting;
+    QList<QAbstractAnimationJob *> stopped;
+
+    QSet<QAbstractAnimationJob *> activeRootAnimations;
+    QSet<QQuickAnimatorJob *> activeLeafAnimations;
+
+    QHash<QQuickItem *, QQuickTransformAnimatorJob::Helper *> transforms;
+
+    QQuickWindow *window;
+
+    QAnimationDriver *driver;
+
+    QMutex mutex;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKANIMATORCONTROLLER_P_H
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3270faa652ae434a120cd82cc2ae273991a673a9
--- /dev/null
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -0,0 +1,532 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickanimatorcontroller_p.h"
+#include "qquickanimatorjob_p.h"
+#include "qquickanimator_p.h"
+#include "qquickanimator_p_p.h"
+#include <private/qquickwindow_p.h>
+#include <private/qquickitem_p.h>
+#include <private/qquickshadereffectnode_p.h>
+
+#include <private/qanimationgroupjob_p.h>
+
+#include <qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+QQuickAnimatorProxyJob::QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObject *item)
+    : m_controller(0)
+    , m_job(job)
+    , m_internalState(State_Stopped)
+{
+    m_isRenderThreadProxy = true;
+    m_animation = qobject_cast<QQuickAbstractAnimation *>(item);
+
+    setLoopCount(job->loopCount());
+
+    // Instead of setting duration to job->duration() we need to set it to -1 so that
+    // it runs as long as the job is running on the render thread. If we gave it
+    // an explicit duration, it would be stopped, potentially stopping the RT animation
+    // prematurely.
+    // This means that the animation driver will tick on the GUI thread as long
+    // as the animation is running on the render thread, but this overhead will
+    // be negligiblie compared to animating and re-rendering the scene on the render thread.
+    m_duration = -1;
+
+    job->addAnimationChangeListener(this, QAbstractAnimationJob::Completion);
+
+    QObject *ctx = findAnimationContext(m_animation);
+    if (!ctx) {
+        qWarning("QtQuick: unable to find animation context for RT animation...");
+        return;
+    }
+
+    QQuickWindow *window = qobject_cast<QQuickWindow *>(ctx);
+    if (window) {
+        setWindow(window);
+    } else {
+        QQuickItem *item = qobject_cast<QQuickItem *>(ctx);
+        if (item->window())
+            setWindow(item->window());
+        else
+            connect(item, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(windowChanged(QQuickWindow*)));
+    }
+}
+
+QQuickAnimatorProxyJob::~QQuickAnimatorProxyJob()
+{
+    deleteJob();
+}
+
+void QQuickAnimatorProxyJob::deleteJob()
+{
+    if (m_job) {
+        if (m_controller && m_internalState != State_Starting)
+            QCoreApplication::postEvent(m_controller, new QQuickAnimatorController::Event(m_job, QQuickAnimatorController::DeleteAnimation));
+        else
+            delete m_job;
+        m_job = 0;
+    }
+}
+
+QObject *QQuickAnimatorProxyJob::findAnimationContext(QQuickAbstractAnimation *a)
+{
+    QObject *p = a->parent();
+    while (p != 0 && qobject_cast<QQuickWindow *>(p) == 0 && qobject_cast<QQuickItem *>(p) == 0)
+        p = p->parent();
+    return p;
+}
+
+void QQuickAnimatorProxyJob::updateCurrentTime(int)
+{
+}
+
+void QQuickAnimatorProxyJob::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State)
+{
+    if (m_state == Running) {
+        if (m_controller) {
+            m_internalState = State_Running;
+            startOnRenderThread();
+        } else {
+            m_internalState = State_Starting;
+        }
+    } else if (newState == Stopped) {
+        syncBackCurrentValues();
+        if (m_internalState == State_Starting)
+            m_internalState = State_Stopped;
+        else {
+            QCoreApplication::postEvent(m_controller, new QQuickAnimatorController::Event(m_job, QQuickAnimatorController::StopAnimation));
+        }
+    }
+}
+
+void QQuickAnimatorProxyJob::windowChanged(QQuickWindow *window)
+{
+    setWindow(window);
+}
+
+void QQuickAnimatorProxyJob::setWindow(QQuickWindow *window)
+{
+    if (m_controller) {
+        stop();
+        deleteJob();
+        m_controller = 0;
+    }
+    if (!window)
+        return;
+
+    m_controller = QQuickWindowPrivate::get(window)->animationController;
+
+    if (window->openglContext())
+        readyToAnimate();
+    else
+        connect(window, SIGNAL(sceneGraphInitialized()), this, SLOT(sceneGraphInitialized()));
+}
+
+void QQuickAnimatorProxyJob::sceneGraphInitialized()
+{
+    readyToAnimate();
+    disconnect(this, SLOT(sceneGraphInitialized()));
+}
+
+void QQuickAnimatorProxyJob::readyToAnimate()
+{
+    if (m_internalState == State_Starting) {
+        startOnRenderThread();
+    }
+}
+
+void QQuickAnimatorProxyJob::animationFinished(QAbstractAnimationJob *job)
+{
+    QCoreApplication::postEvent(this, new QQuickAnimatorController::Event(job, QQuickAnimatorController::AnimationFinished));
+}
+
+bool QQuickAnimatorProxyJob::event(QEvent *e)
+{
+    if ((uint) e->type() == QQuickAnimatorController::AnimationFinished) {
+        // Update the duration of this proxy to the current time and stop it so
+        // that parent animations can progress gracefully
+        m_duration = m_currentTime;
+        stop();
+        return true;
+    }
+
+    return QObject::event(e);
+}
+
+void QQuickAnimatorProxyJob::startOnRenderThread()
+{
+    m_internalState = State_Running;
+    // Force a "sync" pass as the newly started animation needs to sync properties from GUI.
+    m_controller->startAnimation(m_job);
+    QQuickWindowPrivate::get(m_controller->window)->dirtyItem(0);
+}
+
+static void qquick_syncback_helper(QAbstractAnimationJob *job)
+{
+    if (job->isRenderThreadJob()) {
+        QQuickAnimatorJob *a = static_cast<QQuickAnimatorJob *>(job);
+        if (a->controller())
+            a->writeBack();
+    } else if (job->isGroup()) {
+        QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job);
+        for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling())
+            qquick_syncback_helper(a);
+    }
+}
+
+void QQuickAnimatorProxyJob::syncBackCurrentValues()
+{
+    qquick_syncback_helper(m_job);
+}
+
+QQuickAnimatorJob::QQuickAnimatorJob()
+    : m_target(0)
+    , m_controller(0)
+    , m_from(0)
+    , m_to(0)
+    , m_value(0)
+    , m_duration(0)
+    , m_isTransform(false)
+    , m_isUniform(false)
+{
+    m_isRenderThreadJob = true;
+}
+
+qreal QQuickAnimatorJob::value() const
+{
+    qreal v;
+    m_controller->mutex.lock();
+    v = m_value;
+    m_controller->mutex.unlock();
+    return v;
+}
+
+void QQuickAnimatorJob::setTarget(QQuickItem *target)
+{
+    m_target = target;
+}
+
+void QQuickAnimatorJob::initialize(QQuickAnimatorController *controller)
+{
+    m_controller = controller;
+}
+
+void QQuickAnimatorJob::updateState(State newState, State oldState)
+{
+    if (newState == Running) {
+        m_controller->activeLeafAnimations << this;
+    } else if (oldState == Running) {
+        m_controller->activeLeafAnimations.remove(this);
+    }
+}
+
+QQuickTransformAnimatorJob::QQuickTransformAnimatorJob()
+    : m_helper(0)
+{
+    m_isTransform = true;
+}
+
+QQuickTransformAnimatorJob::~QQuickTransformAnimatorJob()
+{
+    if (m_helper && --m_helper->ref == 0) {
+        m_controller->transforms.remove(m_helper->item);
+        delete m_helper;
+    }
+}
+
+void QQuickTransformAnimatorJob::initialize(QQuickAnimatorController *controller)
+{
+    QQuickAnimatorJob::initialize(controller);
+
+    m_helper = m_controller->transforms.value(m_target);
+    if (!m_helper) {
+        m_helper = new Helper();
+        m_helper->item = m_target;
+        m_controller->transforms.insert(m_target, m_helper);
+    } else {
+        ++m_helper->ref;
+    }
+    m_helper->sync();
+}
+
+
+void QQuickTransformAnimatorJob::Helper::sync()
+{
+    const quint32 mask = QQuickItemPrivate::Position
+            | QQuickItemPrivate::BasicTransform
+            | QQuickItemPrivate::TransformOrigin;
+
+    quint32 dirty = mask & QQuickItemPrivate::get(item)->dirtyAttributes;
+
+    if (!wasSynced) {
+        dirty = 0xffffffffu;
+        wasSynced = true;
+    }
+
+    if (dirty == 0)
+        return;
+
+    node = QQuickItemPrivate::get(item)->itemNode();
+
+    if (dirty & QQuickItemPrivate::Position) {
+        dx = item->x();
+        dy = item->y();
+    }
+
+    if (dirty & QQuickItemPrivate::BasicTransform) {
+        scale = item->scale();
+        rotation = item->rotation();
+    }
+
+    if (dirty & QQuickItemPrivate::TransformOrigin) {
+        QPointF o = item->transformOriginPoint();
+        ox = o.x();
+        oy = o.y();
+    }
+}
+
+void QQuickTransformAnimatorJob::Helper::apply()
+{
+    if (!wasChanged)
+        return;
+
+    QMatrix4x4 m;
+    m.translate(dx, dy);
+    m.translate(ox, oy);
+    m.scale(scale);
+    m.rotate(rotation, 0, 0, 1);
+    m.translate(-ox, -oy);
+    node->setMatrix(m);
+
+    wasChanged = false;
+}
+
+
+
+void QQuickXAnimatorJob::writeBack()
+{
+    if (m_target)
+        m_target->setX(value());
+}
+
+void QQuickXAnimatorJob::updateCurrentTime(int time)
+{
+    Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+
+    m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
+    m_helper->dx = m_value;
+    m_helper->wasChanged = true;
+}
+
+void QQuickYAnimatorJob::writeBack()
+{
+    if (m_target)
+        m_target->setY(value());
+}
+
+void QQuickYAnimatorJob::updateCurrentTime(int time)
+{
+    Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+
+    m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
+    m_helper->dy = m_value;
+    m_helper->wasChanged = true;
+}
+
+QQuickOpacityAnimatorJob::QQuickOpacityAnimatorJob()
+    : m_opacityNode(0)
+{
+}
+
+void QQuickOpacityAnimatorJob::initialize(QQuickAnimatorController *controller)
+{
+    QQuickAnimatorJob::initialize(controller);
+    QQuickItemPrivate *d = QQuickItemPrivate::get(m_target);
+    m_opacityNode = d->opacityNode();
+    if (!m_opacityNode) {
+        m_opacityNode = new QSGOpacityNode();
+        d->extra.value().opacityNode = m_opacityNode;
+
+        QSGNode *child = d->clipNode();
+        if (!child)
+            child = d->rootNode();
+        if (!child)
+            child = d->groupNode;
+
+        if (child) {
+            if (child->parent())
+                child->parent()->removeChildNode(child);
+            m_opacityNode->appendChildNode(child);
+        }
+
+        d->itemNode()->appendChildNode(m_opacityNode);
+    }
+}
+
+void QQuickOpacityAnimatorJob::writeBack()
+{
+    if (m_target)
+        m_target->setOpacity(value());
+}
+
+void QQuickOpacityAnimatorJob::updateCurrentTime(int time)
+{
+    Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+
+    m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
+    m_opacityNode->setOpacity(m_value);
+}
+
+void QQuickScaleAnimatorJob::writeBack()
+{
+    if (m_target)
+        m_target->setScale(value());
+}
+
+void QQuickScaleAnimatorJob::updateCurrentTime(int time)
+{
+    Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+
+    m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
+    m_helper->scale = m_value;
+    m_helper->wasChanged = true;
+}
+
+QQuickRotationAnimatorJob::QQuickRotationAnimatorJob()
+    : m_direction(QQuickRotationAnimator::Numerical)
+{
+}
+
+extern QVariant _q_interpolateShortestRotation(qreal &f, qreal &t, qreal progress);
+extern QVariant _q_interpolateClockwiseRotation(qreal &f, qreal &t, qreal progress);
+extern QVariant _q_interpolateCounterclockwiseRotation(qreal &f, qreal &t, qreal progress);
+
+void QQuickRotationAnimatorJob::updateCurrentTime(int time)
+{
+    Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+
+    float t =  m_easing.valueForProgress(time / (qreal) m_duration);
+    switch (m_direction) {
+    case QQuickRotationAnimator::Clockwise:
+        m_value = _q_interpolateClockwiseRotation(m_from, m_to, t).toFloat();
+        break;
+    case QQuickRotationAnimator::Counterclockwise:
+        m_value = _q_interpolateCounterclockwiseRotation(m_from, m_to, t).toFloat();
+        break;
+    case QQuickRotationAnimator::Shortest:
+        m_value = _q_interpolateShortestRotation(m_from, m_to, t).toFloat();
+        break;
+    case QQuickRotationAnimator::Numerical:
+        m_value = m_from + (m_to - m_from) * t;
+        break;
+    }
+    m_helper->rotation = m_value;
+    m_helper->wasChanged = true;
+}
+
+void QQuickRotationAnimatorJob::writeBack()
+{
+    if (m_target)
+        m_target->setRotation(value());
+}
+
+QQuickUniformAnimatorJob::QQuickUniformAnimatorJob()
+    : m_node(0)
+    , m_uniformIndex(-1)
+    , m_uniformType(-1)
+{
+    m_isUniform = true;
+}
+
+void QQuickUniformAnimatorJob::setTarget(QQuickItem *target)
+{
+    if (qobject_cast<QQuickShaderEffect *>(target) != 0)
+        m_target = target;
+}
+
+void QQuickUniformAnimatorJob::afterNodeSync()
+{
+    m_node = static_cast<QQuickShaderEffectNode *>(QQuickItemPrivate::get(m_target)->paintNode);
+
+    if (m_node) {
+        m_uniformIndex = -1;
+        m_uniformType = -1;
+        QQuickShaderEffectMaterial *material =
+                static_cast<QQuickShaderEffectMaterial *>(m_node->material());
+        bool found = false;
+        for (int t=0; !found && t<QQuickShaderEffectMaterialKey::ShaderTypeCount; ++t) {
+            const QVector<QQuickShaderEffectMaterial::UniformData> &uniforms = material->uniforms[t];
+            for (int i=0; i<uniforms.size(); ++i) {
+                if (uniforms.at(i).name == m_uniform) {
+                    m_uniformIndex = i;
+                    m_uniformType = t;
+                    found = true;
+                    break;
+                }
+            }
+        }
+    }
+
+}
+
+void QQuickUniformAnimatorJob::updateCurrentTime(int time)
+{
+    Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+
+    if (!m_node || m_uniformIndex == -1 || m_uniformType == -1)
+        return;
+
+    m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
+
+    QQuickShaderEffectMaterial *material =
+            static_cast<QQuickShaderEffectMaterial *>(m_node->material());
+    material->uniforms[m_uniformType][m_uniformIndex].value = m_value;
+}
+
+void QQuickUniformAnimatorJob::writeBack()
+{
+    if (m_target)
+        m_target->setProperty(m_uniform, value());
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h
new file mode 100644
index 0000000000000000000000000000000000000000..c6814523c6eae1127bf1b4741e8ac698aba38379
--- /dev/null
+++ b/src/quick/util/qquickanimatorjob_p.h
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKANIMATORJOB_P_H
+#define QQUICKANIMATORJOB_P_H
+
+#include <private/qabstractanimationjob_p.h>
+#include <private/qquickanimator_p.h>
+#include <private/qtquickglobal_p.h>
+
+#include <QtQuick/qquickitem.h>
+
+#include <QtCore/qeasingcurve.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickAnimator;
+class QQuickWindow;
+class QQuickItem;
+class QQuickAbstractAnimation;
+
+class QQuickAnimatorController;
+class QQuickAnimatorProxyJobPrivate;
+class QQuickShaderEffectNode;
+
+class QSGOpacityNode;
+
+class Q_QUICK_PRIVATE_EXPORT QQuickAnimatorProxyJob : public QObject, public QAbstractAnimationJob, public QAnimationJobChangeListener
+{
+    Q_OBJECT
+
+public:
+    QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObject *item);
+    ~QQuickAnimatorProxyJob();
+
+    int duration() const { return m_duration; }
+
+    virtual void animationFinished(QAbstractAnimationJob *);
+
+protected:
+    bool event(QEvent *);
+
+    void updateCurrentTime(int);
+    void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState);
+
+public Q_SLOTS:
+    void windowChanged(QQuickWindow *window);
+    void sceneGraphInitialized();
+
+private:
+    void deleteJob();
+    void syncBackCurrentValues();
+    void readyToAnimate();
+    void setWindow(QQuickWindow *window);
+    static QObject *findAnimationContext(QQuickAbstractAnimation *);
+    void startOnRenderThread();
+
+    QQuickAnimatorController *m_controller;
+    QQuickAbstractAnimation *m_animation;
+    QAbstractAnimationJob *m_job;
+    int m_duration;
+
+    enum InternalState {
+        State_Starting, // Used when it should be running, but no we're still missing the controller.
+        State_Running,
+        State_Paused,
+        State_Stopped
+    };
+
+    InternalState m_internalState;
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickAnimatorJob : public QAbstractAnimationJob
+{
+public:
+    virtual void setTarget(QQuickItem *target);
+    QQuickItem *target() const { return m_target; }
+
+    void setFrom(qreal scale) { m_from = scale; }
+    qreal from() const { return m_from; }
+
+    void setTo(qreal to) { m_to = to; }
+    qreal to() const { return m_to; }
+
+    void setDuration(int duration) { m_duration = duration; }
+    int duration() const { return m_duration; }
+
+    QEasingCurve easingCurve() const { return m_easing; }
+    void setEasingCurve(const QEasingCurve &curve) { m_easing = curve; }
+
+    virtual void initialize(QQuickAnimatorController *controller);
+    virtual void writeBack() = 0;
+
+    bool isTransform() const { return m_isTransform; }
+    bool isUniform() const { return m_isUniform; }
+
+    qreal value() const;
+
+    QQuickAnimatorController *controller() const { return m_controller; }
+
+protected:
+    QQuickAnimatorJob();
+    void updateState(State newState, State oldState);
+
+    QPointer<QQuickItem> m_target;
+    QQuickAnimatorController *m_controller;
+
+    qreal m_from;
+    qreal m_to;
+    qreal m_value;
+
+    QEasingCurve m_easing;
+
+    int m_duration;
+
+    uint m_feedback : 1;
+    uint m_isTransform : 1;
+    uint m_isUniform : 1;
+};
+
+class QQuickTransformAnimatorJob : public QQuickAnimatorJob
+{
+public:
+
+    struct Helper
+    {
+        Helper()
+            : ref(1)
+            , item(0)
+            , node(0)
+            , ox(0)
+            , oy(0)
+            , dx(0)
+            , dy(0)
+            , scale(1)
+            , rotation(0)
+            , wasSynced(false)
+            , wasChanged(false)
+        {
+        }
+
+        void sync();
+        void apply();
+
+        int ref;
+        QQuickItem *item;
+        QSGTransformNode *node;
+
+        // Origin
+        float ox;
+        float oy;
+
+        float dx;
+        float dy;
+        float scale;
+        float rotation;
+
+        uint wasSynced : 1;
+        uint wasChanged : 1;
+    };
+
+    ~QQuickTransformAnimatorJob();
+    Helper *transformHelper() const { return m_helper; }
+
+protected:
+    QQuickTransformAnimatorJob();
+    void initialize(QQuickAnimatorController *controller);
+
+    Helper *m_helper;
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickScaleAnimatorJob : public QQuickTransformAnimatorJob
+{
+public:
+    void updateCurrentTime(int time);
+    void writeBack();
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickXAnimatorJob : public QQuickTransformAnimatorJob
+{
+public:
+    void updateCurrentTime(int time);
+    void writeBack();
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickYAnimatorJob : public QQuickTransformAnimatorJob
+{
+public:
+    void updateCurrentTime(int time);
+    void writeBack();
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickRotationAnimatorJob : public QQuickTransformAnimatorJob
+{
+public:
+    QQuickRotationAnimatorJob();
+
+    void updateCurrentTime(int time);
+    void writeBack();
+
+    void setDirection(QQuickRotationAnimator::RotationDirection direction) { m_direction = direction; }
+    QQuickRotationAnimator::RotationDirection direction() const { return m_direction; }
+
+private:
+    QQuickRotationAnimator::RotationDirection m_direction;
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickOpacityAnimatorJob : public QQuickAnimatorJob
+{
+public:
+    QQuickOpacityAnimatorJob();
+
+    void initialize(QQuickAnimatorController *controller);
+    void updateCurrentTime(int time);
+    void writeBack();
+
+private:
+    QSGOpacityNode *m_opacityNode;
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickUniformAnimatorJob : public QQuickAnimatorJob
+{
+public:
+    QQuickUniformAnimatorJob();
+
+    void setTarget(QQuickItem *target);
+
+    void setUniform(const QByteArray &uniform) { m_uniform = uniform; }
+    QByteArray uniform() const { return m_uniform; }
+
+    void afterNodeSync();
+
+    void updateCurrentTime(int time);
+    void writeBack();
+
+private:
+    QByteArray m_uniform;
+    QQuickShaderEffectNode *m_node;
+
+    int m_uniformIndex : 8;
+    int m_uniformType : 8;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKANIMATORJOB_P_H
diff --git a/src/quick/util/qquickbehavior.cpp b/src/quick/util/qquickbehavior.cpp
index 2d765dc5ee21ce5f4138a0d1809d421ba486d7b0..855e99e5a9fe149b986ca8e0971d8e4ba3012aa2 100644
--- a/src/quick/util/qquickbehavior.cpp
+++ b/src/quick/util/qquickbehavior.cpp
@@ -49,6 +49,8 @@
 #include <private/qabstractanimationjob_p.h>
 #include <private/qquicktransition_p.h>
 
+#include <private/qquickanimatorjob_p.h>
+
 #include <private/qobject_p.h>
 
 QT_BEGIN_NAMESPACE
@@ -186,14 +188,18 @@ void QQuickBehavior::write(const QVariant &value)
     if (d->animation->isRunning() && value == d->targetValue)
         return;
 
-    const QVariant &currentValue = d->property.read();
     d->targetValue = value;
 
-    if (d->animationInstance && d->animationInstance->duration() != -1
+    if (d->animationInstance
+            && (d->animationInstance->duration() != -1
+                || d->animationInstance->isRenderThreadProxy())
             && !d->animationInstance->isStopped()) {
         d->blockRunningChanged = true;
         d->animationInstance->stop();
     }
+    // Render thread animations use "stop" to synchronize the property back
+    // to the item, so we need to read the value after.
+    const QVariant &currentValue = d->property.read();
 
     QQuickStateOperation::ActionList actions;
     QQuickAction action;
@@ -205,6 +211,10 @@ void QQuickBehavior::write(const QVariant &value)
     QList<QQmlProperty> after;
     QAbstractAnimationJob *prev = d->animationInstance;
     d->animationInstance = d->animation->transition(actions, after, QQuickAbstractAnimation::Forward);
+
+    if (d->animationInstance && d->animation->threadingModel() == QQuickAbstractAnimation::RenderThread)
+        d->animationInstance = new QQuickAnimatorProxyJob(d->animationInstance, d->animation);
+
     if (prev && prev != d->animationInstance)
         delete prev;
 
diff --git a/src/quick/util/qquicktransition.cpp b/src/quick/util/qquicktransition.cpp
index ead28fe49693ca05056afb634ed1887f4d5b3035..4db3fbbad762245cbd7e5dad5ba888462fb6be78 100644
--- a/src/quick/util/qquicktransition.cpp
+++ b/src/quick/util/qquicktransition.cpp
@@ -48,6 +48,8 @@
 #include "qquickanimation_p_p.h"
 #include "qquicktransitionmanager_p_p.h"
 
+#include <private/qquickanimatorjob_p.h>
+
 #include "private/qparallelanimationgroupjob_p.h"
 
 QT_BEGIN_NAMESPACE
@@ -260,8 +262,11 @@ QQuickTransitionInstance *QQuickTransition::prepare(QQuickStateOperation::Action
     QAbstractAnimationJob *anim = 0;
     for (int i = start; i != end;) {
         anim = d->animations.at(i)->transition(actions, after, direction, defaultTarget);
-        if (anim)
+        if (anim) {
+            if (d->animations.at(i)->threadingModel() == QQuickAbstractAnimation::RenderThread)
+                anim = new QQuickAnimatorProxyJob(anim, d->animations.at(i));
             d->reversed ? group->prependAnimation(anim) : group->appendAnimation(anim);
+        }
         d->reversed ? --i : ++i;
     }
 
diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp
index fdf83141454256b9c6cdc83d812f8962485e4281..ccde83ca6eefade9d529858f75b71e06e8a07959 100644
--- a/src/quick/util/qquickutilmodule.cpp
+++ b/src/quick/util/qquickutilmodule.cpp
@@ -53,6 +53,7 @@
 #include "qquickstate_p_p.h"
 #include "qquicksystempalette_p.h"
 #include "qquicktransition_p.h"
+#include "qquickanimator_p.h"
 #include <qqmlinfo.h>
 #include <private/qqmltypenotavailable_p.h>
 #include <private/qquickanimationcontroller_p.h>
@@ -91,6 +92,14 @@ void QQuickUtilModule::defineModule()
     qmlRegisterType<QQuickTransition>("QtQuick",2,0,"Transition");
     qmlRegisterType<QQuickVector3dAnimation>("QtQuick",2,0,"Vector3dAnimation");
 
+    qmlRegisterUncreatableType<QQuickAnimator>("QtQuick", 2, 2, "Animator", QQuickAbstractAnimation::tr("Animator is an abstract class"));
+    qmlRegisterType<QQuickXAnimator>("QtQuick", 2, 2, "XAnimator");
+    qmlRegisterType<QQuickYAnimator>("QtQuick", 2, 2, "YAnimator");
+    qmlRegisterType<QQuickScaleAnimator>("QtQuick", 2, 2, "ScaleAnimator");
+    qmlRegisterType<QQuickRotationAnimator>("QtQuick", 2, 2, "RotationAnimator");
+    qmlRegisterType<QQuickOpacityAnimator>("QtQuick", 2, 2, "OpacityAnimator");
+    qmlRegisterType<QQuickUniformAnimator>("QtQuick", 2, 2, "UniformAnimator");
+
     qmlRegisterType<QQuickStateOperation>();
 
     qmlRegisterCustomType<QQuickPropertyChanges>("QtQuick",2,0,"PropertyChanges", new QQuickPropertyChangesParser);
diff --git a/src/quick/util/util.pri b/src/quick/util/util.pri
index 7f77f7f7020bfa56d30002dbb89c2bb1057c0010..fae1103d47a4c81fb99052d3b3f73a6a902c5653 100644
--- a/src/quick/util/util.pri
+++ b/src/quick/util/util.pri
@@ -22,7 +22,10 @@ SOURCES += \
     $$PWD/qquickimageprovider.cpp \
     $$PWD/qquicksvgparser.cpp \
     $$PWD/qquickvaluetypes.cpp \
-    $$PWD/qquickglobal.cpp
+    $$PWD/qquickglobal.cpp \
+    $$PWD/qquickanimator.cpp \
+    $$PWD/qquickanimatorjob.cpp \
+    $$PWD/qquickanimatorcontroller.cpp
 
 HEADERS += \
     $$PWD/qquickapplication_p.h\
@@ -51,4 +54,8 @@ HEADERS += \
     $$PWD/qquickpathinterpolator_p.h \
     $$PWD/qquickimageprovider.h \
     $$PWD/qquicksvgparser_p.h \
-    $$PWD/qquickvaluetypes_p.h
+    $$PWD/qquickvaluetypes_p.h \
+    $$PWD/qquickanimator_p.h \
+    $$PWD/qquickanimator_p_p.h \
+    $$PWD/qquickanimatorjob_p.h \
+    $$PWD/qquickanimatorcontroller_p.h
diff --git a/tests/auto/quick/qquickanimators/data/Box.qml b/tests/auto/quick/qquickanimators/data/Box.qml
new file mode 100644
index 0000000000000000000000000000000000000000..cff3e7f92943e8390ac1ac1c9265fedbb9d885cb
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/Box.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+
+Rectangle {
+    id: box
+    gradient: Gradient {
+        GradientStop { position: 0.1; color: "red" }
+        GradientStop { position: 0.9; color: "blue" }
+    }
+    width: 100
+    height: 100
+    anchors.centerIn: parent
+    antialiasing: true
+
+    property int rotationChangeCounter: 0
+    onRotationChanged: ++rotationChangeCounter;
+
+    property int scaleChangeCounter: 0
+    onScaleChanged: ++scaleChangeCounter;
+
+    property int opacityChangeCounter: 0
+    onOpacityChanged: ++opacityChangeCounter
+
+    property int xChangeCounter: 0;
+    onXChanged: ++xChangeCounter;
+
+    property int yChangeCounter: 0;
+    onYChanged: ++yChangeCounter;
+
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_behavior.qml b/tests/auto/quick/qquickanimators/data/tst_behavior.qml
new file mode 100644
index 0000000000000000000000000000000000000000..b22cc93b097c57bcdd68941e0e36ea7116520370
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_behavior.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testcase
+        name: "behavior"
+        when: box.scale == 2
+        function test_endresult() {
+            compare(box.scaleChangeCounter, 1);
+            compare(box.scale, 2);
+            var image = grabImage(root);
+            compare(image.pixel(0, 0), Qt.rgba(1, 0, 0, 1));
+            compare(image.pixel(199, 199), Qt.rgba(0, 0, 1, 1));
+        }
+    }
+
+    Box {
+        id: box
+        Behavior on scale { ScaleAnimator { id: animation; duration: 300; } }
+    }
+
+    Timer {
+        interval: 1000;
+        repeat: false
+        running: true
+        onTriggered: box.scale = 2
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_mixedparallel.qml b/tests/auto/quick/qquickanimators/data/tst_mixedparallel.qml
new file mode 100644
index 0000000000000000000000000000000000000000..9cd28f2493d8b68fec7bc2d150e236763a1339d8
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_mixedparallel.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testcase
+        name: "mixedparallel"
+        when: !animation.running
+        function test_endresult() {
+            compare(box.rotationChangeCounter, 1);
+            compare(box.scale, 2);
+            compare(box.rotation, 180);
+            var image = grabImage(root);
+            compare(image.pixel(0, 0), Qt.rgba(0, 0, 1, 1));
+            compare(image.pixel(199, 199), Qt.rgba(1, 0, 0, 1));
+        }
+    }
+
+    Box {
+        id: box
+        ParallelAnimation {
+            id: animation
+            NumberAnimation { target: box; property: "scale"; from: 1; to: 2.0; duration: 1000; }
+            RotationAnimator { target: box; from: 0; to: 180; duration: 1000; }
+            running: true
+            loops: 1;
+        }
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_mixedsequential.qml b/tests/auto/quick/qquickanimators/data/tst_mixedsequential.qml
new file mode 100644
index 0000000000000000000000000000000000000000..4c62bc801865e0d8caa90214caded4e5484b9435
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_mixedsequential.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testcase
+        name: "mixedsequential"
+        when: !animation.running
+        function test_endresult() {
+            compare(box.rotationChangeCounter, 1);
+            compare(box.scale, 2);
+            compare(box.rotation, 180);
+            var image = grabImage(root);
+            compare(image.pixel(0, 0), Qt.rgba(0, 0, 1, 1));
+            compare(image.pixel(199, 199), Qt.rgba(1, 0, 0, 1));
+        }
+    }
+
+    Box {
+        id: box
+        ParallelAnimation {
+            id: animation
+            NumberAnimation { target: box; property: "scale"; from: 1; to: 2.0; duration: 500; }
+            RotationAnimator { target: box; from: 0; to: 180; duration: 500; }
+            running: true
+            loops: 1;
+        }
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_nested.qml b/tests/auto/quick/qquickanimators/data/tst_nested.qml
new file mode 100644
index 0000000000000000000000000000000000000000..95cb70cb482369acd46303430040b44220551405
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_nested.qml
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testCase
+        name: "nested"
+        when: !animation.running
+        function test_endresult() {
+            compare(box.before, 2);
+            compare(box.after, 2);
+        }
+    }
+
+    Box {
+        id: box
+
+        anchors.centerIn: undefined
+
+        property int before: 0;
+        property int after: 0;
+
+        SequentialAnimation {
+            id: animation;
+            ScriptAction { script: box.before++; }
+            ParallelAnimation {
+                ScaleAnimator { target: box; from: 2.0; to: 1; duration: 500; }
+                OpacityAnimator { target: box; from: 0; to: 1; duration: 500; }
+            }
+            PauseAnimation { duration: 500 }
+            SequentialAnimation {
+                ParallelAnimation {
+                    XAnimator { target: box; from: 0; to: 100; duration: 500}
+                    RotationAnimator { target: box; from: 0; to: 90; duration: 500 }
+                }
+                ParallelAnimation {
+                    XAnimator { target: box; from: 100; to: 0; duration: 500 }
+                    RotationAnimator { target: box; from: 90; to: 0; duration: 500 }
+                }
+            }
+            ScriptAction { script: box.after++; }
+            running: true
+            loops: 2
+        }
+    }
+
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_on.qml b/tests/auto/quick/qquickanimators/data/tst_on.qml
new file mode 100644
index 0000000000000000000000000000000000000000..e48d7107f9268d2a7ed8eb168eafeebf9df78a54
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_on.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testCase
+        name: "on"
+        when: !animx.running && !animy.running
+              && !anims.running && !animr.running
+              && !animo.running;
+        function test_endresult() {
+            compare(box.xChangeCounter, 1);
+            compare(box.yChangeCounter, 1);
+            compare(box.scaleChangeCounter, 1);
+            compare(box.rotationChangeCounter, 1);
+            compare(box.opacityChangeCounter, 1);
+            compare(box.x, 100);
+            compare(box.y, 100);
+            compare(box.scale, 2);
+            compare(box.rotation, 180);
+            compare(box.opacity, 0.5);
+        }
+    }
+
+    Box {
+        id: box
+        anchors.centerIn: undefined
+        XAnimator on x { id: animx; from: 0; to: 100; duration: 1000 }
+        YAnimator on y { id: animy; from: 0; to: 100; duration: 1000 }
+        ScaleAnimator on scale { id: anims; from: 1; to: 2; duration: 1000 }
+        RotationAnimator on rotation { id: animr ; from: 0; to: 180; duration: 1000 }
+        OpacityAnimator on opacity { id: animo; from: 1; to: 0.5; duration: 1000 }
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_opacity.qml b/tests/auto/quick/qquickanimators/data/tst_opacity.qml
new file mode 100644
index 0000000000000000000000000000000000000000..a785b2b3f320eaa20cd8ca03cb20fe6474601e8e
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_opacity.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testCase
+        name: "opacity"
+        when: !animation.running
+        function test_endresult() {
+            compare(box.opacityChangeCounter, 1);
+            compare(box.opacity, 0.5);
+            var image = grabImage(root);
+            compare(image.red(50, 50), 255);
+            verify(image.green(50, 50) > 0);
+            verify(image.blue(50, 50) > 0);
+        }
+    }
+
+    Box {
+        id: box
+
+        OpacityAnimator {
+            id: animation
+            target: box
+            from: 1;
+            to: 0.5
+            duration: 1000
+            running: true
+        }
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_parallel.qml b/tests/auto/quick/qquickanimators/data/tst_parallel.qml
new file mode 100644
index 0000000000000000000000000000000000000000..3105d3c2ddc5d177ebb33278bd3220ec85446c16
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_parallel.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testcase
+        name: "parallel"
+        when: !animation.running
+        function test_endresult() {
+            compare(box.rotationChangeCounter, 1);
+            compare(box.scaleChangeCounter, 1);
+            compare(box.scale, 2);
+            compare(box.rotation, 180);
+            var image = grabImage(root);
+            compare(image.pixel(0, 0), Qt.rgba(0, 0, 1, 1));
+            compare(image.pixel(199, 199), Qt.rgba(1, 0, 0, 1));
+        }
+    }
+
+    Box {
+        id: box
+        ParallelAnimation {
+            id: animation
+            ScaleAnimator { target: box; from: 1; to: 2.0; duration: 1000; }
+            RotationAnimator { target: box; from: 0; to: 180; duration: 1000; }
+            running: true
+        }
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_restart.qml b/tests/auto/quick/qquickanimators/data/tst_restart.qml
new file mode 100644
index 0000000000000000000000000000000000000000..42c7a33a8b9d0190f4a3ce85c3cd7c111ab3e2d0
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_restart.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    property int restartCount: 5;
+
+    TestCase {
+        id: testcase
+        name: "restart"
+        when: root.restartCount == 0 && animation.running == false;
+        function test_endresult() {
+            compare(box.scale, 2);
+        }
+    }
+
+    Box {
+        id: box
+
+        ScaleAnimator {
+            id: animation
+            target: box;
+            from: 1;
+            to: 2.0;
+            duration: 100;
+            loops: 1
+            running: false;
+        }
+
+        Timer {
+            id: timer;
+            interval: 500
+            running: true
+            repeat: true
+            onTriggered: {
+                animation.running = true;
+                --root.restartCount;
+            }
+        }
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_rotation.qml b/tests/auto/quick/qquickanimators/data/tst_rotation.qml
new file mode 100644
index 0000000000000000000000000000000000000000..517cf5945631138d1cad241439da3e057d62bf3b
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_rotation.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testCase
+        name: "rotation"
+        when: !animation.running
+        function test_endresult() {
+            compare(box.rotationChangeCounter, 1);
+            compare(box.rotation, 180);
+            var image = grabImage(root);
+            compare(image.pixel(50, 50), Qt.rgba(0, 0, 1));
+        }
+    }
+
+    Box {
+        id: box
+        RotationAnimator {
+            id: animation
+            target: box
+            from: 0;
+            to: 180
+            duration: 1000
+            easing.type: Easing.InOutBack
+            running: true
+        }
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_scale.qml b/tests/auto/quick/qquickanimators/data/tst_scale.qml
new file mode 100644
index 0000000000000000000000000000000000000000..6fd4668684c428fe87e94e1f78be922e42b0c8de
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_scale.qml
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testCase
+        name: "scale"
+        when: !animation.running
+        function test_endresult() {
+            compare(box.scaleChangeCounter, 1);
+            compare(box.scale, 2);
+            var image = grabImage(root);
+            compare(image.pixel(0, 0), Qt.rgba(1, 0, 0));
+        }
+    }
+
+    Box {
+        id: box
+
+        ScaleAnimator {
+            id: animation
+            target: box
+            from: 1;
+            to: 2.0
+            duration: 1000
+            easing.type: Easing.InOutCubic
+            running: true
+        }
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_sequential.qml b/tests/auto/quick/qquickanimators/data/tst_sequential.qml
new file mode 100644
index 0000000000000000000000000000000000000000..2bb14f8acfd78f8069d08c7421a11c9ea0f272c2
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_sequential.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testcase
+        name: "parallel"
+        when: !animation.running
+        function test_endresult() {
+            compare(box.rotationChangeCounter, 1);
+            compare(box.scaleChangeCounter, 1);
+            compare(box.scale, 2);
+            compare(box.rotation, 180);
+            var image = grabImage(root);
+            compare(image.pixel(0, 0), Qt.rgba(0, 0, 1, 1));
+            compare(image.pixel(199, 199), Qt.rgba(1, 0, 0, 1));
+        }
+    }
+
+    Box {
+        id: box
+        SequentialAnimation {
+            id: animation
+            ScaleAnimator { target: box; from: 1; to: 2.0; duration: 1000; }
+            RotationAnimator { target: box; from: 0; to: 180; duration: 1000; }
+            running: true
+        }
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_transformorigin.qml b/tests/auto/quick/qquickanimators/data/tst_transformorigin.qml
new file mode 100644
index 0000000000000000000000000000000000000000..0211d0305d5a129d927b7126e61d5379d6778d97
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_transformorigin.qml
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 300
+    height: 300
+
+    Timer {
+        id: timer;
+        running: testCase.windowShown
+        interval: 1000
+        repeat: false
+        onTriggered: triggered = true;
+        property bool triggered: false;
+    }
+
+    TestCase {
+        id: testCase
+        name: "transformorigin"
+        when: timer.triggered
+        function test_endresult() {
+
+            var image = grabImage(root);
+
+            var white = Qt.rgba(1, 1, 1);
+            var blue = Qt.rgba(0, 0, 1);
+
+
+            // topleft
+            compare(image.pixel(40, 40), white);
+            compare(image.pixel(60, 40), white);
+            compare(image.pixel(40, 60), white);
+            compare(image.pixel(60, 60), blue);
+
+            // top
+            compare(image.pixel(140, 40), white);
+            compare(image.pixel(160, 40), white);
+            compare(image.pixel(140, 60), blue);
+            compare(image.pixel(160, 60), blue);
+
+            // topright
+            compare(image.pixel(240, 40), white);
+            compare(image.pixel(260, 40), white);
+            compare(image.pixel(240, 60), blue);
+            compare(image.pixel(260, 60), white);
+
+
+            // left
+            compare(image.pixel(40, 140), white);
+            compare(image.pixel(60, 140), blue);
+            compare(image.pixel(40, 160), white);
+            compare(image.pixel(60, 160), blue);
+
+            // center
+            compare(image.pixel(140, 140), blue);
+            compare(image.pixel(160, 140), blue);
+            compare(image.pixel(140, 160), blue);
+            compare(image.pixel(160, 160), blue);
+
+            // right
+            compare(image.pixel(240, 140), blue);
+            compare(image.pixel(260, 140), white);
+            compare(image.pixel(240, 160), blue);
+            compare(image.pixel(260, 160), white);
+
+
+            // bottomleft
+            compare(image.pixel(40, 240), white);
+            compare(image.pixel(60, 240), blue);
+            compare(image.pixel(40, 260), white);
+            compare(image.pixel(60, 260), white);
+
+            // bottom
+            compare(image.pixel(140, 240), blue);
+            compare(image.pixel(160, 240), blue);
+            compare(image.pixel(140, 260), white);
+            compare(image.pixel(160, 260), white);
+
+            // bottomright
+            compare(image.pixel(240, 240), blue);
+            compare(image.pixel(260, 240), white);
+            compare(image.pixel(240, 260), white);
+            compare(image.pixel(260, 260), white);
+
+        }
+    }
+
+    property var origins: [Item.TopLeft, Item.Top, Item.TopRight,
+                           Item.Left, Item.Center, Item.Right,
+                           Item.BottomLeft, Item.Bottom, Item.BottomRight];
+
+    Grid {
+        anchors.fill: parent
+        rows: 3
+        columns: 3
+
+        Repeater {
+            model: 9
+            Item {
+                width: 100
+                height: 100
+                Rectangle {
+                    id: box
+                    color: "blue"
+                    anchors.centerIn: parent
+                    width: 10
+                    height: 10
+                    antialiasing: true;
+
+                    transformOrigin: root.origins[index];
+
+                    ScaleAnimator { target: box; from: 1; to: 5.5; duration: 1000; running: true; }
+                }
+            }
+        }
+    }
+
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_transition.qml b/tests/auto/quick/qquickanimators/data/tst_transition.qml
new file mode 100644
index 0000000000000000000000000000000000000000..8e21a6537e8190c5a49435bb13a00e918376b8ee
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_transition.qml
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testcase
+        name: "transition"
+        when: box.scale == 2
+        function test_endresult() {
+            compare(box.scaleChangeCounter, 1);
+            compare(box.scale, 2);
+            var image = grabImage(root);
+            compare(image.pixel(0, 0), Qt.rgba(1, 0, 0));
+            compare(image.pixel(199, 199), Qt.rgba(0, 0, 1));
+        }
+    }
+
+    states: [
+        State {
+            name: "one"
+            PropertyChanges { target: box; scale: 1 }
+        },
+        State {
+            name: "two"
+            PropertyChanges { target: box; scale: 2 }
+        }
+    ]
+    state: "one"
+
+    transitions: [
+        Transition {
+            ScaleAnimator { duration: 200; }
+        }
+    ]
+
+    Box {
+        id: box
+    }
+
+    Timer {
+        interval: 1000;
+        repeat: false
+        running: true
+        onTriggered: root.state = "two"
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_x.qml b/tests/auto/quick/qquickanimators/data/tst_x.qml
new file mode 100644
index 0000000000000000000000000000000000000000..70ecf96346f653c7a8915e46a1f82f82c4159607
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_x.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testCase
+        name: "x"
+        when: !animation.running
+        function test_endresult() {
+            compare(box.xChangeCounter, 1);
+            compare(box.x, 100);
+            var image = grabImage(root);
+            compare(image.pixel(100, 50), Qt.rgba(1, 0, 0));
+            compare(image.pixel(99, 50), Qt.rgba(1, 1, 1)); // outside on the left
+        }
+    }
+
+    Box {
+        id: box
+
+        anchors.centerIn: undefined
+
+        XAnimator {
+            id: animation
+            target: box
+            from: 0;
+            to: 100
+            duration: 1000
+            running: true
+        }
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/data/tst_y.qml b/tests/auto/quick/qquickanimators/data/tst_y.qml
new file mode 100644
index 0000000000000000000000000000000000000000..428d42a6c387c87e036272a9bf5ca2d6b575f21a
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/data/tst_y.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+    id: root;
+    width: 200
+    height: 200
+
+    TestCase {
+        id: testCase
+        name: "y"
+        when: !animation.running
+        function test_endresult() {
+            compare(box.yChangeCounter, 1);
+            compare(box.y, 100);
+            var image = grabImage(root);
+            compare(image.pixel(50, 100), Qt.rgba(1, 0, 0));
+            compare(image.pixel(50, 99), Qt.rgba(1, 1, 1)); // outside on the left
+        }
+    }
+
+    Box {
+        id: box
+
+        anchors.centerIn: undefined
+
+        YAnimator {
+            id: animation
+            target: box
+            from: 0;
+            to: 100
+            duration: 1000
+            running: true
+        }
+    }
+}
diff --git a/tests/auto/quick/qquickanimators/qquickanimators.pro b/tests/auto/quick/qquickanimators/qquickanimators.pro
new file mode 100644
index 0000000000000000000000000000000000000000..4fa0438e412349438e3dcb84e15df381e59ad227
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/qquickanimators.pro
@@ -0,0 +1,14 @@
+QT += core-private gui-private qml-private
+TEMPLATE=app
+TARGET=tst_qquickanimators
+
+CONFIG += qmltestcase
+SOURCES += tst_qquickanimators.cpp
+
+TESTDATA = data/*
+
+OTHER_FILES += \
+    data/tst_scale.qml \
+    data/Scale.qml \
+    tst_on.qml \
+    data/tst_nested.qml
diff --git a/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp b/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f3f982091fb37c430fbed48d3664687e40e66ff7
--- /dev/null
+++ b/tests/auto/quick/qquickanimators/tst_qquickanimators.cpp
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtQuickTest/quicktest.h>
+
+QUICK_TEST_MAIN(qquickanimators)