Merge master <-> api_changes
[profile/ivi/qtdeclarative.git] / src / quick / items / qquickitem.cpp
index a6cff52..77808a6 100644 (file)
@@ -1,10 +1,9 @@
 /****************************************************************************
 **
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
 **
-** This file is part of the QtDeclarative module of the Qt Toolkit.
+** This file is part of the QtQml module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
 ** GNU Lesser General Public License Usage
@@ -35,6 +34,7 @@
 **
 **
 **
+**
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
 #include "qquickitem.h"
 
 #include "qquickcanvas.h"
-#include <QtDeclarative/qjsengine.h>
+#include <QtQml/qjsengine.h>
 #include "qquickcanvas_p.h"
 
 #include "qquickevents_p_p.h"
 #include "qquickscreen_p.h"
 
-#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativecomponent.h>
-#include <QtDeclarative/qdeclarativeinfo.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlinfo.h>
 #include <QtGui/qpen.h>
 #include <QtGui/qcursor.h>
 #include <QtGui/qguiapplication.h>
-#include <QtGui/qinputpanel.h>
+#include <QtGui/qinputmethod.h>
 #include <QtCore/qdebug.h>
 #include <QtCore/qcoreevent.h>
 #include <QtCore/qnumeric.h>
 
-#include <private/qdeclarativeengine_p.h>
-#include <QtQuick/private/qdeclarativestategroup_p.h>
-#include <private/qdeclarativeopenmetaobject_p.h>
-#include <QtQuick/private/qdeclarativestate_p.h>
+#include <private/qqmlglobal_p.h>
+#include <private/qqmlengine_p.h>
+#include <QtQuick/private/qquickstategroup_p.h>
+#include <private/qqmlopenmetaobject_p.h>
+#include <QtQuick/private/qquickstate_p.h>
 #include <private/qlistmodelinterface_p.h>
 #include <private/qquickitem_p.h>
-#include <private/qdeclarativeaccessors_p.h>
+#include <private/qqmlaccessors_p.h>
 #include <QtQuick/private/qquickaccessibleattached_p.h>
 
 #include <float.h>
@@ -74,7 +75,7 @@
 
 QT_BEGIN_NAMESPACE
 
-static void QQuickItem_parentNotifier(QObject *o, intptr_t, QDeclarativeNotifier **n)
+static void QQuickItem_parentNotifier(QObject *o, intptr_t, QQmlNotifier **n)
 {
     QQuickItemPrivate *d = QQuickItemPrivate::get(static_cast<QQuickItem *>(o));
     *n = &d->parentNotifier;
@@ -86,11 +87,11 @@ QML_PRIVATE_ACCESSOR(QQuickItem, qreal, y, y)
 QML_PRIVATE_ACCESSOR(QQuickItem, qreal, width, width)
 QML_PRIVATE_ACCESSOR(QQuickItem, qreal, height, height)
 
-static QDeclarativeAccessors QQuickItem_parent = { QQuickItem_parentRead, QQuickItem_parentNotifier };
-static QDeclarativeAccessors QQuickItem_x = { QQuickItem_xRead, 0 };
-static QDeclarativeAccessors QQuickItem_y = { QQuickItem_yRead, 0 };
-static QDeclarativeAccessors QQuickItem_width = { QQuickItem_widthRead, 0 };
-static QDeclarativeAccessors QQuickItem_height = { QQuickItem_heightRead, 0 };
+static QQmlAccessors QQuickItem_parent = { QQuickItem_parentRead, QQuickItem_parentNotifier };
+static QQmlAccessors QQuickItem_x = { QQuickItem_xRead, 0 };
+static QQmlAccessors QQuickItem_y = { QQuickItem_yRead, 0 };
+static QQmlAccessors QQuickItem_width = { QQuickItem_widthRead, 0 };
+static QQmlAccessors QQuickItem_height = { QQuickItem_heightRead, 0 };
 
 QML_DECLARE_PROPERTIES(QQuickItem) {
     { QML_PROPERTY_NAME(parent), 0, &QQuickItem_parent },
@@ -138,7 +139,7 @@ void QQuickItemPrivate::registerAccessorProperties()
     The following example moves the Y axis of the \l Rectangle elements while still allowing the \l Row element
     to lay the items out as if they had not been transformed:
     \qml
-    import QtQuick 1.0
+    import QtQuick 2.0
 
     Row {
         Rectangle {
@@ -233,7 +234,7 @@ void QQuickItemPrivate::registerAccessorProperties()
     rotations you must specify the axis to rotate around in addition to the origin point.
 
     The following example shows various 3D-like rotations applied to an \l Image.
-    \snippet doc/src/snippets/declarative/rotation.qml 0
+    \snippet doc/src/snippets/qml/rotation.qml 0
 
     \image axisrotation.png
 
@@ -442,8 +443,8 @@ QQuickItemKeyFilter::QQuickItemKeyFilter(QQuickItem *item)
 {
     QQuickItemPrivate *p = item?QQuickItemPrivate::get(item):0;
     if (p) {
-        m_next = p->keyHandler;
-        p->keyHandler = this;
+        m_next = p->extra.value().keyHandler;
+        p->extra->keyHandler = this;
     }
 }
 
@@ -491,7 +492,7 @@ void QQuickItemKeyFilter::componentComplete()
 
     The following example provides key navigation for a 2x2 grid of items:
 
-    \snippet doc/src/snippets/declarative/keynavigation.qml 0
+    \snippet doc/src/snippets/qml/keynavigation.qml 0
 
     The top-left item initially receives focus by setting \l {Item::}{focus} to
     \c true. When an arrow key is pressed, the focus will move to the
@@ -912,13 +913,13 @@ bool QQuickKeysAttachedPrivate::isConnected(const char *signalName)
     be used to test for a certain key; in this case, the left cursor
     key:
 
-    \snippet doc/src/snippets/declarative/keys/keys-pressed.qml key item
+    \snippet doc/src/snippets/qml/keys/keys-pressed.qml key item
 
     Some keys may alternatively be handled via specific signal properties,
     for example \e onSelectPressed.  These handlers automatically set
     \e event.accepted to true.
 
-    \snippet doc/src/snippets/declarative/keys/keys-handler.qml key item
+    \snippet doc/src/snippets/qml/keys/keys-handler.qml key item
 
     See \l{Qt::Key}{Qt.Key} for the list of keyboard codes.
 
@@ -1460,7 +1461,7 @@ QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj)
     from left to right by default, they are now positioned from right to left instead, as demonstrated
     by the numbering and opacity of the items:
 
-    \snippet doc/src/snippets/declarative/layoutmirroring.qml 0
+    \snippet doc/src/snippets/qml/layoutmirroring.qml 0
 
     \image layoutmirroring.png
 
@@ -1505,7 +1506,7 @@ QQuickLayoutMirroringAttached::QQuickLayoutMirroringAttached(QObject *parent) :
 {
     if (QQuickItem *item = qobject_cast<QQuickItem*>(parent)) {
         itemPrivate = QQuickItemPrivate::get(item);
-        itemPrivate->attachedLayoutDirection = this;
+        itemPrivate->extra.value().layoutDirectionAttached = this;
     } else
         qmlInfo(parent) << tr("LayoutDirection attached property only works with Items");
 }
@@ -1598,8 +1599,8 @@ void QQuickItemPrivate::setLayoutMirror(bool mirror)
             emit _anchors->mirroredChanged();
         }
         mirrorChange();
-        if (attachedLayoutDirection) {
-            emit attachedLayoutDirection->enabledChanged();
+        if (extra.isAllocated() && extra->layoutDirectionAttached) {
+            emit extra->layoutDirectionAttached->enabledChanged();
         }
     }
 }
@@ -1626,7 +1627,7 @@ void QQuickItemPrivate::setAccessibleFlagAndListener()
 
     \inmodule QtQuick
 
-    All visual items in Qt Declarative inherit from QQuickItem.  Although QQuickItem
+    All visual items in Qt Quick inherit from QQuickItem.  Although QQuickItem
     has no visual appearance, it defines all the properties that are
     common across visual items - such as the x and y position, the
     width and height, \l {anchor-layout}{anchoring} and key handling.
@@ -1640,11 +1641,12 @@ void QQuickItemPrivate::setAccessibleFlagAndListener()
 
 /*!
     \qmlclass Item QQuickItem
+    \inherits QtObject
     \inqmlmodule QtQuick 2
     \ingroup qml-basic-visual-elements
     \brief The Item is the most basic of all visual items in QML.
 
-    All visual items in Qt Declarative inherit from Item.  Although Item
+    All visual items in Qt Quick inherit from Item.  Although Item
     has no visual appearance, it defines all the properties that are
     common across visual items - such as the x and y position, the
     width and height, \l {anchor-layout}{anchoring} and key handling.
@@ -1823,10 +1825,14 @@ QQuickItem::~QQuickItem()
     }
 
     d->changeListeners.clear();
-    delete d->_anchorLines; d->_anchorLines = 0;
+
+    if (d->extra.isAllocated()) {
+        delete d->extra->contents; d->extra->contents = 0;
+        delete d->extra->layer; d->extra->layer = 0;
+    }
+
     delete d->_anchors; d->_anchors = 0;
     delete d->_stateGroup; d->_stateGroup = 0;
-    delete d->_contents; d->_contents = 0;
 }
 
 /*!
@@ -1867,6 +1873,17 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
     if (parentItem == d->parentItem)
         return;
 
+    if (parentItem) {
+        QQuickItem *itemAncestor = parentItem->parentItem();
+        while (itemAncestor != 0) {
+            if (itemAncestor == this) {
+                qWarning("QQuickItem::setParentItem: Parent is already part of this items subtree.");
+                return;
+            }
+            itemAncestor = itemAncestor->parentItem();
+        }
+    }
+
     d->removeFromDirtyList();
 
     QQuickItem *oldParentItem = d->parentItem;
@@ -1891,7 +1908,11 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
             QQuickCanvasPrivate::get(d->canvas)->clearFocusInScope(scopeItem, scopeFocusedItem,
                                                                 QQuickCanvasPrivate::DontChangeFocusProperty);
 
+        const bool wasVisible = isVisible();
         op->removeChild(this);
+        if (wasVisible) {
+            emit oldParentItem->visibleChildrenChanged();
+        }
     } else if (d->canvas) {
         QQuickCanvasPrivate::get(d->canvas)->parentlessItems.remove(this);
     }
@@ -1911,7 +1932,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
         QQuickItemPrivate::get(d->parentItem)->addChild(this);
 
     d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
-    d->setEffectiveEnableRecur(d->calcEffectiveEnable());
+    d->setEffectiveEnableRecur(0, d->calcEffectiveEnable());
 
     if (scopeFocusedItem && d->parentItem && d->canvas) {
         // We need to test whether this item becomes scope focused
@@ -1938,6 +1959,8 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
     }
 
     emit parentChanged(d->parentItem);
+    if (isVisible() && d->parentItem)
+        emit d->parentItem->visibleChildrenChanged();
 }
 
 void QQuickItem::stackBefore(const QQuickItem *sibling)
@@ -2036,7 +2059,7 @@ QList<QQuickItem *> QQuickItemPrivate::paintOrderChildItems() const
     // the childItems list.  This is by far the most common case.
     bool haveZ = false;
     for (int i = 0; i < childItems.count(); ++i) {
-        if (QQuickItemPrivate::get(childItems.at(i))->z != 0.) {
+        if (QQuickItemPrivate::get(childItems.at(i))->z() != 0.) {
             haveZ = true;
             break;
         }
@@ -2099,7 +2122,7 @@ QQuickItem *QQuickItemPrivate::InitializationState::getFocusScope(QQuickItem *it
 {
     if (!focusScope) {
         QQuickItem *fs = item->parentItem();
-        while (!fs->isFocusScope())
+        while (fs->parentItem() && !fs->isFocusScope())
             fs = fs->parentItem();
         focusScope = fs;
     }
@@ -2131,12 +2154,16 @@ void QQuickItemPrivate::initCanvas(InitializationState *state, QQuickCanvas *c)
         QQuickCanvasPrivate::get(canvas)->itemsToPolish.insert(q);
 
     itemNodeInstance = 0;
-    opacityNode = 0;
-    clipNode = 0;
-    rootNode = 0;
+
+    if (extra.isAllocated()) {
+        extra->opacityNode = 0;
+        extra->clipNode = 0;
+        extra->rootNode = 0;
+        extra->beforePaintNode = 0;
+    }
+
     groupNode = 0;
     paintNode = 0;
-    beforePaintNode = 0;
 
     InitializationState _dummy;
     InitializationState *childState = state;
@@ -2166,8 +2193,8 @@ void QQuickItemPrivate::initCanvas(InitializationState *state, QQuickCanvas *c)
 
     dirty(Canvas);
 
-    if (screenAttached)
-        screenAttached->canvasChanged(c);
+    if (extra.isAllocated() && extra->screenAttached)
+        extra->screenAttached->canvasChanged(c);
     itemChange(QQuickItem::ItemSceneChange, c);
 }
 
@@ -2206,11 +2233,11 @@ void QQuickItemPrivate::itemToParentTransform(QTransform &t) const
         t = m.toTransform();
     }
 
-    if (scale != 1. || rotation != 0.) {
+    if (scale() != 1. || rotation() != 0.) {
         QPointF tp = computeTransformOrigin();
         t.translate(tp.x(), tp.y());
-        t.scale(scale, scale);
-        t.rotate(rotation);
+        t.scale(scale(), scale());
+        t.rotate(rotation());
         t.translate(-tp.x(), -tp.y());
     }
 }
@@ -2271,9 +2298,8 @@ bool QQuickItem::isComponentComplete() const
 }
 
 QQuickItemPrivate::QQuickItemPrivate()
-: _anchors(0), _contents(0), baselineOffset(0), _anchorLines(0), _stateGroup(0), origin(QQuickItem::Center),
-
-  flags(0), widthValid(false), heightValid(false), componentComplete(true),
+: _anchors(0), _stateGroup(0),
+  flags(0), widthValid(false), heightValid(false), baselineOffsetValid(false), componentComplete(true),
   keepMouse(false), keepTouch(false), hoverEnabled(false), smooth(false), focus(false), activeFocus(false), notifiedFocus(false),
   notifiedActiveFocus(false), filtersChildMouseEvents(false), explicitVisible(true),
   effectiveVisible(true), explicitEnable(true), effectiveEnable(true), polishScheduled(false),
@@ -2282,23 +2308,17 @@ QQuickItemPrivate::QQuickItemPrivate()
   staticSubtreeGeometry(false),
   isAccessible(false),
 
+  dirtyAttributes(0), nextDirtyItem(0), prevDirtyItem(0),
+
   canvas(0), parentItem(0), sortedChildItems(&childItems),
 
   subFocusItem(0),
 
   x(0), y(0), width(0), height(0), implicitWidth(0), implicitHeight(0),
-  z(0), scale(1), rotation(0), opacity(1),
 
-  attachedLayoutDirection(0), acceptedMouseButtons(0),
-  imHints(Qt::ImhNone),
+  baselineOffset(0),
 
-  keyHandler(0),
-
-  dirtyAttributes(0), nextDirtyItem(0), prevDirtyItem(0),
-
-  itemNodeInstance(0), opacityNode(0), clipNode(0), rootNode(0), groupNode(0), paintNode(0)
-  , beforePaintNode(0), effectRefCount(0), hideRefCount(0)
-  , screenAttached(0)
+  itemNodeInstance(0), groupNode(0), paintNode(0)
 {
 }
 
@@ -2323,7 +2343,7 @@ void QQuickItemPrivate::init(QQuickItem *parent)
 
     registerAccessorProperties();
 
-    baselineOffset.invalidate();
+    baselineOffsetValid = false;
 
     if (parent) {
         q->setParentItem(parent);
@@ -2332,7 +2352,7 @@ void QQuickItemPrivate::init(QQuickItem *parent)
     }
 }
 
-void QQuickItemPrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
+void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
 {
     if (!o)
         return;
@@ -2391,14 +2411,14 @@ void QQuickItemPrivate::data_append(QDeclarativeListProperty<QObject> *prop, QOb
     specify it.
  */
 
-int QQuickItemPrivate::data_count(QDeclarativeListProperty<QObject> *prop)
+int QQuickItemPrivate::data_count(QQmlListProperty<QObject> *prop)
 {
     Q_UNUSED(prop);
     // XXX todo
     return 0;
 }
 
-QObject *QQuickItemPrivate::data_at(QDeclarativeListProperty<QObject> *prop, int i)
+QObject *QQuickItemPrivate::data_at(QQmlListProperty<QObject> *prop, int i)
 {
     Q_UNUSED(prop);
     Q_UNUSED(i);
@@ -2406,13 +2426,13 @@ QObject *QQuickItemPrivate::data_at(QDeclarativeListProperty<QObject> *prop, int
     return 0;
 }
 
-void QQuickItemPrivate::data_clear(QDeclarativeListProperty<QObject> *prop)
+void QQuickItemPrivate::data_clear(QQmlListProperty<QObject> *prop)
 {
     Q_UNUSED(prop);
     // XXX todo
 }
 
-QObject *QQuickItemPrivate::resources_at(QDeclarativeListProperty<QObject> *prop, int index)
+QObject *QQuickItemPrivate::resources_at(QQmlListProperty<QObject> *prop, int index)
 {
     const QObjectList children = prop->object->children();
     if (index < children.count())
@@ -2421,18 +2441,18 @@ QObject *QQuickItemPrivate::resources_at(QDeclarativeListProperty<QObject> *prop
         return 0;
 }
 
-void QQuickItemPrivate::resources_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
+void QQuickItemPrivate::resources_append(QQmlListProperty<QObject> *prop, QObject *o)
 {
     // XXX todo - do we really want this behavior?
     o->setParent(prop->object);
 }
 
-int QQuickItemPrivate::resources_count(QDeclarativeListProperty<QObject> *prop)
+int QQuickItemPrivate::resources_count(QQmlListProperty<QObject> *prop)
 {
     return prop->object->children().count();
 }
 
-void QQuickItemPrivate::resources_clear(QDeclarativeListProperty<QObject> *prop)
+void QQuickItemPrivate::resources_clear(QQmlListProperty<QObject> *prop)
 {
     // XXX todo - do we really want this behavior?
     const QObjectList children = prop->object->children();
@@ -2440,7 +2460,7 @@ void QQuickItemPrivate::resources_clear(QDeclarativeListProperty<QObject> *prop)
         children.at(index)->setParent(0);
 }
 
-QQuickItem *QQuickItemPrivate::children_at(QDeclarativeListProperty<QQuickItem> *prop, int index)
+QQuickItem *QQuickItemPrivate::children_at(QQmlListProperty<QQuickItem> *prop, int index)
 {
     QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
     if (index >= p->childItems.count() || index < 0)
@@ -2449,7 +2469,7 @@ QQuickItem *QQuickItemPrivate::children_at(QDeclarativeListProperty<QQuickItem>
         return p->childItems.at(index);
 }
 
-void QQuickItemPrivate::children_append(QDeclarativeListProperty<QQuickItem> *prop, QQuickItem *o)
+void QQuickItemPrivate::children_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *o)
 {
     if (!o)
         return;
@@ -2461,13 +2481,13 @@ void QQuickItemPrivate::children_append(QDeclarativeListProperty<QQuickItem> *pr
     o->setParentItem(that);
 }
 
-int QQuickItemPrivate::children_count(QDeclarativeListProperty<QQuickItem> *prop)
+int QQuickItemPrivate::children_count(QQmlListProperty<QQuickItem> *prop)
 {
     QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
     return p->childItems.count();
 }
 
-void QQuickItemPrivate::children_clear(QDeclarativeListProperty<QQuickItem> *prop)
+void QQuickItemPrivate::children_clear(QQmlListProperty<QQuickItem> *prop)
 {
     QQuickItem *that = static_cast<QQuickItem *>(prop->object);
     QQuickItemPrivate *p = QQuickItemPrivate::get(that);
@@ -2475,10 +2495,45 @@ void QQuickItemPrivate::children_clear(QDeclarativeListProperty<QQuickItem> *pro
         p->childItems.at(0)->setParentItem(0);
 }
 
-int QQuickItemPrivate::transform_count(QDeclarativeListProperty<QQuickTransform> *prop)
+void QQuickItemPrivate::visibleChildren_append(QQmlListProperty<QQuickItem>*, QQuickItem *self)
+{
+    // do nothing
+    qmlInfo(self) << "QQuickItem: visibleChildren property is readonly and cannot be assigned to.";
+}
+
+int QQuickItemPrivate::visibleChildren_count(QQmlListProperty<QQuickItem> *prop)
+{
+    QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
+    int visibleCount = 0;
+    int c = p->childItems.count();
+    while (c--) {
+        if (p->childItems.at(c)->isVisible()) visibleCount++;
+    }
+
+    return visibleCount;
+}
+
+QQuickItem *QQuickItemPrivate::visibleChildren_at(QQmlListProperty<QQuickItem> *prop, int index)
+{
+    QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
+    const int childCount = p->childItems.count();
+    if (index >= childCount || index < 0)
+        return 0;
+
+    int visibleCount = -1;
+    for (int i = 0; i < childCount; i++) {
+        if (p->childItems.at(i)->isVisible()) visibleCount++;
+        if (visibleCount == index) return p->childItems.at(i);
+    }
+    return 0;
+}
+
+int QQuickItemPrivate::transform_count(QQmlListProperty<QQuickTransform> *prop)
 {
     QQuickItem *that = static_cast<QQuickItem *>(prop->object);
-    return QQuickItemPrivate::get(that)->transforms.count();
+    QQuickItemPrivate *p = QQuickItemPrivate::get(that);
+
+    return p->transforms.count();
 }
 
 void QQuickTransform::appendToItem(QQuickItem *item)
@@ -2519,7 +2574,7 @@ void QQuickTransform::prependToItem(QQuickItem *item)
     p->dirty(QQuickItemPrivate::Transform);
 }
 
-void QQuickItemPrivate::transform_append(QDeclarativeListProperty<QQuickTransform> *prop, QQuickTransform *transform)
+void QQuickItemPrivate::transform_append(QQmlListProperty<QQuickTransform> *prop, QQuickTransform *transform)
 {
     if (!transform)
         return;
@@ -2528,7 +2583,7 @@ void QQuickItemPrivate::transform_append(QDeclarativeListProperty<QQuickTransfor
     transform->appendToItem(that);
 }
 
-QQuickTransform *QQuickItemPrivate::transform_at(QDeclarativeListProperty<QQuickTransform> *prop, int idx)
+QQuickTransform *QQuickItemPrivate::transform_at(QQmlListProperty<QQuickTransform> *prop, int idx)
 {
     QQuickItem *that = static_cast<QQuickItem *>(prop->object);
     QQuickItemPrivate *p = QQuickItemPrivate::get(that);
@@ -2539,7 +2594,7 @@ QQuickTransform *QQuickItemPrivate::transform_at(QDeclarativeListProperty<QQuick
         return p->transforms.at(idx);
 }
 
-void QQuickItemPrivate::transform_clear(QDeclarativeListProperty<QQuickTransform> *prop)
+void QQuickItemPrivate::transform_clear(QQmlListProperty<QQuickTransform> *prop)
 {
     QQuickItem *that = static_cast<QQuickItem *>(prop->object);
     QQuickItemPrivate *p = QQuickItemPrivate::get(that);
@@ -2787,14 +2842,6 @@ QQuickAnchors *QQuickItemPrivate::anchors() const
     return _anchors;
 }
 
-QQuickItemPrivate::AnchorLines *QQuickItemPrivate::anchorLines() const
-{
-    Q_Q(const QQuickItem);
-    if (!_anchorLines) _anchorLines =
-        new AnchorLines(const_cast<QQuickItem *>(q));
-    return _anchorLines;
-}
-
 void QQuickItemPrivate::siblingOrderChanged()
 {
     Q_Q(QQuickItem);
@@ -2806,9 +2853,9 @@ void QQuickItemPrivate::siblingOrderChanged()
     }
 }
 
-QDeclarativeListProperty<QObject> QQuickItemPrivate::data()
+QQmlListProperty<QObject> QQuickItemPrivate::data()
 {
-    return QDeclarativeListProperty<QObject>(q_func(), 0, QQuickItemPrivate::data_append,
+    return QQmlListProperty<QObject>(q_func(), 0, QQuickItemPrivate::data_append,
                                              QQuickItemPrivate::data_count,
                                              QQuickItemPrivate::data_at,
                                              QQuickItemPrivate::data_clear);
@@ -2817,12 +2864,12 @@ QDeclarativeListProperty<QObject> QQuickItemPrivate::data()
 QRectF QQuickItem::childrenRect()
 {
     Q_D(QQuickItem);
-    if (!d->_contents) {
-        d->_contents = new QQuickContents(this);
+    if (!d->extra.isAllocated() || !d->extra->contents) {
+        d->extra.value().contents = new QQuickContents(this);
         if (d->componentComplete)
-            d->_contents->complete();
+            d->extra->contents->complete();
     }
-    return d->_contents->rectF();
+    return d->extra->contents->rectF();
 }
 
 QList<QQuickItem *> QQuickItem::childItems() const
@@ -2918,7 +2965,11 @@ void QQuickItem::updatePolish()
 
 void QQuickItem::sendAccessibilityUpdate()
 {
-    Q_D(QQuickItem);
+}
+
+void QQuickItemPrivate::addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
+{
+    changeListeners.append(ChangeListener(listener, types));
 }
 
 void QQuickItemPrivate::removeItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
@@ -2937,7 +2988,8 @@ void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListen
         changeListeners.append(change);
 }
 
-void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types)
+void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener,
+                                                             GeometryChangeTypes types)
 {
     ChangeListener change(listener, types);
     if (types == NoChange) {
@@ -2966,7 +3018,7 @@ void QQuickItem::inputMethodEvent(QInputMethodEvent *event)
 
 void QQuickItem::focusInEvent(QFocusEvent *)
 {
-    QAccessible::updateAccessibility(this, 0, QAccessible::Focus);
+    QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, this, 0));
 }
 
 void QQuickItem::focusOutEvent(QFocusEvent *)
@@ -3062,32 +3114,6 @@ void QQuickItem::windowDeactivateEvent()
     }
 }
 
-Qt::InputMethodHints QQuickItem::inputMethodHints() const
-{
-    Q_D(const QQuickItem);
-    return d->imHints;
-}
-
-void QQuickItem::setInputMethodHints(Qt::InputMethodHints hints)
-{
-    Q_D(QQuickItem);
-    d->imHints = hints;
-
-    if (!d->canvas || d->canvas->activeFocusItem() != this)
-        return;
-
-    QInputPanel *p = qApp->inputPanel();
-    if (p->inputItem() == this)
-        qApp->inputPanel()->update(Qt::ImHints);
-}
-
-void QQuickItem::updateMicroFocus()
-{
-    QInputPanel *p = qApp->inputPanel();
-    if (p->inputItem() == this)
-        qApp->inputPanel()->update(Qt::ImQueryInput);
-}
-
 QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
 {
     Q_D(const QQuickItem);
@@ -3098,8 +3124,6 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
         v = (bool)(flags() & ItemAcceptsInputMethod);
         break;
     case Qt::ImHints:
-        v = (int)inputMethodHints();
-        break;
     case Qt::ImCursorRectangle:
     case Qt::ImFont:
     case Qt::ImCursorPosition:
@@ -3108,8 +3132,8 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
     case Qt::ImMaximumTextLength:
     case Qt::ImAnchorPosition:
     case Qt::ImPreferredLanguage:
-        if (d->keyHandler)
-            v = d->keyHandler->inputMethodQuery(query);
+        if (d->extra.isAllocated() && d->extra->keyHandler)
+            v = d->extra->keyHandler->inputMethodQuery(query);
     default:
         break;
     }
@@ -3119,46 +3143,54 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
 
 QQuickAnchorLine QQuickItemPrivate::left() const
 {
-    return anchorLines()->left;
+    Q_Q(const QQuickItem);
+    return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Left);
 }
 
 QQuickAnchorLine QQuickItemPrivate::right() const
 {
-    return anchorLines()->right;
+    Q_Q(const QQuickItem);
+    return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Right);
 }
 
 QQuickAnchorLine QQuickItemPrivate::horizontalCenter() const
 {
-    return anchorLines()->hCenter;
+    Q_Q(const QQuickItem);
+    return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::HCenter);
 }
 
 QQuickAnchorLine QQuickItemPrivate::top() const
 {
-    return anchorLines()->top;
+    Q_Q(const QQuickItem);
+    return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Top);
 }
 
 QQuickAnchorLine QQuickItemPrivate::bottom() const
 {
-    return anchorLines()->bottom;
+    Q_Q(const QQuickItem);
+    return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Bottom);
 }
 
 QQuickAnchorLine QQuickItemPrivate::verticalCenter() const
 {
-    return anchorLines()->vCenter;
+    Q_Q(const QQuickItem);
+    return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::VCenter);
 }
 
 QQuickAnchorLine QQuickItemPrivate::baseline() const
 {
-    return anchorLines()->baseline;
+    Q_Q(const QQuickItem);
+    return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Baseline);
 }
 
 qreal QQuickItem::baselineOffset() const
 {
     Q_D(const QQuickItem);
-    if (!d->baselineOffset.isValid()) {
-        return 0.0;
-    } else
+    if (d->baselineOffsetValid) {
         return d->baselineOffset;
+    } else {
+        return 0.0;
+    }
 }
 
 void QQuickItem::setBaselineOffset(qreal offset)
@@ -3168,6 +3200,7 @@ void QQuickItem::setBaselineOffset(qreal offset)
         return;
 
     d->baselineOffset = offset;
+    d->baselineOffsetValid = true;
 
     for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
         const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
@@ -3201,7 +3234,7 @@ void QQuickItem::polish()
     }
 }
 
-void QQuickItem::mapFromItem(QDeclarativeV8Function *args) const
+void QQuickItem::mapFromItem(QQmlV8Function *args) const
 {
     if (args->Length() != 0) {
         v8::Local<v8::Value> item = (*args)[0];
@@ -3244,7 +3277,7 @@ QTransform QQuickItem::itemTransform(QQuickItem *other, bool *ok) const
     return t;
 }
 
-void QQuickItem::mapToItem(QDeclarativeV8Function *args) const
+void QQuickItem::mapToItem(QQmlV8Function *args) const
 {
     if (args->Length() != 0) {
         v8::Local<v8::Value> item = (*args)[0];
@@ -3300,29 +3333,43 @@ QQuickItem *QQuickItem::childAt(qreal x, qreal y) const
     return 0;
 }
 
-QDeclarativeListProperty<QObject> QQuickItemPrivate::resources()
+QQmlListProperty<QObject> QQuickItemPrivate::resources()
 {
-    return QDeclarativeListProperty<QObject>(q_func(), 0, QQuickItemPrivate::resources_append,
+    return QQmlListProperty<QObject>(q_func(), 0, QQuickItemPrivate::resources_append,
                                              QQuickItemPrivate::resources_count,
                                              QQuickItemPrivate::resources_at,
                                              QQuickItemPrivate::resources_clear);
 }
 
-QDeclarativeListProperty<QQuickItem> QQuickItemPrivate::children()
+QQmlListProperty<QQuickItem> QQuickItemPrivate::children()
 {
-    return QDeclarativeListProperty<QQuickItem>(q_func(), 0, QQuickItemPrivate::children_append,
+    return QQmlListProperty<QQuickItem>(q_func(), 0, QQuickItemPrivate::children_append,
                                              QQuickItemPrivate::children_count,
                                              QQuickItemPrivate::children_at,
                                              QQuickItemPrivate::children_clear);
 
 }
 
-QDeclarativeListProperty<QDeclarativeState> QQuickItemPrivate::states()
+/*!
+  \qmlproperty real QtQuick2::Item::visibleChildren
+  This read-only property lists all of the item's children that are currently visible.
+  Note that a child's visibility may have changed explicitly, or because the visibility
+  of this (it's parent) item or another grandparent changed.
+*/
+QQmlListProperty<QQuickItem> QQuickItemPrivate::visibleChildren()
+{
+    return QQmlListProperty<QQuickItem>(q_func(), 0, QQuickItemPrivate::visibleChildren_append,
+                                             QQuickItemPrivate::visibleChildren_count,
+                                             QQuickItemPrivate::visibleChildren_at);
+
+}
+
+QQmlListProperty<QQuickState> QQuickItemPrivate::states()
 {
     return _states()->statesProperty();
 }
 
-QDeclarativeListProperty<QDeclarativeTransition> QQuickItemPrivate::transitions()
+QQmlListProperty<QQuickTransition> QQuickItemPrivate::transitions()
 {
     return _states()->transitionsProperty();
 }
@@ -3352,9 +3399,9 @@ void QQuickItem::setState(const QString &state)
     d->setState(state);
 }
 
-QDeclarativeListProperty<QQuickTransform> QQuickItem::transform()
+QQmlListProperty<QQuickTransform> QQuickItem::transform()
 {
-    return QDeclarativeListProperty<QQuickTransform>(this, 0, QQuickItemPrivate::transform_append,
+    return QQmlListProperty<QQuickTransform>(this, 0, QQuickItemPrivate::transform_append,
                                                      QQuickItemPrivate::transform_count,
                                                      QQuickItemPrivate::transform_at,
                                                      QQuickItemPrivate::transform_clear);
@@ -3368,6 +3415,8 @@ void QQuickItem::classBegin()
         d->_stateGroup->classBegin();
     if (d->_anchors)
         d->_anchors->classBegin();
+    if (d->extra.isAllocated() && d->extra->layer)
+        d->extra->layer->classBegin();
 }
 
 void QQuickItem::componentComplete()
@@ -3380,17 +3429,22 @@ void QQuickItem::componentComplete()
         d->_anchors->componentComplete();
         QQuickAnchorsPrivate::get(d->_anchors)->updateOnComplete();
     }
-    if (d->keyHandler)
-        d->keyHandler->componentComplete();
-    if (d->_contents)
-        d->_contents->complete();
+
+    if (d->extra.isAllocated() && d->extra->layer)
+        d->extra->layer->componentComplete();
+
+    if (d->extra.isAllocated() && d->extra->keyHandler)
+        d->extra->keyHandler->componentComplete();
+
+    if (d->extra.isAllocated() && d->extra->contents)
+        d->extra->contents->complete();
 }
 
-QDeclarativeStateGroup *QQuickItemPrivate::_states()
+QQuickStateGroup *QQuickItemPrivate::_states()
 {
     Q_Q(QQuickItem);
     if (!_stateGroup) {
-        _stateGroup = new QDeclarativeStateGroup;
+        _stateGroup = new QQuickStateGroup;
         if (!componentComplete)
             _stateGroup->classBegin();
         FAST_CONNECT(_stateGroup, SIGNAL(stateChanged(QString)),
@@ -3400,27 +3454,9 @@ QDeclarativeStateGroup *QQuickItemPrivate::_states()
     return _stateGroup;
 }
 
-QQuickItemPrivate::AnchorLines::AnchorLines(QQuickItem *q)
-{
-    left.item = q;
-    left.anchorLine = QQuickAnchorLine::Left;
-    right.item = q;
-    right.anchorLine = QQuickAnchorLine::Right;
-    hCenter.item = q;
-    hCenter.anchorLine = QQuickAnchorLine::HCenter;
-    top.item = q;
-    top.anchorLine = QQuickAnchorLine::Top;
-    bottom.item = q;
-    bottom.anchorLine = QQuickAnchorLine::Bottom;
-    vCenter.item = q;
-    vCenter.anchorLine = QQuickAnchorLine::VCenter;
-    baseline.item = q;
-    baseline.anchorLine = QQuickAnchorLine::Baseline;
-}
-
 QPointF QQuickItemPrivate::computeTransformOrigin() const
 {
-    switch (origin) {
+    switch (origin()) {
     default:
     case QQuickItem::TopLeft:
         return QPointF(0, 0);
@@ -3445,6 +3481,8 @@ QPointF QQuickItemPrivate::computeTransformOrigin() const
 
 void QQuickItemPrivate::transformChanged()
 {
+    if (extra.isAllocated() && extra->layer)
+        extra->layer->updateMatrix();
 }
 
 void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
@@ -3452,11 +3490,11 @@ void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
     Q_Q(QQuickItem);
 
     Q_ASSERT(e->isAccepted());
-    if (keyHandler) {
+    if (extra.isAllocated() && extra->keyHandler) {
         if (e->type() == QEvent::KeyPress)
-            keyHandler->keyPressed(e, false);
+            extra->keyHandler->keyPressed(e, false);
         else
-            keyHandler->keyReleased(e, false);
+            extra->keyHandler->keyReleased(e, false);
 
         if (e->isAccepted())
             return;
@@ -3472,13 +3510,13 @@ void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
     if (e->isAccepted())
         return;
 
-    if (keyHandler) {
+    if (extra.isAllocated() && extra->keyHandler) {
         e->accept();
 
         if (e->type() == QEvent::KeyPress)
-            keyHandler->keyPressed(e, true);
+            extra->keyHandler->keyPressed(e, true);
         else
-            keyHandler->keyReleased(e, true);
+            extra->keyHandler->keyReleased(e, true);
     }
 }
 
@@ -3487,8 +3525,8 @@ void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e)
     Q_Q(QQuickItem);
 
     Q_ASSERT(e->isAccepted());
-    if (keyHandler) {
-        keyHandler->inputMethodEvent(e, false);
+    if (extra.isAllocated() && extra->keyHandler) {
+        extra->keyHandler->inputMethodEvent(e, false);
 
         if (e->isAccepted())
             return;
@@ -3501,10 +3539,10 @@ void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e)
     if (e->isAccepted())
         return;
 
-    if (keyHandler) {
+    if (extra.isAllocated() && extra->keyHandler) {
         e->accept();
 
-        keyHandler->inputMethodEvent(e, true);
+        extra->keyHandler->inputMethodEvent(e, true);
     }
 }
 
@@ -3600,6 +3638,15 @@ void QQuickItem::itemChange(ItemChange change, const ItemChangeData &value)
     Q_UNUSED(value);
 }
 
+/*!
+    Notify input method on updated query values if needed. \a indicates changed attributes.
+*/
+void QQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
+{
+    if (hasActiveFocus())
+        qApp->inputMethod()->update(queries);
+}
+
 /*! \internal */
 // XXX todo - do we want/need this anymore?
 // Note that it's now used for varying clip rect
@@ -3612,52 +3659,52 @@ QRectF QQuickItem::boundingRect() const
 QQuickItem::TransformOrigin QQuickItem::transformOrigin() const
 {
     Q_D(const QQuickItem);
-    return d->origin;
+    return d->origin();
 }
 
 void QQuickItem::setTransformOrigin(TransformOrigin origin)
 {
     Q_D(QQuickItem);
-    if (origin == d->origin)
+    if (origin == d->origin())
         return;
 
-    d->origin = origin;
+    d->extra.value().origin = origin;
     d->dirty(QQuickItemPrivate::TransformOrigin);
 
-    emit transformOriginChanged(d->origin);
+    emit transformOriginChanged(d->origin());
 }
 
 QPointF QQuickItem::transformOriginPoint() const
 {
     Q_D(const QQuickItem);
-    if (!d->transformOriginPoint.isNull())
-        return d->transformOriginPoint;
+    if (d->extra.isAllocated() && !d->extra->userTransformOriginPoint.isNull())
+        return d->extra->userTransformOriginPoint;
     return d->computeTransformOrigin();
 }
 
 void QQuickItem::setTransformOriginPoint(const QPointF &point)
 {
     Q_D(QQuickItem);
-    if (d->transformOriginPoint == point)
+    if (d->extra.value().userTransformOriginPoint == point)
         return;
 
-    d->transformOriginPoint = point;
+    d->extra->userTransformOriginPoint = point;
     d->dirty(QQuickItemPrivate::TransformOrigin);
 }
 
 qreal QQuickItem::z() const
 {
     Q_D(const QQuickItem);
-    return d->z;
+    return d->z();
 }
 
 void QQuickItem::setZ(qreal v)
 {
     Q_D(QQuickItem);
-    if (d->z == v)
+    if (d->z() == v)
         return;
 
-    d->z = v;
+    d->extra.value().z = v;
 
     d->dirty(QQuickItemPrivate::ZValue);
     if (d->parentItem) {
@@ -3666,6 +3713,9 @@ void QQuickItem::setZ(qreal v)
     }
 
     emit zChanged();
+
+    if (d->extra.isAllocated() && d->extra->layer)
+        d->extra->layer->updateZ();
 }
 
 
@@ -3798,16 +3848,16 @@ void QQuickItem::setZ(qreal v)
 qreal QQuickItem::rotation() const
 {
     Q_D(const QQuickItem);
-    return d->rotation;
+    return d->rotation();
 }
 
 void QQuickItem::setRotation(qreal r)
 {
     Q_D(QQuickItem);
-    if (d->rotation == r)
+    if (d->rotation() == r)
         return;
 
-    d->rotation = r;
+    d->extra.value().rotation = r;
 
     d->dirty(QQuickItemPrivate::BasicTransform);
 
@@ -3819,16 +3869,16 @@ void QQuickItem::setRotation(qreal r)
 qreal QQuickItem::scale() const
 {
     Q_D(const QQuickItem);
-    return d->scale;
+    return d->scale();
 }
 
 void QQuickItem::setScale(qreal s)
 {
     Q_D(QQuickItem);
-    if (d->scale == s)
+    if (d->scale() == s)
         return;
 
-    d->scale = s;
+    d->extra.value().scale = s;
 
     d->dirty(QQuickItemPrivate::BasicTransform);
 
@@ -3838,16 +3888,16 @@ void QQuickItem::setScale(qreal s)
 qreal QQuickItem::opacity() const
 {
     Q_D(const QQuickItem);
-    return d->opacity;
+    return d->opacity();
 }
 
 void QQuickItem::setOpacity(qreal o)
 {
     Q_D(QQuickItem);
-    if (d->opacity == o)
+    if (d->opacity() == o)
         return;
 
-    d->opacity = o;
+    d->extra.value().opacity = o;
 
     d->dirty(QQuickItemPrivate::OpacityValue);
 
@@ -3870,7 +3920,9 @@ void QQuickItem::setVisible(bool v)
 
     d->explicitVisible = v;
 
-    d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
+    const bool childVisibilityChanged = d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
+    if (childVisibilityChanged && d->parentItem)
+        emit d->parentItem->visibleChildrenChanged();   // signal the parent, not this!
 }
 
 bool QQuickItem::isEnabled() const
@@ -3887,7 +3939,11 @@ void QQuickItem::setEnabled(bool e)
 
     d->explicitEnable = e;
 
-    d->setEffectiveEnableRecur(d->calcEffectiveEnable());
+    QQuickItem *scope = parentItem();
+    while (scope && !scope->isFocusScope())
+        scope = scope->parentItem();
+
+    d->setEffectiveEnableRecur(scope, d->calcEffectiveEnable());
 }
 
 bool QQuickItemPrivate::calcEffectiveVisible() const
@@ -3898,18 +3954,18 @@ bool QQuickItemPrivate::calcEffectiveVisible() const
     return explicitVisible && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveVisible);
 }
 
-void QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
+bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
 {
     Q_Q(QQuickItem);
 
     if (newEffectiveVisible && !explicitVisible) {
         // This item locally overrides visibility
-        return;
+        return false;   // effective visibility didn't change
     }
 
     if (newEffectiveVisible == effectiveVisible) {
         // No change necessary
-        return;
+        return false;   // effective visibility didn't change
     }
 
     effectiveVisible = newEffectiveVisible;
@@ -3922,19 +3978,20 @@ void QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
             q->ungrabMouse();
     }
 
+    bool childVisibilityChanged = false;
     for (int ii = 0; ii < childItems.count(); ++ii)
-        QQuickItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
+        childVisibilityChanged |= QQuickItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
 
-    for (int ii = 0; ii < changeListeners.count(); ++ii) {
-        const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
-        if (change.types & QQuickItemPrivate::Visibility)
-            change.listener->itemVisibilityChanged(q);
-    }
+    itemChange(QQuickItem::ItemVisibleHasChanged, effectiveVisible);
 
     if (isAccessible)
-        QAccessible::updateAccessibility(q, 0, effectiveVisible ? QAccessible::ObjectShow : QAccessible::ObjectHide );
+        QAccessible::updateAccessibility(QAccessibleEvent(effectiveVisible ? QAccessible::ObjectShow : QAccessible::ObjectHide, q, 0));
 
     emit q->visibleChanged();
+    if (childVisibilityChanged)
+        emit q->visibleChildrenChanged();
+
+    return true;    // effective visibility DID change
 }
 
 bool QQuickItemPrivate::calcEffectiveEnable() const
@@ -3945,12 +4002,10 @@ bool QQuickItemPrivate::calcEffectiveEnable() const
     return explicitEnable && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveEnable);
 }
 
-void QQuickItemPrivate::setEffectiveEnableRecur(bool newEffectiveEnable)
+void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffectiveEnable)
 {
     Q_Q(QQuickItem);
 
-    // XXX todo - need to fixup focus
-
     if (newEffectiveEnable && !explicitEnable) {
         // This item locally overrides enable
         return;
@@ -3967,10 +4022,21 @@ void QQuickItemPrivate::setEffectiveEnableRecur(bool newEffectiveEnable)
         QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(canvas);
         if (canvasPriv->mouseGrabberItem == q)
             q->ungrabMouse();
+        if (scope && !effectiveEnable && activeFocus) {
+            canvasPriv->clearFocusInScope(
+                    scope, q,  QQuickCanvasPrivate::DontChangeFocusProperty | QQuickCanvasPrivate::DontChangeSubFocusItem);
+        }
     }
 
-    for (int ii = 0; ii < childItems.count(); ++ii)
-        QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(newEffectiveEnable);
+    for (int ii = 0; ii < childItems.count(); ++ii) {
+        QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(
+                flags & QQuickItem::ItemIsFocusScope ? q : scope, newEffectiveEnable);
+    }
+
+    if (canvas && scope && effectiveEnable && focus) {
+        QQuickCanvasPrivate::get(canvas)->setFocusInScope(
+                scope, q, QQuickCanvasPrivate::DontChangeFocusProperty | QQuickCanvasPrivate::DontChangeSubFocusItem);
+    }
 
     emit q->enabledChanged();
 }
@@ -4055,27 +4121,27 @@ void QQuickItemPrivate::removeFromDirtyList()
 
 void QQuickItemPrivate::refFromEffectItem(bool hide)
 {
-    ++effectRefCount;
-    if (1 == effectRefCount) {
+    ++extra.value().effectRefCount;
+    if (1 == extra->effectRefCount) {
         dirty(EffectReference);
         if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
     }
     if (hide) {
-        if (++hideRefCount == 1)
+        if (++extra->hideRefCount == 1)
             dirty(HideReference);
     }
 }
 
 void QQuickItemPrivate::derefFromEffectItem(bool unhide)
 {
-    Q_ASSERT(effectRefCount);
-    --effectRefCount;
-    if (0 == effectRefCount) {
+    Q_ASSERT(extra->effectRefCount);
+    --extra->effectRefCount;
+    if (0 == extra->effectRefCount) {
         dirty(EffectReference);
         if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
     }
     if (unhide) {
-        if (--hideRefCount == 0)
+        if (--extra->hideRefCount == 0)
             dirty(HideReference);
     }
 }
@@ -4356,7 +4422,7 @@ qreal QQuickItem::implicitWidth() const
 
     \qml
     // Label.qml
-    import QtQuick 1.1
+    import QtQuick 2.0
 
     Item {
         property alias icon: image.source
@@ -4615,13 +4681,20 @@ QQuickItem *QQuickItem::scopedFocusItem() const
 Qt::MouseButtons QQuickItem::acceptedMouseButtons() const
 {
     Q_D(const QQuickItem);
-    return d->acceptedMouseButtons;
+    return d->acceptedMouseButtons();
 }
 
 void QQuickItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
 {
     Q_D(QQuickItem);
-    d->acceptedMouseButtons = buttons;
+    if (buttons & Qt::LeftButton)
+        d->extra.setFlag();
+    else
+        d->extra.clearFlag();
+
+    buttons &= ~Qt::LeftButton;
+    if (buttons || d->extra.isAllocated())
+        d->extra.value().acceptedMouseButtons = buttons;
 }
 
 bool QQuickItem::filtersChildMouseEvents() const
@@ -5304,6 +5377,13 @@ qint64 QQuickItemPrivate::restart(QElapsedTimer &t)
     This function can be called from any thread.
  */
 
+bool QQuickItem::isTextureProvider() const
+{
+    Q_D(const QQuickItem);
+    return d->extra.isAllocated() && d->extra->layer && d->extra->layer->effectSource() ?
+           d->extra->layer->effectSource()->isTextureProvider() : false;
+}
+
 /*!
     \fn QSGTextureProvider *QQuickItem::textureProvider() const
 
@@ -5313,6 +5393,478 @@ qint64 QQuickItemPrivate::restart(QElapsedTimer &t)
     This function may only be called on the rendering thread.
  */
 
+QSGTextureProvider *QQuickItem::textureProvider() const
+{
+    Q_D(const QQuickItem);
+    return d->extra.isAllocated() && d->extra->layer && d->extra->layer->effectSource() ?
+           d->extra->layer->effectSource()->textureProvider() : 0;
+}
+
+QQuickItemLayer *QQuickItemPrivate::layer() const
+{
+    if (!extra.isAllocated() || !extra->layer) {
+        extra.value().layer = new QQuickItemLayer(const_cast<QQuickItem *>(q_func()));
+        if (!componentComplete)
+            extra->layer->classBegin();
+    }
+    return extra->layer;
+}
+
+QQuickItemLayer::QQuickItemLayer(QQuickItem *item)
+    : m_item(item)
+    , m_enabled(false)
+    , m_mipmap(false)
+    , m_smooth(false)
+    , m_componentComplete(true)
+    , m_wrapMode(QQuickShaderEffectSource::ClampToEdge)
+    , m_format(QQuickShaderEffectSource::RGBA)
+    , m_name("source")
+    , m_effectComponent(0)
+    , m_effect(0)
+    , m_effectSource(0)
+{
+}
+
+QQuickItemLayer::~QQuickItemLayer()
+{
+    delete m_effectSource;
+    delete m_effect;
+}
+
+
+
+/*!
+    \qmlproperty bool QtQuick2::Item::layer.enabled
+
+    Holds wether the item is layered or not. Layering is disabled by default.
+
+    A layered item is rendered into an offscreen surface and cached until
+    it is changed. Enabling layering for complex QML item hierarchies can
+    some times be an optimization.
+
+    None of the other layer properties have any effect when the layer
+    is disabled.
+ */
+
+void QQuickItemLayer::setEnabled(bool e)
+{
+    if (e == m_enabled)
+        return;
+    m_enabled = e;
+    if (m_componentComplete) {
+        if (m_enabled)
+            activate();
+        else
+            deactivate();
+    }
+
+    emit enabledChanged(e);
+}
+
+void QQuickItemLayer::classBegin()
+{
+    Q_ASSERT(!m_effectSource);
+    Q_ASSERT(!m_effect);
+    m_componentComplete = false;
+}
+
+void QQuickItemLayer::componentComplete()
+{
+    Q_ASSERT(!m_componentComplete);
+    m_componentComplete = true;
+    if (m_enabled)
+        activate();
+}
+
+void QQuickItemLayer::activate()
+{
+    Q_ASSERT(!m_effectSource);
+    m_effectSource = new QQuickShaderEffectSource();
+
+    QQuickItem *parentItem = m_item->parentItem();
+    if (parentItem) {
+        m_effectSource->setParentItem(parentItem);
+        m_effectSource->stackAfter(m_item);
+    }
+
+    m_effectSource->setSourceItem(m_item);
+    m_effectSource->setHideSource(true);
+    m_effectSource->setSmooth(m_smooth);
+    m_effectSource->setTextureSize(m_size);
+    m_effectSource->setSourceRect(m_sourceRect);
+    m_effectSource->setMipmap(m_mipmap);
+    m_effectSource->setWrapMode(m_wrapMode);
+    m_effectSource->setFormat(m_format);
+
+    if (m_effectComponent)
+        activateEffect();
+
+    m_effectSource->setVisible(m_item->isVisible() && !m_effect);
+
+    updateZ();
+    updateGeometry();
+    updateOpacity();
+    updateMatrix();
+
+    QQuickItemPrivate *id = QQuickItemPrivate::get(m_item);
+    id->addItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Opacity | QQuickItemPrivate::Parent | QQuickItemPrivate::Visibility | QQuickItemPrivate::SiblingOrder);
+}
+
+void QQuickItemLayer::deactivate()
+{
+    Q_ASSERT(m_effectSource);
+
+    if (m_effectComponent)
+        deactivateEffect();
+
+    delete m_effectSource;
+    m_effectSource = 0;
+
+    QQuickItemPrivate *id = QQuickItemPrivate::get(m_item);
+    id->removeItemChangeListener(this,  QQuickItemPrivate::Geometry | QQuickItemPrivate::Opacity | QQuickItemPrivate::Parent | QQuickItemPrivate::Visibility | QQuickItemPrivate::SiblingOrder);
+}
+
+void QQuickItemLayer::activateEffect()
+{
+    Q_ASSERT(m_effectSource);
+    Q_ASSERT(m_effectComponent);
+    Q_ASSERT(!m_effect);
+
+    QObject *created = m_effectComponent->create();
+    m_effect = qobject_cast<QQuickItem *>(created);
+    if (!m_effect) {
+        qWarning("Item: layer.effect is not a QML Item.");
+        delete created;
+        return;
+    }
+    QQuickItem *parentItem = m_item->parentItem();
+    if (parentItem) {
+        m_effect->setParentItem(parentItem);
+        m_effect->stackAfter(m_effectSource);
+    }
+    m_effect->setVisible(m_item->isVisible());
+    m_effect->setProperty(m_name, qVariantFromValue<QObject *>(m_effectSource));
+}
+
+void QQuickItemLayer::deactivateEffect()
+{
+    Q_ASSERT(m_effectSource);
+    Q_ASSERT(m_effectComponent);
+
+    delete m_effect;
+    m_effect = 0;
+}
+
+
+/*!
+    \qmlproperty Component QtQuick2::Item::layer.effect
+
+    Holds the effect that is applied to this layer.
+
+    The effect is typically a \l ShaderEffect component, although any \l Item component can be
+    assigned. The effect should have a source texture property with a name matching \l samplerName.
+
+    \sa samplerName
+ */
+
+void QQuickItemLayer::setEffect(QQmlComponent *component)
+{
+    if (component == m_effectComponent)
+        return;
+
+    bool updateNeeded = false;
+    if (m_effectSource && m_effectComponent) {
+        deactivateEffect();
+        updateNeeded = true;
+    }
+
+    m_effectComponent = component;
+
+    if (m_effectSource && m_effectComponent) {
+        activateEffect();
+        updateNeeded = true;
+    }
+
+    if (updateNeeded) {
+        updateZ();
+        updateGeometry();
+        updateOpacity();
+        updateMatrix();
+        m_effectSource->setVisible(m_item->isVisible() && !m_effect);
+    }
+
+    emit effectChanged(component);
+}
+
+
+/*!
+    \qmlproperty bool QtQuick2::Item::layer.mipmap
+
+    If this property is true, mipmaps are generated for the texture.
+
+    \note Some OpenGL ES 2 implementations do not support mipmapping of
+    non-power-of-two textures.
+ */
+
+void QQuickItemLayer::setMipmap(bool mipmap)
+{
+    if (mipmap == m_mipmap)
+        return;
+    m_mipmap = mipmap;
+
+    if (m_effectSource)
+        m_effectSource->setMipmap(m_mipmap);
+
+    emit mipmapChanged(mipmap);
+}
+
+
+/*!
+    \qmlproperty enumeration QtQuick2::Item::layer.format
+
+    This property defines the internal OpenGL format of the texture.
+    Modifying this property makes most sense when the \a layer.effect is also
+    specified. Depending on the OpenGL implementation, this property might
+    allow you to save some texture memory.
+
+    \list
+    \o ShaderEffectSource.Alpha - GL_ALPHA
+    \o ShaderEffectSource.RGB - GL_RGB
+    \o ShaderEffectSource.RGBA - GL_RGBA
+    \endlist
+
+    \note Some OpenGL implementations do not support the GL_ALPHA format.
+ */
+
+void QQuickItemLayer::setFormat(QQuickShaderEffectSource::Format f)
+{
+    if (f == m_format)
+        return;
+    m_format = f;
+
+    if (m_effectSource)
+        m_effectSource->setFormat(m_format);
+
+    emit formatChanged(m_format);
+}
+
+
+/*!
+    \qmlproperty enumeration QtQuick2::Item::layer.sourceRect
+
+    This property defines which rectangular area of the \l sourceItem to
+    render into the texture. The source rectangle can be larger than
+    \l sourceItem itself. If the rectangle is null, which is the default,
+    the whole \l sourceItem is rendered to texture.
+ */
+
+void QQuickItemLayer::setSourceRect(const QRectF &sourceRect)
+{
+    if (sourceRect == m_sourceRect)
+        return;
+    m_sourceRect = sourceRect;
+
+    if (m_effectSource)
+        m_effectSource->setSourceRect(m_sourceRect);
+
+    emit sourceRectChanged(sourceRect);
+}
+
+
+
+/*!
+    \qmlproperty bool QtQuick2::Item::layer.smooth
+
+    Holds whether the layer is smoothly transformed.
+ */
+
+void QQuickItemLayer::setSmooth(bool s)
+{
+    if (m_smooth == s)
+        return;
+    m_smooth = s;
+
+    if (m_effectSource)
+        m_effectSource->setSmooth(m_smooth);
+
+    emit smoothChanged(s);
+}
+
+
+
+/*!
+    \qmlproperty size QtQuick2::Item::layer.textureSize
+
+    This property holds the requested pixel size of the layers texture. If it is empty,
+    which is the default, the size of the item is used.
+
+    \note Some platforms have a limit on how small framebuffer objects can be,
+    which means the actual texture size might be larger than the requested
+    size.
+ */
+
+void QQuickItemLayer::setSize(const QSize &size)
+{
+    if (size == m_size)
+        return;
+    m_size = size;
+
+    if (m_effectSource)
+        m_effectSource->setTextureSize(size);
+
+    emit sizeChanged(size);
+}
+
+
+
+/*!
+    \qmlproperty enumeration QtQuick2::Item::layer.wrapMode
+
+    This property defines the OpenGL wrap modes associated with the texture.
+    Modifying this property makes most sense when the \a layer.effect is
+    specified.
+
+    \list
+    \o ShaderEffectSource.ClampToEdge - GL_CLAMP_TO_EDGE both horizontally and vertically
+    \o ShaderEffectSource.RepeatHorizontally - GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically
+    \o ShaderEffectSource.RepeatVertically - GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically
+    \o ShaderEffectSource.Repeat - GL_REPEAT both horizontally and vertically
+    \endlist
+
+    \note Some OpenGL ES 2 implementations do not support the GL_REPEAT
+    wrap mode with non-power-of-two textures.
+ */
+
+void QQuickItemLayer::setWrapMode(QQuickShaderEffectSource::WrapMode mode)
+{
+    if (mode != m_wrapMode)
+        return;
+    m_wrapMode = mode;
+
+    if (m_effectSource)
+        m_effectSource->setWrapMode(m_wrapMode);
+
+    emit wrapModeChanged(mode);
+}
+
+/*!
+    \qmlproperty string QtQuick2::Item::layer.samplerName
+
+    Holds the name of the effect's source texture property.
+
+    samplerName needs to match the name of the effect's source texture property
+    so that the Item can pass the layer's offscreen surface to the effect correctly.
+
+    \sa effect, ShaderEffect
+ */
+
+void QQuickItemLayer::setName(const QByteArray &name) {
+    if (m_name == name)
+        return;
+    if (m_effect) {
+        m_effect->setProperty(m_name, QVariant());
+        m_effect->setProperty(name, qVariantFromValue<QObject *>(m_effectSource));
+    }
+    m_name = name;
+    emit nameChanged(name);
+}
+
+void QQuickItemLayer::itemOpacityChanged(QQuickItem *item)
+{
+    Q_UNUSED(item)
+    updateOpacity();
+}
+
+void QQuickItemLayer::itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &)
+{
+    updateGeometry();
+}
+
+void QQuickItemLayer::itemParentChanged(QQuickItem *item, QQuickItem *parent)
+{
+    Q_UNUSED(item)
+    Q_ASSERT(item == m_item);
+    Q_ASSERT(parent != m_effectSource);
+    Q_ASSERT(parent == 0 || parent != m_effect);
+
+    m_effectSource->setParentItem(parent);
+    if (parent)
+        m_effectSource->stackAfter(m_item);
+
+    if (m_effect) {
+        m_effect->setParentItem(parent);
+        if (parent)
+            m_effect->stackAfter(m_effectSource);
+    }
+}
+
+void QQuickItemLayer::itemSiblingOrderChanged(QQuickItem *)
+{
+    m_effectSource->stackAfter(m_item);
+    if (m_effect)
+        m_effect->stackAfter(m_effectSource);
+}
+
+void QQuickItemLayer::itemVisibilityChanged(QQuickItem *)
+{
+    QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
+    Q_ASSERT(l);
+    l->setVisible(m_item->isVisible());
+}
+
+void QQuickItemLayer::updateZ()
+{
+    if (!m_componentComplete || !m_enabled)
+        return;
+    QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
+    Q_ASSERT(l);
+    l->setZ(m_item->z());
+}
+
+void QQuickItemLayer::updateOpacity()
+{
+    QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
+    Q_ASSERT(l);
+    l->setOpacity(m_item->opacity());
+}
+
+void QQuickItemLayer::updateGeometry()
+{
+    QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
+    Q_ASSERT(l);
+    QRectF bounds = m_item->boundingRect();
+    l->setWidth(bounds.width());
+    l->setHeight(bounds.height());
+    l->setX(bounds.x() + m_item->x());
+    l->setY(bounds.y() + m_item->y());
+}
+
+void QQuickItemLayer::updateMatrix()
+{
+    // Called directly from transformChanged(), so needs some extra
+    // checks.
+    if (!m_componentComplete || !m_enabled)
+        return;
+    QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
+    Q_ASSERT(l);
+    QQuickItemPrivate *ld = QQuickItemPrivate::get(l);
+    l->setScale(m_item->scale());
+    l->setRotation(m_item->rotation());
+    ld->transforms = QQuickItemPrivate::get(m_item)->transforms;
+    if (ld->origin() != QQuickItemPrivate::get(m_item)->origin())
+        ld->extra.value().origin = QQuickItemPrivate::get(m_item)->origin();
+    ld->dirty(QQuickItemPrivate::Transform);
+}
+
+QQuickItemPrivate::ExtraData::ExtraData()
+: z(0), scale(1), rotation(0), opacity(1),
+  contents(0), screenAttached(0), layoutDirectionAttached(0),
+  keyHandler(0), layer(0), effectRefCount(0), hideRefCount(0),
+  opacityNode(0), clipNode(0), rootNode(0), beforePaintNode(0),
+  acceptedMouseButtons(0), origin(QQuickItem::Center)
+{
+}
+
 QT_END_NAMESPACE
 
 #include <moc_qquickitem.cpp>