diff options
Diffstat (limited to 'src/quick/items/qquickitem.cpp')
-rw-r--r-- | src/quick/items/qquickitem.cpp | 327 |
1 files changed, 221 insertions, 106 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index f8374bdbc2..3a0aea517c 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -87,8 +87,9 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(DBG_MOUSE_TARGET) Q_DECLARE_LOGGING_CATEGORY(DBG_HOVER_TRACE) +Q_DECLARE_LOGGING_CATEGORY(lcTransient) -void debugFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1) +void debugFocusTree(QQuickItem *item, QQuickItem *scope = nullptr, int depth = 1) { if (DBG_FOCUS().isEnabled(QtDebugMsg)) { qCDebug(DBG_FOCUS) @@ -302,9 +303,9 @@ void QQuickContents::itemChildAdded(QQuickItem *, QQuickItem *item) } QQuickItemKeyFilter::QQuickItemKeyFilter(QQuickItem *item) -: m_processPost(false), m_next(0) +: m_processPost(false), m_next(nullptr) { - QQuickItemPrivate *p = item?QQuickItemPrivate::get(item):0; + QQuickItemPrivate *p = item?QQuickItemPrivate::get(item):nullptr; if (p) { m_next = p->extra.value().keyHandler; p->extra->keyHandler = this; @@ -785,7 +786,7 @@ const SigMap sigMap[] = { { Qt::Key_Menu, "menuPressed" }, { Qt::Key_VolumeUp, "volumeUpPressed" }, { Qt::Key_VolumeDown, "volumeDownPressed" }, - { 0, 0 } + { 0, nullptr } }; QByteArray QQuickKeysAttached::keyToSignal(int key) @@ -970,7 +971,7 @@ bool QQuickKeysAttached::isConnected(const char *signalName) const Keys.onEscapePressed: { console.log("escapeItem is handling escape"); - event.accepted = true; + // event.accepted is set to true by default for the specific key handlers } } @@ -1543,6 +1544,13 @@ QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj) mirroring is not the desired behavior, or if the child item already implements mirroring in some custom way. + To set the layout direction based on the \l {Default Layout Direction}{default layout direction} + of the application, use the following code: + + \code + LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft + \endcode + See \l {Right-to-left User Interfaces} for further details on using \c LayoutMirroring and other related features to implement right-to-left support for an application. */ @@ -1569,7 +1577,7 @@ QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj) */ -QQuickLayoutMirroringAttached::QQuickLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(0) +QQuickLayoutMirroringAttached::QQuickLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(nullptr) { if (QQuickItem *item = qobject_cast<QQuickItem *>(parent)) itemPrivate = QQuickItemPrivate::get(item); @@ -1723,7 +1731,7 @@ void QQuickItemPrivate::setLayoutMirror(bool mirror) */ QQuickEnterKeyAttached::QQuickEnterKeyAttached(QObject *parent) - : QObject(parent), itemPrivate(0), keyType(Qt::EnterKeyDefault) + : QObject(parent), itemPrivate(nullptr), keyType(Qt::EnterKeyDefault) { if (QQuickItem *item = qobject_cast<QQuickItem*>(parent)) { itemPrivate = QQuickItemPrivate::get(item); @@ -1776,7 +1784,7 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus) if (oldSubFocusItem) { QQuickItem *sfi = scopePrivate->subFocusItem->parentItem(); while (sfi && sfi != scope) { - QQuickItemPrivate::get(sfi)->subFocusItem = 0; + QQuickItemPrivate::get(sfi)->subFocusItem = nullptr; sfi = sfi->parentItem(); } } @@ -1789,7 +1797,7 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus) sfi = sfi->parentItem(); } } else { - scopePrivate->subFocusItem = 0; + scopePrivate->subFocusItem = nullptr; } } @@ -2067,7 +2075,7 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus) In the QPainter / QWidget world, it is some times favorable to cache complex content in a pixmap, image or texture. In Qt Quick, because of the techniques already applied by the \l {Qt Quick - Scene Graph Renderer} {scene graph renderer}, this will in most + Scene Graph OpenGL Renderer} {scene graph renderer}, this will in most cases not be the case. Excessive draw calls are already reduced because of batching and a cache will in most cases end up blending more pixels than the original content. The overhead of rendering @@ -2374,13 +2382,13 @@ QQuickItem::~QQuickItem() if (d->windowRefCount > 1) d->windowRefCount = 1; // Make sure window is set to null in next call to derefWindow(). if (d->parentItem) - setParentItem(0); + setParentItem(nullptr); else if (d->window) d->derefWindow(); // XXX todo - optimize while (!d->childItems.isEmpty()) - d->childItems.constFirst()->setParentItem(0); + d->childItems.constFirst()->setParentItem(nullptr); if (!d->changeListeners.isEmpty()) { const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732) @@ -2420,14 +2428,14 @@ QQuickItem::~QQuickItem() } if (d->extra.isAllocated()) { - delete d->extra->contents; d->extra->contents = 0; + delete d->extra->contents; d->extra->contents = nullptr; #if QT_CONFIG(quick_shadereffect) - delete d->extra->layer; d->extra->layer = 0; + delete d->extra->layer; d->extra->layer = nullptr; #endif } - delete d->_anchors; d->_anchors = 0; - delete d->_stateGroup; d->_stateGroup = 0; + delete d->_anchors; d->_anchors = nullptr; + delete d->_stateGroup; d->_stateGroup = nullptr; } /*! @@ -2542,7 +2550,7 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo bool all = QGuiApplication::styleHints()->tabFocusBehavior() == Qt::TabFocusAllControls; - QQuickItem *from = 0; + QQuickItem *from = nullptr; bool isTabFence = item->d_func()->isTabFence; if (forward) { if (!isTabFence) @@ -2677,7 +2685,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) if (parentItem) { QQuickItem *itemAncestor = parentItem; - while (itemAncestor != 0) { + while (itemAncestor != nullptr) { if (Q_UNLIKELY(itemAncestor == this)) { qWarning() << "QQuickItem::setParentItem: Parent" << parentItem << "is already part of the subtree of" << this; return; @@ -2689,12 +2697,12 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) d->removeFromDirtyList(); QQuickItem *oldParentItem = d->parentItem; - QQuickItem *scopeFocusedItem = 0; + QQuickItem *scopeFocusedItem = nullptr; if (oldParentItem) { QQuickItemPrivate *op = QQuickItemPrivate::get(oldParentItem); - QQuickItem *scopeItem = 0; + QQuickItem *scopeItem = nullptr; if (hasFocus() || op->subFocusItem == this) scopeFocusedItem = this; @@ -2724,7 +2732,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) QQuickWindowPrivate::get(d->window)->parentlessItems.remove(this); } - QQuickWindow *parentWindow = parentItem ? QQuickItemPrivate::get(parentItem)->window : 0; + QQuickWindow *parentWindow = parentItem ? QQuickItemPrivate::get(parentItem)->window : nullptr; if (d->window == parentWindow) { // Avoid freeing and reallocating resources if the window stays the same. d->parentItem = parentItem; @@ -2744,7 +2752,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) QQuickWindowPrivate::get(d->window)->parentlessItems.insert(this); d->setEffectiveVisibleRecur(d->calcEffectiveVisible()); - d->setEffectiveEnableRecur(0, d->calcEffectiveEnable()); + d->setEffectiveEnableRecur(nullptr, d->calcEffectiveEnable()); if (d->parentItem) { if (!scopeFocusedItem) { @@ -2808,7 +2816,8 @@ void QQuickItem::stackBefore(const QQuickItem *sibling) { Q_D(QQuickItem); if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(sibling)->parentItem) { - qWarning("QQuickItem::stackBefore: Cannot stack before %p, which must be a sibling", sibling); + qWarning().nospace() << "QQuickItem::stackBefore: Cannot stack " + << this << " before " << sibling << ", which must be a sibling"; return; } @@ -2852,7 +2861,8 @@ void QQuickItem::stackAfter(const QQuickItem *sibling) { Q_D(QQuickItem); if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(sibling)->parentItem) { - qWarning("QQuickItem::stackAfter: Cannot stack after %p, which must be a sibling", sibling); + qWarning().nospace() << "QQuickItem::stackAfter: Cannot stack " + << this << " after " << sibling << ", which must be a sibling"; return; } @@ -2942,6 +2952,7 @@ void QQuickItemPrivate::addChild(QQuickItem *child) if (childPrivate->subtreeHoverEnabled && !subtreeHoverEnabled) setHasHoverInChild(true); + childPrivate->recursiveRefFromEffectItem(extra.value().recursiveEffectRefCount); markSortedChildrenDirty(child); dirty(QQuickItemPrivate::ChildrenChanged); @@ -2970,6 +2981,7 @@ void QQuickItemPrivate::removeChild(QQuickItem *child) if (childPrivate->subtreeHoverEnabled && subtreeHoverEnabled) setHasHoverInChild(false); + childPrivate->recursiveRefFromEffectItem(-extra.value().recursiveEffectRefCount); markSortedChildrenDirty(child); dirty(QQuickItemPrivate::ChildrenChanged); @@ -2990,7 +3002,7 @@ void QQuickItemPrivate::refWindow(QQuickWindow *c) // derefWindow() decrements the reference count. Q_Q(QQuickItem); - Q_ASSERT((window != 0) == (windowRefCount > 0)); + Q_ASSERT((window != nullptr) == (windowRefCount > 0)); Q_ASSERT(c); if (++windowRefCount > 1) { if (c != window) @@ -2998,7 +3010,7 @@ void QQuickItemPrivate::refWindow(QQuickWindow *c) return; // Window already set. } - Q_ASSERT(window == 0); + Q_ASSERT(window == nullptr); window = c; if (polishScheduled) @@ -3022,7 +3034,7 @@ void QQuickItemPrivate::refWindow(QQuickWindow *c) void QQuickItemPrivate::derefWindow() { Q_Q(QQuickItem); - Q_ASSERT((window != 0) == (windowRefCount > 0)); + Q_ASSERT((window != nullptr) == (windowRefCount > 0)); if (!window) return; // This can happen when destroying recursive shader effect sources. @@ -3038,7 +3050,7 @@ void QQuickItemPrivate::derefWindow() c->removeGrabber(q); #if QT_CONFIG(cursor) if (c->cursorItem == q) { - c->cursorItem = 0; + c->cursorItem = nullptr; window->unsetCursor(); } #endif @@ -3048,17 +3060,17 @@ void QQuickItemPrivate::derefWindow() if (!parentItem) c->parentlessItems.remove(q); - window = 0; + window = nullptr; - itemNodeInstance = 0; + itemNodeInstance = nullptr; if (extra.isAllocated()) { - extra->opacityNode = 0; - extra->clipNode = 0; - extra->rootNode = 0; + extra->opacityNode = nullptr; + extra->clipNode = nullptr; + extra->rootNode = nullptr; } - paintNode = 0; + paintNode = nullptr; for (int ii = 0; ii < childItems.count(); ++ii) { QQuickItem *child = childItems.at(ii); @@ -3068,8 +3080,8 @@ void QQuickItemPrivate::derefWindow() dirty(Window); if (extra.isAllocated() && extra->screenAttached) - extra->screenAttached->windowChanged(0); - itemChange(QQuickItem::ItemSceneChange, (QQuickWindow *)0); + extra->screenAttached->windowChanged(nullptr); + itemChange(QQuickItem::ItemSceneChange, (QQuickWindow *)nullptr); } @@ -3155,8 +3167,8 @@ bool QQuickItem::isComponentComplete() const } QQuickItemPrivate::QQuickItemPrivate() - : _anchors(0) - , _stateGroup(0) + : _anchors(nullptr) + , _stateGroup(nullptr) , flags(0) , widthValid(false) , heightValid(false) @@ -3197,13 +3209,13 @@ QQuickItemPrivate::QQuickItemPrivate() , touchEnabled(false) #endif , dirtyAttributes(0) - , nextDirtyItem(0) - , prevDirtyItem(0) - , window(0) + , nextDirtyItem(nullptr) + , prevDirtyItem(nullptr) + , window(nullptr) , windowRefCount(0) - , parentItem(0) + , parentItem(nullptr) , sortedChildItems(&childItems) - , subFocusItem(0) + , subFocusItem(nullptr) , x(0) , y(0) , width(0) @@ -3211,8 +3223,8 @@ QQuickItemPrivate::QQuickItemPrivate() , implicitWidth(0) , implicitHeight(0) , baselineOffset(0) - , itemNodeInstance(0) - , paintNode(0) + , itemNodeInstance(nullptr) + , paintNode(nullptr) { } @@ -3253,7 +3265,7 @@ void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o) // because there can be multiple handlers... that->setAcceptedMouseButtons(Qt::AllButtons); QQuickItemPrivate *p = QQuickItemPrivate::get(that); - p->extra.value().pointerHandlers.append(pointerHandler); + p->extra.value().pointerHandlers.prepend(pointerHandler); } else { QQuickWindow *thisWindow = qmlobject_cast<QQuickWindow *>(o); QQuickItem *item = that; @@ -3264,11 +3276,13 @@ void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o) } if (thisWindow) { - if (itemWindow) + if (itemWindow) { + qCDebug(lcTransient) << thisWindow << "is transient for" << itemWindow; thisWindow->setTransientParent(itemWindow); - else + } else { QObject::connect(item, SIGNAL(windowChanged(QQuickWindow*)), thisWindow, SLOT(setTransientParent_helper(QQuickWindow*))); + } } o->setParent(that); } @@ -3335,7 +3349,7 @@ QObject *QQuickItemPrivate::data_at(QQmlListProperty<QObject> *property, int i) const int j = i - resourcesCount; if (j < children_count(&childrenProperty)) return children_at(&childrenProperty, j); - return 0; + return nullptr; } void QQuickItemPrivate::data_clear(QQmlListProperty<QObject> *property) @@ -3389,7 +3403,7 @@ QQuickItem *QQuickItemPrivate::children_at(QQmlListProperty<QQuickItem> *prop, i { QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object)); if (index >= p->childItems.count() || index < 0) - return 0; + return nullptr; else return p->childItems.at(index); } @@ -3401,7 +3415,7 @@ void QQuickItemPrivate::children_append(QQmlListProperty<QQuickItem> *prop, QQui QQuickItem *that = static_cast<QQuickItem *>(prop->object); if (o->parentItem() == that) - o->setParentItem(0); + o->setParentItem(nullptr); o->setParentItem(that); } @@ -3417,7 +3431,7 @@ void QQuickItemPrivate::children_clear(QQmlListProperty<QQuickItem> *prop) QQuickItem *that = static_cast<QQuickItem *>(prop->object); QQuickItemPrivate *p = QQuickItemPrivate::get(that); while (!p->childItems.isEmpty()) - p->childItems.at(0)->setParentItem(0); + p->childItems.at(0)->setParentItem(nullptr); } int QQuickItemPrivate::visibleChildren_count(QQmlListProperty<QQuickItem> *prop) @@ -3437,14 +3451,14 @@ QQuickItem *QQuickItemPrivate::visibleChildren_at(QQmlListProperty<QQuickItem> * QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object)); const int childCount = p->childItems.count(); if (index >= childCount || index < 0) - return 0; + return nullptr; 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; + return nullptr; } int QQuickItemPrivate::transform_count(QQmlListProperty<QQuickTransform> *prop) @@ -3508,7 +3522,7 @@ QQuickTransform *QQuickItemPrivate::transform_at(QQmlListProperty<QQuickTransfor QQuickItemPrivate *p = QQuickItemPrivate::get(that); if (idx < 0 || idx >= p->transforms.count()) - return 0; + return nullptr; else return p->transforms.at(idx); } @@ -3655,7 +3669,7 @@ void QQuickItemPrivate::siblingOrderChanged() QQmlListProperty<QObject> QQuickItemPrivate::data() { - return QQmlListProperty<QObject>(q_func(), 0, QQuickItemPrivate::data_append, + return QQmlListProperty<QObject>(q_func(), nullptr, QQuickItemPrivate::data_append, QQuickItemPrivate::data_count, QQuickItemPrivate::data_at, QQuickItemPrivate::data_clear); @@ -3667,8 +3681,9 @@ QQmlListProperty<QObject> QQuickItemPrivate::data() \qmlproperty real QtQuick::Item::childrenRect.y \qmlproperty real QtQuick::Item::childrenRect.width \qmlproperty real QtQuick::Item::childrenRect.height + \readonly - This property holds the collective position and size of the item's + This read-only property holds the collective position and size of the item's children. This property is useful if you need to access the collective geometry @@ -3833,11 +3848,11 @@ QSGNode *QQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *upda { Q_UNUSED(updatePaintNodeData) delete oldNode; - return 0; + return nullptr; } QQuickItem::UpdatePaintNodeData::UpdatePaintNodeData() -: transformNode(0) +: transformNode(nullptr) { } @@ -3948,8 +3963,8 @@ void QQuickItem::inputMethodEvent(QInputMethodEvent *event) /*! This event handler can be reimplemented in a subclass to receive focus-in - events for an item. The event information is provided by the - \a event parameter. + events for an item. The event information is provided by the \c event + parameter. */ void QQuickItem::focusInEvent(QFocusEvent * /*event*/) { @@ -3965,8 +3980,8 @@ void QQuickItem::focusInEvent(QFocusEvent * /*event*/) /*! This event handler can be reimplemented in a subclass to receive focus-out - events for an item. The event information is provided by the - \a event parameter. + events for an item. The event information is provided by the \c event + parameter. */ void QQuickItem::focusOutEvent(QFocusEvent * /*event*/) { @@ -4402,7 +4417,7 @@ void QQuickItem::mapFromItem(QQmlV4Function *args) const QV4::Scope scope(v4); QV4::ScopedValue item(scope, (*args)[0]); - QQuickItem *itemObj = 0; + QQuickItem *itemObj = nullptr; if (!item->isNull()) { QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, item->as<QV4::QObjectWrapper>()); if (qobjectWrapper) @@ -4490,7 +4505,7 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const QV4::Scope scope(v4); QV4::ScopedValue item(scope, (*args)[0]); - QQuickItem *itemObj = 0; + QQuickItem *itemObj = nullptr; if (!item->isNull()) { QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, item->as<QV4::QObjectWrapper>()); if (qobjectWrapper) @@ -4723,12 +4738,12 @@ QQuickItem *QQuickItem::childAt(qreal x, qreal y) const && child->height() > point.y()) return child; } - return 0; + return nullptr; } QQmlListProperty<QObject> QQuickItemPrivate::resources() { - return QQmlListProperty<QObject>(q_func(), 0, QQuickItemPrivate::resources_append, + return QQmlListProperty<QObject>(q_func(), nullptr, QQuickItemPrivate::resources_append, QQuickItemPrivate::resources_count, QQuickItemPrivate::resources_at, QQuickItemPrivate::resources_clear); @@ -4753,7 +4768,7 @@ QQmlListProperty<QObject> QQuickItemPrivate::resources() */ QQmlListProperty<QQuickItem> QQuickItemPrivate::children() { - return QQmlListProperty<QQuickItem>(q_func(), 0, QQuickItemPrivate::children_append, + return QQmlListProperty<QQuickItem>(q_func(), nullptr, QQuickItemPrivate::children_append, QQuickItemPrivate::children_count, QQuickItemPrivate::children_at, QQuickItemPrivate::children_clear); @@ -4773,7 +4788,7 @@ QQmlListProperty<QQuickItem> QQuickItemPrivate::children() QQmlListProperty<QQuickItem> QQuickItemPrivate::visibleChildren() { return QQmlListProperty<QQuickItem>(q_func(), - 0, + nullptr, QQuickItemPrivate::visibleChildren_count, QQuickItemPrivate::visibleChildren_at); @@ -4923,7 +4938,7 @@ void QQuickItem::setState(const QString &state) */ QQmlListProperty<QQuickTransform> QQuickItem::transform() { - return QQmlListProperty<QQuickTransform>(this, 0, QQuickItemPrivate::transform_append, + return QQmlListProperty<QQuickTransform>(this, nullptr, QQuickItemPrivate::transform_append, QQuickItemPrivate::transform_count, QQuickItemPrivate::transform_at, QQuickItemPrivate::transform_clear); @@ -5171,8 +5186,8 @@ void QQuickItem::updateInputMethod(Qt::InputMethodQueries queries) } #endif // im -/*! \internal */ // XXX todo - do we want/need this anymore? +/*! \internal */ QRectF QQuickItem::boundingRect() const { Q_D(const QQuickItem); @@ -5806,19 +5821,24 @@ bool QQuickItem::isVisible() const return d->effectiveVisible; } -void QQuickItem::setVisible(bool v) +void QQuickItemPrivate::setVisible(bool visible) { - Q_D(QQuickItem); - if (v == d->explicitVisible) + if (visible == explicitVisible) return; - d->explicitVisible = v; - if (!v) - d->dirty(QQuickItemPrivate::Visible); + explicitVisible = visible; + if (!visible) + dirty(QQuickItemPrivate::Visible); - const bool childVisibilityChanged = d->setEffectiveVisibleRecur(d->calcEffectiveVisible()); - if (childVisibilityChanged && d->parentItem) - emit d->parentItem->visibleChildrenChanged(); // signal the parent, not this! + const bool childVisibilityChanged = setEffectiveVisibleRecur(calcEffectiveVisible()); + if (childVisibilityChanged && parentItem) + emit parentItem->visibleChildrenChanged(); // signal the parent, not this! +} + +void QQuickItem::setVisible(bool v) +{ + Q_D(QQuickItem); + d->setVisible(v); } /*! @@ -6052,8 +6072,8 @@ void QQuickItemPrivate::removeFromDirtyList() if (prevDirtyItem) { if (nextDirtyItem) QQuickItemPrivate::get(nextDirtyItem)->prevDirtyItem = prevDirtyItem; *prevDirtyItem = nextDirtyItem; - prevDirtyItem = 0; - nextDirtyItem = 0; + prevDirtyItem = nullptr; + nextDirtyItem = nullptr; } Q_ASSERT(!prevDirtyItem); Q_ASSERT(!nextDirtyItem); @@ -6062,28 +6082,48 @@ void QQuickItemPrivate::removeFromDirtyList() void QQuickItemPrivate::refFromEffectItem(bool hide) { ++extra.value().effectRefCount; - if (1 == extra->effectRefCount) { + if (extra->effectRefCount == 1) { dirty(EffectReference); - if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged); + if (parentItem) + QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged); } if (hide) { if (++extra->hideRefCount == 1) dirty(HideReference); } + recursiveRefFromEffectItem(1); +} + +void QQuickItemPrivate::recursiveRefFromEffectItem(int refs) +{ + Q_Q(QQuickItem); + if (!refs) + return; + extra.value().recursiveEffectRefCount += refs; + for (int ii = 0; ii < childItems.count(); ++ii) { + QQuickItem *child = childItems.at(ii); + QQuickItemPrivate::get(child)->recursiveRefFromEffectItem(refs); + } + // Polish may rely on the effect ref count so trigger one, if item is not visible + // (if visible, it will be triggered automatically). + if (!effectiveVisible && refs > 0 && extra.value().recursiveEffectRefCount == 1) // it wasn't referenced, now it's referenced + q->polish(); } void QQuickItemPrivate::derefFromEffectItem(bool unhide) { Q_ASSERT(extra->effectRefCount); --extra->effectRefCount; - if (0 == extra->effectRefCount) { + if (extra->effectRefCount == 0) { dirty(EffectReference); - if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged); + if (parentItem) + QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged); } if (unhide) { if (--extra->hideRefCount == 0) dirty(HideReference); } + recursiveRefFromEffectItem(-1); } void QQuickItemPrivate::setCulled(bool cull) @@ -7102,7 +7142,7 @@ QQuickItem *QQuickItem::scopedFocusItem() const { Q_D(const QQuickItem); if (!isFocusScope()) - return 0; + return nullptr; else return d->subFocusItem; } @@ -7409,10 +7449,18 @@ void QQuickItem::unsetCursor() void QQuickItem::grabMouse() { Q_D(QQuickItem); - if (!d->window) + if (!d->window || d->window->mouseGrabberItem() == this) return; QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window); - windowPriv->setMouseGrabber(this); + bool fromTouch = windowPriv->isDeliveringTouchAsMouse(); + auto point = fromTouch ? + windowPriv->pointerEventInstance(windowPriv->touchMouseDevice)->pointById(windowPriv->touchMouseId) : + windowPriv->pointerEventInstance(QQuickPointerDevice::genericMouseDevice())->point(0); + if (point) { + QQuickItem *oldGrabber = point->grabberItem(); + point->setGrabberItem(this); + windowPriv->sendUngrabEvent(oldGrabber, fromTouch); + } } /*! @@ -7430,7 +7478,7 @@ void QQuickItem::ungrabMouse() if (!d->window) return; QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window); - windowPriv->removeGrabber(this, true, false); + windowPriv->removeGrabber(this, true, windowPriv->isDeliveringTouchAsMouse()); } @@ -7560,9 +7608,75 @@ void QQuickItem::setKeepTouchGrab(bool keep) bool QQuickItem::contains(const QPointF &point) const { Q_D(const QQuickItem); - qreal x = point.x(); - qreal y = point.y(); - return x >= 0 && y >= 0 && x <= d->width && y <= d->height; + if (d->mask) { + bool res = false; + d->extra->maskContains.invoke(d->mask, + Qt::DirectConnection, + Q_RETURN_ARG(bool, res), + Q_ARG(QPointF, point)); + return res; + } else { + qreal x = point.x(); + qreal y = point.y(); + return x >= 0 && y >= 0 && x <= d->width && y <= d->height; + } +} + +/*! + \qmlproperty QObject* QtQuick::Item::containmentMask + \since 5.11 + This property holds an optional mask for the Item to be used in the + QtQuick::Item::contains method. + QtQuick::Item::contains main use is currently to determine whether + an input event has landed into the item or not. + + By default the \l contains method will return true for any point + within the Item's bounding box. \c containmentMask allows for a + more fine-grained control. For example, the developer could + define and use an AnotherItem element as containmentMask, + which has a specialized contains method, like: + + \code + Item { id: item; containmentMask: AnotherItem { id: anotherItem } } + \endcode + + \e{item}'s contains method would then return true only if + \e{anotherItem}'s contains implementation returns true. +*/ +QObject *QQuickItem::containmentMask() const +{ + Q_D(const QQuickItem); + return d->mask.data(); +} + +void QQuickItem::setContainmentMask(QObject *mask) +{ + Q_D(QQuickItem); + // an Item can't mask itself (to prevent infinite loop in contains()) + if (d->mask.data() == mask || mask == static_cast<QObject *>(this)) + return; + + QQuickItem *quickMask = qobject_cast<QQuickItem *>(d->mask); + if (quickMask) { + QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(quickMask); + maskPrivate->registerAsContainmentMask(this, false); // removed from use as my mask + } + + if (mask) { + int methodIndex = mask->metaObject()->indexOfMethod(QByteArrayLiteral("contains(QPointF)")); + if (methodIndex < 0) { + qmlWarning(this) << QStringLiteral("QQuickItem: Object set as mask does not have an invokable contains method, ignoring it."); + return; + } + d->extra.value().maskContains = mask->metaObject()->method(methodIndex); + } + d->mask = mask; + quickMask = qobject_cast<QQuickItem *>(mask); + if (quickMask) { + QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(quickMask); + maskPrivate->registerAsContainmentMask(this, true); // telling maskPrivate that "this" is using it as mask + } + emit containmentMaskChanged(); } /*! @@ -7949,7 +8063,7 @@ 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; + d->extra->layer->effectSource()->textureProvider() : nullptr; #else return 0; #endif @@ -7988,9 +8102,9 @@ QQuickItemLayer::QQuickItemLayer(QQuickItem *item) , m_wrapMode(QQuickShaderEffectSource::ClampToEdge) , m_format(QQuickShaderEffectSource::RGBA) , m_name("source") - , m_effectComponent(0) - , m_effect(0) - , m_effectSource(0) + , m_effectComponent(nullptr) + , m_effect(nullptr) + , m_effectSource(nullptr) , m_textureMirroring(QQuickShaderEffectSource::MirrorVertically) , m_samples(0) { @@ -8091,7 +8205,7 @@ void QQuickItemLayer::deactivate() deactivateEffect(); delete m_effectSource; - m_effectSource = 0; + m_effectSource = nullptr; QQuickItemPrivate *id = QQuickItemPrivate::get(m_item); id->removeItemChangeListener(this, QQuickItemPrivate::Geometry | QQuickItemPrivate::Opacity | QQuickItemPrivate::Parent | QQuickItemPrivate::Visibility | QQuickItemPrivate::SiblingOrder); @@ -8128,7 +8242,7 @@ void QQuickItemLayer::deactivateEffect() Q_ASSERT(m_effectComponent); delete m_effect; - m_effect = 0; + m_effect = nullptr; } @@ -8436,7 +8550,7 @@ 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); + Q_ASSERT(parent == nullptr || parent != m_effect); m_effectSource->setParentItem(parent); if (parent) @@ -8508,15 +8622,16 @@ void QQuickItemLayer::updateMatrix() QQuickItemPrivate::ExtraData::ExtraData() : z(0), scale(1), rotation(0), opacity(1), - contents(0), screenAttached(0), layoutDirectionAttached(0), - enterKeyAttached(0), - keyHandler(0), + contents(nullptr), screenAttached(nullptr), layoutDirectionAttached(nullptr), + enterKeyAttached(nullptr), + keyHandler(nullptr), #if QT_CONFIG(quick_shadereffect) - layer(0), + layer(nullptr), #endif effectRefCount(0), hideRefCount(0), - opacityNode(0), clipNode(0), rootNode(0), - acceptedMouseButtons(0), origin(QQuickItem::Center), + recursiveEffectRefCount(0), + opacityNode(nullptr), clipNode(nullptr), rootNode(nullptr), + acceptedMouseButtons(nullptr), origin(QQuickItem::Center), transparentForPositioner(false) { } |