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.cpp703
1 files changed, 497 insertions, 206 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index cc860c9ae3..e7b2a31f04 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -48,6 +48,8 @@
# include <QtGui/qcursor.h>
#endif
+#include <QtCore/qpointer.h>
+
#include <algorithm>
#include <limits>
@@ -86,6 +88,14 @@ void debugFocusTree(QQuickItem *item, QQuickItem *scope = nullptr, int depth = 1
}
}
+static void setActiveFocus(QQuickItem *item, Qt::FocusReason reason)
+{
+ QQuickItemPrivate *d = QQuickItemPrivate::get(item);
+ if (d->subFocusItem && d->window && d->flags & QQuickItem::ItemIsFocusScope)
+ QQuickWindowPrivate::get(d->window)->clearFocusInScope(item, d->subFocusItem, reason);
+ item->forceActiveFocus(reason);
+}
+
/*!
\qmltype Transform
\instantiates QQuickTransform
@@ -319,10 +329,10 @@ QVariant QQuickItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const
}
#endif // im
-void QQuickItemKeyFilter::shortcutOverride(QKeyEvent *event)
+void QQuickItemKeyFilter::shortcutOverrideEvent(QKeyEvent *event)
{
if (m_next)
- m_next->shortcutOverride(event);
+ m_next->shortcutOverrideEvent(event);
else
event->ignore();
}
@@ -568,14 +578,12 @@ void QQuickKeyNavigationAttached::setBacktab(QQuickItem *i)
This property determines whether the keys are processed before
or after the attached item's own key handling.
- \list
- \li KeyNavigation.BeforeItem - process the key events before normal
- item key processing. If the event is used for key navigation, it will be accepted and will not
- be passed on to the item.
- \li KeyNavigation.AfterItem (default) - process the key events after normal item key
- handling. If the item accepts the key event it will not be
- handled by the KeyNavigation attached property handler.
- \endlist
+ \value KeyNavigation.BeforeItem process the key events before normal
+ item key processing. If the event is used for key navigation, it will be accepted and
+ will not be passed on to the item.
+ \value KeyNavigation.AfterItem (default) process the key events after normal item key
+ handling. If the item accepts the key event it will not be
+ handled by the KeyNavigation attached property handler.
*/
QQuickKeyNavigationAttached::Priority QQuickKeyNavigationAttached::priority() const
{
@@ -868,14 +876,11 @@ bool QQuickKeysAttached::isConnected(const char *signalName) const
This property determines whether the keys are processed before
or after the attached item's own key handling.
- \list
- \li Keys.BeforeItem (default) - process the key events before normal
- item key processing. If the event is accepted it will not
- be passed on to the item.
- \li Keys.AfterItem - process the key events after normal item key
- handling. If the item accepts the key event it will not be
- handled by the Keys attached property handler.
- \endlist
+ \value Keys.BeforeItem (default) process the key events before normal item key processing.
+ If the event is accepted, it will not be passed on to the item.
+ \value Keys.AfterItem process the key events after normal item key handling. If the item
+ accepts the key event, it will not be handled by the
+ Keys attached property handler.
\sa {Key Handling Priorities}
*/
@@ -1385,7 +1390,7 @@ QVariant QQuickKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const
}
#endif // im
-void QQuickKeysAttached::shortcutOverride(QKeyEvent *event)
+void QQuickKeysAttached::shortcutOverrideEvent(QKeyEvent *event)
{
Q_D(QQuickKeysAttached);
QQuickKeyEvent &keyEvent = d->theKeyEvent;
@@ -1700,6 +1705,53 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
}
}
+
+bool QQuickItemPrivate::setFocusIfNeeded(QEvent::Type eventType)
+{
+ Q_Q(QQuickItem);
+ const bool setFocusOnRelease = QGuiApplication::styleHints()->setFocusOnTouchRelease();
+ Qt::FocusPolicy policy = Qt::ClickFocus;
+
+ switch (eventType) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::TouchBegin:
+ if (setFocusOnRelease)
+ return false;
+ break;
+ case QEvent::MouseButtonRelease:
+ case QEvent::TouchEnd:
+ if (!setFocusOnRelease)
+ return false;
+ break;
+ case QEvent::Wheel:
+ policy = Qt::WheelFocus;
+ break;
+ default:
+ break;
+ }
+
+ if ((focusPolicy & policy) == policy) {
+ setActiveFocus(q, Qt::MouseFocusReason);
+ return true;
+ }
+
+ return false;
+}
+
+Qt::FocusReason QQuickItemPrivate::lastFocusChangeReason() const
+{
+ return static_cast<Qt::FocusReason>(focusReason);
+}
+
+void QQuickItemPrivate::setLastFocusChangeReason(Qt::FocusReason reason)
+{
+ if (focusReason == reason)
+ return;
+
+ focusReason = reason;
+}
+
/*!
\class QQuickItem
\brief The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
@@ -2211,6 +2263,11 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
*/
/*!
+ \fn void QQuickItem::focusPolicyChanged(Qt::FocusPolicy)
+ \internal
+*/
+
+/*!
\fn void QQuickItem::activeFocusOnTabChanged(bool)
\internal
*/
@@ -2381,7 +2438,7 @@ bool QQuickItemPrivate::canAcceptTabFocus(QQuickItem *item)
return true;
#if QT_CONFIG(accessibility)
- QAccessible::Role role = QQuickItemPrivate::get(item)->accessibleRole();
+ QAccessible::Role role = QQuickItemPrivate::get(item)->effectiveAccessibleRole();
if (role == QAccessible::EditableText || role == QAccessible::Table || role == QAccessible::List) {
return true;
} else if (role == QAccessible::ComboBox || role == QAccessible::SpinBox) {
@@ -2413,12 +2470,32 @@ bool QQuickItemPrivate::canAcceptTabFocus(QQuickItem *item)
*/
bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward)
{
- QQuickItem *next = QQuickItemPrivate::nextPrevItemInTabFocusChain(item, forward);
+ QQuickWindow *window = item->window();
+ const bool wrap = !window || window->isTopLevel();
+
+ QQuickItem *next = QQuickItemPrivate::nextPrevItemInTabFocusChain(item, forward, wrap);
if (next == item)
return false;
- next->forceActiveFocus(forward ? Qt::TabFocusReason : Qt::BacktabFocusReason);
+ const auto reason = forward ? Qt::TabFocusReason : Qt::BacktabFocusReason;
+
+ if (!wrap && !next) {
+ // Focus chain wrapped and we are not top-level window
+ // Give focus to parent window
+ Q_ASSERT(window);
+ Q_ASSERT(window->parent());
+
+
+ qt_window_private(window->parent())->setFocusToTarget(
+ forward ? QWindowPrivate::FocusTarget::Next
+ : QWindowPrivate::FocusTarget::Prev,
+ reason);
+ window->parent()->requestActivate();
+ return true;
+ }
+
+ next->forceActiveFocus(reason);
return true;
}
@@ -2467,7 +2544,7 @@ QQuickItem *QQuickItemPrivate::prevTabChildItem(const QQuickItem *item, int star
return nullptr;
}
-QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, bool forward)
+QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, bool forward, bool wrap)
{
Q_ASSERT(item);
qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: item:" << item << ", forward:" << forward;
@@ -2561,6 +2638,14 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo
}
current = parent;
} else if (hasChildren) {
+ if (!wrap && (forward || firstFromItem != from)) {
+ qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain:"
+ << "Focus chain about to wrap.";
+ // If focus chain wraps, we should give the parent window
+ // a chance to get focus, so we should stop here
+ return nullptr;
+ }
+
// Wrap around after checking all items forward
if (forward) {
current = firstChild;
@@ -2806,8 +2891,8 @@ void QQuickItem::stackBefore(const QQuickItem *sibling)
parentPrivate->childItems.move(myIndex, myIndex < siblingIndex ? siblingIndex - 1 : siblingIndex);
- parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
parentPrivate->markSortedChildrenDirty(this);
+ parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
for (int ii = qMin(siblingIndex, myIndex); ii < parentPrivate->childItems.size(); ++ii)
QQuickItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
@@ -2851,8 +2936,8 @@ void QQuickItem::stackAfter(const QQuickItem *sibling)
parentPrivate->childItems.move(myIndex, myIndex > siblingIndex ? siblingIndex + 1 : siblingIndex);
- parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
parentPrivate->markSortedChildrenDirty(this);
+ parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
for (int ii = qMin(myIndex, siblingIndex + 1); ii < parentPrivate->childItems.size(); ++ii)
QQuickItemPrivate::get(parentPrivate->childItems.at(ii))->siblingOrderChanged();
@@ -3050,8 +3135,8 @@ void QQuickItemPrivate::derefWindow()
paintNode = nullptr;
for (int ii = 0; ii < childItems.size(); ++ii) {
- QQuickItem *child = childItems.at(ii);
- QQuickItemPrivate::get(child)->derefWindow();
+ if (QQuickItem *child = childItems.at(ii))
+ QQuickItemPrivate::get(child)->derefWindow();
}
dirty(Window);
@@ -3063,7 +3148,7 @@ void QQuickItemPrivate::derefWindow()
/*!
-Returns a transform that maps points from window space into item space.
+ Returns a transform that maps points from window space into item space.
*/
QTransform QQuickItemPrivate::windowToItemTransform() const
{
@@ -3072,21 +3157,21 @@ QTransform QQuickItemPrivate::windowToItemTransform() const
}
/*!
-Returns a transform that maps points from item space into window space.
+ Returns a transform that maps points from item space into window space.
*/
QTransform QQuickItemPrivate::itemToWindowTransform() const
{
// item's parent must not be itself, otherwise calling itemToWindowTransform() on it is infinite recursion
Q_ASSERT(!parentItem || QQuickItemPrivate::get(parentItem) != this);
QTransform rv = parentItem ? QQuickItemPrivate::get(parentItem)->itemToWindowTransform() : QTransform();
- itemToParentTransform(rv);
+ itemToParentTransform(&rv);
return rv;
}
/*!
-Motifies \a t with this items local transform relative to its parent.
+ Modifies \a t with this item's local transform relative to its parent.
*/
-void QQuickItemPrivate::itemToParentTransform(QTransform &t) const
+void QQuickItemPrivate::itemToParentTransform(QTransform *t) const
{
/* Read the current x and y values. As this is an internal method,
we don't care about it being usable in bindings. Instead, we
@@ -3098,21 +3183,21 @@ void QQuickItemPrivate::itemToParentTransform(QTransform &t) const
qreal x = this->x.valueBypassingBindings();
qreal y = this->y.valueBypassingBindings();
if (x || y)
- t.translate(x, y);
+ t->translate(x, y);
if (!transforms.isEmpty()) {
- QMatrix4x4 m(t);
+ QMatrix4x4 m(*t);
for (int ii = transforms.size() - 1; ii >= 0; --ii)
transforms.at(ii)->applyTo(&m);
- t = m.toTransform();
+ *t = m.toTransform();
}
if (scale() != 1. || rotation() != 0.) {
QPointF tp = computeTransformOrigin();
- t.translate(tp.x(), tp.y());
- t.scale(scale(), scale());
- t.rotate(rotation());
- t.translate(-tp.x(), -tp.y());
+ t->translate(tp.x(), tp.y());
+ t->scale(scale(), scale());
+ t->rotate(rotation());
+ t->translate(-tp.x(), -tp.y());
}
}
@@ -3201,6 +3286,8 @@ QQuickItemPrivate::QQuickItemPrivate()
, maybeHasSubsceneDeliveryAgent(true)
, subtreeTransformChangedEnabled(true)
, inDestructor(false)
+ , focusReason(Qt::OtherFocusReason)
+ , focusPolicy(Qt::NoFocus)
, dirtyAttributes(0)
, nextDirtyItem(nullptr)
, prevDirtyItem(nullptr)
@@ -3218,6 +3305,7 @@ QQuickItemPrivate::QQuickItemPrivate()
, baselineOffset(0)
, itemNodeInstance(nullptr)
, paintNode(nullptr)
+ , szPolicy(QLayoutPolicy::Fixed, QLayoutPolicy::Fixed)
{
}
@@ -3242,6 +3330,17 @@ void QQuickItemPrivate::init(QQuickItem *parent)
}
}
+QLayoutPolicy QQuickItemPrivate::sizePolicy() const
+{
+ return szPolicy;
+}
+
+void QQuickItemPrivate::setSizePolicy(const QLayoutPolicy::Policy& horizontalPolicy, const QLayoutPolicy::Policy& verticalPolicy)
+{
+ szPolicy.setHorizontalPolicy(horizontalPolicy);
+ szPolicy.setVerticalPolicy(verticalPolicy);
+}
+
void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
{
if (!o)
@@ -3251,34 +3350,15 @@ void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
if (QQuickItem *item = qmlobject_cast<QQuickItem *>(o)) {
item->setParentItem(that);
- } else {
- if (QQuickPointerHandler *pointerHandler = qmlobject_cast<QQuickPointerHandler *>(o)) {
- if (pointerHandler->parent() != that) {
- qCDebug(lcHandlerParent) << "reparenting handler" << pointerHandler << ":" << pointerHandler->parent() << "->" << that;
- pointerHandler->setParent(that);
- }
- QQuickItemPrivate::get(that)->addPointerHandler(pointerHandler);
- } else {
- QQuickWindow *thisWindow = qmlobject_cast<QQuickWindow *>(o);
- QQuickItem *item = that;
- QQuickWindow *itemWindow = that->window();
- while (!itemWindow && item && item->parentItem()) {
- item = item->parentItem();
- itemWindow = item->window();
- }
-
- if (thisWindow) {
- if (itemWindow) {
- qCDebug(lcTransient) << thisWindow << "is transient for" << itemWindow;
- thisWindow->setTransientParent(itemWindow);
- } else {
- QObject::connect(item, SIGNAL(windowChanged(QQuickWindow*)),
- thisWindow, SLOT(setTransientParent_helper(QQuickWindow*)));
- }
- }
- o->setParent(that);
- resources_append(prop, o);
+ } else if (QQuickPointerHandler *pointerHandler = qmlobject_cast<QQuickPointerHandler *>(o)) {
+ if (pointerHandler->parent() != that) {
+ qCDebug(lcHandlerParent) << "reparenting handler" << pointerHandler << ":" << pointerHandler->parent() << "->" << that;
+ pointerHandler->setParent(that);
}
+ QQuickItemPrivate::get(that)->addPointerHandler(pointerHandler);
+ } else {
+ o->setParent(that);
+ resources_append(prop, o);
}
}
@@ -3354,6 +3434,22 @@ void QQuickItemPrivate::data_clear(QQmlListProperty<QObject> *property)
children_clear(&childrenProperty);
}
+void QQuickItemPrivate::data_removeLast(QQmlListProperty<QObject> *property)
+{
+ QQuickItem *item = static_cast<QQuickItem*>(property->object);
+ QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
+
+ QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
+ if (children_count(&childrenProperty) > 0) {
+ children_removeLast(&childrenProperty);
+ return;
+ }
+
+ QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
+ if (resources_count(&resourcesProperty) > 0)
+ resources_removeLast(&resourcesProperty);
+}
+
QObject *QQuickItemPrivate::resources_at(QQmlListProperty<QObject> *prop, qsizetype index)
{
QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
@@ -3390,6 +3486,21 @@ void QQuickItemPrivate::resources_clear(QQmlListProperty<QObject> *prop)
}
}
+void QQuickItemPrivate::resources_removeLast(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.
+ QList<QObject *> *resources = &quickItemPrivate->extra->resourcesList;
+ if (resources->isEmpty())
+ return;
+
+ qmlobject_disconnect(resources->last(), QObject, SIGNAL(destroyed(QObject*)),
+ quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
+ resources->removeLast();
+ }
+}
+
QQuickItem *QQuickItemPrivate::children_at(QQmlListProperty<QQuickItem> *prop, qsizetype index)
{
QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
@@ -3425,6 +3536,14 @@ void QQuickItemPrivate::children_clear(QQmlListProperty<QQuickItem> *prop)
p->childItems.at(0)->setParentItem(nullptr);
}
+void QQuickItemPrivate::children_removeLast(QQmlListProperty<QQuickItem> *prop)
+{
+ QQuickItem *that = static_cast<QQuickItem *>(prop->object);
+ QQuickItemPrivate *p = QQuickItemPrivate::get(that);
+ if (!p->childItems.isEmpty())
+ p->childItems.last()->setParentItem(nullptr);
+}
+
qsizetype QQuickItemPrivate::visibleChildren_count(QQmlListProperty<QQuickItem> *prop)
{
QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object));
@@ -3653,10 +3772,16 @@ void QQuickItemPrivate::siblingOrderChanged()
QQmlListProperty<QObject> QQuickItemPrivate::data()
{
- return QQmlListProperty<QObject>(q_func(), nullptr, QQuickItemPrivate::data_append,
- QQuickItemPrivate::data_count,
- QQuickItemPrivate::data_at,
- QQuickItemPrivate::data_clear);
+ // Do not synthesize replace().
+ // It would be extremely expensive and wouldn't work with most methods.
+ QQmlListProperty<QObject> result;
+ result.object = q_func();
+ result.append = QQuickItemPrivate::data_append;
+ result.count = QQuickItemPrivate::data_count;
+ result.at = QQuickItemPrivate::data_at;
+ result.clear = QQuickItemPrivate::data_clear;
+ result.removeLast = QQuickItemPrivate::data_removeLast;
+ return result;
}
/*!
@@ -4021,7 +4146,7 @@ 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 \c event
+ events for an item. The event information is provided by the \a event
parameter.
\input item.qdocinc accepting-events
@@ -4029,8 +4154,9 @@ void QQuickItem::inputMethodEvent(QInputMethodEvent *event)
If you do reimplement this function, you should call the base class
implementation.
*/
-void QQuickItem::focusInEvent(QFocusEvent * /*event*/)
+void QQuickItem::focusInEvent(QFocusEvent *event)
{
+ Q_D(QQuickItem);
#if QT_CONFIG(accessibility)
if (QAccessible::isActive()) {
if (QObject *acc = QQuickAccessibleAttached::findAccessible(this)) {
@@ -4039,17 +4165,20 @@ void QQuickItem::focusInEvent(QFocusEvent * /*event*/)
}
}
#endif
+ d->setLastFocusChangeReason(event->reason());
}
/*!
This event handler can be reimplemented in a subclass to receive focus-out
- events for an item. The event information is provided by the \c event
+ events for an item. The event information is provided by the \a event
parameter.
\input item.qdocinc accepting-events
*/
-void QQuickItem::focusOutEvent(QFocusEvent * /*event*/)
+void QQuickItem::focusOutEvent(QFocusEvent *event)
{
+ Q_D(QQuickItem);
+ d->setLastFocusChangeReason(event->reason());
}
/*!
@@ -4274,7 +4403,11 @@ void QQuickItem::dropEvent(QDropEvent *event)
This method will only be called if filtersChildMouseEvents() is \c true.
Return \c true if the specified \a event should not be passed on to the
- specified child \a item, and \c false otherwise.
+ specified child \a item, and \c false otherwise. If you return \c true, you
+ should also \l {QEvent::accept()}{accept} or \l {QEvent::ignore()}{ignore}
+ the \a event, to signal if event propagation should stop or continue.
+ The \a event will, however, always be sent to all childMouseEventFilters
+ up the parent chain.
\note Despite the name, this function filters all QPointerEvent instances
during delivery to all children (typically mouse, touch, and tablet
@@ -4516,7 +4649,7 @@ void QQuickItem::ensurePolished()
}
#if QT_DEPRECATED_SINCE(6, 5)
-static bool unwrapMapFromToFromItemArgs(QQmlV4Function *args, const QQuickItem *itemForWarning, const QString &functionNameForWarning,
+static bool unwrapMapFromToFromItemArgs(QQmlV4FunctionPtr args, const QQuickItem *itemForWarning, const QString &functionNameForWarning,
QQuickItem **itemObj, qreal *x, qreal *y, qreal *w, qreal *h, bool *isRect)
{
QV4::ExecutionEngine *v4 = args->v4engine();
@@ -4613,7 +4746,7 @@ static bool unwrapMapFromToFromItemArgs(QQmlV4Function *args, const QQuickItem *
\input item.qdocinc mapping
If \a item is a \c null value, this maps the point or rect from the coordinate system of
- the root QML view.
+ the \l{Scene Coordinates}{scene}.
The versions accepting point and rect are since Qt 5.15.
*/
@@ -4622,7 +4755,7 @@ static bool unwrapMapFromToFromItemArgs(QQmlV4Function *args, const QQuickItem *
/*!
\internal
*/
-void QQuickItem::mapFromItem(QQmlV4Function *args) const
+void QQuickItem::mapFromItem(QQmlV4FunctionPtr args) const
{
QV4::ExecutionEngine *v4 = args->v4engine();
QV4::Scope scope(v4);
@@ -4671,7 +4804,7 @@ QTransform QQuickItem::itemTransform(QQuickItem *other, bool *ok) const
\input item.qdocinc mapping
If \a item is a \c null value, this maps the point or rect to the coordinate system of the
- root QML view.
+ \l{Scene Coordinates}{scene}.
The versions accepting point and rect are since Qt 5.15.
*/
@@ -4680,7 +4813,7 @@ QTransform QQuickItem::itemTransform(QQuickItem *other, bool *ok) const
/*!
\internal
*/
-void QQuickItem::mapToItem(QQmlV4Function *args) const
+void QQuickItem::mapToItem(QQmlV4FunctionPtr args) const
{
QV4::ExecutionEngine *v4 = args->v4engine();
QV4::Scope scope(v4);
@@ -4698,7 +4831,7 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const
args->setReturnValue(rv.asReturnedValue());
}
-static bool unwrapMapFromToFromGlobalArgs(QQmlV4Function *args, const QQuickItem *itemForWarning, const QString &functionNameForWarning, qreal *x, qreal *y)
+static bool unwrapMapFromToFromGlobalArgs(QQmlV4FunctionPtr args, const QQuickItem *itemForWarning, const QString &functionNameForWarning, qreal *x, qreal *y)
{
QV4::ExecutionEngine *v4 = args->v4engine();
if (args->length() != 1 && args->length() != 2) {
@@ -4756,7 +4889,7 @@ static bool unwrapMapFromToFromGlobalArgs(QQmlV4Function *args, const QQuickItem
/*!
\internal
*/
-void QQuickItem::mapFromGlobal(QQmlV4Function *args) const
+void QQuickItem::mapFromGlobal(QQmlV4FunctionPtr args) const
{
QV4::ExecutionEngine *v4 = args->v4engine();
QV4::Scope scope(v4);
@@ -4786,7 +4919,7 @@ void QQuickItem::mapFromGlobal(QQmlV4Function *args) const
/*!
\internal
*/
-void QQuickItem::mapToGlobal(QQmlV4Function *args) const
+void QQuickItem::mapToGlobal(QQmlV4FunctionPtr args) const
{
QV4::ExecutionEngine *v4 = args->v4engine();
QV4::Scope scope(v4);
@@ -4860,7 +4993,6 @@ void QQuickItem::forceActiveFocus()
void QQuickItem::forceActiveFocus(Qt::FocusReason reason)
{
- Q_D(QQuickItem);
setFocus(true, reason);
QQuickItem *parent = parentItem();
QQuickItem *scope = nullptr;
@@ -4872,14 +5004,6 @@ void QQuickItem::forceActiveFocus(Qt::FocusReason reason)
}
parent = parent->parentItem();
}
- // In certain reparenting scenarios, d->focus might be true and the scope
- // might also have focus, so that setFocus() returns early without actually
- // acquiring active focus, because it thinks it already has it. In that
- // case, try to set the DeliveryAgent's active focus. (QTBUG-89736).
- if (scope && !d->activeFocus) {
- if (auto da = d->deliveryAgentPrivate())
- da->setFocusInScope(scope, this, Qt::OtherFocusReason);
- }
}
/*!
@@ -4982,12 +5106,17 @@ void QQuickItemPrivate::dumpItemTree(int indent) const
{
Q_Q(const QQuickItem);
- qDebug().nospace().noquote() << QString(indent * 4, QLatin1Char(' ')) <<
+ const auto indentStr = QString(indent * 4, QLatin1Char(' '));
+ qDebug().nospace().noquote() << indentStr <<
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
const_cast<QQuickItem *>(q);
#else
q;
#endif
+ if (extra.isAllocated()) {
+ for (const auto handler : extra->pointerHandlers)
+ qDebug().nospace().noquote() << indentStr << u" \u26ee " << handler;
+ }
for (const QQuickItem *ch : childItems) {
auto itemPriv = QQuickItemPrivate::get(ch);
itemPriv->dumpItemTree(indent + 1);
@@ -4996,10 +5125,16 @@ void QQuickItemPrivate::dumpItemTree(int indent) const
QQmlListProperty<QObject> QQuickItemPrivate::resources()
{
- return QQmlListProperty<QObject>(q_func(), nullptr, QQuickItemPrivate::resources_append,
- QQuickItemPrivate::resources_count,
- QQuickItemPrivate::resources_at,
- QQuickItemPrivate::resources_clear);
+ // Do not synthesize replace().
+ // It would be extremely expensive and wouldn't work with most methods.
+ QQmlListProperty<QObject> result;
+ result.object = q_func();
+ result.append = QQuickItemPrivate::resources_append;
+ result.count = QQuickItemPrivate::resources_count;
+ result.at = QQuickItemPrivate::resources_at;
+ result.clear = QQuickItemPrivate::resources_clear;
+ result.removeLast = QQuickItemPrivate::resources_removeLast;
+ return result;
}
/*!
@@ -5021,11 +5156,16 @@ QQmlListProperty<QObject> QQuickItemPrivate::resources()
*/
QQmlListProperty<QQuickItem> QQuickItemPrivate::children()
{
- return QQmlListProperty<QQuickItem>(q_func(), nullptr, QQuickItemPrivate::children_append,
- QQuickItemPrivate::children_count,
- QQuickItemPrivate::children_at,
- QQuickItemPrivate::children_clear);
-
+ // Do not synthesize replace().
+ // It would be extremely expensive and wouldn't work with most methods.
+ QQmlListProperty<QQuickItem> result;
+ result.object = q_func();
+ result.append = QQuickItemPrivate::children_append;
+ result.count = QQuickItemPrivate::children_count;
+ result.at = QQuickItemPrivate::children_at;
+ result.clear = QQuickItemPrivate::children_clear;
+ result.removeLast = QQuickItemPrivate::children_removeLast;
+ return result;
}
/*!
@@ -5319,7 +5459,8 @@ bool QQuickItemPrivate::transformChanged(QQuickItem *transformedItem)
if (subtreeTransformChangedEnabled) {
// Inform the children in paint order: by the time we visit leaf items,
// they can see any consequences in their parents
- for (auto child : paintOrderChildItems())
+ const auto children = paintOrderChildItems();
+ for (QQuickItem *child : children)
childWantsIt |= QQuickItemPrivate::get(child)->transformChanged(transformedItem);
}
@@ -5337,18 +5478,35 @@ bool QQuickItemPrivate::transformChanged(QQuickItem *transformedItem)
}
// If ItemObservesViewport, clipRect() calculates the intersection with the viewport;
// so each time the item moves in the viewport, its clipnode needs to be updated.
- if (thisWantsIt && q->clip())
+ if (thisWantsIt && q->clip() && !(dirtyAttributes & QQuickItemPrivate::Clip))
dirty(QQuickItemPrivate::Clip);
return ret;
}
+/*! \internal
+ Returns the new position (proposed values for the x and y properties)
+ to which this item should be moved to compensate for the given change
+ in scale from \a startScale to \a activeScale and in rotation from
+ \a startRotation to \a activeRotation. \a centroidParentPos is the
+ point that we wish to hold in place (and then apply \a activeTranslation to),
+ in this item's parent's coordinate system. \a startPos is this item's
+ position in its parent's coordinate system when the gesture began.
+ \a activeTranslation is the amount of translation that should be added to
+ the return value, i.e. the displacement by which the centroid is expected
+ to move.
+
+ If \a activeTranslation is \c (0, 0) the centroid is to be held in place.
+ If \a activeScale is \c 1, it means scale is intended to be held constant,
+ the same as \a startScale. If \a activeRotation is \c 0, it means rotation
+ is intended to be held constant, the same as \a startRotation.
+*/
QPointF QQuickItemPrivate::adjustedPosForTransform(const QPointF &centroidParentPos,
const QPointF &startPos,
- const QVector2D &activeTranslation, //[0,0] means no additional translation from startPos
+ const QVector2D &activeTranslation,
qreal startScale,
- qreal activeScale, // 1.0 means no additional scale from startScale
+ qreal activeScale,
qreal startRotation,
- qreal activeRotation) // 0.0 means no additional rotation from startRotation
+ qreal activeRotation)
{
Q_Q(QQuickItem);
QVector3D xformOrigin(q->transformOriginPoint());
@@ -5474,6 +5632,41 @@ bool QQuickItemPrivate::filterKeyEvent(QKeyEvent *e, bool post)
return e->isAccepted();
}
+void QQuickItemPrivate::deliverPointerEvent(QEvent *event)
+{
+ Q_Q(QQuickItem);
+ const auto eventType = event->type();
+ const bool focusAccepted = setFocusIfNeeded(eventType);
+
+ switch (eventType) {
+ case QEvent::MouseButtonPress:
+ q->mousePressEvent(static_cast<QMouseEvent *>(event));
+ break;
+ case QEvent::MouseButtonRelease:
+ q->mouseReleaseEvent(static_cast<QMouseEvent *>(event));
+ break;
+ case QEvent::MouseButtonDblClick:
+ q->mouseDoubleClickEvent(static_cast<QMouseEvent *>(event));
+ break;
+#if QT_CONFIG(wheelevent)
+ case QEvent::Wheel:
+ q->wheelEvent(static_cast<QWheelEvent*>(event));
+ break;
+#endif
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ case QEvent::TouchCancel:
+ q->touchEvent(static_cast<QTouchEvent *>(event));
+ break;
+ default:
+ break;
+ }
+
+ if (focusAccepted)
+ event->accept();
+}
+
void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
{
Q_Q(QQuickItem);
@@ -5542,7 +5735,7 @@ void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e)
void QQuickItemPrivate::deliverShortcutOverrideEvent(QKeyEvent *event)
{
if (extra.isAllocated() && extra->keyHandler)
- extra->keyHandler->shortcutOverride(event);
+ extra->keyHandler->shortcutOverrideEvent(event);
else
event->ignore();
}
@@ -5945,8 +6138,8 @@ void QQuickItem::setZ(qreal v)
d->dirty(QQuickItemPrivate::ZValue);
if (d->parentItem) {
- QQuickItemPrivate::get(d->parentItem)->dirty(QQuickItemPrivate::ChildrenStackingChanged);
QQuickItemPrivate::get(d->parentItem)->markSortedChildrenDirty(this);
+ QQuickItemPrivate::get(d->parentItem)->dirty(QQuickItemPrivate::ChildrenStackingChanged);
}
emit zChanged();
@@ -6310,7 +6503,11 @@ void QQuickItem::setOpacity(qreal newOpacity)
\note This property's value is only affected by changes to this property or
the parent's \c visible property. It does not change, for example, if this
- item moves off-screen, or if the \l opacity changes to 0.
+ item moves off-screen, or if the \l opacity changes to 0. However, for
+ historical reasons, this property is true after the item's construction, even
+ if the item hasn't been added to a scene yet. Changing or reading this
+ property of an item that has not been added to a scene might not produce
+ the expected results.
\note The notification signal for this property gets emitted during destruction
of the visual parent. C++ signal handlers cannot assume that items in the
@@ -6380,9 +6577,9 @@ void QQuickItem::setVisible(bool v)
Thus, a disabled item can continue to receive hover events, even when this
property is \c false. This makes it possible to show informational feedback
(such as \l ToolTip) even when an interactive item is disabled.
- The same is also true for any \l {HoverHandlers}{QQuickHoverHandler}
+ The same is also true for any \l {HoverHandler}{HoverHandlers}
added as children of the item. A HoverHandler can, however, be
- \l{disabled}{QQuickHoverHandler::enabled} explicitly, or for example
+ \l {PointerHandler::enabled}{disabled} explicitly, or for example
be bound to the \c enabled state of the item.
\sa visible
@@ -6561,9 +6758,6 @@ QString QQuickItemPrivate::dirtyToString() const
void QQuickItemPrivate::dirty(DirtyType type)
{
Q_Q(QQuickItem);
- if (type & (TransformOrigin | Transform | BasicTransform | Position | Size))
- transformChanged(q);
-
if (!(dirtyAttributes & type) || (window && !prevDirtyItem)) {
dirtyAttributes |= type;
if (window && componentComplete) {
@@ -6571,6 +6765,8 @@ void QQuickItemPrivate::dirty(DirtyType type)
QQuickWindowPrivate::get(window)->dirtyItem(q);
}
}
+ if (type & (TransformOrigin | Transform | BasicTransform | Position | Size | Clip))
+ transformChanged(q);
}
void QQuickItemPrivate::addToDirtyList()
@@ -6666,8 +6862,18 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
switch (change) {
case QQuickItem::ItemChildAddedChange: {
q->itemChange(change, data);
- if (!subtreeTransformChangedEnabled)
- subtreeTransformChangedEnabled = true;
+ // The newly added child or any of its descendants may have
+ // ItemObservesViewport set, in which case we need to both
+ // inform the item that the transform has changed, and re-apply
+ // subtreeTransformChangedEnabled to both this item and its
+ // ancestors.
+ if (QQuickItemPrivate::get(data.item)->transformChanged(q)) {
+ if (!subtreeTransformChangedEnabled) {
+ qCDebug(lcVP) << "turned on transformChanged notification for subtree of" << q;
+ subtreeTransformChangedEnabled = true;
+ }
+ enableSubtreeChangeNotificationsForParentHierachy();
+ }
notifyChangeListeners(QQuickItemPrivate::Children, &QQuickItemChangeListener::itemChildAdded, q, data.item);
break;
}
@@ -6779,6 +6985,7 @@ void QQuickItem::setSmooth(bool smooth)
This property holds whether the item wants to be in the tab focus
chain. By default, this is set to \c false.
*/
+// TODO FOCUS: Deprecate
bool QQuickItem::activeFocusOnTab() const
{
Q_D(const QQuickItem);
@@ -6895,15 +7102,23 @@ void QQuickItem::setFlag(Flag flag, bool enabled)
else
setFlags((Flags)(d->flags & ~(quint32)flag));
- if (enabled && flag == ItemObservesViewport) {
- QQuickItem *par = parentItem();
- while (par) {
- auto parPriv = QQuickItemPrivate::get(par);
- if (!parPriv->subtreeTransformChangedEnabled)
- qCDebug(lcVP) << "turned on transformChanged notification for subtree of" << par;
- parPriv->subtreeTransformChangedEnabled = true;
- par = par->parentItem();
- }
+ // We don't return early if the flag did not change. That's useful in case
+ // we need to intentionally trigger this parent-chain traversal again.
+ if (enabled && flag == ItemObservesViewport)
+ d->enableSubtreeChangeNotificationsForParentHierachy();
+}
+
+void QQuickItemPrivate::enableSubtreeChangeNotificationsForParentHierachy()
+{
+ Q_Q(QQuickItem);
+
+ QQuickItem *par = q->parentItem();
+ while (par) {
+ auto parPriv = QQuickItemPrivate::get(par);
+ if (!parPriv->subtreeTransformChangedEnabled)
+ qCDebug(lcVP) << "turned on transformChanged notification for subtree of" << par;
+ parPriv->subtreeTransformChangedEnabled = true;
+ par = par->parentItem();
}
}
@@ -6994,15 +7209,17 @@ void QQuickItem::setX(qreal v)
if (qt_is_nan(v))
return;
- const qreal oldx = d->x;
+ const qreal oldx = d->x.valueBypassingBindings();
if (oldx == v)
return;
- d->x = v;
+ d->x.setValueBypassingBindings(v);
d->dirty(QQuickItemPrivate::Position);
- const qreal y = d->y, w = d->width, h = d->height;
+ const qreal y = d->y.valueBypassingBindings();
+ const qreal w = d->width.valueBypassingBindings();
+ const qreal h = d->height.valueBypassingBindings();
geometryChange(QRectF(v, y, w, h), QRectF(oldx, y, w, h));
}
@@ -7013,17 +7230,19 @@ void QQuickItem::setY(qreal v)
if (qt_is_nan(v))
return;
- const qreal oldy = d->y;
+ const qreal oldy = d->y.valueBypassingBindings();
if (oldy == v)
return;
- d->y = v;
+ d->y.setValueBypassingBindings(v);
d->dirty(QQuickItemPrivate::Position);
// we use v instead of d->y, as that avoid a method call
// and we have v anyway in scope
- const qreal x = d->x, w = d->width, h = d->height;
+ const qreal x = d->x.valueBypassingBindings();
+ const qreal w = d->width.valueBypassingBindings();
+ const qreal h = d->height.valueBypassingBindings();
geometryChange(QRectF(x, v, w, h), QRectF(x, oldy, w, h));
}
@@ -7033,11 +7252,12 @@ void QQuickItem::setY(qreal v)
void QQuickItem::setPosition(const QPointF &pos)
{
Q_D(QQuickItem);
- if (QPointF(d->x, d->y) == pos)
- return;
- const qreal oldx = d->x;
- const qreal oldy = d->y;
+ const qreal oldx = d->x.valueBypassingBindings();
+ const qreal oldy = d->y.valueBypassingBindings();
+
+ if (QPointF(oldx, oldy) == pos)
+ return;
/* This preserves the bindings, because that was what the code used to do
The effect of this is that you can have
@@ -7057,7 +7277,8 @@ void QQuickItem::setPosition(const QPointF &pos)
d->dirty(QQuickItemPrivate::Position);
- const qreal w = d->width, h = d->height;
+ const qreal w = d->width.valueBypassingBindings();
+ const qreal h = d->height.valueBypassingBindings();
geometryChange(QRectF(pos.x(), pos.y(), w, h), QRectF(oldx, oldy, w, h));
}
@@ -7093,15 +7314,17 @@ void QQuickItem::setWidth(qreal w)
return;
d->widthValidFlag = true;
- const qreal oldWidth = d->width;
+ const qreal oldWidth = d->width.valueBypassingBindings();
if (oldWidth == w)
return;
- d->width = w;
+ d->width.setValueBypassingBindings(w);
d->dirty(QQuickItemPrivate::Size);
- const qreal x = d->x, y = d->y, h = d->height;
+ const qreal x = d->x.valueBypassingBindings();
+ const qreal y = d->y.valueBypassingBindings();
+ const qreal h = d->height.valueBypassingBindings();
geometryChange(QRectF(x, y, w, h), QRectF(x, y, oldWidth, h));
}
@@ -7299,15 +7522,17 @@ void QQuickItem::setHeight(qreal h)
return;
d->heightValidFlag = true;
- const qreal oldHeight = d->height;
+ const qreal oldHeight = d->height.valueBypassingBindings();
if (oldHeight == h)
return;
- d->height = h;
+ d->height.setValueBypassingBindings(h);
d->dirty(QQuickItemPrivate::Size);
- const qreal x = d->x, y = d->y, w = d->width;
+ const qreal x = d->x.valueBypassingBindings();
+ const qreal y = d->y.valueBypassingBindings();
+ const qreal w = d->width.valueBypassingBindings();
geometryChange(QRectF(x, y, w, h), QRectF(x, y, w, oldHeight));
}
@@ -7411,11 +7636,11 @@ void QQuickItem::setImplicitSize(qreal w, qreal h)
const qreal oldHeight = height;
if (!wDone) {
width = w;
- d->width = w;
+ d->width.setValueBypassingBindings(w);
}
if (!hDone) {
height = h;
- d->height = h;
+ d->height.setValueBypassingBindings(h);
}
d->dirty(QQuickItemPrivate::Size);
@@ -7471,17 +7696,19 @@ void QQuickItem::setSize(const QSizeF &size)
d->heightValidFlag = true;
d->widthValidFlag = true;
- if (d->width == size.width() && d->height == size.height())
+ const qreal oldHeight = d->height.valueBypassingBindings();
+ const qreal oldWidth = d->width.valueBypassingBindings();
+
+ if (oldWidth == size.width() && oldHeight == size.height())
return;
- const qreal oldHeight = d->height;
- const qreal oldWidth = d->width;
d->height.setValueBypassingBindings(size.height());
d->width.setValueBypassingBindings(size.width());
d->dirty(QQuickItemPrivate::Size);
- const qreal x = d->x, y = d->y;
+ const qreal x = d->x.valueBypassingBindings();
+ const qreal y = d->y.valueBypassingBindings();
geometryChange(QRectF(x, y, size.width(), size.height()), QRectF(x, y, oldWidth, oldHeight));
}
@@ -7662,15 +7889,16 @@ void QQuickItem::setFocus(bool focus)
void QQuickItem::setFocus(bool focus, Qt::FocusReason reason)
{
Q_D(QQuickItem);
- if (d->focus == focus)
+ // Need to find our nearest focus scope
+ QQuickItem *scope = parentItem();
+ while (scope && !scope->isFocusScope() && scope->parentItem())
+ scope = scope->parentItem();
+
+ if (d->focus == focus && (!focus || !scope || QQuickItemPrivate::get(scope)->subFocusItem == this))
return;
bool notifyListeners = false;
if (d->window || d->parentItem) {
- // Need to find our nearest focus scope
- QQuickItem *scope = parentItem();
- while (scope && !scope->isFocusScope() && scope->parentItem())
- scope = scope->parentItem();
if (d->window) {
auto da = d->deliveryAgentPrivate();
Q_ASSERT(da);
@@ -7744,6 +7972,52 @@ QQuickItem *QQuickItem::scopedFocusItem() const
}
/*!
+ \qmlproperty enumeration QtQuick::Item::focusPolicy
+ \since 6.7
+
+ This property determines the way the item accepts focus.
+
+ \value Qt.TabFocus The item accepts focus by tabbing.
+ \value Qt.ClickFocus The item accepts focus by clicking.
+ \value Qt.StrongFocus The item accepts focus by both tabbing and clicking.
+ \value Qt.WheelFocus The item accepts focus by tabbing, clicking, and using the mouse wheel.
+ \value Qt.NoFocus The item does not accept focus.
+
+ \note This property was a member of the \l[QML]{Control} QML type in Qt 6.6 and earlier.
+*/
+/*!
+ \property QQuickItem::focusPolicy
+ \since 6.7
+
+ This property determines the way the item accepts focus.
+
+*/
+Qt::FocusPolicy QQuickItem::focusPolicy() const
+{
+ Q_D(const QQuickItem);
+ uint policy = d->focusPolicy;
+ if (activeFocusOnTab())
+ policy |= Qt::TabFocus;
+ return static_cast<Qt::FocusPolicy>(policy);
+}
+
+/*!
+ Sets the focus policy of this item to \a policy.
+
+ \sa focusPolicy()
+*/
+void QQuickItem::setFocusPolicy(Qt::FocusPolicy policy)
+{
+ Q_D(QQuickItem);
+ if (d->focusPolicy == policy)
+ return;
+
+ d->focusPolicy = policy;
+ setActiveFocusOnTab(policy & Qt::TabFocus);
+ emit focusPolicyChanged(policy);
+}
+
+/*!
Returns \c true if this item is an ancestor of \a child (i.e., if this item
is \a child's parent, or one of \a child's parent's ancestors).
@@ -8343,7 +8617,7 @@ void QQuickItem::setKeepTouchGrab(bool keep)
Returns \c true if this item contains \a point, which is in local coordinates;
returns \c false otherwise. This is the same check that is used for
hit-testing a QEventPoint during event delivery, and is affected by
- containmentMask() if it is set.
+ \l containmentMask if it is set.
*/
/*!
Returns \c true if this item contains \a point, which is in local coordinates;
@@ -8351,7 +8625,7 @@ void QQuickItem::setKeepTouchGrab(bool keep)
This function can be overridden in order to handle point collisions in items
with custom shapes. The default implementation checks whether the point is inside
- containmentMask() if it is set, or inside the bounding box otherwise.
+ \l containmentMask() if it is set, or inside the bounding box otherwise.
\note This method is used for hit-testing each QEventPoint during event
delivery, so the implementation should be kept as lightweight as possible.
@@ -8381,10 +8655,10 @@ bool QQuickItem::contains(const QPointF &point) const
\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. Its main use is currently to determine
+ \l contains() method. Its main use is currently to determine
whether a \l {QPointerEvent}{pointer event} has landed into the item or not.
- By default the \l contains method will return true for any point
+ By default the \c contains() method will return true for any point
within the Item's bounding box. \c containmentMask allows for
more fine-grained control. For example, if a custom C++
QQuickItem subclass with a specialized contains() method
@@ -8495,7 +8769,7 @@ void QQuickItem::setContainmentMask(QObject *mask)
\input item.qdocinc mapping
- If \a item is 0, this maps \a point to the coordinate system of the
+ If \a item is \nullptr, this maps \a point to the coordinate system of the
scene.
\sa {Concepts - Visual Coordinates in Qt Quick}
@@ -8503,8 +8777,13 @@ void QQuickItem::setContainmentMask(QObject *mask)
QPointF QQuickItem::mapToItem(const QQuickItem *item, const QPointF &point) const
{
QPointF p = mapToScene(point);
- if (item)
+ if (item) {
+ const QQuickWindow *itemWindow = item->window();
+ if (itemWindow != nullptr && itemWindow != window())
+ p = itemWindow->mapFromGlobal(window()->mapToGlobal(p));
+
p = item->mapFromScene(p);
+ }
return p;
}
@@ -8553,7 +8832,7 @@ QPointF QQuickItem::mapToGlobal(const QPointF &point) const
\input item.qdocinc mapping
- If \a item is 0, this maps \a rect to the coordinate system of the
+ If \a item is \nullptr, this maps \a rect to the coordinate system of the
scene.
\sa {Concepts - Visual Coordinates in Qt Quick}
@@ -8589,14 +8868,20 @@ QRectF QQuickItem::mapRectToScene(const QRectF &rect) const
\input item.qdocinc mapping
- If \a item is 0, this maps \a point from the coordinate system of the
+ If \a item is \nullptr, this maps \a point from the coordinate system of the
scene.
\sa {Concepts - Visual Coordinates in Qt Quick}
*/
QPointF QQuickItem::mapFromItem(const QQuickItem *item, const QPointF &point) const
{
- QPointF p = item?item->mapToScene(point):point;
+ QPointF p = point;
+ if (item) {
+ p = item->mapToScene(point);
+
+ if (item->window() != window())
+ p = window()->mapFromGlobal(item->window()->mapToGlobal(p));
+ }
return mapFromScene(p);
}
@@ -8656,7 +8941,7 @@ QPointF QQuickItem::mapFromGlobal(const QPointF &point) const
\input item.qdocinc mapping
- If \a item is 0, this maps \a rect from the coordinate system of the
+ If \a item is \nullptr, this maps \a rect from the coordinate system of the
scene.
\sa {Concepts - Visual Coordinates in Qt Quick}
@@ -8764,8 +9049,14 @@ bool QQuickItem::event(QEvent *ev)
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
case QEvent::TouchCancel:
- touchEvent(static_cast<QTouchEvent*>(ev));
- break;
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+#if QT_CONFIG(wheelevent)
+ case QEvent::Wheel:
+#endif
+ d->deliverPointerEvent(ev);
+ break;
case QEvent::StyleAnimationUpdate:
if (isVisible()) {
ev->accept();
@@ -8797,20 +9088,6 @@ bool QQuickItem::event(QEvent *ev)
case QEvent::MouseMove:
mouseMoveEvent(static_cast<QMouseEvent*>(ev));
break;
- case QEvent::MouseButtonPress:
- mousePressEvent(static_cast<QMouseEvent*>(ev));
- break;
- case QEvent::MouseButtonRelease:
- mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
- break;
- case QEvent::MouseButtonDblClick:
- mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
- break;
-#if QT_CONFIG(wheelevent)
- case QEvent::Wheel:
- wheelEvent(static_cast<QWheelEvent*>(ev));
- break;
-#endif
#if QT_CONFIG(quick_draganddrop)
case QEvent::DragEnter:
dragEnterEvent(static_cast<QDragEnterEvent*>(ev));
@@ -8870,6 +9147,16 @@ QDebug operator<<(QDebug debug,
const QRectF rect(item->position(), QSizeF(item->width(), item->height()));
debug << item->metaObject()->className() << '(' << static_cast<void *>(item);
+
+ // Deferred properties will cause recursion when calling nameForObject
+ // before the component is completed, so guard against this situation.
+ if (item->isComponentComplete()) {
+ if (QQmlContext *context = qmlContext(item)) {
+ const auto objectId = context->nameForObject(item);
+ if (!objectId.isEmpty())
+ debug << ", id=" << objectId;
+ }
+ }
if (!item->objectName().isEmpty())
debug << ", name=" << item->objectName();
debug << ", parent=" << static_cast<void *>(item->parentItem())
@@ -9030,12 +9317,12 @@ void QQuickItemPrivate::localizedTouchEvent(const QTouchEvent *event, bool isFil
bool hasAnotherGrabber = pointGrabber && pointGrabber != q;
// if there's no exclusive grabber, look for passive grabbers during filtering
if (isFiltering && !pointGrabber) {
- auto pg = event->passiveGrabbers(p);
+ const auto pg = event->passiveGrabbers(p);
if (!pg.isEmpty()) {
// It seems unlikely to have multiple passive grabbers of one eventpoint with different grandparents.
// So hopefully if we start from one passive grabber and go up the parent chain from there,
// we will find any filtering parent items that exist.
- auto handler = qmlobject_cast<QQuickPointerHandler *>(pg.first());
+ auto handler = qmlobject_cast<QQuickPointerHandler *>(pg.constFirst());
if (handler)
pointGrabber = handler->parentItem();
}
@@ -9368,14 +9655,12 @@ void QQuickItemLayer::setMipmap(bool mipmap)
Modifying this property makes most sense when the \a layer.effect is also
specified.
- \list
- \li ShaderEffectSource.RGBA8
- \li ShaderEffectSource.RGBA16F
- \li ShaderEffectSource.RGBA32F
- \li ShaderEffectSource.Alpha - Starting with Qt 6.0, this value is not in use and has the same effect as RGBA8 in practice.
- \li ShaderEffectSource.RGB - Starting with Qt 6.0, this value is not in use and has the same effect as RGBA8 in practice.
- \li ShaderEffectSource.RGBA - Starting with Qt 6.0, this value is not in use and has the same effect as RGBA8 in practice.
- \endlist
+ \value ShaderEffectSource.RGBA8
+ \value ShaderEffectSource.RGBA16F
+ \value ShaderEffectSource.RGBA32F
+ \value ShaderEffectSource.Alpha Starting with Qt 6.0, this value is not in use and has the same effect as \c RGBA8 in practice.
+ \value ShaderEffectSource.RGB Starting with Qt 6.0, this value is not in use and has the same effect as \c RGBA8 in practice.
+ \value ShaderEffectSource.RGBA Starting with Qt 6.0, this value is not in use and has the same effect as \c RGBA8 in practice.
\sa {Item Layers}
*/
@@ -9496,12 +9781,10 @@ void QQuickItemLayer::setSize(const QSize &size)
Modifying this property makes most sense when the \a layer.effect is
specified.
- \list
- \li ShaderEffectSource.ClampToEdge - GL_CLAMP_TO_EDGE both horizontally and vertically
- \li ShaderEffectSource.RepeatHorizontally - GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically
- \li ShaderEffectSource.RepeatVertically - GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically
- \li ShaderEffectSource.Repeat - GL_REPEAT both horizontally and vertically
- \endlist
+ \value ShaderEffectSource.ClampToEdge GL_CLAMP_TO_EDGE both horizontally and vertically
+ \value ShaderEffectSource.RepeatHorizontally GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically
+ \value ShaderEffectSource.RepeatVertically GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically
+ \value ShaderEffectSource.Repeat GL_REPEAT both horizontally and vertically
\note Some OpenGL ES 2 implementations do not support the GL_REPEAT
wrap mode with non-power-of-two textures.
@@ -9531,11 +9814,9 @@ void QQuickItemLayer::setWrapMode(QQuickShaderEffectSource::WrapMode mode)
such as those specified by ShaderEffect. If no effect is specified for the layered
item, mirroring has no effect on the UI representation of the item.
- \list
- \li ShaderEffectSource.NoMirroring - No mirroring
- \li ShaderEffectSource.MirrorHorizontally - The generated texture is flipped along X-axis.
- \li ShaderEffectSource.MirrorVertically - The generated texture is flipped along Y-axis.
- \endlist
+ \value ShaderEffectSource.NoMirroring No mirroring
+ \value ShaderEffectSource.MirrorHorizontally The generated texture is flipped along X-axis.
+ \value ShaderEffectSource.MirrorVertically The generated texture is flipped along Y-axis.
*/
void QQuickItemLayer::setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring)
@@ -9721,13 +10002,20 @@ QQuickItemPrivate::ExtraData::ExtraData()
#if QT_CONFIG(accessibility)
-QAccessible::Role QQuickItemPrivate::accessibleRole() const
+QAccessible::Role QQuickItemPrivate::effectiveAccessibleRole() const
{
Q_Q(const QQuickItem);
- QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, false));
- if (accessibleAttached)
- return accessibleAttached->role();
+ auto *attached = qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, false);
+ auto role = QAccessible::NoRole;
+ if (auto *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(attached))
+ role = accessibleAttached->role();
+ if (role == QAccessible::NoRole)
+ role = accessibleRole();
+ return role;
+}
+QAccessible::Role QQuickItemPrivate::accessibleRole() const
+{
return QAccessible::NoRole;
}
#endif
@@ -9758,7 +10046,7 @@ void QV4::Heap::QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::MarkS
QObjectWrapper::markObjects(that, markStack);
}
-quint64 QQuickItemPrivate::_q_createJSWrapper(QV4::ExecutionEngine *engine)
+quint64 QQuickItemPrivate::_q_createJSWrapper(QQmlV4ExecutionEnginePtr engine)
{
return (engine->memoryManager->allocate<QQuickItemWrapper>(q_func()))->asReturnedValue();
}
@@ -9802,6 +10090,9 @@ QPointF QQuickItem::mapToGlobal(qreal x, qreal y) const
QPointF QQuickItem::mapFromGlobal(qreal x, qreal y) const
{ return mapFromGlobal(QPointF(x, y)); }
+//! \internal
+QQuickItemChangeListener::~QQuickItemChangeListener() = default;
+
QT_END_NAMESPACE
#include <moc_qquickitem.cpp>