aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickitem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items/qquickitem.cpp')
-rw-r--r--src/quick/items/qquickitem.cpp451
1 files changed, 208 insertions, 243 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index f371138ea3..e6069d692f 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -66,7 +66,6 @@
#include <private/qqmlopenmetaobject_p.h>
#include <QtQuick/private/qquickstate_p.h>
#include <private/qquickitem_p.h>
-#include <private/qqmlaccessors_p.h>
#include <QtQuick/private/qquickaccessibleattached_p.h>
#include <private/qv4engine_p.h>
@@ -85,9 +84,8 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_DEBUG
-static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK");
-#endif
+Q_DECLARE_LOGGING_CATEGORY(DBG_MOUSE_TARGET)
+Q_DECLARE_LOGGING_CATEGORY(DBG_HOVER_TRACE)
void debugFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1)
{
@@ -99,7 +97,8 @@ void debugFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1)
<< item->hasActiveFocus()
<< item->isFocusScope()
<< item;
- foreach (QQuickItem *child, item->childItems()) {
+ const auto childItems = item->childItems();
+ for (QQuickItem *child : childItems) {
debugFocusTree(
child,
item->isFocusScope() || !scope ? item : scope,
@@ -108,37 +107,6 @@ void debugFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1)
}
}
-static void QQuickItem_parentNotifier(QObject *o, QQmlNotifier **n)
-{
- QQuickItemPrivate *d = QQuickItemPrivate::get(static_cast<QQuickItem *>(o));
- *n = &d->parentNotifier;
-}
-
-QML_PRIVATE_ACCESSOR(QQuickItem, QQuickItem *, parent, parentItem)
-QML_PRIVATE_ACCESSOR(QQuickItem, qreal, x, x)
-QML_PRIVATE_ACCESSOR(QQuickItem, qreal, y, y)
-QML_PRIVATE_ACCESSOR(QQuickItem, qreal, width, width)
-QML_PRIVATE_ACCESSOR(QQuickItem, qreal, height, height)
-
-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 },
- { QML_PROPERTY_NAME(x), 0, &QQuickItem_x },
- { QML_PROPERTY_NAME(y), 0, &QQuickItem_y },
- { QML_PROPERTY_NAME(width), 0, &QQuickItem_width },
- { QML_PROPERTY_NAME(height), 0, &QQuickItem_height }
-};
-
-void QQuickItemPrivate::registerAccessorProperties()
-{
- QML_DEFINE_PROPERTIES(QQuickItem);
-}
-
/*!
\qmltype Transform
\instantiates QQuickTransform
@@ -178,8 +146,8 @@ QQuickTransform::QQuickTransform(QQuickTransformPrivate &dd, QObject *parent)
QQuickTransform::~QQuickTransform()
{
Q_D(QQuickTransform);
- for (int ii = 0; ii < d->items.count(); ++ii) {
- QQuickItemPrivate *p = QQuickItemPrivate::get(d->items.at(ii));
+ for (QQuickItem *item : qAsConst(d->items)) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
p->transforms.removeOne(this);
p->dirty(QQuickItemPrivate::Transform);
}
@@ -188,8 +156,8 @@ QQuickTransform::~QQuickTransform()
void QQuickTransform::update()
{
Q_D(QQuickTransform);
- for (int ii = 0; ii < d->items.count(); ++ii) {
- QQuickItemPrivate *p = QQuickItemPrivate::get(d->items.at(ii));
+ for (QQuickItem *item : qAsConst(d->items)) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
p->dirty(QQuickItemPrivate::Transform);
}
}
@@ -201,9 +169,7 @@ QQuickContents::QQuickContents(QQuickItem *item)
QQuickContents::~QQuickContents()
{
- QList<QQuickItem *> children = m_item->childItems();
- for (int i = 0; i < children.count(); ++i) {
- QQuickItem *child = children.at(i);
+ for (QQuickItem *child : m_item->childItems()) {
QQuickItemPrivate::get(child)->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
}
}
@@ -226,9 +192,8 @@ bool QQuickContents::calcHeight(QQuickItem *changed)
} else {
qreal top = std::numeric_limits<qreal>::max();
qreal bottom = -std::numeric_limits<qreal>::max();
- QList<QQuickItem *> children = m_item->childItems();
- for (int i = 0; i < children.count(); ++i) {
- QQuickItem *child = children.at(i);
+ const QList<QQuickItem*> children = m_item->childItems();
+ for (QQuickItem *child : qAsConst(children)) {
qreal y = child->y();
if (y + child->height() > bottom)
bottom = y + child->height();
@@ -261,9 +226,8 @@ bool QQuickContents::calcWidth(QQuickItem *changed)
} else {
qreal left = std::numeric_limits<qreal>::max();
qreal right = -std::numeric_limits<qreal>::max();
- QList<QQuickItem *> children = m_item->childItems();
- for (int i = 0; i < children.count(); ++i) {
- QQuickItem *child = children.at(i);
+ const QList<QQuickItem*> children = m_item->childItems();
+ for (QQuickItem *child : qAsConst(children)) {
qreal x = child->x();
if (x + child->width() > right)
right = x + child->width();
@@ -282,9 +246,7 @@ void QQuickContents::complete()
{
QQuickItemPrivate::get(m_item)->addItemChangeListener(this, QQuickItemPrivate::Children);
- QList<QQuickItem *> children = m_item->childItems();
- for (int i = 0; i < children.count(); ++i) {
- QQuickItem *child = children.at(i);
+ for (QQuickItem *child : m_item->childItems()) {
QQuickItemPrivate::get(child)->addItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
//###what about changes to visibility?
}
@@ -296,15 +258,15 @@ void QQuickContents::updateRect()
QQuickItemPrivate::get(m_item)->emitChildrenRectChanged(rectF());
}
-void QQuickContents::itemGeometryChanged(QQuickItem *changed, const QRectF &newGeometry, const QRectF &oldGeometry)
+void QQuickContents::itemGeometryChanged(QQuickItem *changed, QQuickGeometryChange change, const QRectF &)
{
Q_UNUSED(changed)
bool wChanged = false;
bool hChanged = false;
//### we can only pass changed if the left edge has moved left, or the right edge has moved right
- if (newGeometry.width() != oldGeometry.width() || newGeometry.x() != oldGeometry.x())
+ if (change.horizontalChange())
wChanged = calcWidth(/*changed*/);
- if (newGeometry.height() != oldGeometry.height() || newGeometry.y() != oldGeometry.y())
+ if (change.verticalChange())
hChanged = calcHeight(/*changed*/);
if (wChanged || hChanged)
updateRect();
@@ -1339,8 +1301,7 @@ void QQuickKeysAttached::componentComplete()
#ifndef QT_NO_IM
Q_D(QQuickKeysAttached);
if (d->item) {
- for (int ii = 0; ii < d->targets.count(); ++ii) {
- QQuickItem *targetItem = d->targets.at(ii);
+ for (QQuickItem *targetItem : qAsConst(d->targets)) {
if (targetItem && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) {
d->item->setFlag(QQuickItem::ItemAcceptsInputMethod);
break;
@@ -1362,11 +1323,10 @@ void QQuickKeysAttached::keyPressed(QKeyEvent *event, bool post)
// first process forwards
if (d->item && d->item->window()) {
d->inPress = true;
- for (int ii = 0; ii < d->targets.count(); ++ii) {
- QQuickItem *i = d->targets.at(ii);
- if (i && i->isVisible()) {
+ for (QQuickItem *targetItem : qAsConst(d->targets)) {
+ if (targetItem && targetItem->isVisible()) {
event->accept();
- QCoreApplication::sendEvent(i, event);
+ QCoreApplication::sendEvent(targetItem, event);
if (event->isAccepted()) {
d->inPress = false;
return;
@@ -1376,7 +1336,8 @@ void QQuickKeysAttached::keyPressed(QKeyEvent *event, bool post)
d->inPress = false;
}
- QQuickKeyEvent ke(*event);
+ QQuickKeyEvent &ke = d->theKeyEvent;
+ ke.reset(*event);
QByteArray keySignal = keyToSignal(event->key());
if (!keySignal.isEmpty()) {
keySignal += "(QQuickKeyEvent*)";
@@ -1405,11 +1366,10 @@ void QQuickKeysAttached::keyReleased(QKeyEvent *event, bool post)
if (d->item && d->item->window()) {
d->inRelease = true;
- for (int ii = 0; ii < d->targets.count(); ++ii) {
- QQuickItem *i = d->targets.at(ii);
- if (i && i->isVisible()) {
+ for (QQuickItem *targetItem : qAsConst(d->targets)) {
+ if (targetItem && targetItem->isVisible()) {
event->accept();
- QCoreApplication::sendEvent(i, event);
+ QCoreApplication::sendEvent(targetItem, event);
if (event->isAccepted()) {
d->inRelease = false;
return;
@@ -1419,7 +1379,8 @@ void QQuickKeysAttached::keyReleased(QKeyEvent *event, bool post)
d->inRelease = false;
}
- QQuickKeyEvent ke(*event);
+ QQuickKeyEvent &ke = d->theKeyEvent;
+ ke.reset(*event);
emit released(&ke);
event->setAccepted(ke.isAccepted());
@@ -1432,12 +1393,11 @@ void QQuickKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post)
Q_D(QQuickKeysAttached);
if (post == m_processPost && d->item && !d->inIM && d->item->window()) {
d->inIM = true;
- for (int ii = 0; ii < d->targets.count(); ++ii) {
- QQuickItem *i = d->targets.at(ii);
- if (i && i->isVisible() && (i->flags() & QQuickItem::ItemAcceptsInputMethod)) {
- d->item->window()->sendEvent(i, event);
+ for (QQuickItem *targetItem : qAsConst(d->targets)) {
+ if (targetItem && targetItem->isVisible() && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) {
+ QCoreApplication::sendEvent(targetItem, event);
if (event->isAccepted()) {
- d->imeItem = i;
+ d->imeItem = targetItem;
d->inIM = false;
return;
}
@@ -1452,13 +1412,12 @@ QVariant QQuickKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const
{
Q_D(const QQuickKeysAttached);
if (d->item) {
- for (int ii = 0; ii < d->targets.count(); ++ii) {
- QQuickItem *i = d->targets.at(ii);
- if (i && i->isVisible() && (i->flags() & QQuickItem::ItemAcceptsInputMethod) && i == d->imeItem) {
- //### how robust is i == d->imeItem check?
- QVariant v = i->inputMethodQuery(query);
+ for (QQuickItem *targetItem : qAsConst(d->targets)) {
+ if (targetItem && targetItem->isVisible() && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod) && targetItem == d->imeItem) {
+ //### how robust is targetItem == d->imeItem check?
+ QVariant v = targetItem->inputMethodQuery(query);
if (v.userType() == QVariant::RectF)
- v = d->item->mapRectFromItem(i, v.toRectF()); //### cost?
+ v = d->item->mapRectFromItem(targetItem, v.toRectF()); //### cost?
return v;
}
}
@@ -1491,6 +1450,9 @@ QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj)
behavior to all child items as well. If the \c LayoutMirroring attached property has not been defined
for an item, mirroring is not enabled.
+ \note Since Qt 5.8, \c LayoutMirroring can be attached to a \l Window. In practice, it is the same as
+ attaching \c LayoutMirroring to the window's \c contentItem.
+
The following example shows mirroring in action. The \l Row below is specified as being anchored
to the left of its parent. However, since mirroring has been enabled, the anchor is horizontally
reversed and it is now anchored to the right. Also, since items in a \l Row are positioned
@@ -1540,11 +1502,15 @@ QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj)
QQuickLayoutMirroringAttached::QQuickLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(0)
{
- if (QQuickItem *item = qobject_cast<QQuickItem*>(parent)) {
+ if (QQuickItem *item = qobject_cast<QQuickItem *>(parent))
itemPrivate = QQuickItemPrivate::get(item);
+ else if (QQuickWindow *window = qobject_cast<QQuickWindow *>(parent))
+ itemPrivate = QQuickItemPrivate::get(window->contentItem());
+
+ if (itemPrivate)
itemPrivate->extra.value().layoutDirectionAttached = this;
- } else
- qmlInfo(parent) << tr("LayoutDirection attached property only works with Items");
+ else
+ qmlInfo(parent) << tr("LayoutDirection attached property only works with Items and Windows");
}
QQuickLayoutMirroringAttached * QQuickLayoutMirroringAttached::qmlAttachedProperties(QObject *object)
@@ -1615,11 +1581,9 @@ void QQuickItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit)
if (isMirrorImplicit)
setLayoutMirror(inherit ? inheritedLayoutMirror : false);
- for (int i = 0; i < childItems.count(); ++i) {
- if (QQuickItem *child = qmlobject_cast<QQuickItem *>(childItems.at(i))) {
- QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
- childPrivate->setImplicitLayoutMirror(inheritedLayoutMirror, inheritMirrorFromParent);
- }
+ for (QQuickItem *child : qAsConst(childItems)) {
+ QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
+ childPrivate->setImplicitLayoutMirror(inheritedLayoutMirror, inheritMirrorFromParent);
}
}
@@ -2326,29 +2290,11 @@ QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent)
d->init(parent);
}
-#ifndef QT_NO_DEBUG
-static int qt_item_count = 0;
-
-static void qt_print_item_count()
-{
- qDebug("Number of leaked items: %i", qt_item_count);
- qt_item_count = -1;
-}
-#endif
-
/*!
Destroys the QQuickItem.
*/
QQuickItem::~QQuickItem()
{
-#ifndef QT_NO_DEBUG
- if (qsg_leak_check) {
- --qt_item_count;
- if (qt_item_count < 0)
- qDebug("Item destroyed after qt_print_item_count() was called.");
- }
-#endif
-
Q_D(QQuickItem);
if (d->windowRefCount > 1)
@@ -2362,7 +2308,7 @@ QQuickItem::~QQuickItem()
while (!d->childItems.isEmpty())
d->childItems.constFirst()->setParentItem(0);
- const auto listeners = d->changeListeners;
+ const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
if (anchor)
@@ -2391,15 +2337,16 @@ QQuickItem::~QQuickItem()
remove themselves from our list of transforms when that list has already
been destroyed after ~QQuickItem() has run.
*/
- for (int ii = 0; ii < d->transforms.count(); ++ii) {
- QQuickTransform *t = d->transforms.at(ii);
+ for (QQuickTransform *t : qAsConst(d->transforms)) {
QQuickTransformPrivate *tp = QQuickTransformPrivate::get(t);
tp->items.removeOne(this);
}
if (d->extra.isAllocated()) {
delete d->extra->contents; d->extra->contents = 0;
+#if QT_CONFIG(quick_shadereffect)
delete d->extra->layer; d->extra->layer = 0;
+#endif
}
delete d->_anchors; d->_anchors = 0;
@@ -2758,8 +2705,6 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
d->itemChange(ItemParentHasChanged, d->parentItem);
- d->parentNotifier.notify();
-
emit parentChanged(d->parentItem);
if (isVisible() && d->parentItem)
emit d->parentItem->visibleChildrenChanged();
@@ -2883,8 +2828,8 @@ QList<QQuickItem *> QQuickItemPrivate::paintOrderChildItems() const
// If none of the items have set Z then the paint order list is the same as
// 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.) {
+ for (QQuickItem *childItem : qAsConst(childItems)) {
+ if (QQuickItemPrivate::get(childItem)->z() != 0.) {
haveZ = true;
break;
}
@@ -2913,9 +2858,11 @@ void QQuickItemPrivate::addChild(QQuickItem *child)
// if the added child has a cursor and we do not currently have any children
// with cursors, bubble the notification up
- if (childPrivate->hasCursorInChild && !hasCursorInChild)
+ if (childPrivate->subtreeCursorEnabled && !subtreeCursorEnabled)
setHasCursorInChild(true);
#endif
+ if (childPrivate->subtreeHoverEnabled && !subtreeHoverEnabled)
+ setHasHoverInChild(true);
markSortedChildrenDirty(child);
dirty(QQuickItemPrivate::ChildrenChanged);
@@ -2938,9 +2885,11 @@ void QQuickItemPrivate::removeChild(QQuickItem *child)
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
// turn it off, if nothing else is using it
- if (childPrivate->hasCursorInChild && hasCursorInChild)
+ if (childPrivate->subtreeCursorEnabled && subtreeCursorEnabled)
setHasCursorInChild(false);
#endif
+ if (childPrivate->subtreeHoverEnabled && subtreeHoverEnabled)
+ setHasHoverInChild(false);
markSortedChildrenDirty(child);
dirty(QQuickItemPrivate::ChildrenChanged);
@@ -2979,8 +2928,7 @@ void QQuickItemPrivate::refWindow(QQuickWindow *c)
if (!parentItem)
QQuickWindowPrivate::get(window)->parentlessItems.insert(q);
- for (int ii = 0; ii < childItems.count(); ++ii) {
- QQuickItem *child = childItems.at(ii);
+ for (QQuickItem *child : qAsConst(childItems)) {
QQuickItemPrivate::get(child)->refWindow(c);
}
@@ -3007,13 +2955,7 @@ void QQuickItemPrivate::derefWindow()
QQuickWindowPrivate *c = QQuickWindowPrivate::get(window);
if (polishScheduled)
c->itemsToPolish.removeOne(q);
- QMutableHashIterator<int, QQuickItem *> itemTouchMapIt(c->itemForTouchPointId);
- while (itemTouchMapIt.hasNext()) {
- if (itemTouchMapIt.next().value() == q)
- itemTouchMapIt.remove();
- }
- if (c->mouseGrabberItem == q)
- c->mouseGrabberItem = 0;
+ c->removeGrabber(q);
#ifndef QT_NO_CURSOR
if (c->cursorItem == q) {
c->cursorItem = 0;
@@ -3038,8 +2980,7 @@ void QQuickItemPrivate::derefWindow()
paintNode = 0;
- for (int ii = 0; ii < childItems.count(); ++ii) {
- QQuickItem *child = childItems.at(ii);
+ for (QQuickItem *child : qAsConst(childItems)) {
QQuickItemPrivate::get(child)->derefWindow();
}
@@ -3162,7 +3103,8 @@ QQuickItemPrivate::QQuickItemPrivate()
, isAccessible(false)
, culled(false)
, hasCursor(false)
- , hasCursorInChild(false)
+ , subtreeCursorEnabled(false)
+ , subtreeHoverEnabled(false)
, activeFocusOnTab(false)
, implicitAntialiasing(false)
, antialiasingValid(false)
@@ -3196,21 +3138,8 @@ QQuickItemPrivate::~QQuickItemPrivate()
void QQuickItemPrivate::init(QQuickItem *parent)
{
-#ifndef QT_NO_DEBUG
- if (qsg_leak_check) {
- ++qt_item_count;
- static bool atexit_registered = false;
- if (!atexit_registered) {
- atexit(qt_print_item_count);
- atexit_registered = true;
- }
- }
-#endif
-
Q_Q(QQuickItem);
- registerAccessorProperties();
-
baselineOffset = 0.0;
if (parent) {
@@ -3355,7 +3284,7 @@ void QQuickItemPrivate::resources_clear(QQmlListProperty<QObject> *prop)
QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(quickItem);
if (quickItemPrivate->extra.isAllocated()) {//If extra is not allocated resources is empty.
- foreach (QObject *object, quickItemPrivate->extra->resourcesList) {
+ for (QObject *object : qAsConst(quickItemPrivate->extra->resourcesList)) {
qmlobject_disconnect(object, QObject, SIGNAL(destroyed(QObject*)),
quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
}
@@ -3496,8 +3425,7 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty<QQuickTransform> *prop)
QQuickItem *that = static_cast<QQuickItem *>(prop->object);
QQuickItemPrivate *p = QQuickItemPrivate::get(that);
- for (int ii = 0; ii < p->transforms.count(); ++ii) {
- QQuickTransform *t = p->transforms.at(ii);
+ for (QQuickTransform *t : qAsConst(p->transforms)) {
QQuickTransformPrivate *tp = QQuickTransformPrivate::get(t);
tp->items.removeOne(that);
}
@@ -3621,7 +3549,7 @@ QQuickAnchors *QQuickItemPrivate::anchors() const
void QQuickItemPrivate::siblingOrderChanged()
{
Q_Q(QQuickItem);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::SiblingOrder) {
change.listener->itemSiblingOrderChanged(q);
@@ -3725,32 +3653,31 @@ void QQuickItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeo
if (d->_anchors)
QQuickAnchorsPrivate::get(d->_anchors)->updateMe();
- bool xChange = (newGeometry.x() != oldGeometry.x());
- bool yChange = (newGeometry.y() != oldGeometry.y());
- bool widthChange = (newGeometry.width() != oldGeometry.width());
- bool heightChange = (newGeometry.height() != oldGeometry.height());
-
- const auto listeners = d->changeListeners;
- for (const QQuickItemPrivate::ChangeListener &change : listeners) {
- if (change.types & QQuickItemPrivate::Geometry) {
- if (change.gTypes == QQuickItemPrivate::GeometryChange) {
- change.listener->itemGeometryChanged(this, newGeometry, oldGeometry);
- } else if ((xChange && (change.gTypes & QQuickItemPrivate::XChange)) ||
- (yChange && (change.gTypes & QQuickItemPrivate::YChange)) ||
- (widthChange && (change.gTypes & QQuickItemPrivate::WidthChange)) ||
- (heightChange && (change.gTypes & QQuickItemPrivate::HeightChange))) {
- change.listener->itemGeometryChanged(this, newGeometry, oldGeometry);
- }
+ QQuickGeometryChange change;
+ QRectF diff(newGeometry.x() - oldGeometry.x(),
+ newGeometry.y() - oldGeometry.y(),
+ newGeometry.width() - oldGeometry.width(),
+ newGeometry.height() - oldGeometry.height());
+ change.setXChange(diff.x() != 0);
+ change.setYChange(diff.y() != 0);
+ change.setWidthChange(diff.width() != 0);
+ change.setHeightChange(diff.height() != 0);
+
+ const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732)
+ for (const QQuickItemPrivate::ChangeListener &listener : listeners) {
+ if (listener.types & QQuickItemPrivate::Geometry) {
+ if (change.matches(listener.gTypes))
+ listener.listener->itemGeometryChanged(this, change, diff);
}
}
- if (xChange)
+ if (change.xChange())
emit xChanged();
- if (yChange)
+ if (change.yChange())
emit yChanged();
- if (widthChange)
+ if (change.widthChange())
emit widthChanged();
- if (heightChange)
+ if (change.heightChange())
emit heightChanged();
}
@@ -3815,6 +3742,11 @@ QSGNode *QQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *upda
return 0;
}
+QQuickItem::UpdatePaintNodeData::UpdatePaintNodeData()
+: transformNode(0)
+{
+}
+
/*!
This function is called when an item should release graphics
resources which are not already managed by the nodes returend from
@@ -3864,7 +3796,8 @@ void QQuickItemPrivate::removeItemChangeListener(QQuickItemChangeListener *liste
changeListeners.removeOne(change);
}
-void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types)
+void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener,
+ QQuickGeometryChange types)
{
ChangeListener change(listener, types);
int index = changeListeners.indexOf(change);
@@ -3875,10 +3808,10 @@ void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListen
}
void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener,
- GeometryChangeTypes types)
+ QQuickGeometryChange types)
{
ChangeListener change(listener, types);
- if (types == NoChange) {
+ if (types.noChange()) {
changeListeners.removeOne(change);
} else {
int index = changeListeners.indexOf(change);
@@ -4147,7 +4080,8 @@ bool QQuickItem::childMouseEventFilter(QQuickItem *item, QEvent *event)
*/
void QQuickItem::windowDeactivateEvent()
{
- foreach (QQuickItem* item, childItems()) {
+ const auto children = childItems();
+ for (QQuickItem* item : children) {
item->windowDeactivateEvent();
}
}
@@ -4290,7 +4224,7 @@ void QQuickItem::setBaselineOffset(qreal offset)
d->baselineOffset = offset;
- const auto listeners = d->changeListeners;
+ const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Geometry) {
QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
@@ -4912,8 +4846,10 @@ void QQuickItem::classBegin()
d->_stateGroup->classBegin();
if (d->_anchors)
d->_anchors->classBegin();
+#if QT_CONFIG(quick_shadereffect)
if (d->extra.isAllocated() && d->extra->layer)
d->extra->layer->classBegin();
+#endif
}
/*!
@@ -4932,14 +4868,18 @@ void QQuickItem::componentComplete()
QQuickAnchorsPrivate::get(d->_anchors)->updateOnComplete();
}
- if (d->extra.isAllocated() && d->extra->layer)
- d->extra->layer->componentComplete();
+ if (d->extra.isAllocated()) {
+#if QT_CONFIG(quick_shadereffect)
+ if (d->extra->layer)
+ d->extra->layer->componentComplete();
+#endif
- if (d->extra.isAllocated() && d->extra->keyHandler)
- d->extra->keyHandler->componentComplete();
+ if (d->extra->keyHandler)
+ d->extra->keyHandler->componentComplete();
- if (d->extra.isAllocated() && d->extra->contents)
- d->extra->contents->complete();
+ if (d->extra->contents)
+ d->extra->contents->complete();
+ }
if (d->window && d->dirtyAttributes) {
d->addToDirtyList();
@@ -4988,8 +4928,10 @@ QPointF QQuickItemPrivate::computeTransformOrigin() const
void QQuickItemPrivate::transformChanged()
{
+#if QT_CONFIG(quick_shadereffect)
if (extra.isAllocated() && extra->layer)
extra->layer->updateMatrix();
+#endif
}
void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
@@ -5371,8 +5313,10 @@ void QQuickItem::setZ(qreal v)
emit zChanged();
+#if QT_CONFIG(quick_shadereffect)
if (d->extra.isAllocated() && d->extra->layer)
d->extra->layer->updateZ();
+#endif
}
/*!
@@ -5833,15 +5777,13 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
if (window) {
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
- if (windowPriv->mouseGrabberItem == q)
- q->ungrabMouse();
- if (!effectiveVisible)
- q->ungrabTouchPoints();
+ windowPriv->removeGrabber(q);
}
bool childVisibilityChanged = false;
- for (int ii = 0; ii < childItems.count(); ++ii)
- childVisibilityChanged |= QQuickItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
+ for (QQuickItem *childItem : qAsConst(childItems)) {
+ childVisibilityChanged |= QQuickItemPrivate::get(childItem)->setEffectiveVisibleRecur(newEffectiveVisible);
+ }
itemChange(QQuickItem::ItemVisibleHasChanged, effectiveVisible);
#ifndef QT_NO_ACCESSIBILITY
@@ -5883,18 +5825,15 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec
if (window) {
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
- if (windowPriv->mouseGrabberItem == q)
- q->ungrabMouse();
- if (!effectiveEnable)
- q->ungrabTouchPoints();
+ windowPriv->removeGrabber(q);
if (scope && !effectiveEnable && activeFocus) {
windowPriv->clearFocusInScope(
scope, q, Qt::OtherFocusReason, QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem);
}
}
- for (int ii = 0; ii < childItems.count(); ++ii) {
- QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(
+ for (QQuickItem *childItem : qAsConst(childItems)) {
+ QQuickItemPrivate::get(childItem)->setEffectiveEnableRecur(
(flags & QQuickItem::ItemIsFocusScope) && scope ? q : scope, newEffectiveEnable);
}
@@ -6038,7 +5977,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
switch (change) {
case QQuickItem::ItemChildAddedChange: {
q->itemChange(change, data);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Children) {
change.listener->itemChildAdded(q, data.item);
@@ -6048,7 +5987,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
}
case QQuickItem::ItemChildRemovedChange: {
q->itemChange(change, data);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Children) {
change.listener->itemChildRemoved(q, data.item);
@@ -6061,7 +6000,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
break;
case QQuickItem::ItemVisibleHasChanged: {
q->itemChange(change, data);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Visibility) {
change.listener->itemVisibilityChanged(q);
@@ -6071,7 +6010,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
}
case QQuickItem::ItemParentHasChanged: {
q->itemChange(change, data);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Parent) {
change.listener->itemParentChanged(q, data.item);
@@ -6081,7 +6020,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
}
case QQuickItem::ItemOpacityHasChanged: {
q->itemChange(change, data);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Opacity) {
change.listener->itemOpacityChanged(q);
@@ -6094,7 +6033,7 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
break;
case QQuickItem::ItemRotationHasChanged: {
q->itemChange(change, data);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Rotation) {
change.listener->itemRotationChanged(q);
@@ -6456,7 +6395,7 @@ void QQuickItem::resetWidth()
void QQuickItemPrivate::implicitWidthChanged()
{
Q_Q(QQuickItem);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::ImplicitWidth) {
change.listener->itemImplicitWidthChanged(q);
@@ -6620,7 +6559,7 @@ void QQuickItem::resetHeight()
void QQuickItemPrivate::implicitHeightChanged()
{
Q_Q(QQuickItem);
- const auto listeners = changeListeners;
+ const auto listeners = changeListeners; // NOTE: intentional copy (QTBUG-54732)
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::ImplicitHeight) {
change.listener->itemImplicitHeightChanged(q);
@@ -7047,7 +6986,7 @@ void QQuickItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
}
/*!
- Returns whether mouse events of this item's children should be filtered
+ Returns whether mouse and touch events of this item's children should be filtered
through this item.
\sa setFiltersChildMouseEvents(), childMouseEventFilter()
@@ -7059,7 +6998,7 @@ bool QQuickItem::filtersChildMouseEvents() const
}
/*!
- Sets whether mouse events of this item's children should be filtered
+ Sets whether mouse and touch events of this item's children should be filtered
through this item.
If \a filter is true, childMouseEventFilter() will be called when
@@ -7110,6 +7049,7 @@ void QQuickItem::setAcceptHoverEvents(bool enabled)
{
Q_D(QQuickItem);
d->hoverEnabled = enabled;
+ d->setHasHoverInChild(enabled);
}
void QQuickItemPrivate::setHasCursorInChild(bool hasCursor)
@@ -7118,17 +7058,18 @@ void QQuickItemPrivate::setHasCursorInChild(bool hasCursor)
Q_Q(QQuickItem);
// if we're asked to turn it off (because of an unsetcursor call, or a node
- // removal) then we should check our children and make sure it's really ok
- // to turn it off.
- if (!hasCursor && hasCursorInChild) {
- foreach (QQuickItem *otherChild, childItems) {
+ // removal) then we should make sure it's really ok to turn it off.
+ if (!hasCursor && subtreeCursorEnabled) {
+ if (hasCursor)
+ return; // nope! sorry, I have a cursor myself
+ for (QQuickItem *otherChild : qAsConst(childItems)) {
QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(otherChild);
- if (otherChildPrivate->hasCursorInChild)
+ if (otherChildPrivate->subtreeCursorEnabled || otherChildPrivate->hasCursor)
return; // nope! sorry, something else wants it kept on.
}
}
- hasCursorInChild = hasCursor;
+ subtreeCursorEnabled = hasCursor;
QQuickItem *parent = q->parentItem();
if (parent) {
QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent);
@@ -7137,6 +7078,31 @@ void QQuickItemPrivate::setHasCursorInChild(bool hasCursor)
#endif
}
+void QQuickItemPrivate::setHasHoverInChild(bool hasHover)
+{
+ Q_Q(QQuickItem);
+
+ // if we're asked to turn it off (because of a setAcceptHoverEvents call, or a node
+ // removal) then we should make sure it's really ok to turn it off.
+ if (!hasHover && subtreeHoverEnabled) {
+ if (hoverEnabled)
+ return; // nope! sorry, I need hover myself
+ for (QQuickItem *otherChild : qAsConst(childItems)) {
+ QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(otherChild);
+ if (otherChildPrivate->subtreeHoverEnabled || otherChildPrivate->hoverEnabled)
+ return; // nope! sorry, something else wants it kept on.
+ }
+ }
+
+ qCDebug(DBG_HOVER_TRACE) << q << subtreeHoverEnabled << "->" << hasHover;
+ subtreeHoverEnabled = hasHover;
+ QQuickItem *parent = q->parentItem();
+ if (parent) {
+ QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent);
+ parentPrivate->setHasHoverInChild(hasHover);
+ }
+}
+
#ifndef QT_NO_CURSOR
/*!
@@ -7227,6 +7193,11 @@ void QQuickItem::unsetCursor()
Grabs the mouse input.
This item will receive all mouse events until ungrabMouse() is called.
+ Usually this function should not be called, since accepting for example
+ a mouse press event makes sure that the following events are delivered
+ to the item.
+ If an item wants to take over mouse events from the current receiver,
+ it needs to call this function.
\warning This function should be used with caution.
*/
@@ -7241,6 +7212,12 @@ void QQuickItem::grabMouse()
/*!
Releases the mouse grab following a call to grabMouse().
+
+ Note that this function should only be called when the item wants
+ to stop handling further events. There is no need to call this function
+ after a release or cancel event since no future events will be received
+ in any case. No move or release events will be delivered after this
+ function was called.
*/
void QQuickItem::ungrabMouse()
{
@@ -7248,15 +7225,7 @@ void QQuickItem::ungrabMouse()
if (!d->window)
return;
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window);
- if (windowPriv->mouseGrabberItem != this) {
- qWarning("QQuickItem::ungrabMouse(): Item is not the mouse grabber.");
- return;
- }
-
- windowPriv->mouseGrabberItem = 0;
-
- QEvent ev(QEvent::UngrabMouse);
- d->window->sendEvent(this, &ev);
+ windowPriv->removeGrabber(this, true, false);
}
@@ -7309,31 +7278,16 @@ void QQuickItem::grabTouchPoints(const QVector<int> &ids)
if (!d->window)
return;
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window);
-
- QSet<QQuickItem*> ungrab;
- for (int i = 0; i < ids.count(); ++i) {
- QQuickItem *oldGrabber = windowPriv->itemForTouchPointId.value(ids.at(i));
- if (oldGrabber == this)
- return;
-
- windowPriv->itemForTouchPointId[ids.at(i)] = this;
- if (oldGrabber)
- ungrab.insert(oldGrabber);
-
- QQuickItem *mouseGrabber = windowPriv->mouseGrabberItem;
- if (windowPriv->touchMouseId == ids.at(i) && mouseGrabber && mouseGrabber != this) {
- windowPriv->mouseGrabberItem = 0;
- QEvent ev(QEvent::UngrabMouse);
- d->window->sendEvent(mouseGrabber, &ev);
- }
- }
- foreach (QQuickItem *oldGrabber, ungrab)
- oldGrabber->touchUngrabEvent();
+ windowPriv->grabTouchPoints(this, ids);
}
/*!
Ungrabs the touch points owned by this item.
+ \note there is hardly any reason to call this function. It should only be
+ called when an item does not want to receive any further events, so no
+ move or release events will be delivered after calling this function.
+
\sa grabTouchPoints()
*/
void QQuickItem::ungrabTouchPoints()
@@ -7342,14 +7296,7 @@ void QQuickItem::ungrabTouchPoints()
if (!d->window)
return;
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window);
-
- QMutableHashIterator<int, QQuickItem*> i(windowPriv->itemForTouchPointId);
- while (i.hasNext()) {
- i.next();
- if (i.value() == this)
- i.remove();
- }
- touchUngrabEvent();
+ windowPriv->removeGrabber(this, false, true);
}
/*!
@@ -7408,7 +7355,9 @@ void QQuickItem::setKeepTouchGrab(bool keep)
bool QQuickItem::contains(const QPointF &point) const
{
Q_D(const QQuickItem);
- return QRectF(0, 0, d->width, d->height).contains(point);
+ qreal x = point.x();
+ qreal y = point.y();
+ return x >= 0 && y >= 0 && x <= d->width && y <= d->height;
}
/*!
@@ -7769,9 +7718,13 @@ QDebug operator<<(QDebug debug, QQuickItem *item)
bool QQuickItem::isTextureProvider() const
{
+#if QT_CONFIG(quick_shadereffect)
Q_D(const QQuickItem);
return d->extra.isAllocated() && d->extra->layer && d->extra->layer->effectSource() ?
d->extra->layer->effectSource()->isTextureProvider() : false;
+#else
+ return false;
+#endif
}
/*!
@@ -7785,9 +7738,13 @@ bool QQuickItem::isTextureProvider() const
QSGTextureProvider *QQuickItem::textureProvider() const
{
+#if QT_CONFIG(quick_shadereffect)
Q_D(const QQuickItem);
return d->extra.isAllocated() && d->extra->layer && d->extra->layer->effectSource() ?
d->extra->layer->effectSource()->textureProvider() : 0;
+#else
+ return 0;
+#endif
}
/*!
@@ -7796,14 +7753,19 @@ QSGTextureProvider *QQuickItem::textureProvider() const
*/
QQuickItemLayer *QQuickItemPrivate::layer() const
{
+#if QT_CONFIG(quick_shadereffect)
if (!extra.isAllocated() || !extra->layer) {
extra.value().layer = new QQuickItemLayer(const_cast<QQuickItem *>(q_func()));
if (!componentComplete)
extra->layer->classBegin();
}
return extra->layer;
+#else
+ return 0;
+#endif
}
+#if QT_CONFIG(quick_shadereffect)
QQuickItemLayer::QQuickItemLayer(QQuickItem *item)
: m_item(item)
, m_enabled(false)
@@ -8211,7 +8173,7 @@ void QQuickItemLayer::itemOpacityChanged(QQuickItem *item)
updateOpacity();
}
-void QQuickItemLayer::itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &)
+void QQuickItemLayer::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
{
updateGeometry();
}
@@ -8291,12 +8253,16 @@ void QQuickItemLayer::updateMatrix()
ld->extra.value().origin = QQuickItemPrivate::get(m_item)->origin();
ld->dirty(QQuickItemPrivate::Transform);
}
+#endif // quick_shadereffect
QQuickItemPrivate::ExtraData::ExtraData()
: z(0), scale(1), rotation(0), opacity(1),
contents(0), screenAttached(0), layoutDirectionAttached(0),
enterKeyAttached(0),
- keyHandler(0), layer(0),
+ keyHandler(0),
+#if QT_CONFIG(quick_shadereffect)
+ layer(0),
+#endif
effectRefCount(0), hideRefCount(0),
opacityNode(0), clipNode(0), rootNode(0),
acceptedMouseButtons(0), origin(QQuickItem::Center),
@@ -8322,7 +8288,6 @@ QAccessible::Role QQuickItemPrivate::accessibleRole() const
namespace QV4 {
namespace Heap {
struct QQuickItemWrapper : public QObjectWrapper {
- QQuickItemWrapper(QQuickItem *item) : QObjectWrapper(item) {}
};
}
}
@@ -8337,7 +8302,7 @@ DEFINE_OBJECT_VTABLE(QQuickItemWrapper);
void QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e)
{
QObjectWrapper::Data *This = static_cast<QObjectWrapper::Data *>(that);
- if (QQuickItem *item = static_cast<QQuickItem*>(This->object.data())) {
+ if (QQuickItem *item = static_cast<QQuickItem*>(This->object())) {
foreach (QQuickItem *child, QQuickItemPrivate::get(item)->childItems)
QV4::QObjectWrapper::markWrapper(child, e);
}