1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquickitem.h"
5
6#include "qquickwindow.h"
7#include "qquickrendercontrol.h"
8#include <QtQml/qjsengine.h>
9#include "qquickwindow_p.h"
10
11#include "qquickevents_p_p.h"
12#include "qquickscreen_p.h"
13#include "qquicksafearea_p.h"
14
15#include <QtQml/qqmlengine.h>
16#include <QtQml/qqmlcomponent.h>
17#include <QtQml/qqmlinfo.h>
18#include <QtGui/qpen.h>
19#include <QtGui/qguiapplication.h>
20#include <QtGui/qstylehints.h>
21#include <QtGui/private/qeventpoint_p.h>
22#include <QtGui/private/qguiapplication_p.h>
23#include <QtGui/private/qpointingdevice_p.h>
24#include <QtGui/qinputmethod.h>
25#include <QtCore/qcoreevent.h>
26#include <QtCore/private/qnumeric_p.h>
27#include <QtGui/qpa/qplatformtheme.h>
28#include <QtCore/qloggingcategory.h>
29#include <QtCore/private/qduplicatetracker_p.h>
30
31#include <private/qqmlglobal_p.h>
32#include <private/qqmlengine_p.h>
33#include <QtQuick/private/qquickstategroup_p.h>
34#include <private/qqmlopenmetaobject_p.h>
35#include <QtQuick/private/qquickstate_p.h>
36#include <private/qquickitem_p.h>
37#include <QtQuick/private/qquickaccessibleattached_p.h>
38#include <QtQuick/private/qquickhoverhandler_p.h>
39#include <QtQuick/private/qquickpointerhandler_p.h>
40#include <QtQuick/private/qquickpointerhandler_p_p.h>
41
42#include <private/qv4engine_p.h>
43#include <private/qv4object_p.h>
44#include <private/qv4qobjectwrapper_p.h>
45#include <private/qdebug_p.h>
46#include <private/qqmlvaluetypewrapper_p.h>
47
48#if QT_CONFIG(cursor)
49# include <QtGui/qcursor.h>
50#endif
51
52#include <QtCore/qpointer.h>
53
54#include <algorithm>
55#include <limits>
56
57// XXX todo Check that elements that create items handle memory correctly after visual ownership change
58
59QT_BEGIN_NAMESPACE
60
61Q_LOGGING_CATEGORY(lcHandlerParent, "qt.quick.handler.parent")
62Q_LOGGING_CATEGORY(lcVP, "qt.quick.viewport")
63Q_STATIC_LOGGING_CATEGORY(lcChangeListeners, "qt.quick.item.changelisteners")
64
65// after 100ms, a mouse/non-mouse cursor conflict is resolved in favor of the mouse handler
66static const quint64 kCursorOverrideTimeout = 100;
67
68void debugFocusTree(QQuickItem *item, QQuickItem *scope = nullptr, int depth = 1)
69{
70 if (lcFocus().isEnabled(type: QtDebugMsg)) {
71 qCDebug(lcFocus)
72 << QByteArray(depth, '\t').constData()
73 << (scope && QQuickItemPrivate::get(item: scope)->subFocusItem == item ? '*' : ' ')
74 << item->hasFocus()
75 << item->hasActiveFocus()
76 << item->isFocusScope()
77 << item;
78 const auto childItems = item->childItems();
79 for (QQuickItem *child : childItems) {
80 debugFocusTree(
81 item: child,
82 scope: item->isFocusScope() || !scope ? item : scope,
83 depth: item->isFocusScope() || !scope ? depth + 1 : depth);
84 }
85 }
86}
87
88static void setActiveFocus(QQuickItem *item, Qt::FocusReason reason)
89{
90 QQuickItemPrivate *d = QQuickItemPrivate::get(item);
91 if (d->subFocusItem && d->window && d->flags & QQuickItem::ItemIsFocusScope)
92 d->deliveryAgentPrivate()->clearFocusInScope(scope: item, item: d->subFocusItem, reason);
93 item->forceActiveFocus(reason);
94}
95
96/*!
97 \qmltype Transform
98 \nativetype QQuickTransform
99 \inqmlmodule QtQuick
100 \ingroup qtquick-visual-transforms
101 \brief For specifying advanced transformations on Items.
102
103 The Transform type is a base type which cannot be instantiated directly.
104 The following concrete Transform types are available:
105
106 \list
107 \li \l Rotation
108 \li \l Scale
109 \li \l Translate
110 \li \l Shear
111 \li \l Matrix4x4
112 \endlist
113
114 The Transform types let you create and control advanced transformations that can be configured
115 independently using specialized properties.
116
117 You can assign any number of Transforms to an \l Item. Each Transform is applied in order,
118 one at a time.
119*/
120QQuickTransformPrivate::QQuickTransformPrivate()
121{
122}
123
124QQuickTransform::QQuickTransform(QObject *parent)
125: QObject(*(new QQuickTransformPrivate), parent)
126{
127}
128
129QQuickTransform::QQuickTransform(QQuickTransformPrivate &dd, QObject *parent)
130: QObject(dd, parent)
131{
132}
133
134QQuickTransform::~QQuickTransform()
135{
136 Q_D(QQuickTransform);
137 for (int ii = 0; ii < d->items.size(); ++ii) {
138 QQuickItemPrivate *p = QQuickItemPrivate::get(item: d->items.at(i: ii));
139 p->transforms.removeOne(t: this);
140 p->dirty(QQuickItemPrivate::Transform);
141 }
142}
143
144void QQuickTransform::update()
145{
146 Q_D(QQuickTransform);
147 for (int ii = 0; ii < d->items.size(); ++ii) {
148 QQuickItemPrivate *p = QQuickItemPrivate::get(item: d->items.at(i: ii));
149 p->dirty(QQuickItemPrivate::Transform);
150 }
151}
152
153QQuickContents::QQuickContents(QQuickItem *item)
154: m_item(item)
155{
156}
157
158QQuickContents::~QQuickContents()
159{
160 inDestructor = true;
161 QList<QQuickItem *> children = m_item->childItems();
162 for (int i = 0; i < children.size(); ++i) {
163 QQuickItem *child = children.at(i);
164 QQuickItemPrivate::get(item: child)->removeItemChangeListener(this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
165 }
166}
167
168bool QQuickContents::calcHeight(QQuickItem *changed)
169{
170 qreal oldy = m_contents.y();
171 qreal oldheight = m_contents.height();
172
173 if (changed) {
174 qreal top = oldy;
175 qreal bottom = oldy + oldheight;
176 qreal y = changed->y();
177 if (y + changed->height() > bottom)
178 bottom = y + changed->height();
179 if (y < top)
180 top = y;
181 m_contents.setY(top);
182 m_contents.setHeight(bottom - top);
183 } else {
184 qreal top = std::numeric_limits<qreal>::max();
185 qreal bottom = -std::numeric_limits<qreal>::max();
186 QList<QQuickItem *> children = m_item->childItems();
187 for (int i = 0; i < children.size(); ++i) {
188 QQuickItem *child = children.at(i);
189 qreal y = child->y();
190 if (y + child->height() > bottom)
191 bottom = y + child->height();
192 if (y < top)
193 top = y;
194 }
195 if (!children.isEmpty())
196 m_contents.setY(top);
197 m_contents.setHeight(qMax(a: bottom - top, b: qreal(0.0)));
198 }
199
200 return (m_contents.height() != oldheight || m_contents.y() != oldy);
201}
202
203bool QQuickContents::calcWidth(QQuickItem *changed)
204{
205 qreal oldx = m_contents.x();
206 qreal oldwidth = m_contents.width();
207
208 if (changed) {
209 qreal left = oldx;
210 qreal right = oldx + oldwidth;
211 qreal x = changed->x();
212 if (x + changed->width() > right)
213 right = x + changed->width();
214 if (x < left)
215 left = x;
216 m_contents.setX(left);
217 m_contents.setWidth(right - left);
218 } else {
219 qreal left = std::numeric_limits<qreal>::max();
220 qreal right = -std::numeric_limits<qreal>::max();
221 QList<QQuickItem *> children = m_item->childItems();
222 for (int i = 0; i < children.size(); ++i) {
223 QQuickItem *child = children.at(i);
224 qreal x = child->x();
225 if (x + child->width() > right)
226 right = x + child->width();
227 if (x < left)
228 left = x;
229 }
230 if (!children.isEmpty())
231 m_contents.setX(left);
232 m_contents.setWidth(qMax(a: right - left, b: qreal(0.0)));
233 }
234
235 return (m_contents.width() != oldwidth || m_contents.x() != oldx);
236}
237
238void QQuickContents::complete()
239{
240 QQuickItemPrivate::get(item: m_item)->addItemChangeListener(listener: this, types: QQuickItemPrivate::Children);
241
242 QList<QQuickItem *> children = m_item->childItems();
243 for (int i = 0; i < children.size(); ++i) {
244 QQuickItem *child = children.at(i);
245 QQuickItemPrivate::get(item: child)->addItemChangeListener(listener: this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
246 //###what about changes to visibility?
247 }
248 calcGeometry();
249}
250
251void QQuickContents::updateRect()
252{
253 QQuickItemPrivate::get(item: m_item)->emitChildrenRectChanged(rect: rectF());
254}
255
256void QQuickContents::itemGeometryChanged(QQuickItem *changed, QQuickGeometryChange change, const QRectF &)
257{
258 Q_UNUSED(changed);
259 bool wChanged = false;
260 bool hChanged = false;
261 //### we can only pass changed if the left edge has moved left, or the right edge has moved right
262 if (change.horizontalChange())
263 wChanged = calcWidth(/*changed*/);
264 if (change.verticalChange())
265 hChanged = calcHeight(/*changed*/);
266 if (wChanged || hChanged)
267 updateRect();
268}
269
270void QQuickContents::itemDestroyed(QQuickItem *item)
271{
272 if (item)
273 QQuickItemPrivate::get(item)->removeItemChangeListener(this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
274 calcGeometry();
275}
276
277void QQuickContents::itemChildRemoved(QQuickItem *, QQuickItem *item)
278{
279 if (item)
280 QQuickItemPrivate::get(item)->removeItemChangeListener(this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
281 calcGeometry();
282}
283
284void QQuickContents::itemChildAdded(QQuickItem *, QQuickItem *item)
285{
286 if (item)
287 QQuickItemPrivate::get(item)->addItemChangeListener(listener: this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
288 calcGeometry(changed: item);
289}
290
291QQuickItemKeyFilter::QQuickItemKeyFilter(QQuickItem *item)
292: m_processPost(false), m_next(nullptr)
293{
294 QQuickItemPrivate *p = item?QQuickItemPrivate::get(item):nullptr;
295 if (p) {
296 m_next = p->extra.value().keyHandler;
297 p->extra->keyHandler = this;
298 }
299}
300
301QQuickItemKeyFilter::~QQuickItemKeyFilter()
302{
303}
304
305void QQuickItemKeyFilter::keyPressed(QKeyEvent *event, bool post)
306{
307 if (m_next) m_next->keyPressed(event, post);
308}
309
310void QQuickItemKeyFilter::keyReleased(QKeyEvent *event, bool post)
311{
312 if (m_next) m_next->keyReleased(event, post);
313}
314
315#if QT_CONFIG(im)
316void QQuickItemKeyFilter::inputMethodEvent(QInputMethodEvent *event, bool post)
317{
318 if (m_next)
319 m_next->inputMethodEvent(event, post);
320 else
321 event->ignore();
322}
323
324QVariant QQuickItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const
325{
326 if (m_next) return m_next->inputMethodQuery(query);
327 return QVariant();
328}
329#endif // im
330
331void QQuickItemKeyFilter::shortcutOverrideEvent(QKeyEvent *event)
332{
333 if (m_next)
334 m_next->shortcutOverrideEvent(event);
335 else
336 event->ignore();
337}
338
339void QQuickItemKeyFilter::componentComplete()
340{
341 if (m_next) m_next->componentComplete();
342}
343/*!
344 \qmltype KeyNavigation
345 \nativetype QQuickKeyNavigationAttached
346 \inqmlmodule QtQuick
347 \ingroup qtquick-input-handlers
348 \brief Supports key navigation by arrow keys.
349
350 Key-based user interfaces commonly allow the use of arrow keys to navigate between
351 focusable items. The KeyNavigation attaching type enables this behavior by providing a
352 convenient way to specify the item that should gain focus when an arrow or tab key is pressed.
353
354 The following example provides key navigation for a 2x2 grid of items:
355
356 \snippet qml/keynavigation.qml 0
357
358 The top-left item initially receives focus by setting \l {Item::}{focus} to
359 \c true. When an arrow key is pressed, the focus will move to the
360 appropriate item, as defined by the value that has been set for
361 the KeyNavigation \l left, \l right, \l up or \l down properties.
362
363 Note that if a KeyNavigation attaching type receives the key press and release
364 events for a requested arrow or tab key, the event is accepted and does not
365 propagate any further.
366
367 By default, KeyNavigation receives key events after the item to which it is attached.
368 If the item accepts the key event, the KeyNavigation attaching type will not
369 receive an event for that key. Setting the \l priority property to
370 \c KeyNavigation.BeforeItem allows the event to be used for key navigation
371 before the item, rather than after.
372
373 If the item to which the focus is switching is not enabled or visible, an attempt will
374 be made to skip this item and focus on the next. This is possible if there are
375 a chain of items with the same KeyNavigation handler. If multiple items in a row are not enabled
376 or visible, they will also be skipped.
377
378 KeyNavigation will implicitly set the other direction to return focus to this item. So if you set
379 \l left to another item, \l right will be set on that item's KeyNavigation to set focus back to this
380 item. However, if that item's KeyNavigation has had right explicitly set then no change will occur.
381 This means that the example above could achieve the same behavior without specifying
382 KeyNavigation.right or KeyNavigation.down for any of the items.
383
384 \sa {Keys}{Keys attached property}
385*/
386
387/*!
388 \qmlattachedproperty Item QtQuick::KeyNavigation::left
389
390 This property holds the item to assign focus to
391 when the left cursor key is pressed.
392*/
393
394/*!
395 \qmlattachedproperty Item QtQuick::KeyNavigation::right
396
397 This property holds the item to assign focus to
398 when the right cursor key is pressed.
399*/
400
401/*!
402 \qmlattachedproperty Item QtQuick::KeyNavigation::up
403
404 This property holds the item to assign focus to
405 when the up cursor key is pressed.
406*/
407
408/*!
409 \qmlattachedproperty Item QtQuick::KeyNavigation::down
410
411 This property holds the item to assign focus to
412 when the down cursor key is pressed.
413*/
414
415/*!
416 \qmlattachedproperty Item QtQuick::KeyNavigation::tab
417
418 This property holds the item to assign focus to
419 when the Tab key is pressed.
420*/
421
422/*!
423 \qmlattachedproperty Item QtQuick::KeyNavigation::backtab
424
425 This property holds the item to assign focus to
426 when the Shift+Tab key combination (Backtab) is pressed.
427*/
428
429QQuickKeyNavigationAttached::QQuickKeyNavigationAttached(QObject *parent)
430: QObject(*(new QQuickKeyNavigationAttachedPrivate), parent),
431 QQuickItemKeyFilter(qmlobject_cast<QQuickItem*>(object: parent))
432{
433 m_processPost = true;
434}
435
436QQuickKeyNavigationAttached *
437QQuickKeyNavigationAttached::qmlAttachedProperties(QObject *obj)
438{
439 return new QQuickKeyNavigationAttached(obj);
440}
441
442QQuickItem *QQuickKeyNavigationAttached::left() const
443{
444 Q_D(const QQuickKeyNavigationAttached);
445 return d->left;
446}
447
448void QQuickKeyNavigationAttached::setLeft(QQuickItem *i)
449{
450 Q_D(QQuickKeyNavigationAttached);
451 if (d->leftSet && d->left == i)
452 return;
453 d->leftSet = d->left != i;
454 d->left = i;
455 QQuickKeyNavigationAttached* other =
456 qobject_cast<QQuickKeyNavigationAttached*>(object: qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: i));
457 if (other && !other->d_func()->rightSet){
458 other->d_func()->right = qobject_cast<QQuickItem*>(o: parent());
459 emit other->rightChanged();
460 }
461 emit leftChanged();
462}
463
464QQuickItem *QQuickKeyNavigationAttached::right() const
465{
466 Q_D(const QQuickKeyNavigationAttached);
467 return d->right;
468}
469
470void QQuickKeyNavigationAttached::setRight(QQuickItem *i)
471{
472 Q_D(QQuickKeyNavigationAttached);
473 if (d->rightSet && d->right == i)
474 return;
475 d->rightSet = d->right != i;
476 d->right = i;
477 QQuickKeyNavigationAttached* other =
478 qobject_cast<QQuickKeyNavigationAttached*>(object: qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: i));
479 if (other && !other->d_func()->leftSet){
480 other->d_func()->left = qobject_cast<QQuickItem*>(o: parent());
481 emit other->leftChanged();
482 }
483 emit rightChanged();
484}
485
486QQuickItem *QQuickKeyNavigationAttached::up() const
487{
488 Q_D(const QQuickKeyNavigationAttached);
489 return d->up;
490}
491
492void QQuickKeyNavigationAttached::setUp(QQuickItem *i)
493{
494 Q_D(QQuickKeyNavigationAttached);
495 if (d->upSet && d->up == i)
496 return;
497 d->upSet = d->up != i;
498 d->up = i;
499 QQuickKeyNavigationAttached* other =
500 qobject_cast<QQuickKeyNavigationAttached*>(object: qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: i));
501 if (other && !other->d_func()->downSet){
502 other->d_func()->down = qobject_cast<QQuickItem*>(o: parent());
503 emit other->downChanged();
504 }
505 emit upChanged();
506}
507
508QQuickItem *QQuickKeyNavigationAttached::down() const
509{
510 Q_D(const QQuickKeyNavigationAttached);
511 return d->down;
512}
513
514void QQuickKeyNavigationAttached::setDown(QQuickItem *i)
515{
516 Q_D(QQuickKeyNavigationAttached);
517 if (d->downSet && d->down == i)
518 return;
519 d->downSet = d->down != i;
520 d->down = i;
521 QQuickKeyNavigationAttached* other =
522 qobject_cast<QQuickKeyNavigationAttached*>(object: qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: i));
523 if (other && !other->d_func()->upSet) {
524 other->d_func()->up = qobject_cast<QQuickItem*>(o: parent());
525 emit other->upChanged();
526 }
527 emit downChanged();
528}
529
530QQuickItem *QQuickKeyNavigationAttached::tab() const
531{
532 Q_D(const QQuickKeyNavigationAttached);
533 return d->tab;
534}
535
536void QQuickKeyNavigationAttached::setTab(QQuickItem *i)
537{
538 Q_D(QQuickKeyNavigationAttached);
539 if (d->tabSet && d->tab == i)
540 return;
541 d->tabSet = d->tab != i;
542 d->tab = i;
543 QQuickKeyNavigationAttached* other =
544 qobject_cast<QQuickKeyNavigationAttached*>(object: qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: i));
545 if (other && !other->d_func()->backtabSet) {
546 other->d_func()->backtab = qobject_cast<QQuickItem*>(o: parent());
547 emit other->backtabChanged();
548 }
549 emit tabChanged();
550}
551
552QQuickItem *QQuickKeyNavigationAttached::backtab() const
553{
554 Q_D(const QQuickKeyNavigationAttached);
555 return d->backtab;
556}
557
558void QQuickKeyNavigationAttached::setBacktab(QQuickItem *i)
559{
560 Q_D(QQuickKeyNavigationAttached);
561 if (d->backtabSet && d->backtab == i)
562 return;
563 d->backtabSet = d->backtab != i;
564 d->backtab = i;
565 QQuickKeyNavigationAttached* other =
566 qobject_cast<QQuickKeyNavigationAttached*>(object: qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: i));
567 if (other && !other->d_func()->tabSet) {
568 other->d_func()->tab = qobject_cast<QQuickItem*>(o: parent());
569 emit other->tabChanged();
570 }
571 emit backtabChanged();
572}
573
574/*!
575 \qmlattachedproperty enumeration QtQuick::KeyNavigation::priority
576
577 This property determines whether the keys are processed before
578 or after the attached item's own key handling.
579
580 \value KeyNavigation.BeforeItem process the key events before normal
581 item key processing. If the event is used for key navigation, it will be accepted and
582 will not be passed on to the item.
583 \value KeyNavigation.AfterItem (default) process the key events after normal item key
584 handling. If the item accepts the key event it will not be
585 handled by the KeyNavigation attached property handler.
586*/
587QQuickKeyNavigationAttached::Priority QQuickKeyNavigationAttached::priority() const
588{
589 return m_processPost ? AfterItem : BeforeItem;
590}
591
592void QQuickKeyNavigationAttached::setPriority(Priority order)
593{
594 bool processPost = order == AfterItem;
595 if (processPost != m_processPost) {
596 m_processPost = processPost;
597 emit priorityChanged();
598 }
599}
600
601void QQuickKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post)
602{
603 Q_D(QQuickKeyNavigationAttached);
604 event->ignore();
605
606 if (post != m_processPost) {
607 QQuickItemKeyFilter::keyPressed(event, post);
608 return;
609 }
610
611 bool mirror = false;
612 switch (event->key()) {
613 case Qt::Key_Left: {
614 if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(o: parent()))
615 mirror = QQuickItemPrivate::get(item: parentItem)->effectiveLayoutMirror;
616 QQuickItem* leftItem = mirror ? d->right : d->left;
617 if (leftItem) {
618 setFocusNavigation(currentItem: leftItem, dir: mirror ? "right" : "left", reason: mirror ? Qt::TabFocusReason : Qt::BacktabFocusReason);
619 event->accept();
620 }
621 break;
622 }
623 case Qt::Key_Right: {
624 if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(o: parent()))
625 mirror = QQuickItemPrivate::get(item: parentItem)->effectiveLayoutMirror;
626 QQuickItem* rightItem = mirror ? d->left : d->right;
627 if (rightItem) {
628 setFocusNavigation(currentItem: rightItem, dir: mirror ? "left" : "right", reason: mirror ? Qt::BacktabFocusReason : Qt::TabFocusReason);
629 event->accept();
630 }
631 break;
632 }
633 case Qt::Key_Up:
634 if (d->up) {
635 setFocusNavigation(currentItem: d->up, dir: "up", reason: Qt::BacktabFocusReason);
636 event->accept();
637 }
638 break;
639 case Qt::Key_Down:
640 if (d->down) {
641 setFocusNavigation(currentItem: d->down, dir: "down", reason: Qt::TabFocusReason);
642 event->accept();
643 }
644 break;
645 case Qt::Key_Tab:
646 if (d->tab) {
647 setFocusNavigation(currentItem: d->tab, dir: "tab", reason: Qt::TabFocusReason);
648 event->accept();
649 }
650 break;
651 case Qt::Key_Backtab:
652 if (d->backtab) {
653 setFocusNavigation(currentItem: d->backtab, dir: "backtab", reason: Qt::BacktabFocusReason);
654 event->accept();
655 }
656 break;
657 default:
658 break;
659 }
660
661 if (!event->isAccepted()) QQuickItemKeyFilter::keyPressed(event, post);
662}
663
664void QQuickKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post)
665{
666 Q_D(QQuickKeyNavigationAttached);
667 event->ignore();
668
669 if (post != m_processPost) {
670 QQuickItemKeyFilter::keyReleased(event, post);
671 return;
672 }
673
674 bool mirror = false;
675 switch (event->key()) {
676 case Qt::Key_Left:
677 if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(o: parent()))
678 mirror = QQuickItemPrivate::get(item: parentItem)->effectiveLayoutMirror;
679 if (mirror ? d->right : d->left)
680 event->accept();
681 break;
682 case Qt::Key_Right:
683 if (QQuickItem *parentItem = qobject_cast<QQuickItem*>(o: parent()))
684 mirror = QQuickItemPrivate::get(item: parentItem)->effectiveLayoutMirror;
685 if (mirror ? d->left : d->right)
686 event->accept();
687 break;
688 case Qt::Key_Up:
689 if (d->up) {
690 event->accept();
691 }
692 break;
693 case Qt::Key_Down:
694 if (d->down) {
695 event->accept();
696 }
697 break;
698 case Qt::Key_Tab:
699 if (d->tab) {
700 event->accept();
701 }
702 break;
703 case Qt::Key_Backtab:
704 if (d->backtab) {
705 event->accept();
706 }
707 break;
708 default:
709 break;
710 }
711
712 if (!event->isAccepted()) QQuickItemKeyFilter::keyReleased(event, post);
713}
714
715void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, const char *dir,
716 Qt::FocusReason reason)
717{
718 QQuickItem *initialItem = currentItem;
719 bool isNextItem = false;
720 QVector<QQuickItem *> visitedItems;
721 do {
722 isNextItem = false;
723 if (currentItem->isVisible() && currentItem->isEnabled()) {
724 currentItem->forceActiveFocus(reason);
725 } else {
726 QObject *attached =
727 qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(obj: currentItem, create: false);
728 if (attached) {
729 QQuickItem *tempItem = qvariant_cast<QQuickItem*>(v: attached->property(name: dir));
730 if (tempItem) {
731 visitedItems.append(t: currentItem);
732 currentItem = tempItem;
733 isNextItem = true;
734 }
735 }
736 }
737 }
738 while (currentItem != initialItem && isNextItem && !visitedItems.contains(t: currentItem));
739}
740
741struct SigMap {
742 int key;
743 const char *sig;
744};
745
746const SigMap sigMap[] = {
747 { .key: Qt::Key_Left, .sig: "leftPressed" },
748 { .key: Qt::Key_Right, .sig: "rightPressed" },
749 { .key: Qt::Key_Up, .sig: "upPressed" },
750 { .key: Qt::Key_Down, .sig: "downPressed" },
751 { .key: Qt::Key_Tab, .sig: "tabPressed" },
752 { .key: Qt::Key_Backtab, .sig: "backtabPressed" },
753 { .key: Qt::Key_Asterisk, .sig: "asteriskPressed" },
754 { .key: Qt::Key_NumberSign, .sig: "numberSignPressed" },
755 { .key: Qt::Key_Escape, .sig: "escapePressed" },
756 { .key: Qt::Key_Return, .sig: "returnPressed" },
757 { .key: Qt::Key_Enter, .sig: "enterPressed" },
758 { .key: Qt::Key_Delete, .sig: "deletePressed" },
759 { .key: Qt::Key_Space, .sig: "spacePressed" },
760 { .key: Qt::Key_Back, .sig: "backPressed" },
761 { .key: Qt::Key_Cancel, .sig: "cancelPressed" },
762 { .key: Qt::Key_Select, .sig: "selectPressed" },
763 { .key: Qt::Key_Yes, .sig: "yesPressed" },
764 { .key: Qt::Key_No, .sig: "noPressed" },
765 { .key: Qt::Key_Context1, .sig: "context1Pressed" },
766 { .key: Qt::Key_Context2, .sig: "context2Pressed" },
767 { .key: Qt::Key_Context3, .sig: "context3Pressed" },
768 { .key: Qt::Key_Context4, .sig: "context4Pressed" },
769 { .key: Qt::Key_Call, .sig: "callPressed" },
770 { .key: Qt::Key_Hangup, .sig: "hangupPressed" },
771 { .key: Qt::Key_Flip, .sig: "flipPressed" },
772 { .key: Qt::Key_Menu, .sig: "menuPressed" },
773 { .key: Qt::Key_VolumeUp, .sig: "volumeUpPressed" },
774 { .key: Qt::Key_VolumeDown, .sig: "volumeDownPressed" },
775 { .key: 0, .sig: nullptr }
776};
777
778QByteArray QQuickKeysAttached::keyToSignal(int key)
779{
780 QByteArray keySignal;
781 if (key >= Qt::Key_0 && key <= Qt::Key_9) {
782 keySignal = "digit0Pressed";
783 keySignal[5] = '0' + (key - Qt::Key_0);
784 } else {
785 int i = 0;
786 while (sigMap[i].key && sigMap[i].key != key)
787 ++i;
788 keySignal = sigMap[i].sig;
789 }
790 return keySignal;
791}
792
793bool QQuickKeysAttached::isConnected(const char *signalName) const
794{
795 Q_D(const QQuickKeysAttached);
796 int signal_index = d->signalIndex(signalName);
797 return d->isSignalConnected(signalIdx: signal_index);
798}
799
800/*!
801 \qmltype Keys
802 \nativetype QQuickKeysAttached
803 \inqmlmodule QtQuick
804 \ingroup qtquick-input-handlers
805 \brief Provides key handling to Items.
806
807 All visual primitives support key handling via the Keys
808 attaching type. Keys can be handled via the onPressed
809 and onReleased signal properties.
810
811 The signal properties have a \l KeyEvent parameter, named
812 \e event which contains details of the event. If a key is
813 handled \e event.accepted should be set to true to prevent the
814 event from propagating up the item hierarchy.
815
816 \section1 Example Usage
817
818 The following example shows how the general onPressed handler can
819 be used to test for a certain key; in this case, the left cursor
820 key:
821
822 \snippet qml/keys/keys-pressed.qml key item
823
824 Some keys may alternatively be handled via specific signal properties,
825 for example \e onSelectPressed. These handlers automatically set
826 \e event.accepted to true.
827
828 \snippet qml/keys/keys-handler.qml key item
829
830 See \l{Qt::Key}{Qt.Key} for the list of keyboard codes.
831
832 \section1 Key Handling Priorities
833
834 The Keys attaching type can be configured to handle key events
835 before or after the item it is attached to. This makes it possible
836 to intercept events in order to override an item's default behavior,
837 or act as a fallback for keys not handled by the item.
838
839 If \l priority is Keys.BeforeItem (default) the order of key event processing is:
840
841 \list 1
842 \li Items specified in \c forwardTo
843 \li specific key handlers, e.g. onReturnPressed
844 \li onPressed, onReleased handlers
845 \li Item specific key handling, e.g. TextInput key handling
846 \li parent item
847 \endlist
848
849 If priority is Keys.AfterItem the order of key event processing is:
850
851 \list 1
852 \li Item specific key handling, e.g. TextInput key handling
853 \li Items specified in \c forwardTo
854 \li specific key handlers, e.g. onReturnPressed
855 \li onPressed, onReleased handlers
856 \li parent item
857 \endlist
858
859 If the event is accepted during any of the above steps, key
860 propagation stops.
861
862 \sa KeyEvent, {KeyNavigation}{KeyNavigation attached property}
863*/
864
865/*!
866 \qmlproperty bool QtQuick::Keys::enabled
867
868 This flags enables key handling if true (default); otherwise
869 no key handlers will be called.
870*/
871
872/*!
873 \qmlproperty enumeration QtQuick::Keys::priority
874
875 This property determines whether the keys are processed before
876 or after the attached item's own key handling.
877
878 \value Keys.BeforeItem (default) process the key events before normal item key processing.
879 If the event is accepted, it will not be passed on to the item.
880 \value Keys.AfterItem process the key events after normal item key handling. If the item
881 accepts the key event, it will not be handled by the
882 Keys attached property handler.
883
884 \sa {Key Handling Priorities}
885*/
886
887/*!
888 \qmlproperty list<Item> QtQuick::Keys::forwardTo
889
890 This property provides a way to forward key presses, key releases, and keyboard input
891 coming from input methods to other items. This can be useful when you want
892 one item to handle some keys (e.g. the up and down arrow keys), and another item to
893 handle other keys (e.g. the left and right arrow keys). Once an item that has been
894 forwarded keys accepts the event it is no longer forwarded to items later in the
895 list.
896
897 This example forwards key events to two lists:
898 \qml
899 Item {
900 ListView {
901 id: list1
902 // ...
903 }
904 ListView {
905 id: list2
906 // ...
907 }
908 Keys.forwardTo: [list1, list2]
909 focus: true
910 }
911 \endqml
912
913 To see the order in which events are received when using forwardTo, see
914 \l {Key Handling Priorities}.
915*/
916
917/*!
918 \qmlsignal QtQuick::Keys::pressed(KeyEvent event)
919
920 This signal is emitted when a key has been pressed. The \a event
921 parameter provides information about the event.
922*/
923
924/*!
925 \qmlsignal QtQuick::Keys::released(KeyEvent event)
926
927 This signal is emitted when a key has been released. The \a event
928 parameter provides information about the event.
929*/
930
931/*!
932 \qmlsignal QtQuick::Keys::shortcutOverride(KeyEvent event)
933 \since 5.9
934
935 This signal is emitted when a key has been pressed that could potentially
936 be used as a shortcut. The \a event parameter provides information about
937 the event.
938
939 Set \c event.accepted to \c true if you wish to prevent the pressed key
940 from being used as a shortcut by other types, such as \l Shortcut. For
941 example:
942
943 \code
944 Item {
945 id: escapeItem
946 focus: true
947
948 // Ensure that we get escape key press events first.
949 Keys.onShortcutOverride: (event)=> event.accepted = (event.key === Qt.Key_Escape)
950
951 Keys.onEscapePressed: {
952 console.log("escapeItem is handling escape");
953 // event.accepted is set to true by default for the specific key handlers
954 }
955 }
956
957 Shortcut {
958 sequence: "Escape"
959 onActivated: console.log("Shortcut is handling escape")
960 }
961 \endcode
962
963 As with the other signals, \c shortcutOverride will only be emitted for an
964 item if that item has \l {Item::}{activeFocus}.
965
966 \sa Shortcut
967*/
968
969/*!
970 \qmlsignal QtQuick::Keys::digit0Pressed(KeyEvent event)
971
972 This signal is emitted when the digit '0' has been pressed. The \a event
973 parameter provides information about the event.
974*/
975
976/*!
977 \qmlsignal QtQuick::Keys::digit1Pressed(KeyEvent event)
978
979 This signal is emitted when the digit '1' has been pressed. The \a event
980 parameter provides information about the event.
981*/
982
983/*!
984 \qmlsignal QtQuick::Keys::digit2Pressed(KeyEvent event)
985
986 This signal is emitted when the digit '2' has been pressed. The \a event
987 parameter provides information about the event.
988*/
989
990/*!
991 \qmlsignal QtQuick::Keys::digit3Pressed(KeyEvent event)
992
993 This signal is emitted when the digit '3' has been pressed. The \a event
994 parameter provides information about the event.
995*/
996
997/*!
998 \qmlsignal QtQuick::Keys::digit4Pressed(KeyEvent event)
999
1000 This signal is emitted when the digit '4' has been pressed. The \a event
1001 parameter provides information about the event.
1002*/
1003
1004/*!
1005 \qmlsignal QtQuick::Keys::digit5Pressed(KeyEvent event)
1006
1007 This signal is emitted when the digit '5' has been pressed. The \a event
1008 parameter provides information about the event.
1009*/
1010
1011/*!
1012 \qmlsignal QtQuick::Keys::digit6Pressed(KeyEvent event)
1013
1014 This signal is emitted when the digit '6' has been pressed. The \a event
1015 parameter provides information about the event.
1016*/
1017
1018/*!
1019 \qmlsignal QtQuick::Keys::digit7Pressed(KeyEvent event)
1020
1021 This signal is emitted when the digit '7' has been pressed. The \a event
1022 parameter provides information about the event.
1023*/
1024
1025/*!
1026 \qmlsignal QtQuick::Keys::digit8Pressed(KeyEvent event)
1027
1028 This signal is emitted when the digit '8' has been pressed. The \a event
1029 parameter provides information about the event.
1030*/
1031
1032/*!
1033 \qmlsignal QtQuick::Keys::digit9Pressed(KeyEvent event)
1034
1035 This signal is emitted when the digit '9' has been pressed. The \a event
1036 parameter provides information about the event.
1037*/
1038
1039/*!
1040 \qmlsignal QtQuick::Keys::leftPressed(KeyEvent event)
1041
1042 This signal is emitted when the Left arrow has been pressed. The \a event
1043 parameter provides information about the event.
1044*/
1045
1046/*!
1047 \qmlsignal QtQuick::Keys::rightPressed(KeyEvent event)
1048
1049 This signal is emitted when the Right arrow has been pressed. The \a event
1050 parameter provides information about the event.
1051*/
1052
1053/*!
1054 \qmlsignal QtQuick::Keys::upPressed(KeyEvent event)
1055
1056 This signal is emitted when the Up arrow has been pressed. The \a event
1057 parameter provides information about the event.
1058*/
1059
1060/*!
1061 \qmlsignal QtQuick::Keys::downPressed(KeyEvent event)
1062
1063 This signal is emitted when the Down arrow has been pressed. The \a event
1064 parameter provides information about the event.
1065*/
1066
1067/*!
1068 \qmlsignal QtQuick::Keys::tabPressed(KeyEvent event)
1069
1070 This signal is emitted when the Tab key has been pressed. The \a event
1071 parameter provides information about the event.
1072*/
1073
1074/*!
1075 \qmlsignal QtQuick::Keys::backtabPressed(KeyEvent event)
1076
1077 This signal is emitted when the Shift+Tab key combination (Backtab) has
1078 been pressed. The \a event parameter provides information about the event.
1079*/
1080
1081/*!
1082 \qmlsignal QtQuick::Keys::asteriskPressed(KeyEvent event)
1083
1084 This signal is emitted when the Asterisk '*' has been pressed. The \a event
1085 parameter provides information about the event.
1086*/
1087
1088/*!
1089 \qmlsignal QtQuick::Keys::escapePressed(KeyEvent event)
1090
1091 This signal is emitted when the Escape key has been pressed. The \a event
1092 parameter provides information about the event.
1093*/
1094
1095/*!
1096 \qmlsignal QtQuick::Keys::returnPressed(KeyEvent event)
1097
1098 This signal is emitted when the Return key has been pressed. The \a event
1099 parameter provides information about the event.
1100*/
1101
1102/*!
1103 \qmlsignal QtQuick::Keys::enterPressed(KeyEvent event)
1104
1105 This signal is emitted when the Enter key has been pressed. The \a event
1106 parameter provides information about the event.
1107*/
1108
1109/*!
1110 \qmlsignal QtQuick::Keys::deletePressed(KeyEvent event)
1111
1112 This signal is emitted when the Delete key has been pressed. The \a event
1113 parameter provides information about the event.
1114*/
1115
1116/*!
1117 \qmlsignal QtQuick::Keys::spacePressed(KeyEvent event)
1118
1119 This signal is emitted when the Space key has been pressed. The \a event
1120 parameter provides information about the event.
1121*/
1122
1123/*!
1124 \qmlsignal QtQuick::Keys::backPressed(KeyEvent event)
1125
1126 This signal is emitted when the Back key has been pressed. The \a event
1127 parameter provides information about the event.
1128*/
1129
1130/*!
1131 \qmlsignal QtQuick::Keys::cancelPressed(KeyEvent event)
1132
1133 This signal is emitted when the Cancel key has been pressed. The \a event
1134 parameter provides information about the event.
1135*/
1136
1137/*!
1138 \qmlsignal QtQuick::Keys::selectPressed(KeyEvent event)
1139
1140 This signal is emitted when the Select key has been pressed. The \a event
1141 parameter provides information about the event.
1142*/
1143
1144/*!
1145 \qmlsignal QtQuick::Keys::yesPressed(KeyEvent event)
1146
1147 This signal is emitted when the Yes key has been pressed. The \a event
1148 parameter provides information about the event.
1149*/
1150
1151/*!
1152 \qmlsignal QtQuick::Keys::noPressed(KeyEvent event)
1153
1154 This signal is emitted when the No key has been pressed. The \a event
1155 parameter provides information about the event.
1156*/
1157
1158/*!
1159 \qmlsignal QtQuick::Keys::context1Pressed(KeyEvent event)
1160
1161 This signal is emitted when the Context1 key has been pressed. The \a event
1162 parameter provides information about the event.
1163*/
1164
1165/*!
1166 \qmlsignal QtQuick::Keys::context2Pressed(KeyEvent event)
1167
1168 This signal is emitted when the Context2 key has been pressed. The \a event
1169 parameter provides information about the event.
1170*/
1171
1172/*!
1173 \qmlsignal QtQuick::Keys::context3Pressed(KeyEvent event)
1174
1175 This signal is emitted when the Context3 key has been pressed. The \a event
1176 parameter provides information about the event.
1177*/
1178
1179/*!
1180 \qmlsignal QtQuick::Keys::context4Pressed(KeyEvent event)
1181
1182 This signal is emitted when the Context4 key has been pressed. The \a event
1183 parameter provides information about the event.
1184*/
1185
1186/*!
1187 \qmlsignal QtQuick::Keys::callPressed(KeyEvent event)
1188
1189 This signal is emitted when the Call key has been pressed. The \a event
1190 parameter provides information about the event.
1191*/
1192
1193/*!
1194 \qmlsignal QtQuick::Keys::hangupPressed(KeyEvent event)
1195
1196 This signal is emitted when the Hangup key has been pressed. The \a event
1197 parameter provides information about the event.
1198*/
1199
1200/*!
1201 \qmlsignal QtQuick::Keys::flipPressed(KeyEvent event)
1202
1203 This signal is emitted when the Flip key has been pressed. The \a event
1204 parameter provides information about the event.
1205*/
1206
1207/*!
1208 \qmlsignal QtQuick::Keys::menuPressed(KeyEvent event)
1209
1210 This signal is emitted when the Menu key has been pressed. The \a event
1211 parameter provides information about the event.
1212*/
1213
1214/*!
1215 \qmlsignal QtQuick::Keys::volumeUpPressed(KeyEvent event)
1216
1217 This signal is emitted when the VolumeUp key has been pressed. The \a event
1218 parameter provides information about the event.
1219*/
1220
1221/*!
1222 \qmlsignal QtQuick::Keys::volumeDownPressed(KeyEvent event)
1223
1224 This signal is emitted when the VolumeDown key has been pressed. The \a event
1225 parameter provides information about the event.
1226*/
1227
1228QQuickKeysAttached::QQuickKeysAttached(QObject *parent)
1229: QObject(*(new QQuickKeysAttachedPrivate), parent),
1230 QQuickItemKeyFilter(qmlobject_cast<QQuickItem*>(object: parent))
1231{
1232 Q_D(QQuickKeysAttached);
1233 m_processPost = false;
1234 d->item = qmlobject_cast<QQuickItem*>(object: parent);
1235 if (d->item != parent)
1236 qWarning() << "Could not attach Keys property to: " << parent << " is not an Item";
1237}
1238
1239QQuickKeysAttached::~QQuickKeysAttached()
1240{
1241}
1242
1243QQuickKeysAttached::Priority QQuickKeysAttached::priority() const
1244{
1245 return m_processPost ? AfterItem : BeforeItem;
1246}
1247
1248void QQuickKeysAttached::setPriority(Priority order)
1249{
1250 bool processPost = order == AfterItem;
1251 if (processPost != m_processPost) {
1252 m_processPost = processPost;
1253 emit priorityChanged();
1254 }
1255}
1256
1257void QQuickKeysAttached::componentComplete()
1258{
1259#if QT_CONFIG(im)
1260 Q_D(QQuickKeysAttached);
1261 if (d->item) {
1262 for (int ii = 0; ii < d->targets.size(); ++ii) {
1263 QQuickItem *targetItem = d->targets.at(i: ii);
1264 if (targetItem && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) {
1265 d->item->setFlag(flag: QQuickItem::ItemAcceptsInputMethod);
1266 break;
1267 }
1268 }
1269 }
1270#endif
1271}
1272
1273void QQuickKeysAttached::keyPressed(QKeyEvent *event, bool post)
1274{
1275 Q_D(QQuickKeysAttached);
1276 if (post != m_processPost || !d->enabled || d->inPress) {
1277 event->ignore();
1278 QQuickItemKeyFilter::keyPressed(event, post);
1279 return;
1280 }
1281
1282 // first process forwards
1283 if (d->item && d->item->window()) {
1284 d->inPress = true;
1285 for (int ii = 0; ii < d->targets.size(); ++ii) {
1286 QQuickItem *i = d->targets.at(i: ii);
1287 if (i && i->isVisible()) {
1288 event->accept();
1289 QCoreApplication::sendEvent(receiver: i, event);
1290 if (event->isAccepted()) {
1291 d->inPress = false;
1292 return;
1293 }
1294 }
1295 }
1296 d->inPress = false;
1297 }
1298
1299 QQuickKeyEvent &ke = d->theKeyEvent;
1300 ke.reset(ke: *event);
1301 QByteArray keySignal = keyToSignal(key: event->key());
1302 if (!keySignal.isEmpty()) {
1303 keySignal += "(QQuickKeyEvent*)";
1304 if (isConnected(signalName: keySignal)) {
1305 // If we specifically handle a key then default to accepted
1306 ke.setAccepted(true);
1307 int idx = QQuickKeysAttached::staticMetaObject.indexOfSignal(signal: keySignal);
1308 metaObject()->method(index: idx).invoke(obj: this, c: Qt::DirectConnection, Q_ARG(QQuickKeyEvent*, &ke));
1309 }
1310 }
1311 if (!ke.isAccepted())
1312 emit pressed(event: &ke);
1313 event->setAccepted(ke.isAccepted());
1314
1315 if (!event->isAccepted()) QQuickItemKeyFilter::keyPressed(event, post);
1316}
1317
1318void QQuickKeysAttached::keyReleased(QKeyEvent *event, bool post)
1319{
1320 Q_D(QQuickKeysAttached);
1321 if (post != m_processPost || !d->enabled || d->inRelease) {
1322 event->ignore();
1323 QQuickItemKeyFilter::keyReleased(event, post);
1324 return;
1325 }
1326
1327 if (d->item && d->item->window()) {
1328 d->inRelease = true;
1329 for (int ii = 0; ii < d->targets.size(); ++ii) {
1330 QQuickItem *i = d->targets.at(i: ii);
1331 if (i && i->isVisible()) {
1332 event->accept();
1333 QCoreApplication::sendEvent(receiver: i, event);
1334 if (event->isAccepted()) {
1335 d->inRelease = false;
1336 return;
1337 }
1338 }
1339 }
1340 d->inRelease = false;
1341 }
1342
1343 QQuickKeyEvent &ke = d->theKeyEvent;
1344 ke.reset(ke: *event);
1345 emit released(event: &ke);
1346 event->setAccepted(ke.isAccepted());
1347
1348 if (!event->isAccepted()) QQuickItemKeyFilter::keyReleased(event, post);
1349}
1350
1351#if QT_CONFIG(im)
1352void QQuickKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post)
1353{
1354 Q_D(QQuickKeysAttached);
1355 if (post == m_processPost && d->item && !d->inIM && d->item->window()) {
1356 d->inIM = true;
1357 for (int ii = 0; ii < d->targets.size(); ++ii) {
1358 QQuickItem *targetItem = d->targets.at(i: ii);
1359 if (targetItem && targetItem->isVisible() && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) {
1360 QCoreApplication::sendEvent(receiver: targetItem, event);
1361 if (event->isAccepted()) {
1362 d->imeItem = targetItem;
1363 d->inIM = false;
1364 return;
1365 }
1366 }
1367 }
1368 d->inIM = false;
1369 }
1370 QQuickItemKeyFilter::inputMethodEvent(event, post);
1371}
1372
1373QVariant QQuickKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const
1374{
1375 Q_D(const QQuickKeysAttached);
1376 if (d->item) {
1377 for (int ii = 0; ii < d->targets.size(); ++ii) {
1378 QQuickItem *i = d->targets.at(i: ii);
1379 if (i && i->isVisible() && (i->flags() & QQuickItem::ItemAcceptsInputMethod) && i == d->imeItem) {
1380 //### how robust is i == d->imeItem check?
1381 QVariant v = i->inputMethodQuery(query);
1382 if (v.userType() == QMetaType::QRectF)
1383 v = d->item->mapRectFromItem(item: i, rect: v.toRectF()); //### cost?
1384 return v;
1385 }
1386 }
1387 }
1388 return QQuickItemKeyFilter::inputMethodQuery(query);
1389}
1390#endif // im
1391
1392void QQuickKeysAttached::shortcutOverrideEvent(QKeyEvent *event)
1393{
1394 Q_D(QQuickKeysAttached);
1395 QQuickKeyEvent &keyEvent = d->theKeyEvent;
1396 keyEvent.reset(ke: *event);
1397 emit shortcutOverride(event: &keyEvent);
1398
1399 event->setAccepted(keyEvent.isAccepted());
1400}
1401
1402QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj)
1403{
1404 return new QQuickKeysAttached(obj);
1405}
1406
1407/*!
1408 \qmltype LayoutMirroring
1409 \nativetype QQuickLayoutMirroringAttached
1410 \inqmlmodule QtQuick
1411 \ingroup qtquick-positioners
1412 \ingroup qml-utility-elements
1413 \brief Property used to mirror layout behavior.
1414
1415 The LayoutMirroring attaching type is used to horizontally mirror \l {anchor-layout}{Item anchors},
1416 \l{Item Positioners}{positioner} types (such as \l Row and \l Grid)
1417 and views (such as \l GridView and horizontal \l ListView). Mirroring is a visual change: left
1418 anchors become right anchors, and positioner types like \l Grid and \l Row reverse the
1419 horizontal layout of child items.
1420
1421 Mirroring is enabled for an item by setting the \l enabled property to true. By default, this
1422 only affects the item itself; setting the \l childrenInherit property to true propagates the mirroring
1423 behavior to all child items as well. If the \c LayoutMirroring attaching type has not been defined
1424 for an item, mirroring is not enabled.
1425
1426 \note Since Qt 5.8, \c LayoutMirroring can be attached to a \l Window. In practice, it is the same as
1427 attaching \c LayoutMirroring to the window's \c contentItem.
1428
1429 The following example shows mirroring in action. The \l Row below is specified as being anchored
1430 to the left of its parent. However, since mirroring has been enabled, the anchor is horizontally
1431 reversed and it is now anchored to the right. Also, since items in a \l Row are positioned
1432 from left to right by default, they are now positioned from right to left instead, as demonstrated
1433 by the numbering and opacity of the items:
1434
1435 \snippet qml/layoutmirroring.qml 0
1436
1437 \image layoutmirroring.png
1438
1439 Layout mirroring is useful when it is necessary to support both left-to-right and right-to-left
1440 layout versions of an application to target different language areas. The \l childrenInherit
1441 property allows layout mirroring to be applied without manually setting layout configurations
1442 for every item in an application. Keep in mind, however, that mirroring does not affect any
1443 positioning that is defined by the \l Item \l {Item::}{x} coordinate value, so even with
1444 mirroring enabled, it will often be necessary to apply some layout fixes to support the
1445 desired layout direction. Also, it may be necessary to disable the mirroring of individual
1446 child items (by setting \l {enabled}{LayoutMirroring.enabled} to false for such items) if
1447 mirroring is not the desired behavior, or if the child item already implements mirroring in
1448 some custom way.
1449
1450 To set the layout direction based on the \l {Default Layout Direction}{default layout direction}
1451 of the application, use the following code:
1452
1453 \code
1454 LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
1455 \endcode
1456
1457 See \l {Right-to-left User Interfaces} for further details on using \c LayoutMirroring and
1458 other related features to implement right-to-left support for an application.
1459*/
1460
1461/*!
1462 \qmlproperty bool QtQuick::LayoutMirroring::enabled
1463
1464 This property holds whether the item's layout is mirrored horizontally. Setting this to true
1465 horizontally reverses \l {anchor-layout}{anchor} settings such that left anchors become right,
1466 and right anchors become left. For \l{Item Positioners}{positioner} types
1467 (such as \l Row and \l Grid) and view types (such as \l {GridView}{GridView} and \l {ListView}{ListView})
1468 this also mirrors the horizontal layout direction of the item.
1469
1470 The default value is false.
1471*/
1472
1473/*!
1474 \qmlproperty bool QtQuick::LayoutMirroring::childrenInherit
1475
1476 This property holds whether the \l {enabled}{LayoutMirroring.enabled} value for this item
1477 is inherited by its children.
1478
1479 The default value is false.
1480*/
1481
1482
1483QQuickLayoutMirroringAttached::QQuickLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(nullptr)
1484{
1485 if (QQuickItem *item = qobject_cast<QQuickItem *>(o: parent))
1486 itemPrivate = QQuickItemPrivate::get(item);
1487 else if (QQuickWindow *window = qobject_cast<QQuickWindow *>(object: parent))
1488 itemPrivate = QQuickItemPrivate::get(item: window->contentItem());
1489
1490 if (itemPrivate)
1491 itemPrivate->extra.value().layoutDirectionAttached = this;
1492 else
1493 qmlWarning(me: parent) << tr(s: "LayoutMirroring attached property only works with Items and Windows");
1494}
1495
1496QQuickLayoutMirroringAttached * QQuickLayoutMirroringAttached::qmlAttachedProperties(QObject *object)
1497{
1498 return new QQuickLayoutMirroringAttached(object);
1499}
1500
1501bool QQuickLayoutMirroringAttached::enabled() const
1502{
1503 return itemPrivate ? itemPrivate->effectiveLayoutMirror : false;
1504}
1505
1506void QQuickLayoutMirroringAttached::setEnabled(bool enabled)
1507{
1508 if (!itemPrivate)
1509 return;
1510
1511 itemPrivate->isMirrorImplicit = false;
1512 if (enabled != itemPrivate->effectiveLayoutMirror) {
1513 itemPrivate->setLayoutMirror(enabled);
1514 if (itemPrivate->inheritMirrorFromItem)
1515 itemPrivate->resolveLayoutMirror();
1516 }
1517}
1518
1519void QQuickLayoutMirroringAttached::resetEnabled()
1520{
1521 if (itemPrivate && !itemPrivate->isMirrorImplicit) {
1522 itemPrivate->isMirrorImplicit = true;
1523 itemPrivate->resolveLayoutMirror();
1524 }
1525}
1526
1527bool QQuickLayoutMirroringAttached::childrenInherit() const
1528{
1529 return itemPrivate ? itemPrivate->inheritMirrorFromItem : false;
1530}
1531
1532void QQuickLayoutMirroringAttached::setChildrenInherit(bool childrenInherit) {
1533 if (itemPrivate && childrenInherit != itemPrivate->inheritMirrorFromItem) {
1534 itemPrivate->inheritMirrorFromItem = childrenInherit;
1535 itemPrivate->resolveLayoutMirror();
1536 childrenInheritChanged();
1537 }
1538}
1539
1540void QQuickItemPrivate::resolveLayoutMirror()
1541{
1542 Q_Q(QQuickItem);
1543 if (QQuickItem *parentItem = q->parentItem()) {
1544 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(item: parentItem);
1545 setImplicitLayoutMirror(mirror: parentPrivate->inheritedLayoutMirror, inherit: parentPrivate->inheritMirrorFromParent);
1546 } else {
1547 setImplicitLayoutMirror(mirror: isMirrorImplicit ? false : effectiveLayoutMirror, inherit: inheritMirrorFromItem);
1548 }
1549}
1550
1551void QQuickItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit)
1552{
1553 inherit = inherit || inheritMirrorFromItem;
1554 if (!isMirrorImplicit && inheritMirrorFromItem)
1555 mirror = effectiveLayoutMirror;
1556 if (mirror == inheritedLayoutMirror && inherit == inheritMirrorFromParent)
1557 return;
1558
1559 inheritMirrorFromParent = inherit;
1560 inheritedLayoutMirror = inheritMirrorFromParent ? mirror : false;
1561
1562 if (isMirrorImplicit)
1563 setLayoutMirror(inherit ? inheritedLayoutMirror : false);
1564 for (int i = 0; i < childItems.size(); ++i) {
1565 if (QQuickItem *child = qmlobject_cast<QQuickItem *>(object: childItems.at(i))) {
1566 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(item: child);
1567 childPrivate->setImplicitLayoutMirror(mirror: inheritedLayoutMirror, inherit: inheritMirrorFromParent);
1568 }
1569 }
1570}
1571
1572void QQuickItemPrivate::setLayoutMirror(bool mirror)
1573{
1574 if (mirror != effectiveLayoutMirror) {
1575 effectiveLayoutMirror = mirror;
1576 if (_anchors) {
1577 QQuickAnchorsPrivate *anchor_d = QQuickAnchorsPrivate::get(o: _anchors);
1578 anchor_d->fillChanged();
1579 anchor_d->centerInChanged();
1580 anchor_d->updateHorizontalAnchors();
1581 }
1582 mirrorChange();
1583 if (extra.isAllocated() && extra->layoutDirectionAttached) {
1584 emit extra->layoutDirectionAttached->enabledChanged();
1585 }
1586 }
1587}
1588
1589/*!
1590 \qmltype EnterKey
1591 \nativetype QQuickEnterKeyAttached
1592 \inqmlmodule QtQuick
1593 \ingroup qtquick-input
1594 \since 5.6
1595 \brief Provides a property to manipulate the appearance of Enter key on
1596 an on-screen keyboard.
1597
1598 The EnterKey attached property is used to manipulate the appearance and
1599 behavior of the Enter key on an on-screen keyboard.
1600*/
1601
1602/*!
1603 \qmlattachedproperty enumeration QtQuick::EnterKey::type
1604
1605 Holds the type of the Enter key.
1606
1607 \note Not all of these values are supported on all platforms. For
1608 unsupported values the default key is used instead.
1609
1610 \value Qt.EnterKeyDefault The default Enter key. This can be either a
1611 button to accept the input and close the
1612 keyboard, or a \e Return button to enter a
1613 newline in case of a multi-line input field.
1614
1615 \value Qt.EnterKeyReturn Show a \e Return button that inserts a
1616 newline.
1617
1618 \value Qt.EnterKeyDone Show a \e {"Done"} button. Typically, the
1619 keyboard is expected to close when the button
1620 is pressed.
1621
1622 \value Qt.EnterKeyGo Show a \e {"Go"} button. Typically used in an
1623 address bar when entering a URL.
1624
1625 \value Qt.EnterKeySend Show a \e {"Send"} button.
1626
1627 \value Qt.EnterKeySearch Show a \e {"Search"} button.
1628
1629 \value Qt.EnterKeyNext Show a \e {"Next"} button. Typically used in a
1630 form to allow navigating to the next input
1631 field without the keyboard closing.
1632
1633 \value Qt.EnterKeyPrevious Show a \e {"Previous"} button.
1634*/
1635
1636QQuickEnterKeyAttached::QQuickEnterKeyAttached(QObject *parent)
1637 : QObject(parent), itemPrivate(nullptr), keyType(Qt::EnterKeyDefault)
1638{
1639 if (QQuickItem *item = qobject_cast<QQuickItem*>(o: parent)) {
1640 itemPrivate = QQuickItemPrivate::get(item);
1641 itemPrivate->extra.value().enterKeyAttached = this;
1642 } else
1643 qmlWarning(me: parent) << tr(s: "EnterKey attached property only works with Items");
1644}
1645
1646QQuickEnterKeyAttached *QQuickEnterKeyAttached::qmlAttachedProperties(QObject *object)
1647{
1648 return new QQuickEnterKeyAttached(object);
1649}
1650
1651Qt::EnterKeyType QQuickEnterKeyAttached::type() const
1652{
1653 return keyType;
1654}
1655
1656void QQuickEnterKeyAttached::setType(Qt::EnterKeyType type)
1657{
1658 if (keyType != type) {
1659 keyType = type;
1660#if QT_CONFIG(im)
1661 if (itemPrivate && itemPrivate->activeFocus)
1662 QGuiApplication::inputMethod()->update(queries: Qt::ImEnterKeyType);
1663#endif
1664 typeChanged();
1665 }
1666}
1667
1668void QQuickItemPrivate::setAccessible()
1669{
1670 isAccessible = true;
1671}
1672
1673/*!
1674Clears all sub focus items from \a scope.
1675If \a focus is true, sets the scope's subFocusItem
1676to be this item.
1677*/
1678void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
1679{
1680 Q_Q(QQuickItem);
1681 Q_ASSERT(scope);
1682
1683 QQuickItemPrivate *scopePrivate = QQuickItemPrivate::get(item: scope);
1684
1685 QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem;
1686 // Correct focus chain in scope
1687 if (oldSubFocusItem) {
1688 QQuickItem *sfi = scopePrivate->subFocusItem->parentItem();
1689 while (sfi && sfi != scope) {
1690 QQuickItemPrivate::get(item: sfi)->subFocusItem = nullptr;
1691 sfi = sfi->parentItem();
1692 }
1693 }
1694
1695 if (focus) {
1696 scopePrivate->subFocusItem = q;
1697 QQuickItem *sfi = scopePrivate->subFocusItem->parentItem();
1698 while (sfi && sfi != scope) {
1699 QQuickItemPrivate::get(item: sfi)->subFocusItem = q;
1700 sfi = sfi->parentItem();
1701 }
1702 } else {
1703 scopePrivate->subFocusItem = nullptr;
1704 }
1705}
1706
1707
1708bool QQuickItemPrivate::setFocusIfNeeded(QEvent::Type eventType)
1709{
1710 Q_Q(QQuickItem);
1711 const bool setFocusOnRelease = QGuiApplication::styleHints()->setFocusOnTouchRelease();
1712 Qt::FocusPolicy policy = Qt::ClickFocus;
1713
1714 switch (eventType) {
1715 case QEvent::MouseButtonPress:
1716 case QEvent::MouseButtonDblClick:
1717 case QEvent::TouchBegin:
1718 if (setFocusOnRelease)
1719 return false;
1720 break;
1721 case QEvent::MouseButtonRelease:
1722 case QEvent::TouchEnd:
1723 if (!setFocusOnRelease)
1724 return false;
1725 break;
1726 case QEvent::Wheel:
1727 policy = Qt::WheelFocus;
1728 break;
1729 default:
1730 break;
1731 }
1732
1733 if ((focusPolicy & policy) == policy) {
1734 setActiveFocus(item: q, reason: Qt::MouseFocusReason);
1735 return true;
1736 }
1737
1738 return false;
1739}
1740
1741Qt::FocusReason QQuickItemPrivate::lastFocusChangeReason() const
1742{
1743 return static_cast<Qt::FocusReason>(focusReason);
1744}
1745
1746bool QQuickItemPrivate::setLastFocusChangeReason(Qt::FocusReason reason)
1747{
1748 if (focusReason == reason)
1749 return false;
1750
1751 focusReason = reason;
1752 return true;
1753}
1754
1755/*!
1756 \class QQuickItem
1757 \brief The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
1758 \inmodule QtQuick
1759
1760 All visual items in Qt Quick inherit from QQuickItem. Although a QQuickItem
1761 instance has no visual appearance, it defines all the attributes that are
1762 common across visual items, such as x and y position, width and height,
1763 \l {Positioning with Anchors}{anchoring} and key handling support.
1764
1765 You can subclass QQuickItem to provide your own custom visual item
1766 that inherits these features.
1767
1768 \section1 Custom Scene Graph Items
1769
1770 All visual QML items are rendered using the scene graph, the
1771 default implementation of which is a low-level, high-performance
1772 rendering stack, closely tied to accelerated graphics APIs, such
1773 as OpenGL, Vulkan, Metal, or Direct 3D. It is possible for
1774 subclasses of QQuickItem to add their own custom content into the
1775 scene graph by setting the QQuickItem::ItemHasContents flag and
1776 reimplementing the QQuickItem::updatePaintNode() function.
1777
1778 \warning It is crucial that graphics operations and interaction with
1779 the scene graph happens exclusively on the rendering thread,
1780 primarily during the updatePaintNode() call. The best rule of
1781 thumb is to only use classes with the "QSG" prefix inside the
1782 QQuickItem::updatePaintNode() function.
1783
1784 \note All classes with QSG prefix should be used solely on the scene graph's
1785 rendering thread. See \l {Scene Graph and Rendering} for more information.
1786
1787 \section2 Graphics Resource Handling
1788
1789 The preferred way to handle cleanup of graphics resources used in
1790 the scene graph, is to rely on the automatic cleanup of nodes. A
1791 QSGNode returned from QQuickItem::updatePaintNode() is
1792 automatically deleted on the right thread at the right time. Trees
1793 of QSGNode instances are managed through the use of
1794 QSGNode::OwnedByParent, which is set by default. So, for the
1795 majority of custom scene graph items, no extra work will be
1796 required.
1797
1798 Implementations that store graphics resources outside the node
1799 tree, such as an item implementing QQuickItem::textureProvider(),
1800 will need to take care in cleaning it up correctly depending on
1801 how the item is used in QML. The situations to handle are:
1802
1803 \list
1804
1805 \li The scene graph is invalidated; This can happen, depending on
1806 the platform and QQuickWindow configuration, when the window is
1807 hidden using QQuickWindow::hide(), or when it is closed. If the
1808 item class implements a \c slot named \c invalidateSceneGraph(),
1809 this slot will be called on the rendering thread while the GUI
1810 thread is blocked. This is equivalent to connecting to
1811 QQuickWindow::sceneGraphInvalidated(). When rendering through
1812 OpenGL, the OpenGL context of this item's window will be bound
1813 when this slot is called. The only exception is if the native
1814 OpenGL has been destroyed outside Qt's control, for instance
1815 through \c EGL_CONTEXT_LOST.
1816
1817 \li The item is removed from the scene; If an item is taken out of
1818 the scene, for instance because it's parent was set to \c null or
1819 an item in another window, the QQuickItem::releaseResources() will
1820 be called on the GUI thread. QQuickWindow::scheduleRenderJob()
1821 should be used to schedule cleanup of rendering resources.
1822
1823 \li The item is deleted; When the destructor if an item runs, it
1824 should delete any graphics resources it has. If neither of the two
1825 conditions above were already met, the item will be part of a
1826 window and it is possible to use QQuickWindow::scheduleRenderJob()
1827 to have them cleaned up. If an implementation ignores the call to
1828 QQuickItem::releaseResources(), the item will in many cases no
1829 longer have access to a QQuickWindow and thus no means of
1830 scheduling cleanup.
1831
1832 \endlist
1833
1834 When scheduling cleanup of graphics resources using
1835 QQuickWindow::scheduleRenderJob(), one should use either
1836 QQuickWindow::BeforeSynchronizingStage or
1837 QQuickWindow::AfterSynchronizingStage. The \l {Scene Graph and
1838 Rendering}{synchronization stage} is where the scene graph is
1839 changed as a result of changes to the QML tree. If cleanup is
1840 scheduled at any other time, it may result in other parts of the
1841 scene graph referencing the newly deleted objects as these parts
1842 have not been updated.
1843
1844 \note Use of QObject::deleteLater() to clean up graphics resources
1845 is strongly discouraged as this will make the \c delete operation
1846 run at an arbitrary time and it is unknown if there will be an
1847 OpenGL context bound when the deletion takes place.
1848
1849 \section1 Custom QPainter Items
1850
1851 The QQuickItem provides a subclass, QQuickPaintedItem, which
1852 allows the users to render content using QPainter.
1853
1854 \warning Using QQuickPaintedItem uses an indirect 2D surface to
1855 render its content, using software rasterization, so the rendering
1856 is a two-step operation. First rasterize the surface, then draw
1857 the surface. Using scene graph API directly is always
1858 significantly faster.
1859
1860 \section1 Behavior Animations
1861
1862 If your Item uses the \l Behavior type to define animations for property
1863 changes, you should always use either QObject::setProperty(),
1864 QQmlProperty(), or QMetaProperty::write() when you need to modify those
1865 properties from C++. This ensures that the QML engine knows about the
1866 property change. Otherwise, the engine won't be able to carry out your
1867 requested animation.
1868 Note that these functions incur a slight performance penalty. For more
1869 details, see \l {Accessing Members of a QML Object Type from C++}.
1870
1871 \sa QQuickWindow, QQuickPaintedItem
1872*/
1873
1874/*!
1875 \qmltype Item
1876 \nativetype QQuickItem
1877 \inherits QtObject
1878 \inqmlmodule QtQuick
1879 \ingroup qtquick-visual
1880 \brief A basic visual QML type.
1881
1882 The Item type is the base type for all visual items in Qt Quick.
1883
1884 All visual items in Qt Quick inherit from Item. Although an Item
1885 object has no visual appearance, it defines all the attributes that are
1886 common across visual items, such as x and y position, width and height,
1887 \l {Positioning with Anchors}{anchoring} and key handling support.
1888
1889 The Item type can be useful for grouping several items under a single
1890 root visual item. For example:
1891
1892 \qml
1893 import QtQuick 2.0
1894
1895 Item {
1896 Image {
1897 source: "tile.png"
1898 }
1899 Image {
1900 x: 80
1901 width: 100
1902 height: 100
1903 source: "tile.png"
1904 }
1905 Image {
1906 x: 190
1907 width: 100
1908 height: 100
1909 fillMode: Image.Tile
1910 source: "tile.png"
1911 }
1912 }
1913 \endqml
1914
1915
1916 \section2 Event Handling
1917
1918 All Item-based visual types can use \l {Qt Quick Input Handlers}{Input Handlers}
1919 to handle incoming input events (subclasses of QInputEvent), such as mouse,
1920 touch and key events. This is the preferred declarative way to handle events.
1921
1922 An alternative way to handle touch events is to subclass QQuickItem, call
1923 setAcceptTouchEvents() in the constructor, and override touchEvent().
1924 \l {QEvent::setAccepted()}{Accept} the entire event to stop delivery to
1925 items underneath, and to exclusively grab for all the event's touch points.
1926 Use QPointerEvent::setExclusiveGrabber() to grab only certain touchpoints,
1927 and allow the event to be delivered further.
1928
1929 Likewise, a QQuickItem subclass can call setAcceptedMouseButtons()
1930 to register to receive mouse button events, setAcceptHoverEvents()
1931 to receive hover events (mouse movements while no button is pressed),
1932 and override the virtual functions mousePressEvent(), mouseMoveEvent(), and
1933 mouseReleaseEvent(). Those can also accept the event to prevent further
1934 delivery and get an implicit grab at the same time; or explicitly
1935 \l {QPointerEvent::setExclusiveGrabber()}{grab} the single QEventPoint
1936 that the QMouseEvent carries.
1937
1938 Key handling is available to all Item-based visual types via the \l Keys
1939 attached property. The \e Keys attached property provides basic signals
1940 such as \l {Keys::}{pressed} and \l {Keys::}{released}, as well as
1941 signals for specific keys, such as \l {Keys::}{spacePressed}. The
1942 example below assigns \l {Keyboard Focus in Qt Quick}{keyboard focus} to
1943 the item and handles the left key via the general \c onPressed handler
1944 and the return key via the \c onReturnPressed handler:
1945
1946 \qml
1947 import QtQuick 2.0
1948
1949 Item {
1950 focus: true
1951 Keys.onPressed: (event)=> {
1952 if (event.key == Qt.Key_Left) {
1953 console.log("move left");
1954 event.accepted = true;
1955 }
1956 }
1957 Keys.onReturnPressed: console.log("Pressed return");
1958 }
1959 \endqml
1960
1961 See the \l Keys attached property for detailed documentation.
1962
1963 \section2 Layout Mirroring
1964
1965 Item layouts can be mirrored using the \l LayoutMirroring attached
1966 property. This causes \l{anchors.top}{anchors} to be horizontally
1967 reversed, and also causes items that lay out or position their children
1968 (such as ListView or \l Row) to horizontally reverse the direction of
1969 their layouts.
1970
1971 See LayoutMirroring for more details.
1972
1973 \section1 Item Layers
1974
1975 An Item will normally be rendered directly into the window it
1976 belongs to. However, by setting \l layer.enabled, it is possible
1977 to delegate the item and its entire subtree into an offscreen
1978 surface. Only the offscreen surface, a texture, will be then drawn
1979 into the window.
1980
1981 If it is desired to have a texture size different from that of the
1982 item, this is possible using \l layer.textureSize. To render only
1983 a section of the item into the texture, use \l
1984 layer.sourceRect. It is also possible to specify \l
1985 layer.sourceRect so it extends beyond the bounds of the item. In
1986 this case, the exterior will be padded with transparent pixels.
1987
1988 The item will use linear interpolation for scaling if
1989 \l layer.smooth is set to \c true and will use mipmap for
1990 downsampling if \l layer.mipmap is set to \c true. Mipmapping may
1991 improve visual quality of downscaled items. For mipmapping of
1992 single Image items, prefer Image::mipmap.
1993
1994 \section2 Layer Opacity vs Item Opacity
1995
1996 When applying \l opacity to an item hierarchy the opacity is
1997 applied to each item individually. This can lead to undesired
1998 visual results when the opacity is applied to a subtree. Consider
1999 the following example:
2000
2001 \table
2002 \row
2003 \li \inlineimage qml-blending-nonlayered.png
2004 \li \b {Non-layered Opacity} \snippet qml/layerblending.qml non-layered
2005 \endtable
2006
2007 A layer is rendered with the root item's opacity being 1, and then
2008 the root item's opacity is applied to the texture when it is
2009 drawn. This means that fading in a large item hierarchy from
2010 transparent to opaque, or vice versa, can be done without the
2011 overlap artifacts that the normal item by item alpha blending
2012 has. Here is the same example with layer enabled:
2013
2014 \table
2015 \row
2016 \li \image qml-blending-layered.png
2017 \li \b {Layered Opacity} \snippet qml/layerblending.qml layered
2018 \endtable
2019
2020 \section2 Combined with ShaderEffects
2021
2022 Setting \l layer.enabled to true will turn the item into a \l
2023 {QQuickItem::isTextureProvider}{texture provider}, making it
2024 possible to use the item directly as a texture, for instance
2025 in combination with the ShaderEffect type.
2026
2027 It is possible to apply an effect on a layer at runtime using
2028 layer.effect:
2029
2030 \qml
2031 Item {
2032 id: layerRoot
2033 layer.enabled: true
2034 layer.effect: ShaderEffect {
2035 fragmentShader: "effect.frag.qsb"
2036 }
2037 }
2038 \endqml
2039
2040 See ShaderEffect for more information about using effects.
2041
2042 \note \l layer.enabled is actually just a more convenient way of using
2043 ShaderEffectSource.
2044
2045
2046 \section2 Memory and Performance
2047
2048 When an item's layer is enabled, the scene graph will allocate memory
2049 in the GPU equal to \c {width x height x 4}. In memory constrained
2050 configurations, large layers should be used with care.
2051
2052 In the QPainter / QWidget world, it is sometimes favorable to
2053 cache complex content in a pixmap, image or texture. In Qt Quick,
2054 because of the techniques already applied by the \l {Qt Quick
2055 Scene Graph Default Renderer} {scene graph renderer}, this will in most
2056 cases not be the case. Excessive draw calls are already reduced
2057 because of batching and a cache will in most cases end up blending
2058 more pixels than the original content. The overhead of rendering
2059 to an offscreen and the blending involved with drawing the
2060 resulting texture is therefore often more costly than simply
2061 letting the item and its children be drawn normally.
2062
2063 Also, an item using a layer can not be \l {Batching} {batched} during
2064 rendering. This means that a scene with many layered items may
2065 have performance problems.
2066
2067 Layering can be convenient and useful for visual effects, but
2068 should in most cases be enabled for the duration of the effect and
2069 disabled afterwards.
2070
2071*/
2072
2073/*!
2074 \enum QQuickItem::Flag
2075
2076 This enum type is used to specify various item properties.
2077
2078 \value ItemClipsChildrenToShape Indicates this item should visually clip
2079 its children so that they are rendered only within the boundaries of this
2080 item.
2081 \value ItemAcceptsInputMethod Indicates the item supports text input
2082 methods.
2083 \value ItemIsFocusScope Indicates the item is a focus scope. See
2084 \l {Keyboard Focus in Qt Quick} for more information.
2085 \value ItemHasContents Indicates the item has visual content and should be
2086 rendered by the scene graph.
2087 \value ItemAcceptsDrops Indicates the item accepts drag and drop events.
2088 \value ItemIsViewport Indicates that the item defines a viewport for its children.
2089 \value ItemObservesViewport Indicates that the item wishes to know the
2090 viewport bounds when any ancestor has the ItemIsViewport flag set.
2091
2092 \sa setFlag(), setFlags(), flags()
2093*/
2094
2095/*!
2096 \enum QQuickItem::ItemChange
2097 \brief Used in conjunction with QQuickItem::itemChange() to notify
2098 the item about certain types of changes.
2099
2100 \value ItemChildAddedChange A child was added. ItemChangeData::item contains
2101 the added child.
2102
2103 \value ItemChildRemovedChange A child was removed. ItemChangeData::item
2104 contains the removed child.
2105
2106 \value ItemSceneChange The item was added to or removed from a scene. The
2107 QQuickWindow rendering the scene is specified in using ItemChangeData::window.
2108 The window parameter is null when the item is removed from a scene.
2109
2110 \value ItemVisibleHasChanged The item's visibility has changed.
2111 ItemChangeData::boolValue contains the new visibility.
2112
2113 \value ItemParentHasChanged The item's parent has changed.
2114 ItemChangeData::item contains the new parent.
2115
2116 \value ItemOpacityHasChanged The item's opacity has changed.
2117 ItemChangeData::realValue contains the new opacity.
2118
2119 \value ItemActiveFocusHasChanged The item's focus has changed.
2120 ItemChangeData::boolValue contains whether the item has focus or not.
2121
2122 \value ItemRotationHasChanged The item's rotation has changed.
2123 ItemChangeData::realValue contains the new rotation.
2124
2125 \value ItemDevicePixelRatioHasChanged The device pixel ratio of the screen
2126 the item is on has changed. ItemChangedData::realValue contains the new
2127 device pixel ratio.
2128
2129 \value ItemAntialiasingHasChanged The antialiasing has changed. The current
2130 (boolean) value can be found in QQuickItem::antialiasing.
2131
2132 \value ItemEnabledHasChanged The item's enabled state has changed.
2133 ItemChangeData::boolValue contains the new enabled state. (since Qt 5.10)
2134
2135 \value ItemScaleHasChanged The item's scale has changed.
2136 ItemChangeData::realValue contains the scale. (since Qt 6.9)
2137
2138 \value ItemTransformHasChanged The item's transform has changed. This
2139 occurs when the item's position, size, rotation, scale, transformOrigin
2140 or attached transforms change. ItemChangeData::item contains the item
2141 that caused the change. (since Qt 6.9)
2142*/
2143
2144/*!
2145 \class QQuickItem::ItemChangeData
2146 \inmodule QtQuick
2147 \brief Adds supplementary information to the QQuickItem::itemChange()
2148 function.
2149
2150 The meaning of each member of this class is defined by the change type.
2151
2152 \sa QQuickItem::ItemChange
2153*/
2154
2155/*!
2156 \fn QQuickItem::ItemChangeData::ItemChangeData(QQuickItem *)
2157 \internal
2158 */
2159
2160/*!
2161 \fn QQuickItem::ItemChangeData::ItemChangeData(QQuickWindow *)
2162 \internal
2163 */
2164
2165/*!
2166 \fn QQuickItem::ItemChangeData::ItemChangeData(qreal)
2167 \internal
2168 */
2169
2170/*!
2171 \fn QQuickItem::ItemChangeData::ItemChangeData(bool)
2172 \internal
2173 */
2174
2175/*!
2176 \variable QQuickItem::ItemChangeData::realValue
2177 The numeric value that has changed: \l {QQuickItem::opacity()}{opacity},
2178 \l {QQuickItem::rotation()}{rotation}, or
2179 \l {QQuickItem::scale()}{scale}, or
2180 \l {QScreen::devicePixelRatio}{device pixel ratio}.
2181 \sa QQuickItem::ItemChange
2182 */
2183
2184/*!
2185 \variable QQuickItem::ItemChangeData::boolValue
2186 The boolean value that has changed: \l {QQuickItem::isVisible()}{visible},
2187 \l {QQuickItem::isEnabled()}{enabled}, \l {QQuickItem::hasActiveFocus()}{activeFocus},
2188 or \l {QQuickItem::antialiasing()}{antialiasing}.
2189 \sa QQuickItem::ItemChange
2190 */
2191
2192/*!
2193 \variable QQuickItem::ItemChangeData::item
2194 The item that has been added or removed as a \l{QQuickItem::childItems()}{child},
2195 or the new \l{QQuickItem::parentItem()}{parent}.
2196 \sa QQuickItem::ItemChange
2197 */
2198
2199/*!
2200 \variable QQuickItem::ItemChangeData::window
2201 The \l{QQuickWindow}{window} in which the item has been shown, or \c nullptr
2202 if the item has been removed from a window.
2203 \sa QQuickItem::ItemChange
2204 */
2205
2206/*!
2207 \enum QQuickItem::TransformOrigin
2208
2209 Controls the point about which simple transforms like scale apply.
2210
2211 \value TopLeft The top-left corner of the item.
2212 \value Top The center point of the top of the item.
2213 \value TopRight The top-right corner of the item.
2214 \value Left The left most point of the vertical middle.
2215 \value Center The center of the item.
2216 \value Right The right most point of the vertical middle.
2217 \value BottomLeft The bottom-left corner of the item.
2218 \value Bottom The center point of the bottom of the item.
2219 \value BottomRight The bottom-right corner of the item.
2220
2221 \sa transformOrigin(), setTransformOrigin()
2222*/
2223
2224/*!
2225 \fn void QQuickItem::childrenRectChanged(const QRectF &)
2226 \internal
2227*/
2228
2229/*!
2230 \fn void QQuickItem::baselineOffsetChanged(qreal)
2231 \internal
2232*/
2233
2234/*!
2235 \fn void QQuickItem::stateChanged(const QString &state)
2236 \internal
2237*/
2238
2239/*!
2240 \fn void QQuickItem::parentChanged(QQuickItem *)
2241 \internal
2242*/
2243
2244/*!
2245 \fn void QQuickItem::smoothChanged(bool)
2246 \internal
2247*/
2248
2249/*!
2250 \fn void QQuickItem::antialiasingChanged(bool)
2251 \internal
2252*/
2253
2254/*!
2255 \fn void QQuickItem::clipChanged(bool)
2256 \internal
2257*/
2258
2259/*!
2260 \fn void QQuickItem::transformOriginChanged(TransformOrigin)
2261 \internal
2262*/
2263
2264/*!
2265 \fn void QQuickItem::focusChanged(bool)
2266 \internal
2267*/
2268
2269/*!
2270 \fn void QQuickItem::activeFocusChanged(bool)
2271 \internal
2272*/
2273
2274/*!
2275 \fn void QQuickItem::focusPolicyChanged(Qt::FocusPolicy)
2276 \internal
2277*/
2278
2279/*!
2280 \fn void QQuickItem::activeFocusOnTabChanged(bool)
2281 \internal
2282*/
2283
2284/*!
2285 \fn void QQuickItem::childrenChanged()
2286 \internal
2287*/
2288
2289/*!
2290 \fn void QQuickItem::opacityChanged()
2291 \internal
2292*/
2293
2294/*!
2295 \fn void QQuickItem::enabledChanged()
2296 \internal
2297*/
2298
2299/*!
2300 \fn void QQuickItem::visibleChanged()
2301 \internal
2302*/
2303
2304/*!
2305 \fn void QQuickItem::visibleChildrenChanged()
2306 \internal
2307*/
2308
2309/*!
2310 \fn void QQuickItem::rotationChanged()
2311 \internal
2312*/
2313
2314/*!
2315 \fn void QQuickItem::scaleChanged()
2316 \internal
2317*/
2318
2319/*!
2320 \fn void QQuickItem::xChanged()
2321 \internal
2322*/
2323
2324/*!
2325 \fn void QQuickItem::yChanged()
2326 \internal
2327*/
2328
2329/*!
2330 \fn void QQuickItem::widthChanged()
2331 \internal
2332*/
2333
2334/*!
2335 \fn void QQuickItem::heightChanged()
2336 \internal
2337*/
2338
2339/*!
2340 \fn void QQuickItem::zChanged()
2341 \internal
2342*/
2343
2344/*!
2345 \fn void QQuickItem::implicitWidthChanged()
2346 \internal
2347*/
2348
2349/*!
2350 \fn void QQuickItem::implicitHeightChanged()
2351 \internal
2352*/
2353
2354/*!
2355 \fn QQuickItem::QQuickItem(QQuickItem *parent)
2356
2357 Constructs a QQuickItem with the given \a parent.
2358
2359 The \c parent will be used as both the \l {setParentItem()}{visual parent}
2360 and the \l QObject parent.
2361*/
2362QQuickItem::QQuickItem(QQuickItem* parent)
2363: QObject(*(new QQuickItemPrivate), parent)
2364{
2365 Q_D(QQuickItem);
2366 d->init(parent);
2367}
2368
2369/*! \internal
2370*/
2371QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent)
2372: QObject(dd, parent)
2373{
2374 Q_D(QQuickItem);
2375 d->init(parent);
2376}
2377
2378/*!
2379 Destroys the QQuickItem.
2380*/
2381QQuickItem::~QQuickItem()
2382{
2383 Q_D(QQuickItem);
2384 d->inDestructor = true;
2385
2386 if (d->windowRefCount > 1)
2387 d->windowRefCount = 1; // Make sure window is set to null in next call to derefWindow().
2388 if (d->parentItem)
2389 setParentItem(nullptr);
2390 else if (d->window)
2391 d->derefWindow();
2392
2393 for (QQuickItem *child : std::as_const(t&: d->childItems))
2394 child->setParentItem(nullptr);
2395 d->childItems.clear();
2396
2397 d->notifyChangeListeners(changeTypes: QQuickItemPrivate::AllChanges, function: [this](const QQuickItemPrivate::ChangeListener &change){
2398 QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
2399 if (anchor)
2400 anchor->clearItem(this);
2401 });
2402 /*
2403 update item anchors that depended on us unless they are our child (and will also be destroyed),
2404 or our sibling, and our parent is also being destroyed.
2405 */
2406 d->notifyChangeListeners(changeTypes: QQuickItemPrivate::AllChanges, function: [this](const QQuickItemPrivate::ChangeListener &change){
2407 QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
2408 if (anchor && anchor->item && anchor->item->parentItem() && anchor->item->parentItem() != this)
2409 anchor->update();
2410 });
2411 d->notifyChangeListeners(changeTypes: QQuickItemPrivate::Destroyed, function: &QQuickItemChangeListener::itemDestroyed, args: this);
2412 d->changeListeners.clear();
2413
2414 /*
2415 Remove any references our transforms have to us, in case they try to
2416 remove themselves from our list of transforms when that list has already
2417 been destroyed after ~QQuickItem() has run.
2418 */
2419 for (int ii = 0; ii < d->transforms.size(); ++ii) {
2420 QQuickTransform *t = d->transforms.at(i: ii);
2421 QQuickTransformPrivate *tp = QQuickTransformPrivate::get(transform: t);
2422 tp->items.removeOne(t: this);
2423 }
2424
2425 if (d->extra.isAllocated()) {
2426 delete d->extra->contents; d->extra->contents = nullptr;
2427#if QT_CONFIG(quick_shadereffect)
2428 delete d->extra->layer; d->extra->layer = nullptr;
2429#endif
2430 }
2431
2432 delete d->_anchors; d->_anchors = nullptr;
2433 delete d->_stateGroup; d->_stateGroup = nullptr;
2434
2435 d->isQuickItem = false;
2436}
2437
2438/*!
2439 \internal
2440*/
2441bool QQuickItemPrivate::canAcceptTabFocus(QQuickItem *item)
2442{
2443 if (!item->window())
2444 return false;
2445
2446 if (item == item->window()->contentItem())
2447 return true;
2448
2449 const auto tabFocus = QGuiApplication::styleHints()->tabFocusBehavior();
2450 if (tabFocus == Qt::NoTabFocus)
2451 return false;
2452 if (tabFocus == Qt::TabFocusAllControls)
2453 return true;
2454
2455 QVariant editable = item->property(name: "editable");
2456 if (editable.isValid())
2457 return editable.toBool();
2458
2459 QVariant readonly = item->property(name: "readOnly");
2460 if (readonly.isValid())
2461 return !readonly.toBool() && item->property(name: "text").isValid();
2462
2463#if QT_CONFIG(accessibility)
2464 QAccessible::Role role = QQuickItemPrivate::get(item)->effectiveAccessibleRole();
2465 if (role == QAccessible::EditableText || role == QAccessible::Table || role == QAccessible::List) {
2466 return true;
2467 } else if (role == QAccessible::ComboBox || role == QAccessible::SpinBox) {
2468 if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(item))
2469 return iface->state().editable;
2470 }
2471#endif
2472
2473 return false;
2474}
2475
2476/*!
2477 \internal
2478 \brief QQuickItemPrivate::focusNextPrev focuses the next/prev item in the tab-focus-chain
2479 \param item The item that currently has the focus
2480 \param forward The direction
2481 \return Whether the next item in the focus chain is found or not
2482
2483 If \a next is true, the next item visited will be in depth-first order relative to \a item.
2484 If \a next is false, the next item visited will be in reverse depth-first order relative to \a item.
2485*/
2486bool QQuickItemPrivate::focusNextPrev(QQuickItem *item, bool forward)
2487{
2488 QQuickWindow *window = item->window();
2489 const bool wrap = !window || window->isTopLevel();
2490
2491 QQuickItem *next = QQuickItemPrivate::nextPrevItemInTabFocusChain(item, forward, wrap);
2492
2493 if (next == item)
2494 return false;
2495
2496 const auto reason = forward ? Qt::TabFocusReason : Qt::BacktabFocusReason;
2497
2498 if (!wrap && !next) {
2499 // Focus chain wrapped and we are not top-level window
2500 // Give focus to parent window
2501 Q_ASSERT(window);
2502 Q_ASSERT(window->parent());
2503
2504
2505 qt_window_private(window: window->parent())->setFocusToTarget(
2506 forward ? QWindowPrivate::FocusTarget::Next
2507 : QWindowPrivate::FocusTarget::Prev,
2508 reason);
2509 window->parent()->requestActivate();
2510 return true;
2511 }
2512
2513 next->forceActiveFocus(reason);
2514
2515 return true;
2516}
2517
2518QQuickItem *QQuickItemPrivate::nextTabChildItem(const QQuickItem *item, int start)
2519{
2520 if (!item) {
2521 qWarning() << "QQuickItemPrivate::nextTabChildItem called with null item.";
2522 return nullptr;
2523 }
2524 const QList<QQuickItem *> &children = item->childItems();
2525 const int count = children.size();
2526 if (start < 0 || start >= count) {
2527 qWarning() << "QQuickItemPrivate::nextTabChildItem: Start index value out of range for item" << item;
2528 return nullptr;
2529 }
2530 while (start < count) {
2531 QQuickItem *child = children.at(i: start);
2532 if (!child->d_func()->isTabFence)
2533 return child;
2534 ++start;
2535 }
2536 return nullptr;
2537}
2538
2539QQuickItem *QQuickItemPrivate::prevTabChildItem(const QQuickItem *item, int start)
2540{
2541 if (!item) {
2542 qWarning() << "QQuickItemPrivate::prevTabChildItem called with null item.";
2543 return nullptr;
2544 }
2545 const QList<QQuickItem *> &children = item->childItems();
2546 const int count = children.size();
2547 if (start == -1)
2548 start = count - 1;
2549 if (start < 0 || start >= count) {
2550 qWarning() << "QQuickItemPrivate::prevTabChildItem: Start index value out of range for item" << item;
2551 return nullptr;
2552 }
2553 while (start >= 0) {
2554 QQuickItem *child = children.at(i: start);
2555 if (!child->d_func()->isTabFence)
2556 return child;
2557 --start;
2558 }
2559 return nullptr;
2560}
2561
2562QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, bool forward, bool wrap)
2563{
2564 Q_ASSERT(item);
2565 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: item:" << item << ", forward:" << forward;
2566
2567 if (!item->window())
2568 return item;
2569 const QQuickItem * const contentItem = item->window()->contentItem();
2570 if (!contentItem)
2571 return item;
2572
2573 QQuickItem *from = nullptr;
2574 bool isTabFence = item->d_func()->isTabFence;
2575 if (forward) {
2576 if (!isTabFence)
2577 from = item->parentItem();
2578 } else {
2579 if (!item->childItems().isEmpty())
2580 from = item->d_func()->childItems.constFirst();
2581 else if (!isTabFence)
2582 from = item->parentItem();
2583 }
2584 bool skip = false;
2585
2586 QQuickItem *startItem = item;
2587 QQuickItem *originalStartItem = startItem;
2588 // Protect from endless loop:
2589 // If we start on an invisible item we will not find it again.
2590 // If there is no other item which can become the focus item, we have a forever loop,
2591 // since the protection only works if we encounter the first item again.
2592 while (startItem && !startItem->isVisible()) {
2593 startItem = startItem->parentItem();
2594 }
2595 if (!startItem)
2596 return item;
2597
2598 QQuickItem *firstFromItem = from;
2599 QQuickItem *current = item;
2600 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: startItem:" << startItem;
2601 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: firstFromItem:" << firstFromItem;
2602 QDuplicateTracker<QQuickItem *> cycleDetector;
2603 do {
2604 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: current:" << current;
2605 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: from:" << from;
2606 skip = false;
2607 QQuickItem *last = current;
2608
2609 bool hasChildren = !current->childItems().isEmpty() && current->isEnabled() && current->isVisible();
2610 QQuickItem *firstChild = nullptr;
2611 QQuickItem *lastChild = nullptr;
2612 if (hasChildren) {
2613 firstChild = nextTabChildItem(item: current, start: 0);
2614 if (!firstChild)
2615 hasChildren = false;
2616 else
2617 lastChild = prevTabChildItem(item: current, start: -1);
2618 }
2619 isTabFence = current->d_func()->isTabFence;
2620 if (isTabFence && !hasChildren)
2621 return current;
2622
2623 // coming from parent: check children
2624 if (hasChildren && from == current->parentItem()) {
2625 if (forward) {
2626 current = firstChild;
2627 } else {
2628 current = lastChild;
2629 if (!current->childItems().isEmpty())
2630 skip = true;
2631 }
2632 } else if (hasChildren && forward && from != lastChild) {
2633 // not last child going forwards
2634 int nextChild = current->childItems().indexOf(t: from) + 1;
2635 current = nextTabChildItem(item: current, start: nextChild);
2636 } else if (hasChildren && !forward && from != firstChild) {
2637 // not first child going backwards
2638 int prevChild = current->childItems().indexOf(t: from) - 1;
2639 current = prevTabChildItem(item: current, start: prevChild);
2640 if (!current->childItems().isEmpty())
2641 skip = true;
2642 // back to the parent
2643 } else if (QQuickItem *parent = !isTabFence ? current->parentItem() : nullptr) {
2644 // we would evaluate the parent twice, thus we skip
2645 if (forward) {
2646 skip = true;
2647 } else if (QQuickItem *firstSibling = !forward ? nextTabChildItem(item: parent, start: 0) : nullptr) {
2648 if (last != firstSibling
2649 || (parent->isFocusScope() && parent->activeFocusOnTab() && parent->hasActiveFocus()))
2650 skip = true;
2651 }
2652 current = parent;
2653 } else if (hasChildren) {
2654 if (!wrap) {
2655 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain:"
2656 << "Focus chain about to wrap but wrapping was set to false."
2657 << "Returning.";
2658 return nullptr;
2659 }
2660
2661 // Wrap around after checking all items forward
2662 if (forward) {
2663 current = firstChild;
2664 } else {
2665 current = lastChild;
2666 if (!current->childItems().isEmpty())
2667 skip = true;
2668 }
2669 }
2670 from = last;
2671 // if [from] item is equal to [firstFromItem], means we have traversed one path and
2672 // jump back to parent of the chain, and then we have to check whether we have
2673 // traversed all of the chain (by compare the [current] item with [startItem])
2674 // Since the [startItem] might be promoted to its parent if it is invisible,
2675 // we still have to check [current] item with original start item
2676 // We might also run into a cycle before we reach firstFromItem again
2677 // but note that we have to ignore current if we are meant to skip it
2678 if (((current == startItem || current == originalStartItem) && from == firstFromItem) ||
2679 (!skip && cycleDetector.hasSeen(s: current))) {
2680 // wrapped around, avoid endless loops
2681 if (item == contentItem) {
2682 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem";
2683 return item;
2684 } else {
2685 qCDebug(lcFocus) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return " << startItem;
2686 return startItem;
2687 }
2688 }
2689 if (!firstFromItem) {
2690 if (startItem->d_func()->isTabFence) {
2691 if (current == startItem)
2692 firstFromItem = from;
2693 } else { //start from root
2694 startItem = current;
2695 firstFromItem = from;
2696 }
2697 }
2698 } while (skip || !current->activeFocusOnTab() || !current->isEnabled() || !current->isVisible()
2699 || !(QQuickItemPrivate::canAcceptTabFocus(item: current)));
2700
2701 return current;
2702}
2703
2704/*!
2705 \qmlproperty Item QtQuick::Item::parent
2706 This property holds the visual parent of the item.
2707
2708 \note The concept of the \e {visual parent} differs from that of the
2709 \e {QObject parent}. An item's visual parent may not necessarily be the
2710 same as its object parent. See \l {Concepts - Visual Parent in Qt Quick}
2711 for more details.
2712*/
2713/*!
2714 \property QQuickItem::parent
2715 This property holds the visual parent of the item.
2716
2717 \note The concept of the \e {visual parent} differs from that of the
2718 \e {QObject parent}. An item's visual parent may not necessarily be the
2719 same as its object parent. See \l {Concepts - Visual Parent in Qt Quick}
2720 for more details.
2721
2722 \note The notification signal for this property gets emitted during destruction
2723 of the visual parent. C++ signal handlers cannot assume that items in the
2724 visual parent hierarchy are still fully constructed. Use \l qobject_cast to
2725 verify that items in the parent hierarchy can be used safely as the expected
2726 type.
2727*/
2728QQuickItem *QQuickItem::parentItem() const
2729{
2730 Q_D(const QQuickItem);
2731 return d->parentItem;
2732}
2733
2734void QQuickItem::setParentItem(QQuickItem *parentItem)
2735{
2736 Q_D(QQuickItem);
2737 if (parentItem == d->parentItem)
2738 return;
2739
2740 if (parentItem) {
2741 QQuickItem *itemAncestor = parentItem;
2742 while (itemAncestor != nullptr) {
2743 if (Q_UNLIKELY(itemAncestor == this)) {
2744 qWarning() << "QQuickItem::setParentItem: Parent" << parentItem << "is already part of the subtree of" << this;
2745 return;
2746 }
2747 itemAncestor = itemAncestor->parentItem();
2748 }
2749 auto engine = qmlEngine(this);
2750 if (engine) {
2751 QV4::ExecutionEngine *v4 = engine->handle();
2752 QV4::WriteBarrier::markCustom(engine: v4, markFunction: [this](QV4::MarkStack *ms){
2753 QV4::QObjectWrapper::markWrapper(object: this, markStack: ms);
2754 });
2755 }
2756 }
2757
2758 d->removeFromDirtyList();
2759
2760 QQuickItem *oldParentItem = d->parentItem;
2761 QQuickItem *scopeFocusedItem = nullptr;
2762
2763 if (oldParentItem) {
2764 QQuickItemPrivate *op = QQuickItemPrivate::get(item: oldParentItem);
2765
2766 QQuickItem *scopeItem = nullptr;
2767
2768 if (hasFocus() || op->subFocusItem == this)
2769 scopeFocusedItem = this;
2770 else if (!isFocusScope() && d->subFocusItem)
2771 scopeFocusedItem = d->subFocusItem;
2772
2773 if (scopeFocusedItem) {
2774 scopeItem = oldParentItem;
2775 while (!scopeItem->isFocusScope() && scopeItem->parentItem())
2776 scopeItem = scopeItem->parentItem();
2777 if (d->window) {
2778 if (QQuickDeliveryAgentPrivate *da = d->deliveryAgentPrivate()) {
2779 da->clearFocusInScope(scope: scopeItem, item: scopeFocusedItem, reason: Qt::OtherFocusReason,
2780 QQuickDeliveryAgentPrivate::DontChangeFocusProperty);
2781 }
2782 if (scopeFocusedItem != this)
2783 QQuickItemPrivate::get(item: scopeFocusedItem)->updateSubFocusItem(scope: this, focus: true);
2784 } else {
2785 QQuickItemPrivate::get(item: scopeFocusedItem)->updateSubFocusItem(scope: scopeItem, focus: false);
2786 }
2787 }
2788
2789 const bool wasVisible = isVisible();
2790 op->removeChild(this);
2791 if (wasVisible && !op->inDestructor)
2792 emit oldParentItem->visibleChildrenChanged();
2793 } else if (d->window) {
2794 QQuickWindowPrivate::get(c: d->window)->parentlessItems.remove(value: this);
2795 }
2796
2797 QQuickWindow *parentWindow = parentItem ? QQuickItemPrivate::get(item: parentItem)->window : nullptr;
2798 bool alreadyAddedChild = false;
2799 if (d->window == parentWindow) {
2800 // Avoid freeing and reallocating resources if the window stays the same.
2801 d->parentItem = parentItem;
2802 } else {
2803 auto oldParentItem = d->parentItem;
2804 d->parentItem = parentItem;
2805 if (d->parentItem) {
2806 QQuickItemPrivate::get(item: d->parentItem)->addChild(this);
2807 alreadyAddedChild = true;
2808 }
2809 if (d->window) {
2810 d->derefWindow();
2811 // as we potentially changed d->parentWindow above
2812 // the check in derefWindow could not work
2813 // thus, we redo it here with the old parent
2814 // Also, the window may have been deleted by derefWindow()
2815 if (!oldParentItem && d->window) {
2816 QQuickWindowPrivate::get(c: d->window)->parentlessItems.remove(value: this);
2817 }
2818 }
2819 if (parentWindow)
2820 d->refWindow(parentWindow);
2821 }
2822
2823 d->dirty(QQuickItemPrivate::ParentChanged);
2824
2825 if (d->parentItem && !alreadyAddedChild)
2826 QQuickItemPrivate::get(item: d->parentItem)->addChild(this);
2827 else if (d->window && !alreadyAddedChild)
2828 QQuickWindowPrivate::get(c: d->window)->parentlessItems.insert(value: this);
2829
2830 d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
2831 d->setEffectiveEnableRecur(scope: nullptr, d->calcEffectiveEnable());
2832
2833 if (d->parentItem) {
2834 if (!scopeFocusedItem) {
2835 if (hasFocus())
2836 scopeFocusedItem = this;
2837 else if (!isFocusScope() && d->subFocusItem)
2838 scopeFocusedItem = d->subFocusItem;
2839 }
2840
2841 if (scopeFocusedItem) {
2842 // We need to test whether this item becomes scope focused
2843 QQuickItem *scopeItem = d->parentItem;
2844 while (!scopeItem->isFocusScope() && scopeItem->parentItem())
2845 scopeItem = scopeItem->parentItem();
2846
2847 if (QQuickItemPrivate::get(item: scopeItem)->subFocusItem
2848 || (!scopeItem->isFocusScope() && scopeItem->hasFocus())) {
2849 if (scopeFocusedItem != this)
2850 QQuickItemPrivate::get(item: scopeFocusedItem)->updateSubFocusItem(scope: this, focus: false);
2851 QQuickItemPrivate::get(item: scopeFocusedItem)->focus = false;
2852 emit scopeFocusedItem->focusChanged(false);
2853 } else {
2854 if (d->window) {
2855 if (QQuickDeliveryAgentPrivate *da = d->deliveryAgentPrivate()) {
2856 da->setFocusInScope(scope: scopeItem, item: scopeFocusedItem, reason: Qt::OtherFocusReason,
2857 QQuickDeliveryAgentPrivate::DontChangeFocusProperty);
2858 }
2859 } else {
2860 QQuickItemPrivate::get(item: scopeFocusedItem)->updateSubFocusItem(scope: scopeItem, focus: true);
2861 }
2862 }
2863 }
2864 }
2865
2866 if (d->parentItem)
2867 d->resolveLayoutMirror();
2868
2869 d->itemChange(ItemParentHasChanged, d->parentItem);
2870
2871 if (!d->inDestructor)
2872 emit parentChanged(d->parentItem);
2873 if (isVisible() && d->parentItem && !QQuickItemPrivate::get(item: d->parentItem)->inDestructor)
2874 emit d->parentItem->visibleChildrenChanged();
2875}
2876
2877/*!
2878 Moves this item to the index before the specified
2879 sibling item within the list of children.
2880 The order of children affects both the
2881 visual stacking order and tab focus navigation order.
2882
2883 Assuming the z values of both items are the same, this will cause \a
2884 sibling to be rendered above this item.
2885
2886 If both items have activeFocusOnTab set to \c true, this will also cause
2887 the tab focus order to change, with \a sibling receiving focus after this
2888 item.
2889
2890 The given \a sibling must be a sibling of this item; that is, they must
2891 have the same immediate \l parent.
2892
2893 \sa {Concepts - Visual Parent in Qt Quick}
2894*/
2895void QQuickItem::stackBefore(const QQuickItem *sibling)
2896{
2897 Q_D(QQuickItem);
2898 if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(item: sibling)->parentItem) {
2899 qWarning().nospace() << "QQuickItem::stackBefore: Cannot stack "
2900 << this << " before " << sibling << ", which must be a sibling";
2901 return;
2902 }
2903
2904 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(item: d->parentItem);
2905
2906 int myIndex = parentPrivate->childItems.lastIndexOf(t: this);
2907 int siblingIndex = parentPrivate->childItems.lastIndexOf(t: const_cast<QQuickItem *>(sibling));
2908
2909 Q_ASSERT(myIndex != -1 && siblingIndex != -1);
2910
2911 if (myIndex == siblingIndex - 1)
2912 return;
2913
2914 parentPrivate->childItems.move(from: myIndex, to: myIndex < siblingIndex ? siblingIndex - 1 : siblingIndex);
2915
2916 parentPrivate->markSortedChildrenDirty(child: this);
2917 parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
2918
2919 for (int ii = qMin(a: siblingIndex, b: myIndex); ii < parentPrivate->childItems.size(); ++ii)
2920 QQuickItemPrivate::get(item: parentPrivate->childItems.at(i: ii))->siblingOrderChanged();
2921}
2922
2923/*!
2924 Moves this item to the index after the specified
2925 sibling item within the list of children.
2926 The order of children affects both the
2927 visual stacking order and tab focus navigation order.
2928
2929 Assuming the z values of both items are the same, this will cause \a
2930 sibling to be rendered below this item.
2931
2932 If both items have activeFocusOnTab set to \c true, this will also cause
2933 the tab focus order to change, with \a sibling receiving focus before this
2934 item.
2935
2936 The given \a sibling must be a sibling of this item; that is, they must
2937 have the same immediate \l parent.
2938
2939 \sa {Concepts - Visual Parent in Qt Quick}
2940*/
2941void QQuickItem::stackAfter(const QQuickItem *sibling)
2942{
2943 Q_D(QQuickItem);
2944 if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(item: sibling)->parentItem) {
2945 qWarning().nospace() << "QQuickItem::stackAfter: Cannot stack "
2946 << this << " after " << sibling << ", which must be a sibling";
2947 return;
2948 }
2949
2950 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(item: d->parentItem);
2951
2952 int myIndex = parentPrivate->childItems.lastIndexOf(t: this);
2953 int siblingIndex = parentPrivate->childItems.lastIndexOf(t: const_cast<QQuickItem *>(sibling));
2954
2955 Q_ASSERT(myIndex != -1 && siblingIndex != -1);
2956
2957 if (myIndex == siblingIndex + 1)
2958 return;
2959
2960 parentPrivate->childItems.move(from: myIndex, to: myIndex > siblingIndex ? siblingIndex + 1 : siblingIndex);
2961
2962 parentPrivate->markSortedChildrenDirty(child: this);
2963 parentPrivate->dirty(QQuickItemPrivate::ChildrenStackingChanged);
2964
2965 for (int ii = qMin(a: myIndex, b: siblingIndex + 1); ii < parentPrivate->childItems.size(); ++ii)
2966 QQuickItemPrivate::get(item: parentPrivate->childItems.at(i: ii))->siblingOrderChanged();
2967}
2968
2969/*! \fn void QQuickItem::windowChanged(QQuickWindow *window)
2970 This signal is emitted when the item's \a window changes.
2971*/
2972
2973/*!
2974 Returns the window in which this item is rendered.
2975
2976 The item does not have a window until it has been assigned into a scene. The
2977 \l windowChanged() signal provides a notification both when the item is entered
2978 into a scene and when it is removed from a scene.
2979 */
2980QQuickWindow *QQuickItem::window() const
2981{
2982 Q_D(const QQuickItem);
2983 return d->window;
2984}
2985
2986static bool itemZOrder_sort(QQuickItem *lhs, QQuickItem *rhs)
2987{
2988 return lhs->z() < rhs->z();
2989}
2990
2991QList<QQuickItem *> QQuickItemPrivate::paintOrderChildItems() const
2992{
2993 if (sortedChildItems)
2994 return *sortedChildItems;
2995
2996 // If none of the items have set Z then the paint order list is the same as
2997 // the childItems list. This is by far the most common case.
2998 bool haveZ = false;
2999 for (int i = 0; i < childItems.size(); ++i) {
3000 if (QQuickItemPrivate::get(item: childItems.at(i))->z() != 0.) {
3001 haveZ = true;
3002 break;
3003 }
3004 }
3005 if (haveZ) {
3006 sortedChildItems = new QList<QQuickItem*>(childItems);
3007 std::stable_sort(first: sortedChildItems->begin(), last: sortedChildItems->end(), comp: itemZOrder_sort);
3008 return *sortedChildItems;
3009 }
3010
3011 sortedChildItems = const_cast<QList<QQuickItem*>*>(&childItems);
3012
3013 return childItems;
3014}
3015
3016void QQuickItemPrivate::addChild(QQuickItem *child)
3017{
3018 Q_Q(QQuickItem);
3019
3020 Q_ASSERT(!childItems.contains(child));
3021
3022 childItems.append(t: child);
3023
3024 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(item: child);
3025
3026#if QT_CONFIG(cursor)
3027 // if the added child has a cursor and we do not currently have any children
3028 // with cursors, bubble the notification up
3029 if (childPrivate->subtreeCursorEnabled && !subtreeCursorEnabled)
3030 setHasCursorInChild(true);
3031#endif
3032
3033 if (childPrivate->subtreeHoverEnabled && !subtreeHoverEnabled)
3034 setHasHoverInChild(true);
3035
3036 childPrivate->recursiveRefFromEffectItem(refs: extra.value().recursiveEffectRefCount);
3037 markSortedChildrenDirty(child);
3038 dirty(QQuickItemPrivate::ChildrenChanged);
3039
3040 itemChange(QQuickItem::ItemChildAddedChange, child);
3041
3042 emit q->childrenChanged();
3043}
3044
3045void QQuickItemPrivate::removeChild(QQuickItem *child)
3046{
3047 Q_Q(QQuickItem);
3048
3049 Q_ASSERT(child);
3050 if (!inDestructor) {
3051 // if we are getting destroyed, then the destructor will clear the list
3052 Q_ASSERT(childItems.contains(child));
3053 childItems.removeOne(t: child);
3054 Q_ASSERT(!childItems.contains(child));
3055 }
3056
3057 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(item: child);
3058
3059#if QT_CONFIG(cursor)
3060 // turn it off, if nothing else is using it
3061 if (childPrivate->subtreeCursorEnabled && subtreeCursorEnabled)
3062 setHasCursorInChild(false);
3063#endif
3064
3065 if (childPrivate->subtreeHoverEnabled && subtreeHoverEnabled)
3066 setHasHoverInChild(false);
3067
3068 childPrivate->recursiveRefFromEffectItem(refs: -extra.value().recursiveEffectRefCount);
3069 if (!inDestructor) {
3070 markSortedChildrenDirty(child);
3071 dirty(QQuickItemPrivate::ChildrenChanged);
3072 }
3073
3074 itemChange(QQuickItem::ItemChildRemovedChange, child);
3075
3076 if (!inDestructor)
3077 emit q->childrenChanged();
3078}
3079
3080void QQuickItemPrivate::refWindow(QQuickWindow *c)
3081{
3082 // An item needs a window if it is referenced by another item which has a window.
3083 // Typically the item is referenced by a parent, but can also be referenced by a
3084 // ShaderEffect or ShaderEffectSource. 'windowRefCount' counts how many items with
3085 // a window is referencing this item. When the reference count goes from zero to one,
3086 // or one to zero, the window of this item is updated and propagated to the children.
3087 // As long as the reference count stays above zero, the window is unchanged.
3088 // refWindow() increments the reference count.
3089 // derefWindow() decrements the reference count.
3090
3091 Q_Q(QQuickItem);
3092 Q_ASSERT((window != nullptr) == (windowRefCount > 0));
3093 Q_ASSERT(c);
3094 if (++windowRefCount > 1) {
3095 if (c != window)
3096 qWarning(msg: "QQuickItem: Cannot use same item on different windows at the same time.");
3097 return; // Window already set.
3098 }
3099
3100 Q_ASSERT(window == nullptr);
3101 window = c;
3102
3103 if (polishScheduled)
3104 QQuickWindowPrivate::get(c: window)->itemsToPolish.append(t: q);
3105
3106 if (!parentItem)
3107 QQuickWindowPrivate::get(c: window)->parentlessItems.insert(value: q);
3108
3109 for (int ii = 0; ii < childItems.size(); ++ii) {
3110 QQuickItem *child = childItems.at(i: ii);
3111 QQuickItemPrivate::get(item: child)->refWindow(c);
3112 }
3113
3114 dirty(Window);
3115
3116 if (extra.isAllocated() && extra->screenAttached)
3117 extra->screenAttached->windowChanged(c);
3118 itemChange(QQuickItem::ItemSceneChange, c);
3119}
3120
3121void QQuickItemPrivate::derefWindow()
3122{
3123 Q_Q(QQuickItem);
3124 Q_ASSERT((window != nullptr) == (windowRefCount > 0));
3125
3126 if (!window)
3127 return; // This can happen when destroying recursive shader effect sources.
3128
3129 if (--windowRefCount > 0)
3130 return; // There are still other references, so don't set window to null yet.
3131
3132 q->releaseResources();
3133 removeFromDirtyList();
3134 QQuickWindowPrivate *c = QQuickWindowPrivate::get(c: window);
3135 if (polishScheduled)
3136 c->itemsToPolish.removeOne(t: q);
3137#if QT_CONFIG(cursor)
3138 if (c->cursorItem == q) {
3139 c->cursorItem = nullptr;
3140 window->unsetCursor();
3141 }
3142#endif
3143 if (itemNodeInstance)
3144 c->cleanup(itemNodeInstance);
3145 if (!parentItem)
3146 c->parentlessItems.remove(value: q);
3147
3148 window = nullptr;
3149
3150 itemNodeInstance = nullptr;
3151
3152 if (extra.isAllocated()) {
3153 extra->opacityNode = nullptr;
3154 extra->clipNode = nullptr;
3155 extra->rootNode = nullptr;
3156 }
3157
3158 paintNode = nullptr;
3159
3160 for (int ii = 0; ii < childItems.size(); ++ii) {
3161 if (QQuickItem *child = childItems.at(i: ii))
3162 QQuickItemPrivate::get(item: child)->derefWindow();
3163 }
3164
3165 dirty(Window);
3166
3167 if (extra.isAllocated() && extra->screenAttached)
3168 extra->screenAttached->windowChanged(nullptr);
3169 itemChange(QQuickItem::ItemSceneChange, (QQuickWindow *)nullptr);
3170}
3171
3172qreal QQuickItemPrivate::effectiveDevicePixelRatio() const
3173{
3174 return (window ? window->effectiveDevicePixelRatio() : qApp->devicePixelRatio());
3175}
3176
3177/*!
3178 Returns a transform that maps points from window space into item space.
3179*/
3180QTransform QQuickItemPrivate::windowToItemTransform() const
3181{
3182 // XXX todo - optimize
3183 return itemToWindowTransform().inverted();
3184}
3185
3186/*!
3187 Returns a transform that maps points from item space into window space.
3188*/
3189QTransform QQuickItemPrivate::itemToWindowTransform() const
3190{
3191 // item's parent must not be itself, otherwise calling itemToWindowTransform() on it is infinite recursion
3192 Q_ASSERT(!parentItem || QQuickItemPrivate::get(parentItem) != this);
3193 QTransform rv = parentItem ? QQuickItemPrivate::get(item: parentItem)->itemToWindowTransform() : QTransform();
3194 itemToParentTransform(&rv);
3195 return rv;
3196}
3197
3198/*!
3199 Modifies \a t with this item's local transform relative to its parent.
3200*/
3201void QQuickItemPrivate::itemToParentTransform(QTransform *t) const
3202{
3203 /* Read the current x and y values. As this is an internal method,
3204 we don't care about it being usable in bindings. Instead, we
3205 care about performance here, and thus we read the value with
3206 valueBypassingBindings. This avoids any checks whether we are
3207 in a binding (which sholdn't be too expensive, but can add up).
3208 */
3209
3210 qreal x = this->x.valueBypassingBindings();
3211 qreal y = this->y.valueBypassingBindings();
3212 if (x || y)
3213 t->translate(dx: x, dy: y);
3214
3215 if (!transforms.isEmpty()) {
3216 QMatrix4x4 m(*t);
3217 for (int ii = transforms.size() - 1; ii >= 0; --ii)
3218 transforms.at(i: ii)->applyTo(matrix: &m);
3219 *t = m.toTransform();
3220 }
3221
3222 if (scale() != 1. || rotation() != 0.) {
3223 QPointF tp = computeTransformOrigin();
3224 t->translate(dx: tp.x(), dy: tp.y());
3225 t->scale(sx: scale(), sy: scale());
3226 t->rotate(a: rotation());
3227 t->translate(dx: -tp.x(), dy: -tp.y());
3228 }
3229}
3230
3231/*!
3232 Returns true if construction of the QML component is complete; otherwise
3233 returns false.
3234
3235 It is often desirable to delay some processing until the component is
3236 completed.
3237
3238 \sa componentComplete()
3239*/
3240bool QQuickItem::isComponentComplete() const
3241{
3242 Q_D(const QQuickItem);
3243 return d->componentComplete;
3244}
3245
3246QQuickItemPrivate::QQuickItemPrivate()
3247 : _anchors(nullptr)
3248 , _stateGroup(nullptr)
3249 , flags(0)
3250 , widthValidFlag(false)
3251 , heightValidFlag(false)
3252 , componentComplete(true)
3253 , keepMouse(false)
3254 , keepTouch(false)
3255 , hoverEnabled(false)
3256 , smooth(true)
3257 , antialiasing(false)
3258 , focus(false)
3259 , activeFocus(false)
3260 , notifiedFocus(false)
3261 , notifiedActiveFocus(false)
3262 , filtersChildMouseEvents(false)
3263 , explicitVisible(true)
3264 , effectiveVisible(true)
3265 , explicitEnable(true)
3266 , effectiveEnable(true)
3267 , polishScheduled(false)
3268 , inheritedLayoutMirror(false)
3269 , effectiveLayoutMirror(false)
3270 , isMirrorImplicit(true)
3271 , inheritMirrorFromParent(false)
3272 , inheritMirrorFromItem(false)
3273 , isAccessible(false)
3274 , culled(false)
3275 , hasCursor(false)
3276 , subtreeCursorEnabled(false)
3277 , subtreeHoverEnabled(false)
3278 , activeFocusOnTab(false)
3279 , implicitAntialiasing(false)
3280 , antialiasingValid(false)
3281 , isTabFence(false)
3282 , replayingPressEvent(false)
3283 , touchEnabled(false)
3284 , hasCursorHandler(false)
3285 , maybeHasSubsceneDeliveryAgent(true)
3286 , subtreeTransformChangedEnabled(true)
3287 , inDestructor(false)
3288 , focusReason(Qt::OtherFocusReason)
3289 , focusPolicy(Qt::NoFocus)
3290 , dirtyAttributes(0)
3291 , nextDirtyItem(nullptr)
3292 , prevDirtyItem(nullptr)
3293 , window(nullptr)
3294 , windowRefCount(0)
3295 , parentItem(nullptr)
3296 , sortedChildItems(&childItems)
3297 , subFocusItem(nullptr)
3298 , x(0)
3299 , y(0)
3300 , width(0)
3301 , height(0)
3302 , implicitWidth(0)
3303 , implicitHeight(0)
3304 , baselineOffset(0)
3305 , itemNodeInstance(nullptr)
3306 , paintNode(nullptr)
3307 , szPolicy(QLayoutPolicy::Fixed, QLayoutPolicy::Fixed)
3308{
3309}
3310
3311QQuickItemPrivate::~QQuickItemPrivate()
3312{
3313 if (sortedChildItems != &childItems)
3314 delete sortedChildItems;
3315}
3316
3317void QQuickItemPrivate::init(QQuickItem *parent)
3318{
3319 Q_Q(QQuickItem);
3320
3321 isQuickItem = true;
3322
3323 baselineOffset = 0.0;
3324
3325 if (parent) {
3326 q->setParentItem(parent);
3327 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(item: parent);
3328 setImplicitLayoutMirror(mirror: parentPrivate->inheritedLayoutMirror, inherit: parentPrivate->inheritMirrorFromParent);
3329 }
3330}
3331
3332QLayoutPolicy QQuickItemPrivate::sizePolicy() const
3333{
3334 return szPolicy;
3335}
3336
3337void QQuickItemPrivate::setSizePolicy(const QLayoutPolicy::Policy& horizontalPolicy, const QLayoutPolicy::Policy& verticalPolicy)
3338{
3339 szPolicy.setHorizontalPolicy(horizontalPolicy);
3340 szPolicy.setVerticalPolicy(verticalPolicy);
3341}
3342
3343void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
3344{
3345 if (!o)
3346 return;
3347
3348 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3349
3350 if (QQuickItem *item = qmlobject_cast<QQuickItem *>(object: o)) {
3351 item->setParentItem(that);
3352 } else if (QQuickPointerHandler *pointerHandler = qmlobject_cast<QQuickPointerHandler *>(object: o)) {
3353 if (pointerHandler->parent() != that) {
3354 qCDebug(lcHandlerParent) << "reparenting handler" << pointerHandler << ":" << pointerHandler->parent() << "->" << that;
3355 pointerHandler->setParent(that);
3356 }
3357 QQuickItemPrivate::get(item: that)->addPointerHandler(h: pointerHandler);
3358 } else {
3359 o->setParent(that);
3360 resources_append(prop, o);
3361 }
3362}
3363
3364/*!
3365 \qmlproperty list<QtObject> QtQuick::Item::data
3366 \qmldefault
3367
3368 The data property allows you to freely mix visual children and resources
3369 in an item. If you assign a visual item to the data list it becomes
3370 a child and if you assign any other object type, it is added as a resource.
3371
3372 So you can write:
3373 \qml
3374 Item {
3375 Text {}
3376 Rectangle {}
3377 Timer {}
3378 }
3379 \endqml
3380
3381 instead of:
3382 \qml
3383 Item {
3384 children: [
3385 Text {},
3386 Rectangle {}
3387 ]
3388 resources: [
3389 Timer {}
3390 ]
3391 }
3392 \endqml
3393
3394 It should not generally be necessary to refer to the \c data property,
3395 as it is the default property for Item and thus all child items are
3396 automatically assigned to this property.
3397 */
3398
3399qsizetype QQuickItemPrivate::data_count(QQmlListProperty<QObject> *property)
3400{
3401 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3402 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3403 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3404 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3405
3406 return resources_count(&resourcesProperty) + children_count(&childrenProperty);
3407}
3408
3409QObject *QQuickItemPrivate::data_at(QQmlListProperty<QObject> *property, qsizetype i)
3410{
3411 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3412 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3413 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3414 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3415
3416 qsizetype resourcesCount = resources_count(&resourcesProperty);
3417 if (i < resourcesCount)
3418 return resources_at(&resourcesProperty, i);
3419 const qsizetype j = i - resourcesCount;
3420 if (j < children_count(&childrenProperty))
3421 return children_at(&childrenProperty, j);
3422 return nullptr;
3423}
3424
3425void QQuickItemPrivate::data_clear(QQmlListProperty<QObject> *property)
3426{
3427 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3428 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3429 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3430 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3431
3432 resources_clear(&resourcesProperty);
3433 children_clear(&childrenProperty);
3434}
3435
3436void QQuickItemPrivate::data_removeLast(QQmlListProperty<QObject> *property)
3437{
3438 QQuickItem *item = static_cast<QQuickItem*>(property->object);
3439 QQuickItemPrivate *privateItem = QQuickItemPrivate::get(item);
3440
3441 QQmlListProperty<QQuickItem> childrenProperty = privateItem->children();
3442 if (children_count(&childrenProperty) > 0) {
3443 children_removeLast(&childrenProperty);
3444 return;
3445 }
3446
3447 QQmlListProperty<QObject> resourcesProperty = privateItem->resources();
3448 if (resources_count(&resourcesProperty) > 0)
3449 resources_removeLast(&resourcesProperty);
3450}
3451
3452QObject *QQuickItemPrivate::resources_at(QQmlListProperty<QObject> *prop, qsizetype index)
3453{
3454 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(item: static_cast<QQuickItem *>(prop->object));
3455 return quickItemPrivate->extra.isAllocated() ? quickItemPrivate->extra->resourcesList.value(i: index) : 0;
3456}
3457
3458void QQuickItemPrivate::resources_append(QQmlListProperty<QObject> *prop, QObject *object)
3459{
3460 QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
3461 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(item: quickItem);
3462 if (!quickItemPrivate->extra.value().resourcesList.contains(t: object)) {
3463 quickItemPrivate->extra.value().resourcesList.append(t: object);
3464 qmlobject_connect(object, QObject, SIGNAL(destroyed(QObject*)),
3465 quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
3466 }
3467}
3468
3469qsizetype QQuickItemPrivate::resources_count(QQmlListProperty<QObject> *prop)
3470{
3471 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(item: static_cast<QQuickItem *>(prop->object));
3472 return quickItemPrivate->extra.isAllocated() ? quickItemPrivate->extra->resourcesList.size() : 0;
3473}
3474
3475void QQuickItemPrivate::resources_clear(QQmlListProperty<QObject> *prop)
3476{
3477 QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
3478 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(item: quickItem);
3479 if (quickItemPrivate->extra.isAllocated()) {//If extra is not allocated resources is empty.
3480 for (QObject *object : std::as_const(t&: quickItemPrivate->extra->resourcesList)) {
3481 qmlobject_disconnect(object, QObject, SIGNAL(destroyed(QObject*)),
3482 quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
3483 }
3484 quickItemPrivate->extra->resourcesList.clear();
3485 }
3486}
3487
3488void QQuickItemPrivate::resources_removeLast(QQmlListProperty<QObject> *prop)
3489{
3490 QQuickItem *quickItem = static_cast<QQuickItem *>(prop->object);
3491 QQuickItemPrivate *quickItemPrivate = QQuickItemPrivate::get(item: quickItem);
3492 if (quickItemPrivate->extra.isAllocated()) {//If extra is not allocated resources is empty.
3493 QList<QObject *> *resources = &quickItemPrivate->extra->resourcesList;
3494 if (resources->isEmpty())
3495 return;
3496
3497 qmlobject_disconnect(resources->last(), QObject, SIGNAL(destroyed(QObject*)),
3498 quickItem, QQuickItem, SLOT(_q_resourceObjectDeleted(QObject*)));
3499 resources->removeLast();
3500 }
3501}
3502
3503QQuickItem *QQuickItemPrivate::children_at(QQmlListProperty<QQuickItem> *prop, qsizetype index)
3504{
3505 QQuickItemPrivate *p = QQuickItemPrivate::get(item: static_cast<QQuickItem *>(prop->object));
3506 if (index >= p->childItems.size() || index < 0)
3507 return nullptr;
3508 else
3509 return p->childItems.at(i: index);
3510}
3511
3512void QQuickItemPrivate::children_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *o)
3513{
3514 if (!o)
3515 return;
3516
3517 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3518 if (o->parentItem() == that)
3519 o->setParentItem(nullptr);
3520
3521 o->setParentItem(that);
3522}
3523
3524qsizetype QQuickItemPrivate::children_count(QQmlListProperty<QQuickItem> *prop)
3525{
3526 QQuickItemPrivate *p = QQuickItemPrivate::get(item: static_cast<QQuickItem *>(prop->object));
3527 return p->childItems.size();
3528}
3529
3530void QQuickItemPrivate::children_clear(QQmlListProperty<QQuickItem> *prop)
3531{
3532 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3533 QQuickItemPrivate *p = QQuickItemPrivate::get(item: that);
3534 while (!p->childItems.isEmpty())
3535 p->childItems.at(i: 0)->setParentItem(nullptr);
3536}
3537
3538void QQuickItemPrivate::children_removeLast(QQmlListProperty<QQuickItem> *prop)
3539{
3540 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3541 QQuickItemPrivate *p = QQuickItemPrivate::get(item: that);
3542 if (!p->childItems.isEmpty())
3543 p->childItems.last()->setParentItem(nullptr);
3544}
3545
3546qsizetype QQuickItemPrivate::visibleChildren_count(QQmlListProperty<QQuickItem> *prop)
3547{
3548 QQuickItemPrivate *p = QQuickItemPrivate::get(item: static_cast<QQuickItem *>(prop->object));
3549 qsizetype visibleCount = 0;
3550 qsizetype c = p->childItems.size();
3551 while (c--) {
3552 if (p->childItems.at(i: c)->isVisible()) visibleCount++;
3553 }
3554
3555 return visibleCount;
3556}
3557
3558QQuickItem *QQuickItemPrivate::visibleChildren_at(QQmlListProperty<QQuickItem> *prop, qsizetype index)
3559{
3560 QQuickItemPrivate *p = QQuickItemPrivate::get(item: static_cast<QQuickItem *>(prop->object));
3561 const qsizetype childCount = p->childItems.size();
3562 if (index >= childCount || index < 0)
3563 return nullptr;
3564
3565 qsizetype visibleCount = -1;
3566 for (qsizetype i = 0; i < childCount; i++) {
3567 if (p->childItems.at(i)->isVisible()) visibleCount++;
3568 if (visibleCount == index) return p->childItems.at(i);
3569 }
3570 return nullptr;
3571}
3572
3573qsizetype QQuickItemPrivate::transform_count(QQmlListProperty<QQuickTransform> *prop)
3574{
3575 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3576 QQuickItemPrivate *p = QQuickItemPrivate::get(item: that);
3577
3578 return p->transforms.size();
3579}
3580
3581void QQuickTransform::appendToItem(QQuickItem *item)
3582{
3583 Q_D(QQuickTransform);
3584 if (!item)
3585 return;
3586
3587 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
3588
3589 if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(t: this)) {
3590 p->transforms.removeOne(t: this);
3591 p->transforms.append(t: this);
3592 } else {
3593 p->transforms.append(t: this);
3594 d->items.append(t: item);
3595 }
3596
3597 p->dirty(QQuickItemPrivate::Transform);
3598}
3599
3600void QQuickTransform::prependToItem(QQuickItem *item)
3601{
3602 Q_D(QQuickTransform);
3603 if (!item)
3604 return;
3605
3606 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
3607
3608 if (!d->items.isEmpty() && !p->transforms.isEmpty() && p->transforms.contains(t: this)) {
3609 p->transforms.removeOne(t: this);
3610 p->transforms.prepend(t: this);
3611 } else {
3612 p->transforms.prepend(t: this);
3613 d->items.append(t: item);
3614 }
3615
3616 p->dirty(QQuickItemPrivate::Transform);
3617}
3618
3619void QQuickItemPrivate::transform_append(QQmlListProperty<QQuickTransform> *prop, QQuickTransform *transform)
3620{
3621 if (!transform)
3622 return;
3623
3624 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3625 transform->appendToItem(item: that);
3626}
3627
3628QQuickTransform *QQuickItemPrivate::transform_at(QQmlListProperty<QQuickTransform> *prop, qsizetype idx)
3629{
3630 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3631 QQuickItemPrivate *p = QQuickItemPrivate::get(item: that);
3632
3633 if (idx < 0 || idx >= p->transforms.size())
3634 return nullptr;
3635 else
3636 return p->transforms.at(i: idx);
3637}
3638
3639void QQuickItemPrivate::transform_clear(QQmlListProperty<QQuickTransform> *prop)
3640{
3641 QQuickItem *that = static_cast<QQuickItem *>(prop->object);
3642 QQuickItemPrivate *p = QQuickItemPrivate::get(item: that);
3643
3644 for (qsizetype ii = 0; ii < p->transforms.size(); ++ii) {
3645 QQuickTransform *t = p->transforms.at(i: ii);
3646 QQuickTransformPrivate *tp = QQuickTransformPrivate::get(transform: t);
3647 tp->items.removeOne(t: that);
3648 }
3649
3650 p->transforms.clear();
3651
3652 p->dirty(QQuickItemPrivate::Transform);
3653}
3654
3655void QQuickItemPrivate::_q_resourceObjectDeleted(QObject *object)
3656{
3657 if (extra.isAllocated() && extra->resourcesList.contains(t: object))
3658 extra->resourcesList.removeAll(t: object);
3659}
3660
3661/*!
3662 \qmlpropertygroup QtQuick::Item::anchors
3663 \qmlproperty AnchorLine QtQuick::Item::anchors.top
3664 \qmlproperty AnchorLine QtQuick::Item::anchors.bottom
3665 \qmlproperty AnchorLine QtQuick::Item::anchors.left
3666 \qmlproperty AnchorLine QtQuick::Item::anchors.right
3667 \qmlproperty AnchorLine QtQuick::Item::anchors.horizontalCenter
3668 \qmlproperty AnchorLine QtQuick::Item::anchors.verticalCenter
3669 \qmlproperty AnchorLine QtQuick::Item::anchors.baseline
3670
3671 \qmlproperty Item QtQuick::Item::anchors.fill
3672 \qmlproperty Item QtQuick::Item::anchors.centerIn
3673
3674 \qmlproperty real QtQuick::Item::anchors.margins
3675 \qmlproperty real QtQuick::Item::anchors.topMargin
3676 \qmlproperty real QtQuick::Item::anchors.bottomMargin
3677 \qmlproperty real QtQuick::Item::anchors.leftMargin
3678 \qmlproperty real QtQuick::Item::anchors.rightMargin
3679 \qmlproperty real QtQuick::Item::anchors.horizontalCenterOffset
3680 \qmlproperty real QtQuick::Item::anchors.verticalCenterOffset
3681 \qmlproperty real QtQuick::Item::anchors.baselineOffset
3682
3683 \qmlproperty bool QtQuick::Item::anchors.alignWhenCentered
3684
3685 Anchors provide a way to position an item by specifying its
3686 relationship with other items.
3687
3688 Margins apply to top, bottom, left, right, and fill anchors.
3689 The \l anchors.margins property can be used to set all of the various margins at once, to the same value.
3690 It will not override a specific margin that has been previously set; to clear an explicit margin
3691 set its value to \c undefined.
3692 Note that margins are anchor-specific and are not applied if an item does not
3693 use anchors.
3694
3695 Offsets apply for horizontal center, vertical center, and baseline anchors.
3696
3697 \table
3698 \row
3699 \li \image declarative-anchors_example.png
3700 \li Text anchored to Image, horizontally centered and vertically below, with a margin.
3701 \qml
3702 Item {
3703 Image {
3704 id: pic
3705 // ...
3706 }
3707 Text {
3708 id: label
3709 anchors.horizontalCenter: pic.horizontalCenter
3710 anchors.top: pic.bottom
3711 anchors.topMargin: 5
3712 // ...
3713 }
3714 }
3715 \endqml
3716 \row
3717 \li \image declarative-anchors_example2.png
3718 \li
3719 Left of Text anchored to right of Image, with a margin. The y
3720 property of both defaults to 0.
3721
3722 \qml
3723 Item {
3724 Image {
3725 id: pic
3726 // ...
3727 }
3728 Text {
3729 id: label
3730 anchors.left: pic.right
3731 anchors.leftMargin: 5
3732 // ...
3733 }
3734 }
3735 \endqml
3736 \endtable
3737
3738 \l anchors.fill provides a convenient way for one item to have the
3739 same geometry as another item, and is equivalent to connecting all
3740 four directional anchors.
3741
3742 To clear an anchor value, set it to \c undefined.
3743
3744 \l anchors.alignWhenCentered (default \c true) forces centered anchors to align to a
3745 whole pixel; if the item being centered has an odd \l width or \l height, the item
3746 will be positioned on a whole pixel rather than being placed on a half-pixel.
3747 This ensures the item is painted crisply. There are cases where this is not
3748 desirable, for example when rotating the item jitters may be apparent as the
3749 center is rounded.
3750
3751 \note You can only anchor an item to siblings or a parent.
3752
3753 For more information see \l {anchor-layout}{Anchor Layouts}.
3754*/
3755QQuickAnchors *QQuickItemPrivate::anchors() const
3756{
3757 if (!_anchors) {
3758 Q_Q(const QQuickItem);
3759 _anchors = new QQuickAnchors(const_cast<QQuickItem *>(q));
3760 if (!componentComplete)
3761 _anchors->classBegin();
3762 }
3763 return _anchors;
3764}
3765
3766void QQuickItemPrivate::siblingOrderChanged()
3767{
3768 Q_Q(QQuickItem);
3769 notifyChangeListeners(changeTypes: QQuickItemPrivate::SiblingOrder, function: &QQuickItemChangeListener::itemSiblingOrderChanged, args: q);
3770}
3771
3772QQmlListProperty<QObject> QQuickItemPrivate::data()
3773{
3774 // Do not synthesize replace().
3775 // It would be extremely expensive and wouldn't work with most methods.
3776 QQmlListProperty<QObject> result;
3777 result.object = q_func();
3778 result.append = QQuickItemPrivate::data_append;
3779 result.count = QQuickItemPrivate::data_count;
3780 result.at = QQuickItemPrivate::data_at;
3781 result.clear = QQuickItemPrivate::data_clear;
3782 result.removeLast = QQuickItemPrivate::data_removeLast;
3783 return result;
3784}
3785
3786/*!
3787 \qmlpropertygroup QtQuick::Item::childrenRect
3788 \qmlproperty real QtQuick::Item::childrenRect.x
3789 \qmlproperty real QtQuick::Item::childrenRect.y
3790 \qmlproperty real QtQuick::Item::childrenRect.width
3791 \qmlproperty real QtQuick::Item::childrenRect.height
3792 \readonly
3793
3794 This read-only property holds the collective position and size of the item's
3795 children.
3796
3797 This property is useful if you need to access the collective geometry
3798 of an item's children in order to correctly size the item.
3799
3800 The geometry that is returned is local to the item. For example:
3801
3802 \snippet qml/item/childrenRect.qml local
3803*/
3804/*!
3805 \property QQuickItem::childrenRect
3806
3807 This property holds the collective position and size of the item's
3808 children.
3809
3810 This property is useful if you need to access the collective geometry
3811 of an item's children in order to correctly size the item.
3812
3813 The geometry that is returned is local to the item. For example:
3814
3815 \snippet qml/item/childrenRect.qml local
3816*/
3817QRectF QQuickItem::childrenRect()
3818{
3819 Q_D(QQuickItem);
3820 if (!d->extra.isAllocated() || !d->extra->contents) {
3821 d->extra.value().contents = new QQuickContents(this);
3822 if (d->componentComplete)
3823 d->extra->contents->complete();
3824 }
3825 return d->extra->contents->rectF();
3826}
3827
3828/*!
3829 Returns the children of this item.
3830 */
3831QList<QQuickItem *> QQuickItem::childItems() const
3832{
3833 Q_D(const QQuickItem);
3834 return d->childItems;
3835}
3836
3837/*!
3838 \qmlproperty bool QtQuick::Item::clip
3839 This property holds whether clipping is enabled. The default clip value is \c false.
3840
3841 If clipping is enabled, an item will clip its own painting, as well
3842 as the painting of its children, to its bounding rectangle.
3843
3844 \note Clipping can affect rendering performance. See \l {Clipping} for more
3845 information.
3846*/
3847/*!
3848 \property QQuickItem::clip
3849 This property holds whether clipping is enabled. The default clip value is \c false.
3850
3851 If clipping is enabled, an item will clip its own painting, as well
3852 as the painting of its children, to its bounding rectangle. If you set
3853 clipping during an item's paint operation, remember to re-set it to
3854 prevent clipping the rest of your scene.
3855
3856 \note Clipping can affect rendering performance. See \l {Clipping} for more
3857 information.
3858
3859 \note For the sake of QML, setting clip to \c true also sets the
3860 \l ItemIsViewport flag, which sometimes acts as an optimization: child items
3861 that have the \l ItemObservesViewport flag may forego creating scene graph nodes
3862 that fall outside the viewport. But the \c ItemIsViewport flag can also be set
3863 independently.
3864*/
3865bool QQuickItem::clip() const
3866{
3867 return flags() & ItemClipsChildrenToShape;
3868}
3869
3870void QQuickItem::setClip(bool c)
3871{
3872 if (clip() == c)
3873 return;
3874
3875 setFlag(flag: ItemClipsChildrenToShape, enabled: c);
3876 if (c)
3877 setFlag(flag: ItemIsViewport);
3878 else if (!(inherits(classname: "QQuickFlickable") || inherits(classname: "QQuickRootItem")))
3879 setFlag(flag: ItemIsViewport, enabled: false);
3880
3881 emit clipChanged(c);
3882}
3883
3884/*!
3885 \since 6.0
3886
3887 This function is called to handle this item's changes in
3888 geometry from \a oldGeometry to \a newGeometry. If the two
3889 geometries are the same, it doesn't do anything.
3890
3891 Derived classes must call the base class method within their implementation.
3892 */
3893void QQuickItem::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
3894{
3895 Q_D(QQuickItem);
3896
3897 if (d->_anchors)
3898 QQuickAnchorsPrivate::get(o: d->_anchors)->updateMe();
3899
3900 QQuickGeometryChange change;
3901 change.setXChange(newGeometry.x() != oldGeometry.x());
3902 change.setYChange(newGeometry.y() != oldGeometry.y());
3903 change.setWidthChange(newGeometry.width() != oldGeometry.width());
3904 change.setHeightChange(newGeometry.height() != oldGeometry.height());
3905
3906 d->notifyChangeListeners(changeTypes: QQuickItemPrivate::Geometry, function: [&](const QQuickItemPrivate::ChangeListener &listener){
3907 if (change.matches(other: listener.gTypes))
3908 listener.listener->itemGeometryChanged(this, change, oldGeometry);
3909 });
3910
3911 // The notify method takes care of emitting the signal, and also notifies any
3912 // property observers.
3913 if (change.xChange())
3914 d->x.notify();
3915 if (change.yChange())
3916 d->y.notify();
3917 if (change.widthChange())
3918 d->width.notify();
3919 if (change.heightChange())
3920 d->height.notify();
3921#if QT_CONFIG(accessibility)
3922 if (d->isAccessible && QAccessible::isActive() && d->effectiveVisible) {
3923 QAccessibleEvent ev(this, QAccessible::LocationChanged);
3924 QAccessible::updateAccessibility(event: &ev);
3925 }
3926#endif
3927}
3928
3929/*!
3930 Called on the render thread when it is time to sync the state
3931 of the item with the scene graph.
3932
3933 The function is called as a result of QQuickItem::update(), if
3934 the user has set the QQuickItem::ItemHasContents flag on the item.
3935
3936 The function should return the root of the scene graph subtree for
3937 this item. Most implementations will return a single
3938 QSGGeometryNode containing the visual representation of this item.
3939 \a oldNode is the node that was returned the last time the
3940 function was called. \a updatePaintNodeData provides a pointer to
3941 the QSGTransformNode associated with this QQuickItem.
3942
3943 \code
3944 QSGNode *MyItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
3945 {
3946 QSGSimpleRectNode *n = static_cast<QSGSimpleRectNode *>(node);
3947 if (!n) {
3948 n = new QSGSimpleRectNode();
3949 n->setColor(Qt::red);
3950 }
3951 n->setRect(boundingRect());
3952 return n;
3953 }
3954 \endcode
3955
3956 The main thread is blocked while this function is executed so it is safe to read
3957 values from the QQuickItem instance and other objects in the main thread.
3958
3959 If no call to QQuickItem::updatePaintNode() result in actual scene graph
3960 changes, like QSGNode::markDirty() or adding and removing nodes, then
3961 the underlying implementation may decide to not render the scene again as
3962 the visual outcome is identical.
3963
3964 \warning It is crucial that graphics operations and interaction with
3965 the scene graph happens exclusively on the render thread,
3966 primarily during the QQuickItem::updatePaintNode() call. The best
3967 rule of thumb is to only use classes with the "QSG" prefix inside
3968 the QQuickItem::updatePaintNode() function.
3969
3970 \warning This function is called on the render thread. This means any
3971 QObjects or thread local storage that is created will have affinity to the
3972 render thread, so apply caution when doing anything other than rendering
3973 in this function. Similarly for signals, these will be emitted on the render
3974 thread and will thus often be delivered via queued connections.
3975
3976 \note All classes with QSG prefix should be used solely on the scene graph's
3977 rendering thread. See \l {Scene Graph and Rendering} for more information.
3978
3979 \sa QSGMaterial, QSGGeometryNode, QSGGeometry,
3980 QSGFlatColorMaterial, QSGTextureMaterial, QSGNode::markDirty(), {Graphics Resource Handling}
3981 */
3982
3983QSGNode *QQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
3984{
3985 Q_UNUSED(updatePaintNodeData);
3986 delete oldNode;
3987 return nullptr;
3988}
3989
3990QQuickItem::UpdatePaintNodeData::UpdatePaintNodeData()
3991: transformNode(nullptr)
3992{
3993}
3994
3995/*!
3996 This function is called when an item should release graphics
3997 resources which are not already managed by the nodes returned from
3998 QQuickItem::updatePaintNode().
3999
4000 This happens when the item is about to be removed from the window it
4001 was previously rendering to. The item is guaranteed to have a
4002 \l {QQuickItem::window()}{window} when the function is called.
4003
4004 The function is called on the GUI thread and the state of the
4005 rendering thread, when it is used, is unknown. Objects should
4006 not be deleted directly, but instead scheduled for cleanup
4007 using QQuickWindow::scheduleRenderJob().
4008
4009 \sa {Graphics Resource Handling}
4010 */
4011
4012void QQuickItem::releaseResources()
4013{
4014}
4015
4016QSGTransformNode *QQuickItemPrivate::createTransformNode()
4017{
4018 return new QSGTransformNode;
4019}
4020
4021/*!
4022 This function should perform any layout as required for this item.
4023
4024 When polish() is called, the scene graph schedules a polish event for this
4025 item. When the scene graph is ready to render this item, it calls
4026 updatePolish() to do any item layout as required before it renders the
4027 next frame.
4028
4029 \sa ensurePolished()
4030 */
4031void QQuickItem::updatePolish()
4032{
4033}
4034
4035#define PRINT_LISTENERS() \
4036do { \
4037 qDebug().nospace() << q_func() << " (" << this \
4038 << ") now has the following listeners:"; \
4039 for (const auto &listener : std::as_const(changeListeners)) { \
4040 const auto objectPrivate = dynamic_cast<QObjectPrivate*>(listener.listener); \
4041 qDebug().nospace() << "- " << listener << " (QObject: " << (objectPrivate ? objectPrivate->q_func() : nullptr) << ")"; \
4042 } \
4043} \
4044while (false)
4045
4046void QQuickItemPrivate::addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
4047{
4048 Q_Q(QQuickItem);
4049 changeListeners.append(t: ChangeListener(listener, types));
4050 listener->addSourceItem(q);
4051
4052 if (lcChangeListeners().isDebugEnabled())
4053 PRINT_LISTENERS();
4054}
4055
4056void QQuickItemPrivate::updateOrAddItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
4057{
4058 Q_Q(QQuickItem);
4059
4060 const ChangeListener changeListener(listener, types);
4061 const int index = changeListeners.indexOf(t: changeListener);
4062 if (index > -1) {
4063 changeListeners[index].types = changeListener.types;
4064 } else {
4065 changeListeners.append(t: changeListener);
4066 listener->addSourceItem(q);
4067 }
4068
4069 if (lcChangeListeners().isDebugEnabled())
4070 PRINT_LISTENERS();
4071}
4072
4073void QQuickItemPrivate::removeItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
4074{
4075 Q_Q(QQuickItem);
4076
4077 ChangeListener change(listener, types);
4078 changeListeners.removeOne(t: change);
4079 listener->removeSourceItem(q);
4080
4081 if (lcChangeListeners().isDebugEnabled())
4082 PRINT_LISTENERS();
4083}
4084
4085void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener,
4086 QQuickGeometryChange types)
4087{
4088 Q_Q(QQuickItem);
4089
4090 ChangeListener change(listener, types);
4091 int index = changeListeners.indexOf(t: change);
4092 if (index > -1) {
4093 changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
4094 } else {
4095 changeListeners.append(t: change);
4096 listener->addSourceItem(q);
4097 }
4098
4099 if (lcChangeListeners().isDebugEnabled())
4100 PRINT_LISTENERS();
4101}
4102
4103void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener,
4104 QQuickGeometryChange types)
4105{
4106 Q_Q(QQuickItem);
4107
4108 ChangeListener change(listener, types);
4109 if (types.noChange()) {
4110 changeListeners.removeOne(t: change);
4111 listener->removeSourceItem(q);
4112 } else {
4113 int index = changeListeners.indexOf(t: change);
4114 if (index > -1)
4115 changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
4116 }
4117
4118 if (lcChangeListeners().isDebugEnabled())
4119 PRINT_LISTENERS();
4120}
4121
4122/*!
4123 This event handler can be reimplemented in a subclass to receive key
4124 press events for an item. The event information is provided by the
4125 \a event parameter.
4126
4127 \input item.qdocinc accepting-events
4128 */
4129void QQuickItem::keyPressEvent(QKeyEvent *event)
4130{
4131 event->ignore();
4132}
4133
4134/*!
4135 This event handler can be reimplemented in a subclass to receive key
4136 release events for an item. The event information is provided by the
4137 \a event parameter.
4138
4139 \input item.qdocinc accepting-events
4140 */
4141void QQuickItem::keyReleaseEvent(QKeyEvent *event)
4142{
4143 event->ignore();
4144}
4145
4146#if QT_CONFIG(im)
4147/*!
4148 This event handler can be reimplemented in a subclass to receive input
4149 method events for an item. The event information is provided by the
4150 \a event parameter.
4151
4152 \input item.qdocinc accepting-events
4153 */
4154void QQuickItem::inputMethodEvent(QInputMethodEvent *event)
4155{
4156 event->ignore();
4157}
4158#endif // im
4159
4160/*!
4161 This event handler can be reimplemented in a subclass to receive focus-in
4162 events for an item. The event information is provided by the \a event
4163 parameter.
4164
4165 \input item.qdocinc accepting-events
4166
4167 If you do reimplement this function, you should call the base class
4168 implementation.
4169 */
4170void QQuickItem::focusInEvent(QFocusEvent *event)
4171{
4172 Q_D(QQuickItem);
4173#if QT_CONFIG(accessibility)
4174 if (QAccessible::isActive()) {
4175 if (QObject *acc = QQuickAccessibleAttached::findAccessible(object: this)) {
4176 QAccessibleEvent ev(acc, QAccessible::Focus);
4177 QAccessible::updateAccessibility(event: &ev);
4178 }
4179 }
4180#endif
4181 d->setLastFocusChangeReason(event->reason());
4182}
4183
4184/*!
4185 This event handler can be reimplemented in a subclass to receive focus-out
4186 events for an item. The event information is provided by the \a event
4187 parameter.
4188
4189 \input item.qdocinc accepting-events
4190 */
4191void QQuickItem::focusOutEvent(QFocusEvent *event)
4192{
4193 Q_D(QQuickItem);
4194 d->setLastFocusChangeReason(event->reason());
4195}
4196
4197/*!
4198 This event handler can be reimplemented in a subclass to receive mouse
4199 press events for an item. The event information is provided by the
4200 \a event parameter.
4201
4202 In order to receive mouse press events, \l acceptedMouseButtons() must
4203 return the relevant mouse button.
4204
4205 \input item.qdocinc accepting-events
4206 */
4207void QQuickItem::mousePressEvent(QMouseEvent *event)
4208{
4209 event->ignore();
4210}
4211
4212/*!
4213 This event handler can be reimplemented in a subclass to receive mouse
4214 move events for an item. The event information is provided by the
4215 \a event parameter.
4216
4217 In order to receive mouse movement events, the preceding mouse press event
4218 must be accepted (by overriding \l mousePressEvent(), for example) and
4219 \l acceptedMouseButtons() must return the relevant mouse button.
4220
4221 \input item.qdocinc accepting-events
4222 */
4223void QQuickItem::mouseMoveEvent(QMouseEvent *event)
4224{
4225 event->ignore();
4226}
4227
4228/*!
4229 This event handler can be reimplemented in a subclass to receive mouse
4230 release events for an item. The event information is provided by the
4231 \a event parameter.
4232
4233 In order to receive mouse release events, the preceding mouse press event
4234 must be accepted (by overriding \l mousePressEvent(), for example) and
4235 \l acceptedMouseButtons() must return the relevant mouse button.
4236
4237 \input item.qdocinc accepting-events
4238 */
4239void QQuickItem::mouseReleaseEvent(QMouseEvent *event)
4240{
4241 event->ignore();
4242}
4243
4244/*!
4245 This event handler can be reimplemented in a subclass to receive mouse
4246 double-click events for an item. The event information is provided by the
4247 \a event parameter.
4248
4249 \input item.qdocinc accepting-events
4250 */
4251void QQuickItem::mouseDoubleClickEvent(QMouseEvent *event)
4252{
4253 event->ignore();
4254}
4255
4256/*!
4257 This event handler can be reimplemented in a subclass to be notified
4258 when a mouse ungrab event has occurred on this item.
4259 */
4260void QQuickItem::mouseUngrabEvent()
4261{
4262 // XXX todo
4263}
4264
4265/*!
4266 This event handler can be reimplemented in a subclass to be notified
4267 when a touch ungrab event has occurred on this item.
4268 */
4269void QQuickItem::touchUngrabEvent()
4270{
4271 // XXX todo
4272}
4273
4274#if QT_CONFIG(wheelevent)
4275/*!
4276 This event handler can be reimplemented in a subclass to receive
4277 wheel events for an item. The event information is provided by the
4278 \a event parameter.
4279
4280 \input item.qdocinc accepting-events
4281 */
4282void QQuickItem::wheelEvent(QWheelEvent *event)
4283{
4284 event->ignore();
4285}
4286#endif
4287
4288/*!
4289 This event handler can be reimplemented in a subclass to receive touch
4290 events for an item. The event information is provided by the
4291 \a event parameter.
4292
4293 \input item.qdocinc accepting-events
4294 */
4295void QQuickItem::touchEvent(QTouchEvent *event)
4296{
4297 event->ignore();
4298}
4299
4300/*!
4301 This event handler can be reimplemented in a subclass to receive hover-enter
4302 events for an item. The event information is provided by the
4303 \a event parameter.
4304
4305 Hover events are only provided if acceptHoverEvents() is true.
4306
4307 \input item.qdocinc accepting-events
4308 */
4309void QQuickItem::hoverEnterEvent(QHoverEvent *event)
4310{
4311 event->ignore();
4312}
4313
4314/*!
4315 This event handler can be reimplemented in a subclass to receive hover-move
4316 events for an item. The event information is provided by the
4317 \a event parameter.
4318
4319 Hover events are only provided if acceptHoverEvents() is true.
4320
4321 \input item.qdocinc accepting-events
4322 */
4323void QQuickItem::hoverMoveEvent(QHoverEvent *event)
4324{
4325 event->ignore();
4326}
4327
4328/*!
4329 This event handler can be reimplemented in a subclass to receive hover-leave
4330 events for an item. The event information is provided by the
4331 \a event parameter.
4332
4333 Hover events are only provided if acceptHoverEvents() is true.
4334
4335 \input item.qdocinc accepting-events
4336 */
4337void QQuickItem::hoverLeaveEvent(QHoverEvent *event)
4338{
4339 event->ignore();
4340}
4341
4342#if QT_CONFIG(quick_draganddrop)
4343/*!
4344 This event handler can be reimplemented in a subclass to receive drag-enter
4345 events for an item. The event information is provided by the
4346 \a event parameter.
4347
4348 Drag and drop events are only provided if the ItemAcceptsDrops flag
4349 has been set for this item.
4350
4351 \input item.qdocinc accepting-events
4352
4353 \sa Drag, {Drag and Drop}
4354 */
4355void QQuickItem::dragEnterEvent(QDragEnterEvent *event)
4356{
4357 Q_UNUSED(event);
4358}
4359
4360/*!
4361 This event handler can be reimplemented in a subclass to receive drag-move
4362 events for an item. The event information is provided by the
4363 \a event parameter.
4364
4365 Drag and drop events are only provided if the ItemAcceptsDrops flag
4366 has been set for this item.
4367
4368 \input item.qdocinc accepting-events
4369
4370 \sa Drag, {Drag and Drop}
4371 */
4372void QQuickItem::dragMoveEvent(QDragMoveEvent *event)
4373{
4374 Q_UNUSED(event);
4375}
4376
4377/*!
4378 This event handler can be reimplemented in a subclass to receive drag-leave
4379 events for an item. The event information is provided by the
4380 \a event parameter.
4381
4382 Drag and drop events are only provided if the ItemAcceptsDrops flag
4383 has been set for this item.
4384
4385 \input item.qdocinc accepting-events
4386
4387 \sa Drag, {Drag and Drop}
4388 */
4389void QQuickItem::dragLeaveEvent(QDragLeaveEvent *event)
4390{
4391 Q_UNUSED(event);
4392}
4393
4394/*!
4395 This event handler can be reimplemented in a subclass to receive drop
4396 events for an item. The event information is provided by the
4397 \a event parameter.
4398
4399 Drag and drop events are only provided if the ItemAcceptsDrops flag
4400 has been set for this item.
4401
4402 \input item.qdocinc accepting-events
4403
4404 \sa Drag, {Drag and Drop}
4405 */
4406void QQuickItem::dropEvent(QDropEvent *event)
4407{
4408 Q_UNUSED(event);
4409}
4410#endif // quick_draganddrop
4411
4412/*!
4413 Reimplement this method to filter the pointer events that are received by
4414 this item's children.
4415
4416 This method will only be called if filtersChildMouseEvents() is \c true.
4417
4418 Return \c true if the specified \a event should not be passed on to the
4419 specified child \a item, and \c false otherwise. If you return \c true, you
4420 should also \l {QEvent::accept()}{accept} or \l {QEvent::ignore()}{ignore}
4421 the \a event, to signal if event propagation should stop or continue.
4422 The \a event will, however, always be sent to all childMouseEventFilters
4423 up the parent chain.
4424
4425 \note Despite the name, this function filters all QPointerEvent instances
4426 during delivery to all children (typically mouse, touch, and tablet
4427 events). When overriding this function in a subclass, we suggest writing
4428 generic event-handling code using only the accessors found in
4429 QPointerEvent. Alternatively you can switch on \c event->type() and/or
4430 \c event->device()->type() to handle different event types in different ways.
4431
4432 \note Filtering is just one way to share responsibility in case of gestural
4433 ambiguity (for example on press, you don't know whether the user will tap
4434 or drag). Another way is to call QPointerEvent::addPassiveGrabber() on
4435 press, so as to non-exclusively monitor the progress of the QEventPoint.
4436 In either case, the item or pointer handler that is monitoring can steal
4437 the exclusive grab later on, when it becomes clear that the gesture fits
4438 the pattern that it is expecting.
4439
4440 \sa setFiltersChildMouseEvents()
4441 */
4442bool QQuickItem::childMouseEventFilter(QQuickItem *item, QEvent *event)
4443{
4444 Q_UNUSED(item);
4445 Q_UNUSED(event);
4446 return false;
4447}
4448
4449#if QT_CONFIG(im)
4450/*!
4451 This method is only relevant for input items.
4452
4453 If this item is an input item, this method should be reimplemented to
4454 return the relevant input method flags for the given \a query.
4455
4456 \sa QWidget::inputMethodQuery()
4457 */
4458QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
4459{
4460 Q_D(const QQuickItem);
4461 QVariant v;
4462
4463 switch (query) {
4464 case Qt::ImEnabled:
4465 v = (bool)(flags() & ItemAcceptsInputMethod);
4466 break;
4467 case Qt::ImHints:
4468 case Qt::ImAnchorRectangle:
4469 case Qt::ImCursorRectangle:
4470 case Qt::ImFont:
4471 case Qt::ImCursorPosition:
4472 case Qt::ImSurroundingText:
4473 case Qt::ImCurrentSelection:
4474 case Qt::ImMaximumTextLength:
4475 case Qt::ImAnchorPosition:
4476 case Qt::ImPreferredLanguage:
4477 case Qt::ImReadOnly:
4478 if (d->extra.isAllocated() && d->extra->keyHandler)
4479 v = d->extra->keyHandler->inputMethodQuery(query);
4480 break;
4481 case Qt::ImEnterKeyType:
4482 if (d->extra.isAllocated() && d->extra->enterKeyAttached)
4483 v = d->extra->enterKeyAttached->type();
4484 break;
4485 case Qt::ImInputItemClipRectangle:
4486 if (!(!window() ||!isVisible() || qFuzzyIsNull(d: opacity()))) {
4487 QRectF rect = QRectF(0,0, width(), height());
4488 const QQuickItem *par = this;
4489 while (QQuickItem *parpar = par->parentItem()) {
4490 rect = parpar->mapRectFromItem(item: par, rect);
4491 if (parpar->clip())
4492 rect = rect.intersected(r: parpar->clipRect());
4493 par = parpar;
4494 }
4495 rect = par->mapRectToScene(rect);
4496 // once we have the rect in scene coordinates, clip to window
4497 rect = rect.intersected(r: QRectF(QPoint(0,0), window()->size()));
4498 // map it back to local coordinates
4499 v = mapRectFromScene(rect);
4500 }
4501 break;
4502 default:
4503 break;
4504 }
4505
4506 return v;
4507}
4508#endif // im
4509
4510QQuickAnchorLine QQuickItemPrivate::left() const
4511{
4512 Q_Q(const QQuickItem);
4513 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::LeftAnchor);
4514}
4515
4516QQuickAnchorLine QQuickItemPrivate::right() const
4517{
4518 Q_Q(const QQuickItem);
4519 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::RightAnchor);
4520}
4521
4522QQuickAnchorLine QQuickItemPrivate::horizontalCenter() const
4523{
4524 Q_Q(const QQuickItem);
4525 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::HCenterAnchor);
4526}
4527
4528QQuickAnchorLine QQuickItemPrivate::top() const
4529{
4530 Q_Q(const QQuickItem);
4531 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::TopAnchor);
4532}
4533
4534QQuickAnchorLine QQuickItemPrivate::bottom() const
4535{
4536 Q_Q(const QQuickItem);
4537 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::BottomAnchor);
4538}
4539
4540QQuickAnchorLine QQuickItemPrivate::verticalCenter() const
4541{
4542 Q_Q(const QQuickItem);
4543 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::VCenterAnchor);
4544}
4545
4546QQuickAnchorLine QQuickItemPrivate::baseline() const
4547{
4548 Q_Q(const QQuickItem);
4549 return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::BaselineAnchor);
4550}
4551
4552/*!
4553 \qmlproperty int QtQuick::Item::baselineOffset
4554
4555 Specifies the position of the item's baseline in local coordinates.
4556
4557 The baseline of a \l Text item is the imaginary line on which the text
4558 sits. Controls containing text usually set their baseline to the
4559 baseline of their text.
4560
4561 For non-text items, a default baseline offset of 0 is used.
4562*/
4563/*!
4564 \property QQuickItem::baselineOffset
4565
4566 Specifies the position of the item's baseline in local coordinates.
4567
4568 The baseline of a \l Text item is the imaginary line on which the text
4569 sits. Controls containing text usually set their baseline to the
4570 baseline of their text.
4571
4572 For non-text items, a default baseline offset of 0 is used.
4573*/
4574qreal QQuickItem::baselineOffset() const
4575{
4576 Q_D(const QQuickItem);
4577 return d->baselineOffset;
4578}
4579
4580void QQuickItem::setBaselineOffset(qreal offset)
4581{
4582 Q_D(QQuickItem);
4583 if (offset == d->baselineOffset)
4584 return;
4585
4586 d->baselineOffset = offset;
4587
4588 d->notifyChangeListeners(changeTypes: QQuickItemPrivate::Geometry, function: [](const QQuickItemPrivate::ChangeListener &change){
4589 QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
4590 if (anchor)
4591 anchor->updateVerticalAnchors();
4592 });
4593
4594 if (d->_anchors && (d->_anchors->usedAnchors() & QQuickAnchors::BaselineAnchor))
4595 QQuickAnchorsPrivate::get(o: d->_anchors)->updateVerticalAnchors();
4596
4597 emit baselineOffsetChanged(offset);
4598}
4599
4600
4601/*!
4602 * Schedules a call to updatePaintNode() for this item.
4603 *
4604 * The call to QQuickItem::updatePaintNode() will always happen if the
4605 * item is showing in a QQuickWindow.
4606 *
4607 * Only items which specify QQuickItem::ItemHasContents are allowed
4608 * to call QQuickItem::update().
4609 */
4610void QQuickItem::update()
4611{
4612 Q_D(QQuickItem);
4613 if (!(flags() & ItemHasContents)) {
4614#ifndef QT_NO_DEBUG
4615 qWarning() << metaObject()->className() << ": Update called for a item without content";
4616#endif
4617 return;
4618 }
4619 d->dirty(QQuickItemPrivate::Content);
4620}
4621
4622/*!
4623 Schedules a polish event for this item.
4624
4625 When the scene graph processes the request, it will call updatePolish()
4626 on this item.
4627
4628 \sa updatePolish(), QQuickTest::qIsPolishScheduled(), ensurePolished()
4629 */
4630void QQuickItem::polish()
4631{
4632 Q_D(QQuickItem);
4633 if (!d->polishScheduled) {
4634 d->polishScheduled = true;
4635 if (d->window) {
4636 QQuickWindowPrivate *p = QQuickWindowPrivate::get(c: d->window);
4637 bool maybeupdate = p->itemsToPolish.isEmpty();
4638 p->itemsToPolish.append(t: this);
4639 if (maybeupdate) d->window->maybeUpdate();
4640 }
4641 }
4642}
4643
4644/*!
4645 \since 6.3
4646
4647 Calls updatePolish()
4648
4649 This can be useful for items such as Layouts (or Positioners) which delay calculation of
4650 their implicitWidth and implicitHeight until they receive a PolishEvent.
4651
4652 Normally, if e.g. a child item is added or removed to a Layout, the implicit size is not
4653 immediately calculated (this is an optimization). In some cases it might be desirable to
4654 query the implicit size of the layout right after a child item has been added.
4655 If this is the case, use this function right before querying the implicit size.
4656
4657 \sa updatePolish(), polish()
4658 */
4659void QQuickItem::ensurePolished()
4660{
4661 updatePolish();
4662}
4663
4664#if QT_DEPRECATED_SINCE(6, 5)
4665static bool unwrapMapFromToFromItemArgs(QQmlV4FunctionPtr args, const QQuickItem *itemForWarning, const QString &functionNameForWarning,
4666 QQuickItem **itemObj, qreal *x, qreal *y, qreal *w, qreal *h, bool *isRect)
4667{
4668 QV4::ExecutionEngine *v4 = args->v4engine();
4669 if (args->length() != 2 && args->length() != 3 && args->length() != 5) {
4670 v4->throwTypeError();
4671 return false;
4672 }
4673
4674 QV4::Scope scope(v4);
4675 QV4::ScopedValue item(scope, (*args)[0]);
4676
4677 *itemObj = nullptr;
4678 if (!item->isNull()) {
4679 QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, item->as<QV4::QObjectWrapper>());
4680 if (qobjectWrapper)
4681 *itemObj = qobject_cast<QQuickItem*>(o: qobjectWrapper->object());
4682 }
4683
4684 if (!(*itemObj) && !item->isNull()) {
4685 qmlWarning(me: itemForWarning) << functionNameForWarning << " given argument \"" << item->toQStringNoThrow()
4686 << "\" which is neither null nor an Item";
4687 v4->throwTypeError();
4688 return false;
4689 }
4690
4691 *isRect = false;
4692
4693 if (args->length() == 2) {
4694 QV4::ScopedValue sv(scope, (*args)[1]);
4695 if (sv->isNull()) {
4696 qmlWarning(me: itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow()
4697 << "\" which is neither a point nor a rect";
4698 v4->throwTypeError();
4699 return false;
4700 }
4701 const QV4::Scoped<QV4::QQmlValueTypeWrapper> variantWrapper(scope, sv->as<QV4::QQmlValueTypeWrapper>());
4702 const QVariant v = variantWrapper ? variantWrapper->toVariant() : QVariant();
4703 if (v.canConvert<QPointF>()) {
4704 const QPointF p = v.toPointF();
4705 *x = p.x();
4706 *y = p.y();
4707 } else if (v.canConvert<QRectF>()) {
4708 const QRectF r = v.toRectF();
4709 *x = r.x();
4710 *y = r.y();
4711 *w = r.width();
4712 *h = r.height();
4713 *isRect = true;
4714 } else {
4715 qmlWarning(me: itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow()
4716 << "\" which is neither a point nor a rect";
4717 v4->throwTypeError();
4718 return false;
4719 }
4720 } else {
4721 QV4::ScopedValue vx(scope, (*args)[1]);
4722 QV4::ScopedValue vy(scope, (*args)[2]);
4723
4724 if (!vx->isNumber() || !vy->isNumber()) {
4725 v4->throwTypeError();
4726 return false;
4727 }
4728
4729 *x = vx->asDouble();
4730 *y = vy->asDouble();
4731
4732 if (args->length() > 3) {
4733 QV4::ScopedValue vw(scope, (*args)[3]);
4734 QV4::ScopedValue vh(scope, (*args)[4]);
4735 if (!vw->isNumber() || !vh->isNumber()) {
4736 v4->throwTypeError();
4737 return false;
4738 }
4739 *w = vw->asDouble();
4740 *h = vh->asDouble();
4741 *isRect = true;
4742 }
4743 }
4744
4745 return true;
4746}
4747#endif
4748
4749/*!
4750 \qmlmethod point QtQuick::Item::mapFromItem(Item item, real x, real y)
4751 \qmlmethod point QtQuick::Item::mapFromItem(Item item, point p)
4752 \qmlmethod rect QtQuick::Item::mapFromItem(Item item, real x, real y, real width, real height)
4753 \qmlmethod rect QtQuick::Item::mapFromItem(Item item, rect r)
4754
4755 Maps the point (\a x, \a y) or rect (\a x, \a y, \a width, \a height), which is in \a
4756 item's coordinate system, to this item's coordinate system, and returns a \l point or \l rect
4757 matching the mapped coordinate.
4758
4759 \input item.qdocinc mapping
4760
4761 If \a item is a \c null value, this maps the point or rect from the coordinate system of
4762 the \l{Scene Coordinates}{scene}.
4763
4764 The versions accepting point and rect are since Qt 5.15.
4765*/
4766
4767#if QT_DEPRECATED_SINCE(6, 5)
4768/*!
4769 \internal
4770 */
4771void QQuickItem::mapFromItem(QQmlV4FunctionPtr args) const
4772{
4773 QV4::ExecutionEngine *v4 = args->v4engine();
4774 QV4::Scope scope(v4);
4775
4776 qreal x, y, w, h;
4777 bool isRect;
4778 QQuickItem *itemObj;
4779 if (!unwrapMapFromToFromItemArgs(args, itemForWarning: this, QStringLiteral("mapFromItem()"), itemObj: &itemObj, x: &x, y: &y, w: &w, h: &h, isRect: &isRect))
4780 return;
4781
4782 const QVariant result = isRect ? QVariant(mapRectFromItem(item: itemObj, rect: QRectF(x, y, w, h)))
4783 : QVariant(mapFromItem(item: itemObj, point: QPointF(x, y)));
4784
4785 QV4::ScopedObject rv(scope, v4->fromVariant(result));
4786 args->setReturnValue(rv.asReturnedValue());
4787}
4788#endif
4789
4790/*!
4791 \internal
4792 */
4793QTransform QQuickItem::itemTransform(QQuickItem *other, bool *ok) const
4794{
4795 Q_D(const QQuickItem);
4796
4797 // XXX todo - we need to be able to handle common parents better and detect
4798 // invalid cases
4799 if (ok) *ok = true;
4800
4801 QTransform t = d->itemToWindowTransform();
4802 if (other) t *= QQuickItemPrivate::get(item: other)->windowToItemTransform();
4803
4804 return t;
4805}
4806
4807/*!
4808 \qmlmethod point QtQuick::Item::mapToItem(Item item, real x, real y)
4809 \qmlmethod point QtQuick::Item::mapToItem(Item item, point p)
4810 \qmlmethod rect QtQuick::Item::mapToItem(Item item, real x, real y, real width, real height)
4811 \qmlmethod rect QtQuick::Item::mapToItem(Item item, rect r)
4812
4813 Maps the point (\a x, \a y) or rect (\a x, \a y, \a width, \a height), which is in this
4814 item's coordinate system, to \a item's coordinate system, and returns a \l point or \l rect
4815 matching the mapped coordinate.
4816
4817 \input item.qdocinc mapping
4818
4819 If \a item is a \c null value, this maps the point or rect to the coordinate system of the
4820 \l{Scene Coordinates}{scene}.
4821
4822 The versions accepting point and rect are since Qt 5.15.
4823*/
4824
4825#if QT_DEPRECATED_SINCE(6, 5)
4826/*!
4827 \internal
4828 */
4829void QQuickItem::mapToItem(QQmlV4FunctionPtr args) const
4830{
4831 QV4::ExecutionEngine *v4 = args->v4engine();
4832 QV4::Scope scope(v4);
4833
4834 qreal x, y, w, h;
4835 bool isRect;
4836 QQuickItem *itemObj;
4837 if (!unwrapMapFromToFromItemArgs(args, itemForWarning: this, QStringLiteral("mapToItem()"), itemObj: &itemObj, x: &x, y: &y, w: &w, h: &h, isRect: &isRect))
4838 return;
4839
4840 const QVariant result = isRect ? QVariant(mapRectToItem(item: itemObj, rect: QRectF(x, y, w, h)))
4841 : QVariant(mapToItem(item: itemObj, point: QPointF(x, y)));
4842
4843 QV4::ScopedObject rv(scope, v4->fromVariant(result));
4844 args->setReturnValue(rv.asReturnedValue());
4845}
4846
4847static bool unwrapMapFromToFromGlobalArgs(QQmlV4FunctionPtr args, const QQuickItem *itemForWarning, const QString &functionNameForWarning, qreal *x, qreal *y)
4848{
4849 QV4::ExecutionEngine *v4 = args->v4engine();
4850 if (args->length() != 1 && args->length() != 2) {
4851 v4->throwTypeError();
4852 return false;
4853 }
4854
4855 QV4::Scope scope(v4);
4856
4857 if (args->length() == 1) {
4858 QV4::ScopedValue sv(scope, (*args)[0]);
4859 if (sv->isNull()) {
4860 qmlWarning(me: itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow()
4861 << "\" which is not a point";
4862 v4->throwTypeError();
4863 return false;
4864 }
4865 const QV4::Scoped<QV4::QQmlValueTypeWrapper> variantWrapper(scope, sv->as<QV4::QQmlValueTypeWrapper>());
4866 const QVariant v = variantWrapper ? variantWrapper->toVariant() : QVariant();
4867 if (v.canConvert<QPointF>()) {
4868 const QPointF p = v.toPointF();
4869 *x = p.x();
4870 *y = p.y();
4871 } else {
4872 qmlWarning(me: itemForWarning) << functionNameForWarning << "given argument \"" << sv->toQStringNoThrow()
4873 << "\" which is not a point";
4874 v4->throwTypeError();
4875 return false;
4876 }
4877 } else {
4878 QV4::ScopedValue vx(scope, (*args)[0]);
4879 QV4::ScopedValue vy(scope, (*args)[1]);
4880
4881 if (!vx->isNumber() || !vy->isNumber()) {
4882 v4->throwTypeError();
4883 return false;
4884 }
4885
4886 *x = vx->asDouble();
4887 *y = vy->asDouble();
4888 }
4889
4890 return true;
4891}
4892
4893/*!
4894 \since 5.7
4895 \qmlmethod point QtQuick::Item::mapFromGlobal(real x, real y)
4896
4897 Maps the point (\a x, \a y), which is in the global coordinate system, to the
4898 item's coordinate system, and returns a \l point matching the mapped coordinate.
4899
4900 \input item.qdocinc mapping
4901*/
4902/*!
4903 \internal
4904 */
4905void QQuickItem::mapFromGlobal(QQmlV4FunctionPtr args) const
4906{
4907 QV4::ExecutionEngine *v4 = args->v4engine();
4908 QV4::Scope scope(v4);
4909
4910 qreal x, y;
4911 if (!unwrapMapFromToFromGlobalArgs(args, itemForWarning: this, QStringLiteral("mapFromGlobal()"), x: &x, y: &y))
4912 return;
4913
4914 QVariant result = mapFromGlobal(point: QPointF(x, y));
4915
4916 QV4::ScopedObject rv(scope, v4->fromVariant(result));
4917 args->setReturnValue(rv.asReturnedValue());
4918}
4919#endif
4920
4921/*!
4922 \since 5.7
4923 \qmlmethod point QtQuick::Item::mapToGlobal(real x, real y)
4924
4925 Maps the point (\a x, \a y), which is in this item's coordinate system, to the
4926 global coordinate system, and returns a \l point matching the mapped coordinate.
4927
4928 \input item.qdocinc mapping
4929*/
4930
4931#if QT_DEPRECATED_SINCE(6, 5)
4932/*!
4933 \internal
4934 */
4935void QQuickItem::mapToGlobal(QQmlV4FunctionPtr args) const
4936{
4937 QV4::ExecutionEngine *v4 = args->v4engine();
4938 QV4::Scope scope(v4);
4939
4940 qreal x, y;
4941 if (!unwrapMapFromToFromGlobalArgs(args, itemForWarning: this, QStringLiteral("mapFromGlobal()"), x: &x, y: &y))
4942 return;
4943
4944 QVariant result = mapToGlobal(point: QPointF(x, y));
4945
4946 QV4::ScopedObject rv(scope, v4->fromVariant(result));
4947 args->setReturnValue(rv.asReturnedValue());
4948}
4949#endif
4950
4951/*!
4952 \qmlmethod QtQuick::Item::forceActiveFocus()
4953
4954 Forces active focus on the item.
4955
4956 This method sets focus on the item and ensures that all ancestor
4957 FocusScope objects in the object hierarchy are also given \l focus.
4958
4959 The reason for the focus change will be \l [CPP] Qt::OtherFocusReason. Use
4960 the overloaded method to specify the focus reason to enable better
4961 handling of the focus change.
4962
4963 \sa activeFocus
4964*/
4965/*!
4966 Forces active focus on the item.
4967
4968 This method sets focus on the item and ensures that all ancestor
4969 FocusScope objects in the object hierarchy are also given \l focus.
4970
4971 The reason for the focus change will be \l [CPP] Qt::OtherFocusReason. Use
4972 the overloaded method to specify the focus reason to enable better
4973 handling of the focus change.
4974
4975 \sa activeFocus
4976*/
4977void QQuickItem::forceActiveFocus()
4978{
4979 forceActiveFocus(reason: Qt::OtherFocusReason);
4980}
4981
4982/*!
4983 \qmlmethod QtQuick::Item::forceActiveFocus(Qt::FocusReason reason)
4984 \overload
4985
4986 Forces active focus on the item with the given \a reason.
4987
4988 This method sets focus on the item and ensures that all ancestor
4989 FocusScope objects in the object hierarchy are also given \l focus.
4990
4991 \since 5.1
4992
4993 \sa activeFocus, Qt::FocusReason
4994*/
4995/*!
4996 \overload
4997 Forces active focus on the item with the given \a reason.
4998
4999 This method sets focus on the item and ensures that all ancestor
5000 FocusScope objects in the object hierarchy are also given \l focus.
5001
5002 \since 5.1
5003
5004 \sa activeFocus, Qt::FocusReason
5005*/
5006
5007void QQuickItem::forceActiveFocus(Qt::FocusReason reason)
5008{
5009 setFocus(focus: true, reason);
5010 QQuickItem *parent = parentItem();
5011 QQuickItem *scope = nullptr;
5012 while (parent) {
5013 if (parent->flags() & QQuickItem::ItemIsFocusScope) {
5014 parent->setFocus(focus: true, reason);
5015 if (!scope)
5016 scope = parent;
5017 }
5018 parent = parent->parentItem();
5019 }
5020}
5021
5022/*!
5023 \qmlmethod Item QtQuick::Item::nextItemInFocusChain(bool forward)
5024
5025 \since 5.1
5026
5027 Returns the item in the focus chain which is next to this item.
5028 If \a forward is \c true, or not supplied, it is the next item in
5029 the forwards direction. If \a forward is \c false, it is the next
5030 item in the backwards direction.
5031*/
5032/*!
5033 Returns the item in the focus chain which is next to this item.
5034 If \a forward is \c true, or not supplied, it is the next item in
5035 the forwards direction. If \a forward is \c false, it is the next
5036 item in the backwards direction.
5037*/
5038
5039QQuickItem *QQuickItem::nextItemInFocusChain(bool forward)
5040{
5041 return QQuickItemPrivate::nextPrevItemInTabFocusChain(item: this, forward);
5042}
5043
5044/*!
5045 \qmlmethod Item QtQuick::Item::childAt(real x, real y)
5046
5047 Returns the first visible child item found at point (\a x, \a y) within
5048 the coordinate system of this item.
5049
5050 Returns \c null if there is no such item.
5051*/
5052/*!
5053 Returns the first visible child item found at point (\a x, \a y) within
5054 the coordinate system of this item.
5055
5056 Returns \nullptr if there is no such item.
5057*/
5058QQuickItem *QQuickItem::childAt(qreal x, qreal y) const
5059{
5060 const QList<QQuickItem *> children = childItems();
5061 for (int i = children.size()-1; i >= 0; --i) {
5062 QQuickItem *child = children.at(i);
5063 // Map coordinates to the child element's coordinate space
5064 QPointF point = mapToItem(item: child, point: QPointF(x, y));
5065 if (child->isVisible() && child->contains(point))
5066 return child;
5067 }
5068 return nullptr;
5069}
5070
5071/*!
5072 \qmlmethod QtQuick::Item::dumpItemTree()
5073
5074 Dumps some details about the
5075 \l {Concepts - Visual Parent in Qt Quick}{visual tree of Items} starting
5076 with this item and its children, recursively.
5077
5078 The output looks similar to that of this QML code:
5079
5080 \qml
5081 function dump(object, indent) {
5082 console.log(indent + object)
5083 for (const i in object.children)
5084 dump(object.children[i], indent + " ")
5085 }
5086
5087 dump(myItem, "")
5088 \endqml
5089
5090 So if you want more details, you can implement your own function and add
5091 extra output to the console.log, such as values of specific properties.
5092
5093 \sa QObject::dumpObjectTree()
5094 \since 6.3
5095*/
5096/*!
5097 Dumps some details about the
5098 \l {Concepts - Visual Parent in Qt Quick}{visual tree of Items} starting
5099 with this item, recursively.
5100
5101 \note QObject::dumpObjectTree() dumps a similar tree; but, as explained
5102 in \l {Concepts - Visual Parent in Qt Quick}, an item's QObject::parent()
5103 sometimes differs from its QQuickItem::parentItem(). You can dump
5104 both trees to see the difference.
5105
5106 \note The exact output format may change in future versions of Qt.
5107
5108 \since 6.3
5109 \sa {Debugging Techniques}
5110 \sa {https://doc.qt.io/GammaRay/gammaray-qtquick2-inspector.html}{GammaRay's Qt Quick Inspector}
5111*/
5112void QQuickItem::dumpItemTree() const
5113{
5114 Q_D(const QQuickItem);
5115 d->dumpItemTree(indent: 0);
5116}
5117
5118void QQuickItemPrivate::dumpItemTree(int indent) const
5119{
5120 Q_Q(const QQuickItem);
5121
5122 const auto indentStr = QString(indent * 4, QLatin1Char(' '));
5123 qDebug().nospace().noquote() << indentStr <<
5124#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
5125 const_cast<QQuickItem *>(q);
5126#else
5127 q;
5128#endif
5129 if (extra.isAllocated()) {
5130 for (const auto handler : extra->pointerHandlers)
5131 qDebug().nospace().noquote() << indentStr << u" \u26ee " << handler;
5132 }
5133 for (const QQuickItem *ch : childItems) {
5134 auto itemPriv = QQuickItemPrivate::get(item: ch);
5135 itemPriv->dumpItemTree(indent: indent + 1);
5136 }
5137}
5138
5139QQmlListProperty<QObject> QQuickItemPrivate::resources()
5140{
5141 // Do not synthesize replace().
5142 // It would be extremely expensive and wouldn't work with most methods.
5143 QQmlListProperty<QObject> result;
5144 result.object = q_func();
5145 result.append = QQuickItemPrivate::resources_append;
5146 result.count = QQuickItemPrivate::resources_count;
5147 result.at = QQuickItemPrivate::resources_at;
5148 result.clear = QQuickItemPrivate::resources_clear;
5149 result.removeLast = QQuickItemPrivate::resources_removeLast;
5150 return result;
5151}
5152
5153/*!
5154 \qmlproperty list<Item> QtQuick::Item::children
5155 \qmlproperty list<QtObject> QtQuick::Item::resources
5156
5157 The children property contains the list of visual children of this item.
5158 The resources property contains non-visual resources that you want to
5159 reference by name.
5160
5161 It is not generally necessary to refer to these properties when adding
5162 child items or resources, as the default \l data property will
5163 automatically assign child objects to the \c children and \c resources
5164 properties as appropriate. See the \l data documentation for details.
5165*/
5166/*!
5167 \property QQuickItem::children
5168 \internal
5169*/
5170QQmlListProperty<QQuickItem> QQuickItemPrivate::children()
5171{
5172 // Do not synthesize replace().
5173 // It would be extremely expensive and wouldn't work with most methods.
5174 QQmlListProperty<QQuickItem> result;
5175 result.object = q_func();
5176 result.append = QQuickItemPrivate::children_append;
5177 result.count = QQuickItemPrivate::children_count;
5178 result.at = QQuickItemPrivate::children_at;
5179 result.clear = QQuickItemPrivate::children_clear;
5180 result.removeLast = QQuickItemPrivate::children_removeLast;
5181 return result;
5182}
5183
5184/*!
5185 \qmlproperty list<Item> QtQuick::Item::visibleChildren
5186 This read-only property lists all of the item's children that are currently visible.
5187 Note that a child's visibility may have changed explicitly, or because the visibility
5188 of this (it's parent) item or another grandparent changed.
5189*/
5190/*!
5191 \property QQuickItem::visibleChildren
5192 \internal
5193*/
5194QQmlListProperty<QQuickItem> QQuickItemPrivate::visibleChildren()
5195{
5196 return QQmlListProperty<QQuickItem>(q_func(),
5197 nullptr,
5198 QQuickItemPrivate::visibleChildren_count,
5199 QQuickItemPrivate::visibleChildren_at);
5200
5201}
5202
5203/*!
5204 \qmlproperty list<State> QtQuick::Item::states
5205
5206 This property holds the list of possible states for this item. To change
5207 the state of this item, set the \l state property to one of these states,
5208 or set the \l state property to an empty string to revert the item to its
5209 default state.
5210
5211 This property is specified as a list of \l State objects. For example,
5212 below is an item with "red_color" and "blue_color" states:
5213
5214 \qml
5215 import QtQuick 2.0
5216
5217 Rectangle {
5218 id: root
5219 width: 100; height: 100
5220
5221 states: [
5222 State {
5223 name: "red_color"
5224 PropertyChanges { root.color: "red" }
5225 },
5226 State {
5227 name: "blue_color"
5228 PropertyChanges { root.color: "blue" }
5229 }
5230 ]
5231 }
5232 \endqml
5233
5234 See \l{Qt Quick States} and \l{Animation and Transitions in Qt Quick} for
5235 more details on using states and transitions.
5236
5237 \sa transitions
5238*/
5239/*!
5240 \property QQuickItem::states
5241 \internal
5242 */
5243QQmlListProperty<QQuickState> QQuickItemPrivate::states()
5244{
5245 return _states()->statesProperty();
5246}
5247
5248/*!
5249 \qmlproperty list<Transition> QtQuick::Item::transitions
5250
5251 This property holds the list of transitions for this item. These define the
5252 transitions to be applied to the item whenever it changes its \l state.
5253
5254 This property is specified as a list of \l Transition objects. For example:
5255
5256 \qml
5257 import QtQuick 2.0
5258
5259 Item {
5260 transitions: [
5261 Transition {
5262 //...
5263 },
5264 Transition {
5265 //...
5266 }
5267 ]
5268 }
5269 \endqml
5270
5271 See \l{Qt Quick States} and \l{Animation and Transitions in Qt Quick} for
5272 more details on using states and transitions.
5273
5274 \sa states
5275*/
5276/*!
5277 \property QQuickItem::transitions
5278 \internal
5279 */
5280QQmlListProperty<QQuickTransition> QQuickItemPrivate::transitions()
5281{
5282 return _states()->transitionsProperty();
5283}
5284
5285QString QQuickItemPrivate::state() const
5286{
5287 if (!_stateGroup)
5288 return QString();
5289 else
5290 return _stateGroup->state();
5291}
5292
5293void QQuickItemPrivate::setState(const QString &state)
5294{
5295 _states()->setState(state);
5296}
5297
5298/*!
5299 \qmlproperty string QtQuick::Item::state
5300
5301 This property holds the name of the current state of the item.
5302
5303 If the item is in its default state, that is, no explicit state has been
5304 set, then this property holds an empty string. Likewise, you can return
5305 an item to its default state by setting this property to an empty string.
5306
5307 \sa {Qt Quick States}
5308*/
5309/*!
5310 \property QQuickItem::state
5311
5312 This property holds the name of the current state of the item.
5313
5314 If the item is in its default state, that is, no explicit state has been
5315 set, then this property holds an empty string. Likewise, you can return
5316 an item to its default state by setting this property to an empty string.
5317
5318 \sa {Qt Quick States}
5319*/
5320QString QQuickItem::state() const
5321{
5322 Q_D(const QQuickItem);
5323 return d->state();
5324}
5325
5326void QQuickItem::setState(const QString &state)
5327{
5328 Q_D(QQuickItem);
5329 d->setState(state);
5330}
5331
5332/*!
5333 \qmlproperty list<Transform> QtQuick::Item::transform
5334
5335 This property holds the list of transformations to apply.
5336
5337 This property is specified as a list of \l {Transform}-derived objects.
5338 For example:
5339
5340 \snippet qml/two-transforms.qml entire
5341
5342 For more information see \l Transform.
5343*/
5344/*!
5345 \property QQuickItem::transform
5346 \internal
5347 */
5348/*!
5349 \internal
5350 */
5351QQmlListProperty<QQuickTransform> QQuickItem::transform()
5352{
5353 return QQmlListProperty<QQuickTransform>(this, nullptr, QQuickItemPrivate::transform_append,
5354 QQuickItemPrivate::transform_count,
5355 QQuickItemPrivate::transform_at,
5356 QQuickItemPrivate::transform_clear);
5357}
5358
5359/*!
5360 \reimp
5361 Derived classes should call the base class method before adding their own action to
5362 perform at classBegin.
5363*/
5364void QQuickItem::classBegin()
5365{
5366 Q_D(QQuickItem);
5367 d->componentComplete = false;
5368 if (d->_stateGroup)
5369 d->_stateGroup->classBegin();
5370 if (d->_anchors)
5371 d->_anchors->classBegin();
5372#if QT_CONFIG(quick_shadereffect)
5373 if (d->extra.isAllocated() && d->extra->layer)
5374 d->extra->layer->classBegin();
5375#endif
5376}
5377
5378/*!
5379 \reimp
5380 Derived classes should call the base class method before adding their own actions to
5381 perform at componentComplete.
5382*/
5383void QQuickItem::componentComplete()
5384{
5385 Q_D(QQuickItem);
5386 d->componentComplete = true;
5387 if (d->_stateGroup)
5388 d->_stateGroup->componentComplete();
5389 if (d->_anchors) {
5390 d->_anchors->componentComplete();
5391 QQuickAnchorsPrivate::get(o: d->_anchors)->updateOnComplete();
5392 }
5393
5394 if (auto *safeArea = findChild<QQuickSafeArea*>(options: Qt::FindDirectChildrenOnly))
5395 safeArea->updateSafeArea();
5396
5397 if (d->extra.isAllocated()) {
5398#if QT_CONFIG(quick_shadereffect)
5399 if (d->extra->layer)
5400 d->extra->layer->componentComplete();
5401#endif
5402
5403 if (d->extra->keyHandler)
5404 d->extra->keyHandler->componentComplete();
5405
5406 if (d->extra->contents)
5407 d->extra->contents->complete();
5408 }
5409
5410 if (d->window && d->dirtyAttributes) {
5411 d->addToDirtyList();
5412 QQuickWindowPrivate::get(c: d->window)->dirtyItem(this);
5413 }
5414
5415#if QT_CONFIG(accessibility)
5416 if (d->isAccessible && d->effectiveVisible) {
5417 QAccessibleEvent ev(this, QAccessible::ObjectShow);
5418 QAccessible::updateAccessibility(event: &ev);
5419 }
5420#endif
5421}
5422
5423QQuickStateGroup *QQuickItemPrivate::_states()
5424{
5425 Q_Q(QQuickItem);
5426 if (!_stateGroup) {
5427 _stateGroup = new QQuickStateGroup;
5428 if (!componentComplete)
5429 _stateGroup->classBegin();
5430 qmlobject_connect(_stateGroup, QQuickStateGroup, SIGNAL(stateChanged(QString)),
5431 q, QQuickItem, SIGNAL(stateChanged(QString)));
5432 }
5433
5434 return _stateGroup;
5435}
5436
5437QPointF QQuickItemPrivate::computeTransformOrigin() const
5438{
5439 switch (origin()) {
5440 default:
5441 case QQuickItem::TopLeft:
5442 return QPointF(0, 0);
5443 case QQuickItem::Top:
5444 return QPointF(width / 2., 0);
5445 case QQuickItem::TopRight:
5446 return QPointF(width, 0);
5447 case QQuickItem::Left:
5448 return QPointF(0, height / 2.);
5449 case QQuickItem::Center:
5450 return QPointF(width / 2., height / 2.);
5451 case QQuickItem::Right:
5452 return QPointF(width, height / 2.);
5453 case QQuickItem::BottomLeft:
5454 return QPointF(0, height);
5455 case QQuickItem::Bottom:
5456 return QPointF(width / 2., height);
5457 case QQuickItem::BottomRight:
5458 return QPointF(width, height);
5459 }
5460}
5461
5462/*!
5463 \internal
5464 QQuickItemPrivate::dirty() calls transformChanged(q) to inform this item and
5465 all its children that its transform has changed, with \a transformedItem always
5466 being the parent item that caused the change. Override to react, e.g. to
5467 call update() if the item needs to re-generate SG nodes based on visible extents.
5468 If you override in a subclass, you must also call this (superclass) function
5469 and return the value from it.
5470
5471 This function recursively visits all children as long as
5472 subtreeTransformChangedEnabled is true, returns \c true if any of those
5473 children still has the ItemObservesViewport flag set, but otherwise
5474 turns subtreeTransformChangedEnabled off, if no children are observing.
5475*/
5476bool QQuickItemPrivate::transformChanged(QQuickItem *transformedItem)
5477{
5478 Q_Q(QQuickItem);
5479
5480#if QT_CONFIG(quick_shadereffect)
5481 if (q == transformedItem) {
5482 if (extra.isAllocated() && extra->layer)
5483 extra->layer->updateMatrix();
5484 }
5485#endif
5486
5487 itemChange(QQuickItem::ItemTransformHasChanged, transformedItem);
5488
5489 bool childWantsIt = false;
5490 if (subtreeTransformChangedEnabled) {
5491 // Inform the children in paint order: by the time we visit leaf items,
5492 // they can see any consequences in their parents
5493 const auto children = paintOrderChildItems();
5494 for (QQuickItem *child : children)
5495 childWantsIt |= QQuickItemPrivate::get(item: child)->transformChanged(transformedItem);
5496 }
5497
5498 const bool thisWantsIt = q->flags().testFlag(flag: QQuickItem::ItemObservesViewport);
5499 const bool ret = childWantsIt || thisWantsIt;
5500 if (!ret && componentComplete && subtreeTransformChangedEnabled) {
5501 qCDebug(lcVP) << "turned off subtree transformChanged notification after checking all children of" << q;
5502 subtreeTransformChangedEnabled = false;
5503 }
5504 // If ItemObservesViewport, clipRect() calculates the intersection with the viewport;
5505 // so each time the item moves in the viewport, its clipnode needs to be updated.
5506 if (thisWantsIt && q->clip() && !(dirtyAttributes & QQuickItemPrivate::Clip))
5507 dirty(QQuickItemPrivate::Clip);
5508
5509 return ret;
5510}
5511
5512/*! \internal
5513 Returns the new position (proposed values for the x and y properties)
5514 to which this item should be moved to compensate for the given change
5515 in scale from \a startScale to \a activeScale and in rotation from
5516 \a startRotation to \a activeRotation. \a centroidParentPos is the
5517 point that we wish to hold in place (and then apply \a activeTranslation to),
5518 in this item's parent's coordinate system. \a startPos is this item's
5519 position in its parent's coordinate system when the gesture began.
5520 \a activeTranslation is the amount of translation that should be added to
5521 the return value, i.e. the displacement by which the centroid is expected
5522 to move.
5523
5524 If \a activeTranslation is \c (0, 0) the centroid is to be held in place.
5525 If \a activeScale is \c 1, it means scale is intended to be held constant,
5526 the same as \a startScale. If \a activeRotation is \c 0, it means rotation
5527 is intended to be held constant, the same as \a startRotation.
5528*/
5529QPointF QQuickItemPrivate::adjustedPosForTransform(const QPointF &centroidParentPos,
5530 const QPointF &startPos,
5531 const QVector2D &activeTranslation,
5532 qreal startScale,
5533 qreal activeScale,
5534 qreal startRotation,
5535 qreal activeRotation)
5536{
5537 Q_Q(QQuickItem);
5538 QVector3D xformOrigin(q->transformOriginPoint());
5539 QMatrix4x4 startMatrix;
5540 startMatrix.translate(x: float(startPos.x()), y: float(startPos.y()));
5541 startMatrix.translate(vector: xformOrigin);
5542 startMatrix.scale(factor: float(startScale));
5543 startMatrix.rotate(angle: float(startRotation), x: 0, y: 0, z: -1);
5544 startMatrix.translate(vector: -xformOrigin);
5545
5546 const QVector3D centroidParentVector(centroidParentPos);
5547 QMatrix4x4 mat;
5548 mat.translate(vector: centroidParentVector);
5549 mat.rotate(angle: float(activeRotation), x: 0, y: 0, z: 1);
5550 mat.scale(factor: float(activeScale));
5551 mat.translate(vector: -centroidParentVector);
5552 mat.translate(vector: QVector3D(activeTranslation));
5553
5554 mat = mat * startMatrix;
5555
5556 QPointF xformOriginPoint = q->transformOriginPoint();
5557 QPointF pos = mat.map(point: xformOriginPoint);
5558 pos -= xformOriginPoint;
5559
5560 return pos;
5561}
5562
5563/*! \internal
5564 Returns the delivery agent for the narrowest subscene containing this item,
5565 but falls back to QQuickWindowPrivate::deliveryAgent if there are no subscenes.
5566
5567 If this item is not sure whether it's in a subscene (as by default), we need to
5568 explore the parents to find out.
5569
5570 If this item is in a subscene, we will find that DA during the exploration,
5571 and return it.
5572
5573 If we find the root item without finding a DA, then we know that this item
5574 does NOT belong to a subscene, so we remember that by setting
5575 maybeHasSubsceneDeliveryAgent to false, so that exploration of the parents
5576 can be avoided next time.
5577
5578 In the usual case in normal 2D scenes without subscenes,
5579 maybeHasSubsceneDeliveryAgent gets set to false here.
5580
5581 \note When a Qt Quick scene is shown in the usual way in its own window,
5582 subscenes are ignored, and QQuickWindowPrivate::deliveryAgent is used.
5583 Subscene delivery agents are used only in QtQuick 3D so far.
5584*/
5585QQuickDeliveryAgent *QQuickItemPrivate::deliveryAgent()
5586{
5587 Q_Q(QQuickItem);
5588 if (maybeHasSubsceneDeliveryAgent) {
5589 QQuickItemPrivate *p = this;
5590 do {
5591 if (qmlobject_cast<QQuickRootItem *>(object: p->q_ptr)) {
5592 // found the root item without finding a different DA:
5593 // it means we don't need to repeat this search next time.
5594 // TODO maybe optimize further: make this function recursive, and
5595 // set it to false on each item that we visit in the tail
5596 maybeHasSubsceneDeliveryAgent = false;
5597 break;
5598 }
5599 if (p->extra.isAllocated()) {
5600 if (auto da = p->extra->subsceneDeliveryAgent)
5601 return da;
5602 }
5603 p = p->parentItem ? QQuickItemPrivate::get(item: p->parentItem) : nullptr;
5604 } while (p);
5605 // arriving here is somewhat unexpected: a detached root can easily be created (just set an item's parent to null),
5606 // but why would we deliver events to that subtree? only if root got detached while an item in that subtree still has a grab?
5607 qCDebug(lcPtr) << "detached root of" << q << "is not a QQuickRootItem and also does not have its own DeliveryAgent";
5608 }
5609 if (window)
5610 return QQuickWindowPrivate::get(c: window)->deliveryAgent;
5611 return nullptr;
5612}
5613
5614QQuickDeliveryAgentPrivate *QQuickItemPrivate::deliveryAgentPrivate()
5615{
5616 auto da = deliveryAgent();
5617 return da ? static_cast<QQuickDeliveryAgentPrivate *>(QQuickDeliveryAgentPrivate::get(o: da)) : nullptr;
5618}
5619
5620/*! \internal
5621 Ensures that this item, presumably the root of a subscene (e.g. because it
5622 is mapped onto a 3D object in Qt Quick 3D), has a delivery agent to be used
5623 when delivering events to the subscene: i.e. when the viewport delivers an
5624 event to the subscene, or when the outer delivery agent delivers an update
5625 to an item that grabbed during a previous subscene delivery. Creates a new
5626 agent if it was not already created, and returns a pointer to the instance.
5627*/
5628QQuickDeliveryAgent *QQuickItemPrivate::ensureSubsceneDeliveryAgent()
5629{
5630 Q_Q(QQuickItem);
5631 // We are (about to be) sure that it has one now; but just to save space,
5632 // we avoid storing a DA pointer in each item; so deliveryAgent() always needs to
5633 // go up the hierarchy to find it. maybeHasSubsceneDeliveryAgent tells it to do that.
5634 maybeHasSubsceneDeliveryAgent = true;
5635 if (extra.isAllocated() && extra->subsceneDeliveryAgent)
5636 return extra->subsceneDeliveryAgent;
5637 extra.value().subsceneDeliveryAgent = new QQuickDeliveryAgent(q);
5638 qCDebug(lcPtr) << "created new" << extra->subsceneDeliveryAgent;
5639 // every subscene root needs to be a focus scope so that when QQuickItem::forceActiveFocus()
5640 // goes up the parent hierarchy, it finds the subscene root and calls setFocus() on it
5641 q->setFlag(flag: QQuickItem::ItemIsFocusScope);
5642 return extra->subsceneDeliveryAgent;
5643}
5644
5645bool QQuickItemPrivate::filterKeyEvent(QKeyEvent *e, bool post)
5646{
5647 if (!extra.isAllocated() || !extra->keyHandler)
5648 return false;
5649
5650 if (post)
5651 e->accept();
5652
5653 if (e->type() == QEvent::KeyPress)
5654 extra->keyHandler->keyPressed(event: e, post);
5655 else
5656 extra->keyHandler->keyReleased(event: e, post);
5657
5658 return e->isAccepted();
5659}
5660
5661void QQuickItemPrivate::deliverPointerEvent(QEvent *event)
5662{
5663 Q_Q(QQuickItem);
5664 const auto eventType = event->type();
5665 const bool focusAccepted = setFocusIfNeeded(eventType);
5666
5667 switch (eventType) {
5668 case QEvent::MouseButtonPress:
5669 q->mousePressEvent(event: static_cast<QMouseEvent *>(event));
5670 break;
5671 case QEvent::MouseButtonRelease:
5672 q->mouseReleaseEvent(event: static_cast<QMouseEvent *>(event));
5673 break;
5674 case QEvent::MouseButtonDblClick:
5675 q->mouseDoubleClickEvent(event: static_cast<QMouseEvent *>(event));
5676 break;
5677#if QT_CONFIG(wheelevent)
5678 case QEvent::Wheel:
5679 q->wheelEvent(event: static_cast<QWheelEvent*>(event));
5680 break;
5681#endif
5682 case QEvent::TouchBegin:
5683 case QEvent::TouchUpdate:
5684 case QEvent::TouchEnd:
5685 case QEvent::TouchCancel:
5686 q->touchEvent(event: static_cast<QTouchEvent *>(event));
5687 break;
5688 default:
5689 break;
5690 }
5691
5692 if (focusAccepted)
5693 event->accept();
5694}
5695
5696void QQuickItemPrivate::deliverKeyEvent(QKeyEvent *e)
5697{
5698 Q_Q(QQuickItem);
5699
5700 Q_ASSERT(e->isAccepted());
5701 if (filterKeyEvent(e, post: false))
5702 return;
5703 else
5704 e->accept();
5705
5706 if (e->type() == QEvent::KeyPress)
5707 q->keyPressEvent(event: e);
5708 else
5709 q->keyReleaseEvent(event: e);
5710
5711 if (e->isAccepted())
5712 return;
5713
5714 if (filterKeyEvent(e, post: true) || !q->window())
5715 return;
5716
5717 //only care about KeyPress now
5718 if (e->type() == QEvent::KeyPress &&
5719 (q == q->window()->contentItem() || q->activeFocusOnTab())) {
5720 bool res = false;
5721 if (!(e->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
5722 if (e->key() == Qt::Key_Backtab
5723 || (e->key() == Qt::Key_Tab && (e->modifiers() & Qt::ShiftModifier)))
5724 res = QQuickItemPrivate::focusNextPrev(item: q, forward: false);
5725 else if (e->key() == Qt::Key_Tab)
5726 res = QQuickItemPrivate::focusNextPrev(item: q, forward: true);
5727 if (res)
5728 e->setAccepted(true);
5729 }
5730 }
5731}
5732
5733#if QT_CONFIG(im)
5734void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e)
5735{
5736 Q_Q(QQuickItem);
5737
5738 Q_ASSERT(e->isAccepted());
5739 if (extra.isAllocated() && extra->keyHandler) {
5740 extra->keyHandler->inputMethodEvent(event: e, post: false);
5741
5742 if (e->isAccepted())
5743 return;
5744 else
5745 e->accept();
5746 }
5747
5748 q->inputMethodEvent(event: e);
5749
5750 if (e->isAccepted())
5751 return;
5752
5753 if (extra.isAllocated() && extra->keyHandler) {
5754 e->accept();
5755
5756 extra->keyHandler->inputMethodEvent(event: e, post: true);
5757 }
5758}
5759#endif // im
5760
5761void QQuickItemPrivate::deliverShortcutOverrideEvent(QKeyEvent *event)
5762{
5763 if (extra.isAllocated() && extra->keyHandler)
5764 extra->keyHandler->shortcutOverrideEvent(event);
5765 else
5766 event->ignore();
5767}
5768
5769bool QQuickItemPrivate::anyPointerHandlerWants(const QPointerEvent *event, const QEventPoint &point) const
5770{
5771 if (!hasPointerHandlers())
5772 return false;
5773 for (QQuickPointerHandler *handler : extra->pointerHandlers) {
5774 if (handler->wantsEventPoint(event, point))
5775 return true;
5776 }
5777 return false;
5778}
5779
5780/*!
5781 \internal
5782 Deliver the \a event to all this item's PointerHandlers, but skip
5783 HoverHandlers if the event is a QMouseEvent or QWheelEvent (they are visited
5784 in QQuickDeliveryAgentPrivate::deliverHoverEventToItem()), and skip handlers
5785 that are in QQuickPointerHandlerPrivate::deviceDeliveryTargets().
5786 However if the event is a QTabletEvent, we do NOT skip delivery here:
5787 this is the means by which HoverHandler can change the cursor when the
5788 tablet stylus hovers over its parent item.
5789
5790 If \a avoidGrabbers is true, also skip delivery to any handler that
5791 is exclusively or passively grabbing any point within \a event
5792 (because delivery to grabbers is handled separately).
5793*/
5794bool QQuickItemPrivate::handlePointerEvent(QPointerEvent *event, bool avoidGrabbers)
5795{
5796 bool delivered = false;
5797 if (extra.isAllocated()) {
5798 for (QQuickPointerHandler *handler : extra->pointerHandlers) {
5799 bool avoidThisHandler = false;
5800 if (QQuickDeliveryAgentPrivate::isMouseOrWheelEvent(ev: event) &&
5801 qmlobject_cast<const QQuickHoverHandler *>(object: handler)) {
5802 avoidThisHandler = true;
5803 } else if (avoidGrabbers) {
5804 for (auto &p : event->points()) {
5805 if (event->exclusiveGrabber(point: p) == handler || event->passiveGrabbers(point: p).contains(t: handler)) {
5806 avoidThisHandler = true;
5807 break;
5808 }
5809 }
5810 }
5811 if (!avoidThisHandler &&
5812 !QQuickPointerHandlerPrivate::deviceDeliveryTargets(device: event->device()).contains(t: handler)) {
5813 handler->handlePointerEvent(event);
5814 delivered = true;
5815 }
5816 }
5817 }
5818 return delivered;
5819}
5820
5821#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
5822bool QQuickItemPrivate::handleContextMenuEvent(QContextMenuEvent *event)
5823#else
5824bool QQuickItem::contextMenuEvent(QContextMenuEvent *event)
5825#endif
5826{
5827 if (extra.isAllocated() && extra->contextMenu)
5828 return extra->contextMenu->event(event);
5829 event->ignore();
5830 return false;
5831}
5832
5833/*!
5834 Called when \a change occurs for this item.
5835
5836 \a value contains extra information relating to the change, when
5837 applicable.
5838
5839 If you re-implement this method in a subclass, be sure to call
5840 \code
5841 QQuickItem::itemChange(change, value);
5842 \endcode
5843 typically at the end of your implementation, to ensure the
5844 \l windowChanged() signal will be emitted.
5845 */
5846void QQuickItem::itemChange(ItemChange change, const ItemChangeData &value)
5847{
5848 if (change == ItemSceneChange)
5849 emit windowChanged(window: value.window);
5850}
5851
5852#if QT_CONFIG(im)
5853/*!
5854 Notify input method on updated query values if needed. \a queries indicates
5855 the changed attributes.
5856*/
5857void QQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
5858{
5859 if (hasActiveFocus())
5860 QGuiApplication::inputMethod()->update(queries);
5861}
5862#endif // im
5863
5864/*!
5865 Returns the extents of the item in its own coordinate system:
5866 a rectangle from \c{0, 0} to \l width() and \l height().
5867*/
5868QRectF QQuickItem::boundingRect() const
5869{
5870 Q_D(const QQuickItem);
5871 return QRectF(0, 0, d->width, d->height);
5872}
5873
5874/*!
5875 Returns the rectangular area within this item that is currently visible in
5876 \l viewportItem(), if there is a viewport and the \l ItemObservesViewport
5877 flag is set; otherwise, the extents of this item in its own coordinate
5878 system: a rectangle from \c{0, 0} to \l width() and \l height(). This is
5879 the region intended to remain visible if \l clip is \c true. It can also be
5880 used in updatePaintNode() to limit the graphics added to the scene graph.
5881
5882 For example, a large drawing or a large text document might be shown in a
5883 Flickable that occupies only part of the application's Window: in that
5884 case, Flickable is the viewport item, and a custom content-rendering item
5885 may choose to omit scene graph nodes that fall outside the area that is
5886 currently visible. If the \l ItemObservesViewport flag is set, this area
5887 will change each time the user scrolls the content in the Flickable.
5888
5889 In case of nested viewport items, clipRect() is the intersection of the
5890 \c {boundingRect}s of all ancestors that have the \l ItemIsViewport flag set,
5891 mapped to the coordinate system of \e this item.
5892
5893 \sa boundingRect()
5894*/
5895QRectF QQuickItem::clipRect() const
5896{
5897 Q_D(const QQuickItem);
5898 QRectF ret(0, 0, d->width, d->height);
5899 if (flags().testFlag(flag: QQuickItem::ItemObservesViewport)) {
5900 if (QQuickItem *viewport = viewportItem()) {
5901 // if the viewport is already "this", there's nothing to intersect;
5902 // and don't call clipRect() again, to avoid infinite recursion
5903 if (viewport == this)
5904 return ret;
5905 const auto mappedViewportRect = mapRectFromItem(item: viewport, rect: viewport->clipRect());
5906 qCDebug(lcVP) << this << "intersecting" << viewport << mappedViewportRect << ret << "->" << mappedViewportRect.intersected(r: ret);
5907 return mappedViewportRect.intersected(r: ret);
5908 }
5909 }
5910 return ret;
5911}
5912
5913/*!
5914 If the \l ItemObservesViewport flag is set,
5915 returns the nearest parent with the \l ItemIsViewport flag.
5916 Returns the window's contentItem if the flag is not set,
5917 or if no other viewport item is found.
5918
5919 Returns \nullptr only if there is no viewport item and this item is not
5920 shown in a window.
5921
5922 \sa clipRect()
5923*/
5924QQuickItem *QQuickItem::viewportItem() const
5925{
5926 if (flags().testFlag(flag: ItemObservesViewport)) {
5927 QQuickItem *par = parentItem();
5928 while (par) {
5929 if (par->flags().testFlag(flag: QQuickItem::ItemIsViewport))
5930 return par;
5931 par = par->parentItem();
5932 }
5933 }
5934 return (window() ? window()->contentItem() : nullptr);
5935}
5936
5937/*!
5938 \qmlproperty enumeration QtQuick::Item::transformOrigin
5939 This property holds the origin point around which scale and rotation transform.
5940
5941 Nine transform origins are available, as shown in the image below.
5942 The default transform origin is \c Item.Center.
5943
5944 \image declarative-transformorigin.png
5945
5946 This example rotates an image around its bottom-right corner.
5947 \qml
5948 Image {
5949 source: "myimage.png"
5950 transformOrigin: Item.BottomRight
5951 rotation: 45
5952 }
5953 \endqml
5954
5955 To set an arbitrary transform origin point use the \l Scale or \l Rotation
5956 transform types with \l transform.
5957*/
5958/*!
5959 \property QQuickItem::transformOrigin
5960 This property holds the origin point around which scale and rotation transform.
5961
5962 Nine transform origins are available, as shown in the image below.
5963 The default transform origin is \c Item.Center.
5964
5965 \image declarative-transformorigin.png
5966*/
5967QQuickItem::TransformOrigin QQuickItem::transformOrigin() const
5968{
5969 Q_D(const QQuickItem);
5970 return d->origin();
5971}
5972
5973void QQuickItem::setTransformOrigin(TransformOrigin origin)
5974{
5975 Q_D(QQuickItem);
5976 if (origin == d->origin())
5977 return;
5978
5979 d->extra.value().origin = origin;
5980 d->dirty(QQuickItemPrivate::TransformOrigin);
5981
5982 emit transformOriginChanged(d->origin());
5983}
5984
5985/*!
5986 \property QQuickItem::transformOriginPoint
5987 \internal
5988 */
5989/*!
5990 \internal
5991 */
5992QPointF QQuickItem::transformOriginPoint() const
5993{
5994 Q_D(const QQuickItem);
5995 if (d->extra.isAllocated() && !d->extra->userTransformOriginPoint.isNull())
5996 return d->extra->userTransformOriginPoint;
5997 return d->computeTransformOrigin();
5998}
5999
6000/*!
6001 \internal
6002 */
6003void QQuickItem::setTransformOriginPoint(const QPointF &point)
6004{
6005 Q_D(QQuickItem);
6006 if (d->extra.value().userTransformOriginPoint == point)
6007 return;
6008
6009 d->extra->userTransformOriginPoint = point;
6010 d->dirty(QQuickItemPrivate::TransformOrigin);
6011}
6012
6013/*!
6014 \qmlproperty real QtQuick::Item::z
6015
6016 Sets the stacking order of sibling items. By default the stacking order is 0.
6017
6018 Items with a higher stacking value are drawn on top of siblings with a
6019 lower stacking order. Items with the same stacking value are drawn
6020 bottom up in the order they appear. Items with a negative stacking
6021 value are drawn under their parent's content.
6022
6023 The following example shows the various effects of stacking order.
6024
6025 \table
6026 \row
6027 \li \image declarative-item_stacking1.png
6028 \li Same \c z - later children above earlier children:
6029 \qml
6030 Item {
6031 Rectangle {
6032 color: "red"
6033 width: 100; height: 100
6034 }
6035 Rectangle {
6036 color: "blue"
6037 x: 50; y: 50; width: 100; height: 100
6038 }
6039 }
6040 \endqml
6041 \row
6042 \li \image declarative-item_stacking2.png
6043 \li Higher \c z on top:
6044 \qml
6045 Item {
6046 Rectangle {
6047 z: 1
6048 color: "red"
6049 width: 100; height: 100
6050 }
6051 Rectangle {
6052 color: "blue"
6053 x: 50; y: 50; width: 100; height: 100
6054 }
6055 }
6056 \endqml
6057 \row
6058 \li \image declarative-item_stacking3.png
6059 \li Same \c z - children above parents:
6060 \qml
6061 Item {
6062 Rectangle {
6063 color: "red"
6064 width: 100; height: 100
6065 Rectangle {
6066 color: "blue"
6067 x: 50; y: 50; width: 100; height: 100
6068 }
6069 }
6070 }
6071 \endqml
6072 \row
6073 \li \image declarative-item_stacking4.png
6074 \li Lower \c z below:
6075 \qml
6076 Item {
6077 Rectangle {
6078 color: "red"
6079 width: 100; height: 100
6080 Rectangle {
6081 z: -1
6082 color: "blue"
6083 x: 50; y: 50; width: 100; height: 100
6084 }
6085 }
6086 }
6087 \endqml
6088 \endtable
6089 */
6090/*!
6091 \property QQuickItem::z
6092
6093 Sets the stacking order of sibling items. By default the stacking order is 0.
6094
6095 Items with a higher stacking value are drawn on top of siblings with a
6096 lower stacking order. Items with the same stacking value are drawn
6097 bottom up in the order they appear. Items with a negative stacking
6098 value are drawn under their parent's content.
6099
6100 The following example shows the various effects of stacking order.
6101
6102 \table
6103 \row
6104 \li \image declarative-item_stacking1.png
6105 \li Same \c z - later children above earlier children:
6106 \qml
6107 Item {
6108 Rectangle {
6109 color: "red"
6110 width: 100; height: 100
6111 }
6112 Rectangle {
6113 color: "blue"
6114 x: 50; y: 50; width: 100; height: 100
6115 }
6116 }
6117 \endqml
6118 \row
6119 \li \image declarative-item_stacking2.png
6120 \li Higher \c z on top:
6121 \qml
6122 Item {
6123 Rectangle {
6124 z: 1
6125 color: "red"
6126 width: 100; height: 100
6127 }
6128 Rectangle {
6129 color: "blue"
6130 x: 50; y: 50; width: 100; height: 100
6131 }
6132 }
6133 \endqml
6134 \row
6135 \li \image declarative-item_stacking3.png
6136 \li Same \c z - children above parents:
6137 \qml
6138 Item {
6139 Rectangle {
6140 color: "red"
6141 width: 100; height: 100
6142 Rectangle {
6143 color: "blue"
6144 x: 50; y: 50; width: 100; height: 100
6145 }
6146 }
6147 }
6148 \endqml
6149 \row
6150 \li \image declarative-item_stacking4.png
6151 \li Lower \c z below:
6152 \qml
6153 Item {
6154 Rectangle {
6155 color: "red"
6156 width: 100; height: 100
6157 Rectangle {
6158 z: -1
6159 color: "blue"
6160 x: 50; y: 50; width: 100; height: 100
6161 }
6162 }
6163 }
6164 \endqml
6165 \endtable
6166 */
6167qreal QQuickItem::z() const
6168{
6169 Q_D(const QQuickItem);
6170 return d->z();
6171}
6172
6173void QQuickItem::setZ(qreal v)
6174{
6175 Q_D(QQuickItem);
6176 if (d->z() == v)
6177 return;
6178
6179 d->extra.value().z = v;
6180
6181 d->dirty(QQuickItemPrivate::ZValue);
6182 if (d->parentItem) {
6183 QQuickItemPrivate::get(item: d->parentItem)->markSortedChildrenDirty(child: this);
6184 QQuickItemPrivate::get(item: d->parentItem)->dirty(QQuickItemPrivate::ChildrenStackingChanged);
6185 }
6186
6187 emit zChanged();
6188
6189#if QT_CONFIG(quick_shadereffect)
6190 if (d->extra.isAllocated() && d->extra->layer)
6191 d->extra->layer->updateZ();
6192#endif
6193}
6194
6195/*!
6196 \qmlproperty real QtQuick::Item::rotation
6197 This property holds the rotation of the item in degrees clockwise around
6198 its transformOrigin.
6199
6200 The default value is 0 degrees (that is, no rotation).
6201
6202 \table
6203 \row
6204 \li \image declarative-rotation.png
6205 \li
6206 \qml
6207 Rectangle {
6208 color: "blue"
6209 width: 100; height: 100
6210 Rectangle {
6211 color: "red"
6212 x: 25; y: 25; width: 50; height: 50
6213 rotation: 30
6214 }
6215 }
6216 \endqml
6217 \endtable
6218
6219 \sa Transform, Rotation
6220*/
6221/*!
6222 \property QQuickItem::rotation
6223 This property holds the rotation of the item in degrees clockwise around
6224 its transformOrigin.
6225
6226 The default value is 0 degrees (that is, no rotation).
6227
6228 \table
6229 \row
6230 \li \image declarative-rotation.png
6231 \li
6232 \qml
6233 Rectangle {
6234 color: "blue"
6235 width: 100; height: 100
6236 Rectangle {
6237 color: "red"
6238 x: 25; y: 25; width: 50; height: 50
6239 rotation: 30
6240 }
6241 }
6242 \endqml
6243 \endtable
6244
6245 \sa Transform, Rotation
6246 */
6247qreal QQuickItem::rotation() const
6248{
6249 Q_D(const QQuickItem);
6250 return d->rotation();
6251}
6252
6253void QQuickItem::setRotation(qreal r)
6254{
6255 Q_D(QQuickItem);
6256 if (d->rotation() == r)
6257 return;
6258
6259 d->extra.value().rotation = r;
6260
6261 d->dirty(QQuickItemPrivate::BasicTransform);
6262
6263 d->itemChange(ItemRotationHasChanged, r);
6264
6265 emit rotationChanged();
6266}
6267
6268/*!
6269 \qmlproperty real QtQuick::Item::scale
6270 This property holds the scale factor for this item.
6271
6272 A scale of less than 1.0 causes the item to be rendered at a smaller
6273 size, and a scale greater than 1.0 renders the item at a larger size.
6274 A negative scale causes the item to be mirrored when rendered.
6275
6276 The default value is 1.0.
6277
6278 Scaling is applied from the transformOrigin.
6279
6280 \table
6281 \row
6282 \li \image declarative-scale.png
6283 \li
6284 \qml
6285 import QtQuick 2.0
6286
6287 Rectangle {
6288 color: "blue"
6289 width: 100; height: 100
6290
6291 Rectangle {
6292 color: "green"
6293 width: 25; height: 25
6294 }
6295
6296 Rectangle {
6297 color: "red"
6298 x: 25; y: 25; width: 50; height: 50
6299 scale: 1.4
6300 transformOrigin: Item.TopLeft
6301 }
6302 }
6303 \endqml
6304 \endtable
6305
6306 \sa Transform, Scale
6307*/
6308/*!
6309 \property QQuickItem::scale
6310 This property holds the scale factor for this item.
6311
6312 A scale of less than 1.0 causes the item to be rendered at a smaller
6313 size, and a scale greater than 1.0 renders the item at a larger size.
6314 A negative scale causes the item to be mirrored when rendered.
6315
6316 The default value is 1.0.
6317
6318 Scaling is applied from the transformOrigin.
6319
6320 \table
6321 \row
6322 \li \image declarative-scale.png
6323 \li
6324 \qml
6325 import QtQuick 2.0
6326
6327 Rectangle {
6328 color: "blue"
6329 width: 100; height: 100
6330
6331 Rectangle {
6332 color: "green"
6333 width: 25; height: 25
6334 }
6335
6336 Rectangle {
6337 color: "red"
6338 x: 25; y: 25; width: 50; height: 50
6339 scale: 1.4
6340 }
6341 }
6342 \endqml
6343 \endtable
6344
6345 \sa Transform, Scale
6346 */
6347qreal QQuickItem::scale() const
6348{
6349 Q_D(const QQuickItem);
6350 return d->scale();
6351}
6352
6353void QQuickItem::setScale(qreal s)
6354{
6355 Q_D(QQuickItem);
6356 if (d->scale() == s)
6357 return;
6358
6359 d->extra.value().scale = s;
6360
6361 d->dirty(QQuickItemPrivate::BasicTransform);
6362
6363 d->itemChange(ItemScaleHasChanged, s);
6364
6365 emit scaleChanged();
6366}
6367
6368/*!
6369 \qmlproperty real QtQuick::Item::opacity
6370
6371 This property holds the opacity of the item. Opacity is specified as a
6372 number between 0.0 (fully transparent) and 1.0 (fully opaque). The default
6373 value is 1.0.
6374
6375 When this property is set, the specified opacity is also applied
6376 individually to child items. This may have an unintended effect in some
6377 circumstances. For example in the second set of rectangles below, the red
6378 rectangle has specified an opacity of 0.5, which affects the opacity of
6379 its blue child rectangle even though the child has not specified an opacity.
6380
6381 \table
6382 \row
6383 \li \image declarative-item_opacity1.png
6384 \li
6385 \qml
6386 Item {
6387 Rectangle {
6388 color: "red"
6389 width: 100; height: 100
6390 Rectangle {
6391 color: "blue"
6392 x: 50; y: 50; width: 100; height: 100
6393 }
6394 }
6395 }
6396 \endqml
6397 \row
6398 \li \image declarative-item_opacity2.png
6399 \li
6400 \qml
6401 Item {
6402 Rectangle {
6403 opacity: 0.5
6404 color: "red"
6405 width: 100; height: 100
6406 Rectangle {
6407 color: "blue"
6408 x: 50; y: 50; width: 100; height: 100
6409 }
6410 }
6411 }
6412 \endqml
6413 \endtable
6414
6415 Changing an item's opacity does not affect whether the item receives user
6416 input events. (In contrast, setting \l visible property to \c false stops
6417 mouse events, and setting the \l enabled property to \c false stops mouse
6418 and keyboard events, and also removes active focus from the item.)
6419
6420 \sa visible
6421*/
6422/*!
6423 \property QQuickItem::opacity
6424
6425 This property holds the opacity of the item. Opacity is specified as a
6426 number between 0.0 (fully transparent) and 1.0 (fully opaque). The default
6427 value is 1.0.
6428
6429 When this property is set, the specified opacity is also applied
6430 individually to child items. This may have an unintended effect in some
6431 circumstances. For example in the second set of rectangles below, the red
6432 rectangle has specified an opacity of 0.5, which affects the opacity of
6433 its blue child rectangle even though the child has not specified an opacity.
6434
6435 Values outside the range of 0 to 1 will be clamped.
6436
6437 \table
6438 \row
6439 \li \image declarative-item_opacity1.png
6440 \li
6441 \qml
6442 Item {
6443 Rectangle {
6444 color: "red"
6445 width: 100; height: 100
6446 Rectangle {
6447 color: "blue"
6448 x: 50; y: 50; width: 100; height: 100
6449 }
6450 }
6451 }
6452 \endqml
6453 \row
6454 \li \image declarative-item_opacity2.png
6455 \li
6456 \qml
6457 Item {
6458 Rectangle {
6459 opacity: 0.5
6460 color: "red"
6461 width: 100; height: 100
6462 Rectangle {
6463 color: "blue"
6464 x: 50; y: 50; width: 100; height: 100
6465 }
6466 }
6467 }
6468 \endqml
6469 \endtable
6470
6471 Changing an item's opacity does not affect whether the item receives user
6472 input events. (In contrast, setting \l visible property to \c false stops
6473 mouse events, and setting the \l enabled property to \c false stops mouse
6474 and keyboard events, and also removes active focus from the item.)
6475
6476 \sa visible
6477*/
6478qreal QQuickItem::opacity() const
6479{
6480 Q_D(const QQuickItem);
6481 return d->opacity();
6482}
6483
6484void QQuickItem::setOpacity(qreal newOpacity)
6485{
6486 Q_D(QQuickItem);
6487 qreal o = std::clamp(val: newOpacity, lo: qreal(0.0), hi: qreal(1.0));
6488 if (d->opacity() == o)
6489 return;
6490
6491 d->extra.value().opacity = o;
6492
6493 d->dirty(QQuickItemPrivate::OpacityValue);
6494
6495 d->itemChange(ItemOpacityHasChanged, o);
6496
6497 emit opacityChanged();
6498}
6499
6500/*!
6501 \qmlproperty bool QtQuick::Item::visible
6502
6503 This property holds whether the item is visible. By default this is true.
6504
6505 Setting this property directly affects the \c visible value of child
6506 items. When set to \c false, the \c visible values of all child items also
6507 become \c false. When set to \c true, the \c visible values of child items
6508 are returned to \c true, unless they have explicitly been set to \c false.
6509
6510 (Because of this flow-on behavior, using the \c visible property may not
6511 have the intended effect if a property binding should only respond to
6512 explicit property changes. In such cases it may be better to use the
6513 \l opacity property instead.)
6514
6515 If this property is set to \c false, the item will no longer receive mouse
6516 events, but will continue to receive key events and will retain the keyboard
6517 \l focus if it has been set. (In contrast, setting the \l enabled property
6518 to \c false stops both mouse and keyboard events, and also removes focus
6519 from the item.)
6520
6521 \note This property's value is only affected by changes to this property or
6522 the parent's \c visible property. It does not change, for example, if this
6523 item moves off-screen, or if the \l opacity changes to 0.
6524
6525 \sa opacity, enabled
6526*/
6527/*!
6528 \property QQuickItem::visible
6529
6530 This property holds whether the item is visible. By default this is true.
6531
6532 Setting this property directly affects the \c visible value of child
6533 items. When set to \c false, the \c visible values of all child items also
6534 become \c false. When set to \c true, the \c visible values of child items
6535 are returned to \c true, unless they have explicitly been set to \c false.
6536
6537 (Because of this flow-on behavior, using the \c visible property may not
6538 have the intended effect if a property binding should only respond to
6539 explicit property changes. In such cases it may be better to use the
6540 \l opacity property instead.)
6541
6542 If this property is set to \c false, the item will no longer receive mouse
6543 events, but will continue to receive key events and will retain the keyboard
6544 \l focus if it has been set. (In contrast, setting the \l enabled property
6545 to \c false stops both mouse and keyboard events, and also removes focus
6546 from the item.)
6547
6548 \note This property's value is only affected by changes to this property or
6549 the parent's \c visible property. It does not change, for example, if this
6550 item moves off-screen, or if the \l opacity changes to 0. However, for
6551 historical reasons, this property is true after the item's construction, even
6552 if the item hasn't been added to a scene yet. Changing or reading this
6553 property of an item that has not been added to a scene might not produce
6554 the expected results.
6555
6556 \note The notification signal for this property gets emitted during destruction
6557 of the visual parent. C++ signal handlers cannot assume that items in the
6558 visual parent hierarchy are still fully constructed. Use \l qobject_cast to
6559 verify that items in the parent hierarchy can be used safely as the expected
6560 type.
6561
6562 \sa opacity, enabled
6563*/
6564bool QQuickItem::isVisible() const
6565{
6566 Q_D(const QQuickItem);
6567 return d->effectiveVisible;
6568}
6569
6570void QQuickItemPrivate::setVisible(bool visible)
6571{
6572 if (visible == explicitVisible)
6573 return;
6574
6575 explicitVisible = visible;
6576 if (!visible)
6577 dirty(QQuickItemPrivate::Visible);
6578
6579 const bool childVisibilityChanged = setEffectiveVisibleRecur(calcEffectiveVisible());
6580 if (childVisibilityChanged && parentItem)
6581 emit parentItem->visibleChildrenChanged(); // signal the parent, not this!
6582}
6583
6584void QQuickItem::setVisible(bool v)
6585{
6586 Q_D(QQuickItem);
6587 d->setVisible(v);
6588}
6589
6590/*!
6591 \qmlproperty bool QtQuick::Item::enabled
6592
6593 This property holds whether the item receives mouse and keyboard events.
6594 By default, this is \c true.
6595
6596 When set to \c false, the item does not receive keyboard or pointing device
6597 events, such as press, release, or click, but can still receive hover
6598 events.
6599
6600 \note In Qt 5, setting \c enabled to \c false also blocked hover events.
6601 This was changed in Qt 6 to allow \l {QtQuick.Controls::ToolTip}{tooltips}
6602 and similar features to work on disabled items.
6603
6604 Setting this property directly affects the \c enabled value of child
6605 items. When set to \c false, the \c enabled values of all child items also
6606 become \c false. When set to \c true, the \c enabled values of child items
6607 are returned to \c true, unless they have explicitly been set to \c false.
6608
6609 Setting this property to \c false automatically causes \l activeFocus to be
6610 set to \c false, and this item will no longer receive keyboard events.
6611
6612 \sa visible
6613*/
6614/*!
6615 \property QQuickItem::enabled
6616
6617 This property holds whether the item receives mouse and keyboard events.
6618 By default this is true.
6619
6620 Setting this property directly affects the \c enabled value of child
6621 items. When set to \c false, the \c enabled values of all child items also
6622 become \c false. When set to \c true, the \c enabled values of child items
6623 are returned to \c true, unless they have explicitly been set to \c false.
6624
6625 Setting this property to \c false automatically causes \l activeFocus to be
6626 set to \c false, and this item will longer receive keyboard events.
6627
6628 \note Hover events are enabled separately by \l setAcceptHoverEvents().
6629 Thus, a disabled item can continue to receive hover events, even when this
6630 property is \c false. This makes it possible to show informational feedback
6631 (such as \l ToolTip) even when an interactive item is disabled.
6632 The same is also true for any \l {HoverHandler}{HoverHandlers}
6633 added as children of the item. A HoverHandler can, however, be
6634 \l {PointerHandler::enabled}{disabled} explicitly, or for example
6635 be bound to the \c enabled state of the item.
6636
6637 \sa visible
6638*/
6639bool QQuickItem::isEnabled() const
6640{
6641 Q_D(const QQuickItem);
6642 return d->effectiveEnable;
6643}
6644
6645void QQuickItem::setEnabled(bool e)
6646{
6647 Q_D(QQuickItem);
6648 if (e == d->explicitEnable)
6649 return;
6650
6651 d->explicitEnable = e;
6652
6653 QQuickItem *scope = parentItem();
6654 while (scope && !scope->isFocusScope())
6655 scope = scope->parentItem();
6656
6657 d->setEffectiveEnableRecur(scope, d->calcEffectiveEnable());
6658}
6659
6660bool QQuickItemPrivate::calcEffectiveVisible() const
6661{
6662 // An item is visible if it is a child of a visible parent, and not explicitly hidden.
6663 return explicitVisible && parentItem && QQuickItemPrivate::get(item: parentItem)->effectiveVisible;
6664}
6665
6666bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
6667{
6668 Q_Q(QQuickItem);
6669
6670 if (newEffectiveVisible && !explicitVisible) {
6671 // This item locally overrides visibility
6672 return false; // effective visibility didn't change
6673 }
6674
6675 if (newEffectiveVisible == effectiveVisible) {
6676 // No change necessary
6677 return false; // effective visibility didn't change
6678 }
6679
6680 effectiveVisible = newEffectiveVisible;
6681 dirty(Visible);
6682 if (parentItem)
6683 QQuickItemPrivate::get(item: parentItem)->dirty(ChildrenStackingChanged);
6684 if (window) {
6685 if (auto agent = deliveryAgentPrivate())
6686 agent->removeGrabber(grabber: q, mouse: true, touch: true, cancel: true);
6687 }
6688
6689 bool childVisibilityChanged = false;
6690 for (int ii = 0; ii < childItems.size(); ++ii)
6691 childVisibilityChanged |= QQuickItemPrivate::get(item: childItems.at(i: ii))->setEffectiveVisibleRecur(newEffectiveVisible);
6692
6693 itemChange(QQuickItem::ItemVisibleHasChanged, bool(effectiveVisible));
6694#if QT_CONFIG(accessibility)
6695 if (isAccessible) {
6696 QAccessibleEvent ev(q, effectiveVisible ? QAccessible::ObjectShow : QAccessible::ObjectHide);
6697 QAccessible::updateAccessibility(event: &ev);
6698 }
6699#endif
6700 if (!inDestructor) {
6701 emit q->visibleChanged();
6702 if (childVisibilityChanged)
6703 emit q->visibleChildrenChanged();
6704 }
6705
6706 return true; // effective visibility DID change
6707}
6708
6709bool QQuickItemPrivate::calcEffectiveEnable() const
6710{
6711 // XXX todo - Should the effective enable of an element with no parent just be the current
6712 // effective enable? This would prevent pointless re-processing in the case of an element
6713 // moving to/from a no-parent situation, but it is different from what graphics view does.
6714 return explicitEnable && (!parentItem || QQuickItemPrivate::get(item: parentItem)->effectiveEnable);
6715}
6716
6717void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffectiveEnable)
6718{
6719 Q_Q(QQuickItem);
6720
6721 if (newEffectiveEnable && !explicitEnable) {
6722 // This item locally overrides enable
6723 return;
6724 }
6725
6726 if (newEffectiveEnable == effectiveEnable) {
6727 // No change necessary
6728 return;
6729 }
6730
6731 effectiveEnable = newEffectiveEnable;
6732
6733 QQuickDeliveryAgentPrivate *da = deliveryAgentPrivate();
6734 if (da) {
6735 da->removeGrabber(grabber: q, mouse: true, touch: true, cancel: true);
6736 if (scope && !effectiveEnable && activeFocus) {
6737 da->clearFocusInScope(scope, item: q, reason: Qt::OtherFocusReason,
6738 QQuickDeliveryAgentPrivate::DontChangeFocusProperty |
6739 QQuickDeliveryAgentPrivate::DontChangeSubFocusItem);
6740 }
6741 }
6742
6743 for (int ii = 0; ii < childItems.size(); ++ii) {
6744 QQuickItemPrivate::get(item: childItems.at(i: ii))->setEffectiveEnableRecur(
6745 scope: (flags & QQuickItem::ItemIsFocusScope) && scope ? q : scope, newEffectiveEnable);
6746 }
6747
6748 if (scope && effectiveEnable && focus && da) {
6749 da->setFocusInScope(scope, item: q, reason: Qt::OtherFocusReason,
6750 QQuickDeliveryAgentPrivate::DontChangeFocusProperty |
6751 QQuickDeliveryAgentPrivate::DontChangeSubFocusItem);
6752 }
6753
6754 itemChange(QQuickItem::ItemEnabledHasChanged, bool(effectiveEnable));
6755#if QT_CONFIG(accessibility)
6756 if (isAccessible) {
6757 QAccessible::State changedState;
6758 changedState.disabled = true;
6759 changedState.focusable = true;
6760 QAccessibleStateChangeEvent ev(q, changedState);
6761 QAccessible::updateAccessibility(event: &ev);
6762 }
6763#endif
6764 emit q->enabledChanged();
6765}
6766
6767bool QQuickItemPrivate::isTransparentForPositioner() const
6768{
6769 return extra.isAllocated() && extra.value().transparentForPositioner;
6770}
6771
6772void QQuickItemPrivate::setTransparentForPositioner(bool transparent)
6773{
6774 extra.value().transparentForPositioner = transparent;
6775}
6776
6777
6778QString QQuickItemPrivate::dirtyToString() const
6779{
6780#define DIRTY_TO_STRING(value) if (dirtyAttributes & value) { \
6781 if (!rv.isEmpty()) \
6782 rv.append(QLatin1Char('|')); \
6783 rv.append(QLatin1String(#value)); \
6784}
6785
6786// QString rv = QLatin1String("0x") + QString::number(dirtyAttributes, 16);
6787 QString rv;
6788
6789 DIRTY_TO_STRING(TransformOrigin);
6790 DIRTY_TO_STRING(Transform);
6791 DIRTY_TO_STRING(BasicTransform);
6792 DIRTY_TO_STRING(Position);
6793 DIRTY_TO_STRING(Size);
6794 DIRTY_TO_STRING(ZValue);
6795 DIRTY_TO_STRING(Content);
6796 DIRTY_TO_STRING(Smooth);
6797 DIRTY_TO_STRING(OpacityValue);
6798 DIRTY_TO_STRING(ChildrenChanged);
6799 DIRTY_TO_STRING(ChildrenStackingChanged);
6800 DIRTY_TO_STRING(ParentChanged);
6801 DIRTY_TO_STRING(Clip);
6802 DIRTY_TO_STRING(Window);
6803 DIRTY_TO_STRING(EffectReference);
6804 DIRTY_TO_STRING(Visible);
6805 DIRTY_TO_STRING(HideReference);
6806 DIRTY_TO_STRING(Antialiasing);
6807
6808 return rv;
6809}
6810
6811void QQuickItemPrivate::dirty(DirtyType type)
6812{
6813 Q_Q(QQuickItem);
6814 if (!(dirtyAttributes & type) || (window && !prevDirtyItem)) {
6815 dirtyAttributes |= type;
6816 if (window && componentComplete) {
6817 addToDirtyList();
6818 QQuickWindowPrivate::get(c: window)->dirtyItem(q);
6819 }
6820 }
6821 if (type & (TransformOrigin | Transform | BasicTransform | Position | Size | Clip))
6822 transformChanged(transformedItem: q);
6823}
6824
6825void QQuickItemPrivate::addToDirtyList()
6826{
6827 Q_Q(QQuickItem);
6828
6829 Q_ASSERT(window);
6830 if (!prevDirtyItem) {
6831 Q_ASSERT(!nextDirtyItem);
6832
6833 QQuickWindowPrivate *p = QQuickWindowPrivate::get(c: window);
6834 nextDirtyItem = p->dirtyItemList;
6835 if (nextDirtyItem) QQuickItemPrivate::get(item: nextDirtyItem)->prevDirtyItem = &nextDirtyItem;
6836 prevDirtyItem = &p->dirtyItemList;
6837 p->dirtyItemList = q;
6838 p->dirtyItem(q);
6839 }
6840 Q_ASSERT(prevDirtyItem);
6841}
6842
6843void QQuickItemPrivate::removeFromDirtyList()
6844{
6845 if (prevDirtyItem) {
6846 if (nextDirtyItem) QQuickItemPrivate::get(item: nextDirtyItem)->prevDirtyItem = prevDirtyItem;
6847 *prevDirtyItem = nextDirtyItem;
6848 prevDirtyItem = nullptr;
6849 nextDirtyItem = nullptr;
6850 }
6851 Q_ASSERT(!prevDirtyItem);
6852 Q_ASSERT(!nextDirtyItem);
6853}
6854
6855void QQuickItemPrivate::refFromEffectItem(bool hide)
6856{
6857 ++extra.value().effectRefCount;
6858 if (extra->effectRefCount == 1) {
6859 dirty(type: EffectReference);
6860 if (parentItem)
6861 QQuickItemPrivate::get(item: parentItem)->dirty(type: ChildrenStackingChanged);
6862 }
6863 if (hide) {
6864 if (++extra->hideRefCount == 1)
6865 dirty(type: HideReference);
6866 }
6867 recursiveRefFromEffectItem(refs: 1);
6868}
6869
6870void QQuickItemPrivate::recursiveRefFromEffectItem(int refs)
6871{
6872 Q_Q(QQuickItem);
6873 if (!refs)
6874 return;
6875 extra.value().recursiveEffectRefCount += refs;
6876 for (int ii = 0; ii < childItems.size(); ++ii) {
6877 QQuickItem *child = childItems.at(i: ii);
6878 QQuickItemPrivate::get(item: child)->recursiveRefFromEffectItem(refs);
6879 }
6880 // Polish may rely on the effect ref count so trigger one, if item is not visible
6881 // (if visible, it will be triggered automatically).
6882 if (!effectiveVisible && refs > 0 && extra.value().recursiveEffectRefCount == 1) // it wasn't referenced, now it's referenced
6883 q->polish();
6884}
6885
6886void QQuickItemPrivate::derefFromEffectItem(bool unhide)
6887{
6888 Q_ASSERT(extra->effectRefCount);
6889 --extra->effectRefCount;
6890 if (extra->effectRefCount == 0) {
6891 dirty(type: EffectReference);
6892 if (parentItem)
6893 QQuickItemPrivate::get(item: parentItem)->dirty(type: ChildrenStackingChanged);
6894 }
6895 if (unhide) {
6896 if (--extra->hideRefCount == 0)
6897 dirty(type: HideReference);
6898 }
6899 recursiveRefFromEffectItem(refs: -1);
6900}
6901
6902void QQuickItemPrivate::setCulled(bool cull)
6903{
6904 if (cull == culled)
6905 return;
6906
6907 culled = cull;
6908 if ((cull && ++extra.value().hideRefCount == 1) || (!cull && --extra.value().hideRefCount == 0))
6909 dirty(type: HideReference);
6910}
6911
6912void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
6913{
6914 Q_Q(QQuickItem);
6915 switch (change) {
6916 case QQuickItem::ItemChildAddedChange: {
6917 q->itemChange(change, value: data);
6918 // The newly added child or any of its descendants may have
6919 // ItemObservesViewport set, in which case we need to both
6920 // inform the item that the transform has changed, and re-apply
6921 // subtreeTransformChangedEnabled to both this item and its
6922 // ancestors.
6923 if (QQuickItemPrivate::get(item: data.item)->transformChanged(transformedItem: q)) {
6924 if (!subtreeTransformChangedEnabled) {
6925 qCDebug(lcVP) << "turned on transformChanged notification for subtree of" << q;
6926 subtreeTransformChangedEnabled = true;
6927 }
6928 enableSubtreeChangeNotificationsForParentHierachy();
6929 }
6930 notifyChangeListeners(changeTypes: QQuickItemPrivate::Children, function: &QQuickItemChangeListener::itemChildAdded, args: q, args: data.item);
6931 break;
6932 }
6933 case QQuickItem::ItemChildRemovedChange: {
6934 q->itemChange(change, value: data);
6935 notifyChangeListeners(changeTypes: QQuickItemPrivate::Children, function: &QQuickItemChangeListener::itemChildRemoved, args: q, args: data.item);
6936 break;
6937 }
6938 case QQuickItem::ItemSceneChange:
6939 q->itemChange(change, value: data);
6940 break;
6941 case QQuickItem::ItemVisibleHasChanged: {
6942 q->itemChange(change, value: data);
6943 notifyChangeListeners(changeTypes: QQuickItemPrivate::Visibility, function: &QQuickItemChangeListener::itemVisibilityChanged, args: q);
6944 break;
6945 }
6946 case QQuickItem::ItemEnabledHasChanged: {
6947 q->itemChange(change, value: data);
6948 notifyChangeListeners(changeTypes: QQuickItemPrivate::Enabled, function: &QQuickItemChangeListener::itemEnabledChanged, args: q);
6949 break;
6950 }
6951 case QQuickItem::ItemParentHasChanged: {
6952 q->itemChange(change, value: data);
6953 notifyChangeListeners(changeTypes: QQuickItemPrivate::Parent, function: &QQuickItemChangeListener::itemParentChanged, args: q, args: data.item);
6954 break;
6955 }
6956 case QQuickItem::ItemOpacityHasChanged: {
6957 q->itemChange(change, value: data);
6958 notifyChangeListeners(changeTypes: QQuickItemPrivate::Opacity, function: &QQuickItemChangeListener::itemOpacityChanged, args: q);
6959 break;
6960 }
6961 case QQuickItem::ItemActiveFocusHasChanged:
6962 q->itemChange(change, value: data);
6963 break;
6964 case QQuickItem::ItemRotationHasChanged: {
6965 q->itemChange(change, value: data);
6966 notifyChangeListeners(changeTypes: QQuickItemPrivate::Rotation, function: &QQuickItemChangeListener::itemRotationChanged, args: q);
6967 break;
6968 }
6969 case QQuickItem::ItemScaleHasChanged: {
6970 q->itemChange(change, value: data);
6971 notifyChangeListeners(changeTypes: QQuickItemPrivate::Scale, function: &QQuickItemChangeListener::itemScaleChanged, args: q);
6972 break;
6973 }
6974 case QQuickItem::ItemTransformHasChanged: {
6975 q->itemChange(change, value: data);
6976 notifyChangeListeners(changeTypes: QQuickItemPrivate::Matrix, function: &QQuickItemChangeListener::itemTransformChanged, args: q, args: data.item);
6977 break;
6978 }
6979 case QQuickItem::ItemAntialiasingHasChanged:
6980 // fall through
6981 case QQuickItem::ItemDevicePixelRatioHasChanged:
6982 q->itemChange(change, value: data);
6983 break;
6984 }
6985}
6986
6987/*!
6988 \qmlproperty bool QtQuick::Item::smooth
6989
6990 Primarily used in image based items to decide if the item should use smooth
6991 sampling or not. Smooth sampling is performed using linear interpolation, while
6992 non-smooth is performed using nearest neighbor.
6993
6994 In Qt Quick 2.0, this property has minimal impact on performance.
6995
6996 By default, this property is set to \c true.
6997*/
6998/*!
6999 \property QQuickItem::smooth
7000 \brief Specifies whether the item is smoothed or not
7001
7002 Primarily used in image based items to decide if the item should use smooth
7003 sampling or not. Smooth sampling is performed using linear interpolation, while
7004 non-smooth is performed using nearest neighbor.
7005
7006 In Qt Quick 2.0, this property has minimal impact on performance.
7007
7008 By default, this property is set to \c true.
7009*/
7010bool QQuickItem::smooth() const
7011{
7012 Q_D(const QQuickItem);
7013 return d->smooth;
7014}
7015void QQuickItem::setSmooth(bool smooth)
7016{
7017 Q_D(QQuickItem);
7018 if (d->smooth == smooth)
7019 return;
7020
7021 d->smooth = smooth;
7022 d->dirty(type: QQuickItemPrivate::Smooth);
7023
7024 emit smoothChanged(smooth);
7025}
7026
7027/*!
7028 \qmlproperty bool QtQuick::Item::activeFocusOnTab
7029
7030 This property holds whether the item wants to be in the tab focus
7031 chain. By default, this is set to \c false.
7032
7033 The tab focus chain traverses elements by first visiting the
7034 parent, and then its children in the order they occur in the
7035 children property. Pressing the tab key on an item in the tab
7036 focus chain will move keyboard focus to the next item in the
7037 chain. Pressing BackTab (normally Shift+Tab) will move focus
7038 to the previous item.
7039
7040 To set up a manual tab focus chain, see \l KeyNavigation. Tab
7041 key events used by Keys or KeyNavigation have precedence over
7042 focus chain behavior; ignore the events in other key handlers
7043 to allow it to propagate.
7044
7045 \note {QStyleHints::tabFocusBehavior}{tabFocusBehavior} can further limit focus
7046 to only specific types of controls, such as only text or list controls. This is
7047 the case on macOS, where focus to particular controls may be restricted based on
7048 system settings.
7049
7050 \sa QStyleHints::tabFocusBehavior, focusPolicy
7051*/
7052/*!
7053 \property QQuickItem::activeFocusOnTab
7054
7055 This property holds whether the item wants to be in the tab focus
7056 chain. By default, this is set to \c false.
7057
7058 \note {QStyleHints::tabFocusBehavior}{tabFocusBehavior} can further limit focus
7059 to only specific types of controls, such as only text or list controls. This is
7060 the case on macOS, where focus to particular controls may be restricted based on
7061 system settings.
7062
7063 \sa QStyleHints::tabFocusBehavior, focusPolicy
7064*/
7065// TODO FOCUS: Deprecate
7066bool QQuickItem::activeFocusOnTab() const
7067{
7068 Q_D(const QQuickItem);
7069 return d->activeFocusOnTab;
7070}
7071void QQuickItem::setActiveFocusOnTab(bool activeFocusOnTab)
7072{
7073 Q_D(QQuickItem);
7074 if (d->activeFocusOnTab == activeFocusOnTab)
7075 return;
7076
7077 if (window()) {
7078 if ((this == window()->activeFocusItem()) && this != window()->contentItem() && !activeFocusOnTab) {
7079 qWarning(msg: "QQuickItem: Cannot set activeFocusOnTab to false once item is the active focus item.");
7080 return;
7081 }
7082 }
7083
7084 d->activeFocusOnTab = activeFocusOnTab;
7085
7086 emit activeFocusOnTabChanged(activeFocusOnTab);
7087}
7088
7089/*!
7090 \qmlproperty bool QtQuick::Item::antialiasing
7091
7092 Used by visual elements to decide if the item should use antialiasing or not.
7093 In some cases items with antialiasing require more memory and are potentially
7094 slower to render (see \l {Antialiasing} for more details).
7095
7096 The default is false, but may be overridden by derived elements.
7097*/
7098/*!
7099 \property QQuickItem::antialiasing
7100 \brief Specifies whether the item is antialiased or not
7101
7102 Used by visual elements to decide if the item should use antialiasing or not.
7103 In some cases items with antialiasing require more memory and are potentially
7104 slower to render (see \l {Antialiasing} for more details).
7105
7106 The default is false, but may be overridden by derived elements.
7107*/
7108bool QQuickItem::antialiasing() const
7109{
7110 Q_D(const QQuickItem);
7111 return d->antialiasingValid ? d->antialiasing : d->implicitAntialiasing;
7112}
7113
7114void QQuickItem::setAntialiasing(bool aa)
7115{
7116 Q_D(QQuickItem);
7117
7118 if (!d->antialiasingValid) {
7119 d->antialiasingValid = true;
7120 d->antialiasing = d->implicitAntialiasing;
7121 }
7122
7123 if (aa == d->antialiasing)
7124 return;
7125
7126 d->antialiasing = aa;
7127 d->dirty(type: QQuickItemPrivate::Antialiasing);
7128
7129 d->itemChange(change: ItemAntialiasingHasChanged, data: bool(d->antialiasing));
7130
7131 emit antialiasingChanged(antialiasing());
7132}
7133
7134void QQuickItem::resetAntialiasing()
7135{
7136 Q_D(QQuickItem);
7137 if (!d->antialiasingValid)
7138 return;
7139
7140 d->antialiasingValid = false;
7141
7142 if (d->implicitAntialiasing != d->antialiasing)
7143 emit antialiasingChanged(antialiasing());
7144}
7145
7146void QQuickItemPrivate::setImplicitAntialiasing(bool antialiasing)
7147{
7148 Q_Q(QQuickItem);
7149 bool prev = q->antialiasing();
7150 implicitAntialiasing = antialiasing;
7151 if (componentComplete && (q->antialiasing() != prev))
7152 emit q->antialiasingChanged(q->antialiasing());
7153}
7154
7155/*!
7156 Returns the item flags for this item.
7157
7158 \sa setFlag()
7159 */
7160QQuickItem::Flags QQuickItem::flags() const
7161{
7162 Q_D(const QQuickItem);
7163 return (QQuickItem::Flags)d->flags;
7164}
7165
7166/*!
7167 Enables the specified \a flag for this item if \a enabled is true;
7168 if \a enabled is false, the flag is disabled.
7169
7170 These provide various hints for the item; for example, the
7171 ItemClipsChildrenToShape flag indicates that all children of this
7172 item should be clipped to fit within the item area.
7173 */
7174void QQuickItem::setFlag(Flag flag, bool enabled)
7175{
7176 Q_D(QQuickItem);
7177 if (enabled)
7178 setFlags((Flags)(d->flags | (quint32)flag));
7179 else
7180 setFlags((Flags)(d->flags & ~(quint32)flag));
7181
7182 // We don't return early if the flag did not change. That's useful in case
7183 // we need to intentionally trigger this parent-chain traversal again.
7184 if (enabled && flag == ItemObservesViewport)
7185 d->enableSubtreeChangeNotificationsForParentHierachy();
7186}
7187
7188void QQuickItemPrivate::enableSubtreeChangeNotificationsForParentHierachy()
7189{
7190 Q_Q(QQuickItem);
7191
7192 QQuickItem *par = q->parentItem();
7193 while (par) {
7194 auto parPriv = QQuickItemPrivate::get(item: par);
7195 if (!parPriv->subtreeTransformChangedEnabled)
7196 qCDebug(lcVP) << "turned on transformChanged notification for subtree of" << par;
7197 parPriv->subtreeTransformChangedEnabled = true;
7198 par = par->parentItem();
7199 }
7200}
7201
7202/*!
7203 Enables the specified \a flags for this item.
7204
7205 \sa setFlag()
7206 */
7207void QQuickItem::setFlags(Flags flags)
7208{
7209 Q_D(QQuickItem);
7210
7211 if (int(flags & ItemIsFocusScope) != int(d->flags & ItemIsFocusScope)) {
7212 if (flags & ItemIsFocusScope && !d->childItems.isEmpty() && d->window) {
7213 qWarning(msg: "QQuickItem: Cannot set FocusScope once item has children and is in a window.");
7214 flags &= ~ItemIsFocusScope;
7215 } else if (d->flags & ItemIsFocusScope) {
7216 qWarning(msg: "QQuickItem: Cannot unset FocusScope flag.");
7217 flags |= ItemIsFocusScope;
7218 }
7219 }
7220
7221 if (int(flags & ItemClipsChildrenToShape) != int(d->flags & ItemClipsChildrenToShape))
7222 d->dirty(type: QQuickItemPrivate::Clip);
7223
7224 d->flags = flags;
7225}
7226
7227/*!
7228 \qmlproperty real QtQuick::Item::x
7229 \qmlproperty real QtQuick::Item::y
7230 \qmlproperty real QtQuick::Item::width
7231 \qmlproperty real QtQuick::Item::height
7232
7233 Defines the item's position and size.
7234 The default value is \c 0.
7235
7236 The (x,y) position is relative to the \l parent.
7237
7238 \qml
7239 Item { x: 100; y: 100; width: 100; height: 100 }
7240 \endqml
7241 */
7242/*!
7243 \property QQuickItem::x
7244
7245 Defines the item's x position relative to its parent.
7246 */
7247/*!
7248 \property QQuickItem::y
7249
7250 Defines the item's y position relative to its parent.
7251 */
7252qreal QQuickItem::x() const
7253{
7254 Q_D(const QQuickItem);
7255 return d->x;
7256}
7257
7258qreal QQuickItem::y() const
7259{
7260 Q_D(const QQuickItem);
7261 return d->y;
7262}
7263
7264/*!
7265 \internal
7266 */
7267QPointF QQuickItem::position() const
7268{
7269 Q_D(const QQuickItem);
7270 return QPointF(d->x, d->y);
7271}
7272
7273void QQuickItem::setX(qreal v)
7274{
7275 Q_D(QQuickItem);
7276 /* There are two ways in which this function might be called:
7277 a) Either directly by the user, or
7278 b) when a binding has evaluated to a new value and it writes
7279 the value back
7280 In the first case, we want to remove an existing binding, in
7281 the second case, we don't want to remove the binding which
7282 just wrote the value.
7283 removeBindingUnlessInWrapper takes care of this.
7284 */
7285 d->x.removeBindingUnlessInWrapper();
7286 if (qt_is_nan(d: v))
7287 return;
7288
7289 const qreal oldx = d->x.valueBypassingBindings();
7290 if (oldx == v)
7291 return;
7292
7293 d->x.setValueBypassingBindings(v);
7294
7295 d->dirty(type: QQuickItemPrivate::Position);
7296
7297 const qreal y = d->y.valueBypassingBindings();
7298 const qreal w = d->width.valueBypassingBindings();
7299 const qreal h = d->height.valueBypassingBindings();
7300 geometryChange(newGeometry: QRectF(v, y, w, h), oldGeometry: QRectF(oldx, y, w, h));
7301}
7302
7303void QQuickItem::setY(qreal v)
7304{
7305 Q_D(QQuickItem);
7306 d->y.removeBindingUnlessInWrapper();
7307 if (qt_is_nan(d: v))
7308 return;
7309
7310 const qreal oldy = d->y.valueBypassingBindings();
7311 if (oldy == v)
7312 return;
7313
7314 d->y.setValueBypassingBindings(v);
7315
7316 d->dirty(type: QQuickItemPrivate::Position);
7317
7318 // we use v instead of d->y, as that avoid a method call
7319 // and we have v anyway in scope
7320 const qreal x = d->x.valueBypassingBindings();
7321 const qreal w = d->width.valueBypassingBindings();
7322 const qreal h = d->height.valueBypassingBindings();
7323 geometryChange(newGeometry: QRectF(x, v, w, h), oldGeometry: QRectF(x, oldy, w, h));
7324}
7325
7326/*!
7327 \internal
7328 */
7329void QQuickItem::setPosition(const QPointF &pos)
7330{
7331 Q_D(QQuickItem);
7332
7333 const qreal oldx = d->x.valueBypassingBindings();
7334 const qreal oldy = d->y.valueBypassingBindings();
7335
7336 if (QPointF(oldx, oldy) == pos)
7337 return;
7338
7339 /* This preserves the bindings, because that was what the code used to do
7340 The effect of this is that you can have
7341 Item {
7342 Rectangle {
7343 x: someValue; y: someValue
7344 DragHandler {}
7345 }
7346 }
7347 and you can move the rectangle around; once someValue changes, the position gets
7348 reset again (even when a drag is currently ongoing).
7349 Whether we want this is up to discussion.
7350 */
7351
7352 d->x.setValueBypassingBindings(pos.x()); //TODO: investigate whether to break binding here or not
7353 d->y.setValueBypassingBindings(pos.y());
7354
7355 d->dirty(type: QQuickItemPrivate::Position);
7356
7357 const qreal w = d->width.valueBypassingBindings();
7358 const qreal h = d->height.valueBypassingBindings();
7359 geometryChange(newGeometry: QRectF(pos.x(), pos.y(), w, h), oldGeometry: QRectF(oldx, oldy, w, h));
7360}
7361
7362/* The bindable methods return an object which supports inspection (hasBinding) and
7363 modification (setBinding, removeBinding) of the properties bindable state.
7364*/
7365QBindable<qreal> QQuickItem::bindableX()
7366{
7367 return QBindable<qreal>(&d_func()->x);
7368}
7369
7370QBindable<qreal> QQuickItem::bindableY()
7371{
7372 return QBindable<qreal>(&d_func()->y);
7373}
7374
7375/*!
7376 \property QQuickItem::width
7377
7378 This property holds the width of this item.
7379 */
7380qreal QQuickItem::width() const
7381{
7382 Q_D(const QQuickItem);
7383 return d->width;
7384}
7385
7386void QQuickItem::setWidth(qreal w)
7387{
7388 Q_D(QQuickItem);
7389 d->width.removeBindingUnlessInWrapper();
7390 if (qt_is_nan(d: w))
7391 return;
7392
7393 d->widthValidFlag = true;
7394 const qreal oldWidth = d->width.valueBypassingBindings();
7395 if (oldWidth == w)
7396 return;
7397
7398 d->width.setValueBypassingBindings(w);
7399
7400 d->dirty(type: QQuickItemPrivate::Size);
7401
7402 const qreal x = d->x.valueBypassingBindings();
7403 const qreal y = d->y.valueBypassingBindings();
7404 const qreal h = d->height.valueBypassingBindings();
7405 geometryChange(newGeometry: QRectF(x, y, w, h), oldGeometry: QRectF(x, y, oldWidth, h));
7406}
7407
7408void QQuickItem::resetWidth()
7409{
7410 Q_D(QQuickItem);
7411 d->width.takeBinding();
7412 d->widthValidFlag = false;
7413 setImplicitWidth(implicitWidth());
7414}
7415
7416void QQuickItemPrivate::implicitWidthChanged()
7417{
7418 Q_Q(QQuickItem);
7419 notifyChangeListeners(changeTypes: QQuickItemPrivate::ImplicitWidth, function: &QQuickItemChangeListener::itemImplicitWidthChanged, args: q);
7420 emit q->implicitWidthChanged();
7421}
7422
7423qreal QQuickItemPrivate::getImplicitWidth() const
7424{
7425 return implicitWidth;
7426}
7427/*!
7428 Returns the width of the item that is implied by other properties that determine the content.
7429*/
7430qreal QQuickItem::implicitWidth() const
7431{
7432 Q_D(const QQuickItem);
7433 return d->getImplicitWidth();
7434}
7435
7436QBindable<qreal> QQuickItem::bindableWidth()
7437{
7438 return QBindable<qreal>(&d_func()->width);
7439}
7440
7441/*!
7442 \qmlproperty real QtQuick::Item::implicitWidth
7443 \qmlproperty real QtQuick::Item::implicitHeight
7444
7445 Defines the preferred width or height of the Item.
7446
7447 If \l width or \l height is not specified, an item's effective size will be
7448 determined by its \l implicitWidth or \l implicitHeight.
7449
7450 However, if an item is the child of a \l {Qt Quick Layouts}{layout}, the
7451 layout will determine the item's preferred size using its implicit size.
7452 In such a scenario, the explicit \l width or \l height will be ignored.
7453
7454 The default implicit size for most items is 0x0, however some items have an inherent
7455 implicit size which cannot be overridden, for example, \l [QML] Image and \l [QML] Text.
7456
7457 Setting the implicit size is useful for defining components that have a preferred size
7458 based on their content, for example:
7459
7460 \qml
7461 // Label.qml
7462 import QtQuick 2.0
7463
7464 Item {
7465 property alias icon: image.source
7466 property alias label: text.text
7467 implicitWidth: text.implicitWidth + image.implicitWidth
7468 implicitHeight: Math.max(text.implicitHeight, image.implicitHeight)
7469 Image { id: image }
7470 Text {
7471 id: text
7472 wrapMode: Text.Wrap
7473 anchors.left: image.right; anchors.right: parent.right
7474 anchors.verticalCenter: parent.verticalCenter
7475 }
7476 }
7477 \endqml
7478
7479 \note Using implicitWidth of \l [QML] Text or \l [QML] TextEdit and setting the width explicitly
7480 incurs a performance penalty as the text must be laid out twice.
7481*/
7482/*!
7483 \property QQuickItem::implicitWidth
7484 \property QQuickItem::implicitHeight
7485
7486 Defines the preferred width or height of the Item.
7487
7488 If \l width or \l height is not specified, an item's effective size will be
7489 determined by its \l implicitWidth or \l implicitHeight.
7490
7491 However, if an item is the child of a \l {Qt Quick Layouts}{layout}, the
7492 layout will determine the item's preferred size using its implicit size.
7493 In such a scenario, the explicit \l width or \l height will be ignored.
7494
7495 The default implicit size for most items is 0x0, however some items have an inherent
7496 implicit size which cannot be overridden, for example, \l [QML] Image and \l [QML] Text.
7497
7498 Setting the implicit size is useful for defining components that have a preferred size
7499 based on their content, for example:
7500
7501 \qml
7502 // Label.qml
7503 import QtQuick 2.0
7504
7505 Item {
7506 property alias icon: image.source
7507 property alias label: text.text
7508 implicitWidth: text.implicitWidth + image.implicitWidth
7509 implicitHeight: Math.max(text.implicitHeight, image.implicitHeight)
7510 Image { id: image }
7511 Text {
7512 id: text
7513 wrapMode: Text.Wrap
7514 anchors.left: image.right; anchors.right: parent.right
7515 anchors.verticalCenter: parent.verticalCenter
7516 }
7517 }
7518 \endqml
7519
7520 \note Using implicitWidth of \l [QML] Text or \l [QML] TextEdit and setting the width explicitly
7521 incurs a performance penalty as the text must be laid out twice.
7522*/
7523void QQuickItem::setImplicitWidth(qreal w)
7524{
7525 Q_D(QQuickItem);
7526 bool changed = w != d->implicitWidth;
7527 d->implicitWidth = w;
7528 // this uses valueBypassingBindings simply to avoid repeated "am I in a binding" checks
7529 if (d->width.valueBypassingBindings() == w || widthValid()) {
7530 if (changed)
7531 d->implicitWidthChanged();
7532 if (d->width.valueBypassingBindings() == w || widthValid())
7533 return;
7534 changed = false;
7535 }
7536
7537 const qreal oldWidth = d->width.valueBypassingBindings();
7538 Q_ASSERT(!d->width.hasBinding() || QQmlPropertyBinding::isUndefined(d->width.binding()));
7539 // we need to keep the binding if its undefined (therefore we can't use operator=/setValue)
7540 d->width.setValueBypassingBindings(w);
7541
7542 d->dirty(type: QQuickItemPrivate::Size);
7543
7544 const qreal x = d->x.valueBypassingBindings();
7545 const qreal y = d->y.valueBypassingBindings();
7546 const qreal width = w;
7547 const qreal height = d->height.valueBypassingBindings();
7548 geometryChange(newGeometry: QRectF(x, y, width, height), oldGeometry: QRectF(x, y, oldWidth, height));
7549
7550 if (changed)
7551 d->implicitWidthChanged();
7552}
7553
7554/*!
7555 Returns whether the width property has been set explicitly.
7556*/
7557bool QQuickItem::widthValid() const
7558{
7559 Q_D(const QQuickItem);
7560 /* Logic: The width is valid if we assigned a value
7561 or a binding to it. Note that a binding evaluation to
7562 undefined (and thus calling resetWidth) is detached [1];
7563 hasBinding will thus return false for it, which is
7564 what we want here, as resetting width should mean that
7565 width is invalid (until the binding evaluates to a
7566 non-undefined value again).
7567
7568 [1]: A detached binding is a binding which is not set on a property.
7569 In the case of QQmlPropertyBinding and resettable properties, it
7570 still gets reevaluated when it was detached due to the binding
7571 returning undefined, and it gets re-attached, once the binding changes
7572 to a non-undefined value (unless another binding has beenset in the
7573 meantime).
7574 See QQmlPropertyBinding::isUndefined and handleUndefinedAssignment
7575 */
7576
7577 return d->widthValid();
7578}
7579
7580/*!
7581 \property QQuickItem::height
7582
7583 This property holds the height of this item.
7584 */
7585qreal QQuickItem::height() const
7586{
7587 Q_D(const QQuickItem);
7588 return d->height;
7589}
7590
7591void QQuickItem::setHeight(qreal h)
7592{
7593 Q_D(QQuickItem);
7594 // Note that we call removeUnlessInWrapper before returning in the
7595 // NaN and equal value cases; that ensures that an explicit setHeight
7596 // always removes the binding
7597 d->height.removeBindingUnlessInWrapper();
7598 if (qt_is_nan(d: h))
7599 return;
7600
7601 d->heightValidFlag = true;
7602 const qreal oldHeight = d->height.valueBypassingBindings();
7603 if (oldHeight == h)
7604 return;
7605
7606 d->height.setValueBypassingBindings(h);
7607
7608 d->dirty(type: QQuickItemPrivate::Size);
7609
7610 const qreal x = d->x.valueBypassingBindings();
7611 const qreal y = d->y.valueBypassingBindings();
7612 const qreal w = d->width.valueBypassingBindings();
7613 geometryChange(newGeometry: QRectF(x, y, w, h), oldGeometry: QRectF(x, y, w, oldHeight));
7614}
7615
7616void QQuickItem::resetHeight()
7617{
7618 Q_D(QQuickItem);
7619 // using takeBinding, we remove any existing binding from the
7620 // property, but preserve the existing value (and avoid some overhead
7621 // compared to calling setHeight(height())
7622 d->height.takeBinding();
7623 d->heightValidFlag = false;
7624 setImplicitHeight(implicitHeight());
7625}
7626
7627void QQuickItemPrivate::implicitHeightChanged()
7628{
7629 Q_Q(QQuickItem);
7630 notifyChangeListeners(changeTypes: QQuickItemPrivate::ImplicitHeight, function: &QQuickItemChangeListener::itemImplicitHeightChanged, args: q);
7631 emit q->implicitHeightChanged();
7632}
7633
7634qreal QQuickItemPrivate::getImplicitHeight() const
7635{
7636 return implicitHeight;
7637}
7638
7639qreal QQuickItem::implicitHeight() const
7640{
7641 Q_D(const QQuickItem);
7642 return d->getImplicitHeight();
7643}
7644
7645QBindable<qreal> QQuickItem::bindableHeight()
7646{
7647 return QBindable<qreal>(&d_func()->height);
7648}
7649
7650void QQuickItem::setImplicitHeight(qreal h)
7651{
7652 Q_D(QQuickItem);
7653 bool changed = h != d->implicitHeight;
7654 d->implicitHeight = h;
7655 if (d->height.valueBypassingBindings() == h || heightValid()) {
7656 if (changed)
7657 d->implicitHeightChanged();
7658 if (d->height.valueBypassingBindings() == h || heightValid())
7659 return;
7660 changed = false;
7661 }
7662
7663 const qreal oldHeight = d->height.valueBypassingBindings();
7664 Q_ASSERT(!d->height.hasBinding() || QQmlPropertyBinding::isUndefined(d->height.binding()));
7665 // we need to keep the binding if its undefined (therefore we can't use operator=/setValue)
7666 d->height.setValueBypassingBindings(h);
7667
7668 d->dirty(type: QQuickItemPrivate::Size);
7669
7670 const qreal x = d->x.valueBypassingBindings();
7671 const qreal y = d->y.valueBypassingBindings();
7672 const qreal width = d->width.valueBypassingBindings();
7673 const qreal height = d->height.valueBypassingBindings();
7674 geometryChange(newGeometry: QRectF(x, y, width, height),
7675 oldGeometry: QRectF(x, y, width, oldHeight));
7676
7677 if (changed)
7678 d->implicitHeightChanged();
7679}
7680
7681/*!
7682 \internal
7683 */
7684void QQuickItem::setImplicitSize(qreal w, qreal h)
7685{
7686 Q_D(QQuickItem);
7687 bool wChanged = w != d->implicitWidth;
7688 bool hChanged = h != d->implicitHeight;
7689
7690 d->implicitWidth = w;
7691 d->implicitHeight = h;
7692
7693 bool wDone = false;
7694 bool hDone = false;
7695 qreal width = d->width.valueBypassingBindings();
7696 qreal height = d->height.valueBypassingBindings();
7697 if (width == w || widthValid()) {
7698 if (wChanged)
7699 d->implicitWidthChanged();
7700 wDone = width == w || widthValid();
7701 wChanged = false;
7702 }
7703 if (height == h || heightValid()) {
7704 if (hChanged)
7705 d->implicitHeightChanged();
7706 hDone = height == h || heightValid();
7707 hChanged = false;
7708 }
7709 if (wDone && hDone)
7710 return;
7711
7712 const qreal oldWidth = width;
7713 const qreal oldHeight = height;
7714 if (!wDone) {
7715 width = w;
7716 d->width.setValueBypassingBindings(w);
7717 }
7718 if (!hDone) {
7719 height = h;
7720 d->height.setValueBypassingBindings(h);
7721 }
7722
7723 d->dirty(type: QQuickItemPrivate::Size);
7724
7725 const qreal x = d->x.valueBypassingBindings();
7726 const qreal y = d->y.valueBypassingBindings();
7727 geometryChange(newGeometry: QRectF(x, y, width, height),
7728 oldGeometry: QRectF(x, y, oldWidth, oldHeight));
7729
7730 if (!wDone && wChanged)
7731 d->implicitWidthChanged();
7732 if (!hDone && hChanged)
7733 d->implicitHeightChanged();
7734}
7735
7736/*!
7737 Returns whether the height property has been set explicitly.
7738*/
7739bool QQuickItem::heightValid() const
7740{
7741 Q_D(const QQuickItem);
7742 return d->heightValid();
7743}
7744
7745/*!
7746 \since 5.10
7747
7748 Returns the size of the item.
7749
7750 \sa setSize, width, height
7751 */
7752
7753QSizeF QQuickItem::size() const
7754{
7755 Q_D(const QQuickItem);
7756 return QSizeF(d->width, d->height);
7757}
7758
7759
7760/*!
7761 \since 5.10
7762
7763 Sets the size of the item to \a size.
7764 This methods preserves any existing binding on width and height;
7765 thus any change that triggers the binding to execute again will
7766 override the set values.
7767
7768 \sa size, setWidth, setHeight
7769 */
7770void QQuickItem::setSize(const QSizeF &size)
7771{
7772 Q_D(QQuickItem);
7773 d->heightValidFlag = true;
7774 d->widthValidFlag = true;
7775
7776 const qreal oldHeight = d->height.valueBypassingBindings();
7777 const qreal oldWidth = d->width.valueBypassingBindings();
7778
7779 if (oldWidth == size.width() && oldHeight == size.height())
7780 return;
7781
7782 d->height.setValueBypassingBindings(size.height());
7783 d->width.setValueBypassingBindings(size.width());
7784
7785 d->dirty(type: QQuickItemPrivate::Size);
7786
7787 const qreal x = d->x.valueBypassingBindings();
7788 const qreal y = d->y.valueBypassingBindings();
7789 geometryChange(newGeometry: QRectF(x, y, size.width(), size.height()), oldGeometry: QRectF(x, y, oldWidth, oldHeight));
7790}
7791
7792/*!
7793 \qmlproperty bool QtQuick::Item::activeFocus
7794 \readonly
7795
7796 This read-only property indicates whether the item has active focus.
7797
7798 If activeFocus is true, either this item is the one that currently
7799 receives keyboard input, or it is a FocusScope ancestor of the item
7800 that currently receives keyboard input.
7801
7802 Usually, activeFocus is gained by setting \l focus on an item and its
7803 enclosing FocusScope objects. In the following example, the \c input
7804 and \c focusScope objects will have active focus, while the root
7805 rectangle object will not.
7806
7807 \qml
7808 import QtQuick 2.0
7809
7810 Rectangle {
7811 width: 100; height: 100
7812
7813 FocusScope {
7814 id: focusScope
7815 focus: true
7816
7817 TextInput {
7818 id: input
7819 focus: true
7820 }
7821 }
7822 }
7823 \endqml
7824
7825 \sa focus, {Keyboard Focus in Qt Quick}
7826*/
7827/*!
7828 \property QQuickItem::activeFocus
7829 \readonly
7830
7831 This read-only property indicates whether the item has active focus.
7832
7833 If activeFocus is true, either this item is the one that currently
7834 receives keyboard input, or it is a FocusScope ancestor of the item
7835 that currently receives keyboard input.
7836
7837 Usually, activeFocus is gained by setting \l focus on an item and its
7838 enclosing FocusScope objects. In the following example, the \c input
7839 and \c focusScope objects will have active focus, while the root
7840 rectangle object will not.
7841
7842 \qml
7843 import QtQuick 2.0
7844
7845 Rectangle {
7846 width: 100; height: 100
7847
7848 FocusScope {
7849 focus: true
7850
7851 TextInput {
7852 id: input
7853 focus: true
7854 }
7855 }
7856 }
7857 \endqml
7858
7859 \sa focus, {Keyboard Focus in Qt Quick}
7860*/
7861bool QQuickItem::hasActiveFocus() const
7862{
7863 Q_D(const QQuickItem);
7864 return d->activeFocus;
7865}
7866
7867/*!
7868 \qmlproperty bool QtQuick::Item::focus
7869
7870 This property holds whether the item has focus within the enclosing
7871 FocusScope. If true, this item will gain active focus when the
7872 enclosing FocusScope gains active focus.
7873
7874 In the following example, \c input will be given active focus when
7875 \c scope gains active focus:
7876
7877 \qml
7878 import QtQuick 2.0
7879
7880 Rectangle {
7881 width: 100; height: 100
7882
7883 FocusScope {
7884 id: scope
7885
7886 TextInput {
7887 id: input
7888 focus: true
7889 }
7890 }
7891 }
7892 \endqml
7893
7894 For the purposes of this property, the scene as a whole is assumed
7895 to act like a focus scope. On a practical level, that means the
7896 following QML will give active focus to \c input on startup.
7897
7898 \qml
7899 Rectangle {
7900 width: 100; height: 100
7901
7902 TextInput {
7903 id: input
7904 focus: true
7905 }
7906 }
7907 \endqml
7908
7909 \sa activeFocus, {Keyboard Focus in Qt Quick}
7910*/
7911/*!
7912 \property QQuickItem::focus
7913
7914 This property holds whether the item has focus within the enclosing
7915 FocusScope. If true, this item will gain active focus when the
7916 enclosing FocusScope gains active focus.
7917
7918 In the following example, \c input will be given active focus when
7919 \c scope gains active focus:
7920
7921 \qml
7922 import QtQuick 2.0
7923
7924 Rectangle {
7925 width: 100; height: 100
7926
7927 FocusScope {
7928 id: scope
7929
7930 TextInput {
7931 id: input
7932 focus: true
7933 }
7934 }
7935 }
7936 \endqml
7937
7938 For the purposes of this property, the scene as a whole is assumed
7939 to act like a focus scope. On a practical level, that means the
7940 following QML will give active focus to \c input on startup.
7941
7942 \qml
7943 Rectangle {
7944 width: 100; height: 100
7945
7946 TextInput {
7947 id: input
7948 focus: true
7949 }
7950 }
7951 \endqml
7952
7953 \sa activeFocus, {Keyboard Focus in Qt Quick}
7954*/
7955bool QQuickItem::hasFocus() const
7956{
7957 Q_D(const QQuickItem);
7958 return d->focus;
7959}
7960
7961void QQuickItem::setFocus(bool focus)
7962{
7963 setFocus(focus, reason: Qt::OtherFocusReason);
7964}
7965
7966void QQuickItem::setFocus(bool focus, Qt::FocusReason reason)
7967{
7968 Q_D(QQuickItem);
7969 // Need to find our nearest focus scope
7970 QQuickItem *scope = parentItem();
7971 while (scope && !scope->isFocusScope() && scope->parentItem())
7972 scope = scope->parentItem();
7973
7974 if (d->focus == focus && (!focus || !scope || QQuickItemPrivate::get(item: scope)->subFocusItem == this))
7975 return;
7976
7977 bool notifyListeners = false;
7978 if (d->window || d->parentItem) {
7979 if (d->window) {
7980 auto da = d->deliveryAgentPrivate();
7981 Q_ASSERT(da);
7982 if (focus)
7983 da->setFocusInScope(scope, item: this, reason);
7984 else
7985 da->clearFocusInScope(scope, item: this, reason);
7986 } else {
7987 // do the focus changes from setFocusInScope/clearFocusInScope that are
7988 // unrelated to a window
7989 QVarLengthArray<QQuickItem *, 20> changed;
7990 QQuickItem *oldSubFocusItem = QQuickItemPrivate::get(item: scope)->subFocusItem;
7991 if (oldSubFocusItem) {
7992 QQuickItemPrivate::get(item: oldSubFocusItem)->updateSubFocusItem(scope, focus: false);
7993 QQuickItemPrivate::get(item: oldSubFocusItem)->focus = false;
7994 changed << oldSubFocusItem;
7995 } else if (!scope->isFocusScope() && scope->hasFocus()) {
7996 QQuickItemPrivate::get(item: scope)->focus = false;
7997 changed << scope;
7998 }
7999 d->updateSubFocusItem(scope, focus);
8000
8001 d->focus = focus;
8002 changed << this;
8003 notifyListeners = true;
8004 emit focusChanged(focus);
8005
8006 QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(item: changed.data(), remaining: changed.size() - 1, reason);
8007 }
8008 } else {
8009 QVarLengthArray<QQuickItem *, 20> changed;
8010 QQuickItem *oldSubFocusItem = d->subFocusItem;
8011 if (!isFocusScope() && oldSubFocusItem) {
8012 QQuickItemPrivate::get(item: oldSubFocusItem)->updateSubFocusItem(scope: this, focus: false);
8013 QQuickItemPrivate::get(item: oldSubFocusItem)->focus = false;
8014 changed << oldSubFocusItem;
8015 }
8016
8017 d->focus = focus;
8018 changed << this;
8019 notifyListeners = true;
8020 emit focusChanged(focus);
8021
8022 QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(item: changed.data(), remaining: changed.size() - 1, reason);
8023 }
8024 if (notifyListeners)
8025 d->notifyChangeListeners(changeTypes: QQuickItemPrivate::Focus, function: &QQuickItemChangeListener::itemFocusChanged, args: this, args&: reason);
8026}
8027
8028/*!
8029 Returns true if this item is a focus scope, and false otherwise.
8030 */
8031bool QQuickItem::isFocusScope() const
8032{
8033 return flags() & ItemIsFocusScope;
8034}
8035
8036/*!
8037 If this item is a focus scope, this returns the item in its focus chain
8038 that currently has focus.
8039
8040 Returns \nullptr if this item is not a focus scope.
8041 */
8042QQuickItem *QQuickItem::scopedFocusItem() const
8043{
8044 Q_D(const QQuickItem);
8045 if (!isFocusScope())
8046 return nullptr;
8047 else
8048 return d->subFocusItem;
8049}
8050
8051/*!
8052 \qmlproperty enumeration QtQuick::Item::focusPolicy
8053 \since 6.7
8054
8055 This property determines the way the item accepts focus.
8056
8057 \value Qt.TabFocus The item accepts focus by tabbing.
8058 \value Qt.ClickFocus The item accepts focus by clicking.
8059 \value Qt.StrongFocus The item accepts focus by both tabbing and clicking.
8060 \value Qt.WheelFocus The item accepts focus by tabbing, clicking, and using the mouse wheel.
8061 \value Qt.NoFocus The item does not accept focus.
8062
8063 \note This property was a member of the \l[QML]{Control} QML type in Qt 6.6 and earlier.
8064*/
8065/*!
8066 \property QQuickItem::focusPolicy
8067 \since 6.7
8068
8069 This property determines the way the item accepts focus.
8070
8071*/
8072Qt::FocusPolicy QQuickItem::focusPolicy() const
8073{
8074 Q_D(const QQuickItem);
8075 uint policy = d->focusPolicy;
8076 if (activeFocusOnTab())
8077 policy |= Qt::TabFocus;
8078 return static_cast<Qt::FocusPolicy>(policy);
8079}
8080
8081/*!
8082 Sets the focus policy of this item to \a policy.
8083
8084 \sa focusPolicy()
8085*/
8086void QQuickItem::setFocusPolicy(Qt::FocusPolicy policy)
8087{
8088 Q_D(QQuickItem);
8089 if (d->focusPolicy == policy)
8090 return;
8091
8092 d->focusPolicy = policy;
8093 setActiveFocusOnTab(policy & Qt::TabFocus);
8094 emit focusPolicyChanged(policy);
8095}
8096
8097/*!
8098 Returns \c true if this item is an ancestor of \a child (i.e., if this item
8099 is \a child's parent, or one of \a child's parent's ancestors).
8100
8101 \since 5.7
8102
8103 \sa parentItem()
8104 */
8105bool QQuickItem::isAncestorOf(const QQuickItem *child) const
8106{
8107 if (!child || child == this)
8108 return false;
8109 const QQuickItem *ancestor = child;
8110 while ((ancestor = ancestor->parentItem())) {
8111 if (ancestor == this)
8112 return true;
8113 }
8114 return false;
8115}
8116
8117/*!
8118 Returns the mouse buttons accepted by this item.
8119
8120 The default value is Qt::NoButton; that is, no mouse buttons are accepted.
8121
8122 If an item does not accept the mouse button for a particular mouse event,
8123 the mouse event will not be delivered to the item and will be delivered
8124 to the next item in the item hierarchy instead.
8125
8126 \sa acceptTouchEvents()
8127*/
8128Qt::MouseButtons QQuickItem::acceptedMouseButtons() const
8129{
8130 Q_D(const QQuickItem);
8131 return d->acceptedMouseButtons();
8132}
8133
8134/*!
8135 Sets the mouse buttons accepted by this item to \a buttons.
8136
8137 \note In Qt 5, calling setAcceptedMouseButtons() implicitly caused
8138 an item to receive touch events as well as mouse events; but it was
8139 recommended to call setAcceptTouchEvents() to subscribe for them.
8140 In Qt 6, it is necessary to call setAcceptTouchEvents() to continue
8141 to receive them.
8142*/
8143void QQuickItem::setAcceptedMouseButtons(Qt::MouseButtons buttons)
8144{
8145 Q_D(QQuickItem);
8146 d->extra.setTag(d->extra.tag().setFlag(flag: QQuickItemPrivate::LeftMouseButtonAccepted, on: buttons & Qt::LeftButton));
8147
8148 buttons &= ~Qt::LeftButton;
8149 if (buttons || d->extra.isAllocated()) {
8150 d->extra.value().acceptedMouseButtonsWithoutHandlers = buttons;
8151 d->extra.value().acceptedMouseButtons = d->extra->pointerHandlers.isEmpty() ? buttons : Qt::AllButtons;
8152 }
8153}
8154
8155/*!
8156 Returns whether pointer events intended for this item's children should be
8157 filtered through this item.
8158
8159 If both this item and a child item have acceptTouchEvents() \c true, then
8160 when a touch interaction occurs, this item will filter the touch event.
8161 But if either this item or the child cannot handle touch events,
8162 childMouseEventFilter() will be called with a synthesized mouse event.
8163
8164 \sa setFiltersChildMouseEvents(), childMouseEventFilter()
8165 */
8166bool QQuickItem::filtersChildMouseEvents() const
8167{
8168 Q_D(const QQuickItem);
8169 return d->filtersChildMouseEvents;
8170}
8171
8172/*!
8173 Sets whether pointer events intended for this item's children should be
8174 filtered through this item.
8175
8176 If \a filter is true, childMouseEventFilter() will be called when
8177 a pointer event is triggered for a child item.
8178
8179 \sa filtersChildMouseEvents()
8180 */
8181void QQuickItem::setFiltersChildMouseEvents(bool filter)
8182{
8183 Q_D(QQuickItem);
8184 d->filtersChildMouseEvents = filter;
8185}
8186
8187/*!
8188 \internal
8189 */
8190bool QQuickItem::isUnderMouse() const
8191{
8192 Q_D(const QQuickItem);
8193 if (!d->window)
8194 return false;
8195
8196 // QQuickWindow handles QEvent::Leave to reset the lastMousePosition
8197 // FIXME: Using QPointF() as the reset value means an item will not be
8198 // under the mouse if the mouse is at 0,0 of the window.
8199 if (const_cast<QQuickItemPrivate *>(d)->deliveryAgentPrivate()->lastMousePosition == QPointF())
8200 return false;
8201
8202 QPointF cursorPos = QGuiApplicationPrivate::lastCursorPosition;
8203 return contains(point: mapFromScene(point: d->window->mapFromGlobal(pos: cursorPos)));
8204}
8205
8206/*!
8207 Returns whether hover events are accepted by this item.
8208
8209 The default value is false.
8210
8211 If this is false, then the item will not receive any hover events through
8212 the hoverEnterEvent(), hoverMoveEvent() and hoverLeaveEvent() functions.
8213*/
8214bool QQuickItem::acceptHoverEvents() const
8215{
8216 Q_D(const QQuickItem);
8217 return d->hoverEnabled;
8218}
8219
8220/*!
8221 If \a enabled is true, this sets the item to accept hover events;
8222 otherwise, hover events are not accepted by this item.
8223
8224 \sa acceptHoverEvents()
8225*/
8226void QQuickItem::setAcceptHoverEvents(bool enabled)
8227{
8228 Q_D(QQuickItem);
8229 // hoverEnabled causes hoveredLeafItemFound to be set to true when a hover
8230 // event is being delivered to this item, which effectively ends hover
8231 // event delivery, as it will then start sending hover events backwards
8232 // from the child to the root, in a straight line.
8233 d->hoverEnabled = enabled;
8234 // Recursively set subtreeHoverEnabled for all of our parents. Note that
8235 // even though this and hoverEnabled are set to the same values in this
8236 // function, only subtreeHoverEnabled is set for the entire parent chain.
8237 // subtreeHoverEnabled says that a certain tree _may_ want hover events,
8238 // but unlike hoverEnabled, won't prevent delivery to siblings.
8239 d->setHasHoverInChild(enabled);
8240 // The DA needs to resolve which items and handlers should now be hovered or unhovered.
8241 // Marking this item dirty ensures that flushFrameSynchronousEvents() will be called from the render loop,
8242 // even if this change is not in response to a mouse event and no item has already marked itself dirty.
8243 d->dirty(type: QQuickItemPrivate::Content);
8244}
8245
8246/*!
8247 Returns whether touch events are accepted by this item.
8248
8249 The default value is \c false.
8250
8251 If this is \c false, then the item will not receive any touch events through
8252 the touchEvent() function.
8253
8254 \since 5.10
8255*/
8256bool QQuickItem::acceptTouchEvents() const
8257{
8258 Q_D(const QQuickItem);
8259 return d->touchEnabled;
8260}
8261
8262/*!
8263 If \a enabled is true, this sets the item to accept touch events;
8264 otherwise, touch events are not accepted by this item.
8265
8266 \since 5.10
8267
8268 \sa acceptTouchEvents()
8269*/
8270void QQuickItem::setAcceptTouchEvents(bool enabled)
8271{
8272 Q_D(QQuickItem);
8273 d->touchEnabled = enabled;
8274}
8275
8276void QQuickItemPrivate::setHasCursorInChild(bool hc)
8277{
8278#if QT_CONFIG(cursor)
8279 Q_Q(QQuickItem);
8280
8281 // if we're asked to turn it off (because of an unsetcursor call, or a node
8282 // removal) then we should make sure it's really ok to turn it off.
8283 if (!hc && subtreeCursorEnabled) {
8284 if (hasCursor)
8285 return; // nope! sorry, I have a cursor myself
8286 for (QQuickItem *otherChild : std::as_const(t&: childItems)) {
8287 QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(item: otherChild);
8288 if (otherChildPrivate->subtreeCursorEnabled || otherChildPrivate->hasCursor)
8289 return; // nope! sorry, something else wants it kept on.
8290 }
8291 }
8292
8293 subtreeCursorEnabled = hc;
8294 QQuickItem *parent = q->parentItem();
8295 if (parent) {
8296 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(item: parent);
8297 parentPrivate->setHasCursorInChild(hc);
8298 }
8299#else
8300 Q_UNUSED(hc);
8301#endif
8302}
8303
8304void QQuickItemPrivate::setHasHoverInChild(bool hasHover)
8305{
8306 Q_Q(QQuickItem);
8307
8308 // if we're asked to turn it off (because of a setAcceptHoverEvents call, or a node
8309 // removal) then we should make sure it's really ok to turn it off.
8310 if (!hasHover && subtreeHoverEnabled) {
8311 if (hoverEnabled)
8312 return; // nope! sorry, I need hover myself
8313 if (hasEnabledHoverHandlers())
8314 return; // nope! sorry, this item has enabled HoverHandlers
8315
8316 for (QQuickItem *otherChild : std::as_const(t&: childItems)) {
8317 QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(item: otherChild);
8318 if (otherChildPrivate->subtreeHoverEnabled || otherChildPrivate->hoverEnabled)
8319 return; // nope! sorry, something else wants it kept on.
8320 if (otherChildPrivate->hasEnabledHoverHandlers())
8321 return; // nope! sorry, we have pointer handlers which are interested.
8322 }
8323 }
8324
8325 qCDebug(lcHoverTrace) << q << subtreeHoverEnabled << "->" << hasHover;
8326 subtreeHoverEnabled = hasHover;
8327 QQuickItem *parent = q->parentItem();
8328 if (parent) {
8329 QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(item: parent);
8330 parentPrivate->setHasHoverInChild(hasHover);
8331 }
8332}
8333
8334#if QT_CONFIG(cursor)
8335
8336/*!
8337 Returns the cursor shape for this item.
8338
8339 The mouse cursor will assume this shape when it is over this
8340 item, unless an override cursor is set.
8341 See the \l{Qt::CursorShape}{list of predefined cursor objects} for a
8342 range of useful shapes.
8343
8344 If no cursor shape has been set this returns a cursor with the Qt::ArrowCursor shape, however
8345 another cursor shape may be displayed if an overlapping item has a valid cursor.
8346
8347 \sa setCursor(), unsetCursor()
8348*/
8349
8350QCursor QQuickItem::cursor() const
8351{
8352 Q_D(const QQuickItem);
8353 return d->extra.isAllocated()
8354 ? d->extra->cursor
8355 : QCursor();
8356}
8357
8358/*!
8359 Sets the \a cursor shape for this item.
8360
8361 \sa cursor(), unsetCursor()
8362*/
8363
8364void QQuickItem::setCursor(const QCursor &cursor)
8365{
8366 Q_D(QQuickItem);
8367
8368 Qt::CursorShape oldShape = d->extra.isAllocated() ? d->extra->cursor.shape() : Qt::ArrowCursor;
8369 qCDebug(lcHoverTrace) << oldShape << "->" << cursor.shape();
8370
8371 if (oldShape != cursor.shape() || oldShape >= Qt::LastCursor || cursor.shape() >= Qt::LastCursor) {
8372 d->extra.value().cursor = cursor;
8373 if (d->window) {
8374 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(win: d->window);
8375 QWindow *window = renderWindow ? renderWindow : d->window; // this may not be a QQuickWindow
8376 if (QQuickWindowPrivate::get(c: d->window)->cursorItem == this)
8377 window->setCursor(cursor);
8378 }
8379 }
8380
8381 QPointF updateCursorPos;
8382 if (!d->hasCursor) {
8383 d->hasCursor = true;
8384 if (d->window) {
8385 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(win: d->window);
8386 QWindow *window = renderWindow ? renderWindow : d->window;
8387 QPointF pos = window->mapFromGlobal(pos: QGuiApplicationPrivate::lastCursorPosition);
8388 if (contains(point: mapFromScene(point: pos)))
8389 updateCursorPos = pos;
8390 }
8391 }
8392 d->setHasCursorInChild(d->hasCursor || d->hasCursorHandler);
8393 if (!updateCursorPos.isNull())
8394 QQuickWindowPrivate::get(c: d->window)->updateCursor(scenePos: updateCursorPos);
8395}
8396
8397/*!
8398 Clears the cursor shape for this item.
8399
8400 \sa cursor(), setCursor()
8401*/
8402
8403void QQuickItem::unsetCursor()
8404{
8405 Q_D(QQuickItem);
8406 qCDebug(lcHoverTrace) << "clearing cursor";
8407 if (!d->hasCursor)
8408 return;
8409 d->hasCursor = false;
8410 d->setHasCursorInChild(d->hasCursorHandler);
8411 if (d->extra.isAllocated())
8412 d->extra->cursor = QCursor();
8413
8414 if (d->window) {
8415 QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(c: d->window);
8416 if (windowPrivate->cursorItem == this) {
8417 QPointF pos = d->window->mapFromGlobal(pos: QGuiApplicationPrivate::lastCursorPosition);
8418 windowPrivate->updateCursor(scenePos: pos);
8419 }
8420 }
8421}
8422
8423/*!
8424 \internal
8425 Returns the cursor that should actually be shown, allowing the given
8426 \a handler to override the Item cursor if it is active or hovered.
8427
8428 \sa cursor(), setCursor(), QtQuick::PointerHandler::cursor
8429*/
8430QCursor QQuickItemPrivate::effectiveCursor(const QQuickPointerHandler *handler) const
8431{
8432 Q_Q(const QQuickItem);
8433 if (!handler)
8434 return q->cursor();
8435 bool hoverCursorSet = false;
8436 QCursor hoverCursor;
8437 bool activeCursorSet = false;
8438 QCursor activeCursor;
8439 if (const QQuickHoverHandler *hoverHandler = qobject_cast<const QQuickHoverHandler *>(object: handler)) {
8440 hoverCursorSet = hoverHandler->isCursorShapeExplicitlySet();
8441 hoverCursor = hoverHandler->cursorShape();
8442 } else if (handler->active()) {
8443 activeCursorSet = handler->isCursorShapeExplicitlySet();
8444 activeCursor = handler->cursorShape();
8445 }
8446 if (activeCursorSet)
8447 return activeCursor;
8448 if (hoverCursorSet)
8449 return hoverCursor;
8450 return q->cursor();
8451}
8452
8453/*!
8454 \internal
8455 Returns the Pointer Handler that is currently attempting to set the cursor shape,
8456 or null if there is no such handler.
8457
8458 If there are multiple handlers attempting to set the cursor:
8459 \list
8460 \li an active handler has the highest priority (e.g. a DragHandler being dragged)
8461 \li any HoverHandler that is reacting to a non-mouse device has priority for
8462 kCursorOverrideTimeout ms (a tablet stylus is jittery so that's enough)
8463 \li otherwise a HoverHandler that is reacting to the mouse, if any
8464 \endlist
8465
8466 Within each category, if there are multiple handlers, the last-added one wins
8467 (the one that is declared at the bottom wins, because users may intuitively
8468 think it's "on top" even though there is no Z-order; or, one that is added
8469 in a specific use case overrides an imported component).
8470
8471 \sa QtQuick::PointerHandler::cursor
8472*/
8473QQuickPointerHandler *QQuickItemPrivate::effectiveCursorHandler() const
8474{
8475 if (!hasPointerHandlers())
8476 return nullptr;
8477 QQuickPointerHandler* activeHandler = nullptr;
8478 QQuickPointerHandler* mouseHandler = nullptr;
8479 QQuickPointerHandler* nonMouseHandler = nullptr;
8480 for (QQuickPointerHandler *h : extra->pointerHandlers) {
8481 if (!h->isCursorShapeExplicitlySet())
8482 continue;
8483 QQuickHoverHandler *hoverHandler = qmlobject_cast<QQuickHoverHandler *>(object: h);
8484 // Prioritize any HoverHandler that is reacting to a non-mouse device.
8485 // Otherwise, choose the first hovered handler that is found.
8486 // TODO maybe: there was an idea to add QPointerDevice* as argument to this function
8487 // and check the device type, but why? HoverHandler already does that.
8488 if (!activeHandler && hoverHandler && hoverHandler->isHovered()) {
8489 qCDebug(lcHoverTrace) << hoverHandler << hoverHandler->acceptedDevices() << "wants to set cursor" << hoverHandler->cursorShape();
8490 if (hoverHandler->acceptedDevices().testFlag(flag: QPointingDevice::DeviceType::Mouse)) {
8491 // If there's a conflict, the last-added HoverHandler wins. Maybe the user is overriding a default...
8492 if (mouseHandler && mouseHandler->cursorShape() != hoverHandler->cursorShape()) {
8493 qCDebug(lcHoverTrace) << "mouse cursor conflict:" << mouseHandler << "wants" << mouseHandler->cursorShape()
8494 << "but" << hoverHandler << "wants" << hoverHandler->cursorShape();
8495 }
8496 mouseHandler = hoverHandler;
8497 } else {
8498 // If there's a conflict, the last-added HoverHandler wins.
8499 if (nonMouseHandler && nonMouseHandler->cursorShape() != hoverHandler->cursorShape()) {
8500 qCDebug(lcHoverTrace) << "non-mouse cursor conflict:" << nonMouseHandler << "wants" << nonMouseHandler->cursorShape()
8501 << "but" << hoverHandler << "wants" << hoverHandler->cursorShape();
8502 }
8503 nonMouseHandler = hoverHandler;
8504 }
8505 }
8506 if (!hoverHandler && h->active())
8507 activeHandler = h;
8508 }
8509 if (activeHandler) {
8510 qCDebug(lcHoverTrace) << "active handler choosing cursor" << activeHandler << activeHandler->cursorShape();
8511 return activeHandler;
8512 }
8513 // Mouse events are often synthetic; so if a HoverHandler for a non-mouse device wanted to set the cursor,
8514 // let it win, unless more than kCursorOverrideTimeout ms have passed
8515 // since the last time the non-mouse handler actually reacted to an event.
8516 // We could miss the fact that a tablet stylus has left proximity, because we don't deliver proximity events to windows.
8517 if (nonMouseHandler) {
8518 if (mouseHandler) {
8519 const bool beforeTimeout =
8520 QQuickPointerHandlerPrivate::get(q: mouseHandler)->lastEventTime <
8521 QQuickPointerHandlerPrivate::get(q: nonMouseHandler)->lastEventTime + kCursorOverrideTimeout;
8522 QQuickPointerHandler *winner = (beforeTimeout ? nonMouseHandler : mouseHandler);
8523 qCDebug(lcHoverTrace) << "non-mouse handler reacted last time:" << QQuickPointerHandlerPrivate::get(q: nonMouseHandler)->lastEventTime
8524 << "and mouse handler reacted at time:" << QQuickPointerHandlerPrivate::get(q: mouseHandler)->lastEventTime
8525 << "choosing cursor according to" << winner << winner->cursorShape();
8526 return winner;
8527 }
8528 qCDebug(lcHoverTrace) << "non-mouse handler choosing cursor" << nonMouseHandler << nonMouseHandler->cursorShape();
8529 return nonMouseHandler;
8530 }
8531 if (mouseHandler)
8532 qCDebug(lcHoverTrace) << "mouse handler choosing cursor" << mouseHandler << mouseHandler->cursorShape();
8533 return mouseHandler;
8534}
8535
8536#endif
8537
8538/*!
8539 \deprecated Use QPointerEvent::setExclusiveGrabber().
8540
8541 Grabs the mouse input.
8542
8543 This item will receive all mouse events until ungrabMouse() is called.
8544 Usually this function should not be called, since accepting for example
8545 a mouse press event makes sure that the following events are delivered
8546 to the item.
8547 If an item wants to take over mouse events from the current receiver,
8548 it needs to call this function.
8549
8550 \warning This function should be used with caution.
8551 */
8552void QQuickItem::grabMouse()
8553{
8554 Q_D(QQuickItem);
8555 if (!d->window)
8556 return;
8557 auto da = d->deliveryAgentPrivate();
8558 Q_ASSERT(da);
8559 auto eventInDelivery = da->eventInDelivery();
8560 if (!eventInDelivery) {
8561 qWarning() << "cannot grab mouse: no event is currently being delivered";
8562 return;
8563 }
8564 auto epd = da->mousePointData();
8565 eventInDelivery->setExclusiveGrabber(point: epd->eventPoint, exclusiveGrabber: this);
8566}
8567
8568/*!
8569 \deprecated Use QPointerEvent::setExclusiveGrabber().
8570
8571 Releases the mouse grab following a call to grabMouse().
8572
8573 Note that this function should only be called when the item wants
8574 to stop handling further events. There is no need to call this function
8575 after a release or cancel event since no future events will be received
8576 in any case. No move or release events will be delivered after this
8577 function was called.
8578*/
8579void QQuickItem::ungrabMouse()
8580{
8581 Q_D(QQuickItem);
8582 if (!d->window)
8583 return;
8584 auto da = d->deliveryAgentPrivate();
8585 Q_ASSERT(da);
8586 auto eventInDelivery = da->eventInDelivery();
8587 if (!eventInDelivery) {
8588 // do it the expensive way
8589 da->removeGrabber(grabber: this);
8590 return;
8591 }
8592 const auto &eventPoint = da->mousePointData()->eventPoint;
8593 if (eventInDelivery->exclusiveGrabber(point: eventPoint) == this)
8594 eventInDelivery->setExclusiveGrabber(point: eventPoint, exclusiveGrabber: nullptr);
8595}
8596
8597/*!
8598 Returns whether mouse input should exclusively remain with this item.
8599
8600 \sa setKeepMouseGrab(), QEvent::accept(), QEvent::ignore()
8601 */
8602bool QQuickItem::keepMouseGrab() const
8603{
8604 Q_D(const QQuickItem);
8605 return d->keepMouse;
8606}
8607
8608/*!
8609 Sets whether the mouse input should remain exclusively with this item.
8610
8611 This is useful for items that wish to grab and keep mouse
8612 interaction following a predefined gesture. For example,
8613 an item that is interested in horizontal mouse movement
8614 may set keepMouseGrab to true once a threshold has been
8615 exceeded. Once keepMouseGrab has been set to true, filtering
8616 items will not react to mouse events.
8617
8618 If \a keep is false, a filtering item may steal the grab. For example,
8619 \l Flickable may attempt to steal a mouse grab if it detects that the
8620 user has begun to move the viewport.
8621
8622 \sa keepMouseGrab()
8623 */
8624void QQuickItem::setKeepMouseGrab(bool keep)
8625{
8626 Q_D(QQuickItem);
8627 d->keepMouse = keep;
8628}
8629
8630/*!
8631 \deprecated Use QPointerEvent::setExclusiveGrabber().
8632 Grabs the touch points specified by \a ids.
8633
8634 These touch points will be owned by the item until
8635 they are released. Alternatively, the grab can be stolen
8636 by a filtering item like Flickable. Use setKeepTouchGrab()
8637 to prevent the grab from being stolen.
8638*/
8639void QQuickItem::grabTouchPoints(const QList<int> &ids)
8640{
8641 Q_D(QQuickItem);
8642 auto event = d->deliveryAgentPrivate()->eventInDelivery();
8643 if (Q_UNLIKELY(!event)) {
8644 qWarning() << "cannot grab: no event is currently being delivered";
8645 return;
8646 }
8647 for (auto pt : event->points()) {
8648 if (ids.contains(t: pt.id()))
8649 event->setExclusiveGrabber(point: pt, exclusiveGrabber: this);
8650 }
8651}
8652
8653/*!
8654 \deprecated Use QEventPoint::setExclusiveGrabber() instead.
8655 Ungrabs the touch points owned by this item.
8656*/
8657void QQuickItem::ungrabTouchPoints()
8658{
8659 Q_D(QQuickItem);
8660 if (!d->window)
8661 return;
8662 if (QQuickDeliveryAgentPrivate *da = d->deliveryAgentPrivate())
8663 da->removeGrabber(grabber: this, mouse: false, touch: true);
8664}
8665
8666/*!
8667 Returns whether the touch points grabbed by this item should exclusively
8668 remain with this item.
8669
8670 \sa setKeepTouchGrab(), keepMouseGrab(), QEvent::accept(), QEvent::ignore()
8671*/
8672bool QQuickItem::keepTouchGrab() const
8673{
8674 Q_D(const QQuickItem);
8675 return d->keepTouch;
8676}
8677
8678/*!
8679 Sets whether the touch points grabbed by this item should remain
8680 exclusively with this item.
8681
8682 This is useful for items that wish to grab and keep specific touch
8683 points following a predefined gesture. For example,
8684 an item that is interested in horizontal touch point movement
8685 may set setKeepTouchGrab to true once a threshold has been
8686 exceeded. Once setKeepTouchGrab has been set to true, filtering
8687 items will not react to the relevant touch points.
8688
8689 If \a keep is false, a filtering item may steal the grab. For example,
8690 \l Flickable may attempt to steal a touch point grab if it detects that the
8691 user has begun to move the viewport.
8692
8693 \sa keepTouchGrab(), setKeepMouseGrab()
8694 */
8695void QQuickItem::setKeepTouchGrab(bool keep)
8696{
8697 Q_D(QQuickItem);
8698 d->keepTouch = keep;
8699}
8700
8701/*!
8702 \qmlmethod bool QtQuick::Item::contains(point point)
8703
8704 Returns \c true if this item contains \a point, which is in local coordinates;
8705 returns \c false otherwise. This is the same check that is used for
8706 hit-testing a QEventPoint during event delivery, and is affected by
8707 \l containmentMask if it is set.
8708*/
8709/*!
8710 Returns \c true if this item contains \a point, which is in local coordinates;
8711 returns \c false otherwise.
8712
8713 This function can be overridden in order to handle point collisions in items
8714 with custom shapes. The default implementation checks whether the point is inside
8715 \l containmentMask() if it is set, or inside the bounding box otherwise.
8716
8717 \note This method is used for hit-testing each QEventPoint during event
8718 delivery, so the implementation should be kept as lightweight as possible.
8719*/
8720bool QQuickItem::contains(const QPointF &point) const
8721{
8722 Q_D(const QQuickItem);
8723 if (d->extra.isAllocated() && d->extra->mask) {
8724 if (auto quickMask = qobject_cast<QQuickItem *>(o: d->extra->mask))
8725 return quickMask->contains(point: point - quickMask->position());
8726
8727 bool res = false;
8728 QMetaMethod maskContains = d->extra->mask->metaObject()->method(index: d->extra->maskContainsIndex);
8729 maskContains.invoke(obj: d->extra->mask,
8730 c: Qt::DirectConnection,
8731 Q_RETURN_ARG(bool, res),
8732 Q_ARG(QPointF, point));
8733 return res;
8734 }
8735
8736 qreal x = point.x();
8737 qreal y = point.y();
8738 return x >= 0 && y >= 0 && x < d->width && y < d->height;
8739}
8740
8741/*!
8742 \qmlproperty QObject* QtQuick::Item::containmentMask
8743 \since 5.11
8744 This property holds an optional mask for the Item to be used in the
8745 \l contains() method. Its main use is currently to determine
8746 whether a \l {QPointerEvent}{pointer event} has landed into the item or not.
8747
8748 By default the \c contains() method will return true for any point
8749 within the Item's bounding box. \c containmentMask allows for
8750 more fine-grained control. For example, if a custom C++
8751 QQuickItem subclass with a specialized contains() method
8752 is used as containmentMask:
8753
8754 \code
8755 Item { id: item; containmentMask: AnotherItem { id: anotherItem } }
8756 \endcode
8757
8758 \e{item}'s contains method would then return \c true only if
8759 \e{anotherItem}'s contains() implementation returns \c true.
8760
8761 A \l Shape can be used as a mask, to make an item react to
8762 \l {QPointerEvent}{pointer events} only within a non-rectangular region:
8763
8764 \table
8765 \row
8766 \li \image containmentMask-shape.gif
8767 \li \snippet qml/item/containmentMask-shape.qml 0
8768 \endtable
8769
8770 It is also possible to define the contains method in QML. For example,
8771 to create a circular item that only responds to events within its
8772 actual bounds:
8773
8774 \table
8775 \row
8776 \li \image containmentMask-circle.gif
8777 \li \snippet qml/item/containmentMask-circle-js.qml 0
8778 \endtable
8779
8780 \sa {Qt Quick Examples - Shapes}
8781*/
8782/*!
8783 \property QQuickItem::containmentMask
8784 \since 5.11
8785 This property holds an optional mask to be used in the contains() method,
8786 which is mainly used for hit-testing each \l QPointerEvent.
8787
8788 By default, \l contains() will return \c true for any point
8789 within the Item's bounding box. But any QQuickItem, or any QObject
8790 that implements a function of the form
8791 \code
8792 Q_INVOKABLE bool contains(const QPointF &point) const;
8793 \endcode
8794 can be used as a mask, to defer hit-testing to that object.
8795
8796 \note contains() is called frequently during event delivery.
8797 Deferring hit-testing to another object slows it down somewhat.
8798 containmentMask() can cause performance problems if that object's
8799 contains() method is not efficient. If you implement a custom
8800 QQuickItem subclass, you can alternatively override contains().
8801
8802 \sa contains()
8803*/
8804QObject *QQuickItem::containmentMask() const
8805{
8806 Q_D(const QQuickItem);
8807 if (!d->extra.isAllocated())
8808 return nullptr;
8809 return d->extra->mask.data();
8810}
8811
8812void QQuickItem::setContainmentMask(QObject *mask)
8813{
8814 Q_D(QQuickItem);
8815 const bool extraDataExists = d->extra.isAllocated();
8816 // an Item can't mask itself (to prevent infinite loop in contains())
8817 if (mask == static_cast<QObject *>(this))
8818 return;
8819 // mask is null, and we had no mask
8820 if (!extraDataExists && !mask)
8821 return;
8822 // mask is non-null and the same
8823 if (extraDataExists && d->extra->mask == mask)
8824 return;
8825
8826 QQuickItem *quickMask = d->extra.isAllocated() ? qobject_cast<QQuickItem *>(o: d->extra->mask)
8827 : nullptr;
8828 if (quickMask) {
8829 QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(item: quickMask);
8830 maskPrivate->registerAsContainmentMask(this, false); // removed from use as my mask
8831 }
8832
8833 if (!extraDataExists)
8834 d->extra.value(); // ensure extra exists
8835 if (mask) {
8836 int methodIndex = mask->metaObject()->indexOfMethod(QByteArrayLiteral("contains(QPointF)"));
8837 if (methodIndex < 0) {
8838 qmlWarning(me: this) << QStringLiteral("QQuickItem: Object set as mask does not have an invokable contains method, ignoring it.");
8839 return;
8840 }
8841 d->extra->maskContainsIndex = methodIndex;
8842 }
8843 d->extra->mask = mask;
8844 quickMask = qobject_cast<QQuickItem *>(o: mask);
8845 if (quickMask) {
8846 QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(item: quickMask);
8847 maskPrivate->registerAsContainmentMask(this, true); // telling maskPrivate that "this" is using it as mask
8848 }
8849 emit containmentMaskChanged();
8850}
8851
8852/*!
8853 Maps the given \a point in this item's coordinate system to the equivalent
8854 point within \a item's coordinate system, and returns the mapped
8855 coordinate.
8856
8857 \input item.qdocinc mapping
8858
8859 If \a item is \nullptr, this maps \a point to the coordinate system of the
8860 scene.
8861
8862 \sa {Concepts - Visual Coordinates in Qt Quick}
8863*/
8864QPointF QQuickItem::mapToItem(const QQuickItem *item, const QPointF &point) const
8865{
8866 QPointF p = mapToScene(point);
8867 if (item) {
8868 const auto *itemWindow = item->window();
8869 const auto *thisWindow = window();
8870 if (thisWindow && itemWindow && itemWindow != thisWindow)
8871 p = itemWindow->mapFromGlobal(pos: thisWindow->mapToGlobal(pos: p));
8872
8873 p = item->mapFromScene(point: p);
8874 }
8875 return p;
8876}
8877
8878/*!
8879 Maps the given \a point in this item's coordinate system to the equivalent
8880 point within the scene's coordinate system, and returns the mapped
8881 coordinate.
8882
8883 \input item.qdocinc mapping
8884
8885 \sa {Concepts - Visual Coordinates in Qt Quick}
8886*/
8887QPointF QQuickItem::mapToScene(const QPointF &point) const
8888{
8889 Q_D(const QQuickItem);
8890 return d->itemToWindowTransform().map(p: point);
8891}
8892
8893/*!
8894 Maps the given \a point in this item's coordinate system to the equivalent
8895 point within global screen coordinate system, and returns the mapped
8896 coordinate.
8897
8898 \input item.qdocinc mapping
8899
8900 For example, this may be helpful to add a popup to a Qt Quick component.
8901
8902 \note Window positioning is done by the window manager and this value is
8903 treated only as a hint. So, the resulting window position may differ from
8904 what is expected.
8905
8906 \since 5.7
8907
8908 \sa {Concepts - Visual Coordinates in Qt Quick}
8909*/
8910QPointF QQuickItem::mapToGlobal(const QPointF &point) const
8911{
8912 Q_D(const QQuickItem);
8913
8914 if (Q_UNLIKELY(d->window == nullptr))
8915 return mapToScene(point);
8916
8917 QPoint renderOffset;
8918 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(win: d->window, offset: &renderOffset);
8919 QWindow *effectiveWindow = renderWindow ? renderWindow : d->window;
8920 return effectiveWindow->mapToGlobal(pos: (mapToScene(point) + renderOffset));
8921}
8922
8923/*!
8924 Maps the given \a rect in this item's coordinate system to the equivalent
8925 rectangular area within \a item's coordinate system, and returns the mapped
8926 rectangle value.
8927
8928 \input item.qdocinc mapping
8929
8930 If \a item is \nullptr, this maps \a rect to the coordinate system of the
8931 scene.
8932
8933 \sa {Concepts - Visual Coordinates in Qt Quick}
8934*/
8935QRectF QQuickItem::mapRectToItem(const QQuickItem *item, const QRectF &rect) const
8936{
8937 Q_D(const QQuickItem);
8938 QTransform t = d->itemToWindowTransform();
8939 if (item)
8940 t *= QQuickItemPrivate::get(item)->windowToItemTransform();
8941 return t.mapRect(rect);
8942}
8943
8944/*!
8945 Maps the given \a rect in this item's coordinate system to the equivalent
8946 rectangular area within the scene's coordinate system, and returns the mapped
8947 rectangle value.
8948
8949 \input item.qdocinc mapping
8950
8951 \sa {Concepts - Visual Coordinates in Qt Quick}
8952*/
8953QRectF QQuickItem::mapRectToScene(const QRectF &rect) const
8954{
8955 Q_D(const QQuickItem);
8956 return d->itemToWindowTransform().mapRect(rect);
8957}
8958
8959/*!
8960 Maps the given \a point in \a item's coordinate system to the equivalent
8961 point within this item's coordinate system, and returns the mapped
8962 coordinate.
8963
8964 \input item.qdocinc mapping
8965
8966 If \a item is \nullptr, this maps \a point from the coordinate system of the
8967 scene.
8968
8969 \sa {Concepts - Visual Coordinates in Qt Quick}
8970*/
8971QPointF QQuickItem::mapFromItem(const QQuickItem *item, const QPointF &point) const
8972{
8973 QPointF p = point;
8974 if (item) {
8975 p = item->mapToScene(point);
8976 const auto *itemWindow = item->window();
8977 const auto *thisWindow = window();
8978 if (thisWindow && itemWindow && itemWindow != thisWindow)
8979 p = thisWindow->mapFromGlobal(pos: itemWindow->mapToGlobal(pos: p));
8980 }
8981 return mapFromScene(point: p);
8982}
8983
8984/*!
8985 Maps the given \a point in the scene's coordinate system to the equivalent
8986 point within this item's coordinate system, and returns the mapped
8987 coordinate.
8988
8989 \input item.qdocinc mapping
8990
8991 \sa {Concepts - Visual Coordinates in Qt Quick}
8992*/
8993QPointF QQuickItem::mapFromScene(const QPointF &point) const
8994{
8995 Q_D(const QQuickItem);
8996 return d->windowToItemTransform().map(p: point);
8997}
8998
8999/*!
9000 Maps the given \a point in the global screen coordinate system to the
9001 equivalent point within this item's coordinate system, and returns the
9002 mapped coordinate.
9003
9004 \input item.qdocinc mapping
9005
9006 For example, this may be helpful to add a popup to a Qt Quick component.
9007
9008 \note Window positioning is done by the window manager and this value is
9009 treated only as a hint. So, the resulting window position may differ from
9010 what is expected.
9011
9012 \note If this item is in a subscene, e.g. mapped onto a 3D
9013 \l [QtQuick3D QML] {Model}{Model} object, the UV mapping is incorporated
9014 into this transformation, so that it really goes from screen coordinates to
9015 this item's coordinates, as long as \a point is actually within this item's bounds.
9016 The other mapping functions do not yet work that way.
9017
9018 \since 5.7
9019
9020 \sa {Concepts - Visual Coordinates in Qt Quick}
9021*/
9022QPointF QQuickItem::mapFromGlobal(const QPointF &point) const
9023{
9024 Q_D(const QQuickItem);
9025
9026 QPointF scenePoint;
9027 if (Q_LIKELY(d->window)) {
9028 QPoint renderOffset;
9029 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(win: d->window, offset: &renderOffset);
9030 QWindow *effectiveWindow = renderWindow ? renderWindow : d->window;
9031 scenePoint = effectiveWindow->mapFromGlobal(pos: point) - renderOffset;
9032 } else {
9033 scenePoint = point;
9034 }
9035
9036 if (auto da = QQuickDeliveryAgentPrivate::currentOrItemDeliveryAgent(item: this)) {
9037 if (auto sceneTransform = da->sceneTransform())
9038 scenePoint = sceneTransform->map(point: scenePoint);
9039 }
9040 return mapFromScene(point: scenePoint);
9041}
9042
9043/*!
9044 Maps the given \a rect in \a item's coordinate system to the equivalent
9045 rectangular area within this item's coordinate system, and returns the mapped
9046 rectangle value.
9047
9048 \input item.qdocinc mapping
9049
9050 If \a item is \nullptr, this maps \a rect from the coordinate system of the
9051 scene.
9052
9053 \sa {Concepts - Visual Coordinates in Qt Quick}
9054*/
9055QRectF QQuickItem::mapRectFromItem(const QQuickItem *item, const QRectF &rect) const
9056{
9057 Q_D(const QQuickItem);
9058 QTransform t = item?QQuickItemPrivate::get(item)->itemToWindowTransform():QTransform();
9059 t *= d->windowToItemTransform();
9060 return t.mapRect(rect);
9061}
9062
9063/*!
9064 Maps the given \a rect in the scene's coordinate system to the equivalent
9065 rectangular area within this item's coordinate system, and returns the mapped
9066 rectangle value.
9067
9068 \input item.qdocinc mapping
9069
9070 \sa {Concepts - Visual Coordinates in Qt Quick}
9071*/
9072QRectF QQuickItem::mapRectFromScene(const QRectF &rect) const
9073{
9074 Q_D(const QQuickItem);
9075 return d->windowToItemTransform().mapRect(rect);
9076}
9077
9078/*!
9079 \property QQuickItem::anchors
9080 \internal
9081*/
9082
9083/*!
9084 \property QQuickItem::left
9085 \internal
9086*/
9087
9088/*!
9089 \property QQuickItem::right
9090 \internal
9091*/
9092
9093/*!
9094 \property QQuickItem::horizontalCenter
9095 \internal
9096*/
9097
9098/*!
9099 \property QQuickItem::top
9100 \internal
9101*/
9102
9103/*!
9104 \property QQuickItem::bottom
9105 \internal
9106*/
9107
9108/*!
9109 \property QQuickItem::verticalCenter
9110 \internal
9111*/
9112
9113/*!
9114 \property QQuickItem::baseline
9115 \internal
9116*/
9117
9118/*!
9119 \property QQuickItem::data
9120 \internal
9121*/
9122
9123/*!
9124 \property QQuickItem::resources
9125 \internal
9126*/
9127
9128/*!
9129 \reimp
9130 */
9131bool QQuickItem::event(QEvent *ev)
9132{
9133 Q_D(QQuickItem);
9134
9135 switch (ev->type()) {
9136#if QT_CONFIG(im)
9137 case QEvent::InputMethodQuery: {
9138 QInputMethodQueryEvent *query = static_cast<QInputMethodQueryEvent *>(ev);
9139 Qt::InputMethodQueries queries = query->queries();
9140 for (uint i = 0; i < 32; ++i) {
9141 Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
9142 if (q) {
9143 QVariant v = inputMethodQuery(query: q);
9144 query->setValue(query: q, value: v);
9145 }
9146 }
9147 query->accept();
9148 break;
9149 }
9150 case QEvent::InputMethod:
9151 inputMethodEvent(event: static_cast<QInputMethodEvent *>(ev));
9152 break;
9153#endif // im
9154 case QEvent::TouchBegin:
9155 case QEvent::TouchUpdate:
9156 case QEvent::TouchEnd:
9157 case QEvent::TouchCancel:
9158 case QEvent::MouseButtonPress:
9159 case QEvent::MouseButtonRelease:
9160 case QEvent::MouseButtonDblClick:
9161#if QT_CONFIG(wheelevent)
9162 case QEvent::Wheel:
9163#endif
9164 d->deliverPointerEvent(event: ev);
9165 break;
9166 case QEvent::StyleAnimationUpdate:
9167 if (isVisible()) {
9168 ev->accept();
9169 update();
9170 }
9171 break;
9172 case QEvent::HoverEnter:
9173 hoverEnterEvent(event: static_cast<QHoverEvent*>(ev));
9174 break;
9175 case QEvent::HoverLeave:
9176 hoverLeaveEvent(event: static_cast<QHoverEvent*>(ev));
9177 break;
9178 case QEvent::HoverMove:
9179 hoverMoveEvent(event: static_cast<QHoverEvent*>(ev));
9180 break;
9181 case QEvent::KeyPress:
9182 case QEvent::KeyRelease:
9183 d->deliverKeyEvent(e: static_cast<QKeyEvent*>(ev));
9184 break;
9185 case QEvent::ShortcutOverride:
9186 d->deliverShortcutOverrideEvent(event: static_cast<QKeyEvent*>(ev));
9187 break;
9188 case QEvent::FocusIn:
9189 focusInEvent(event: static_cast<QFocusEvent*>(ev));
9190 break;
9191 case QEvent::FocusOut:
9192 focusOutEvent(event: static_cast<QFocusEvent*>(ev));
9193 break;
9194 case QEvent::MouseMove:
9195 mouseMoveEvent(event: static_cast<QMouseEvent*>(ev));
9196 break;
9197#if QT_CONFIG(quick_draganddrop)
9198 case QEvent::DragEnter:
9199 dragEnterEvent(event: static_cast<QDragEnterEvent*>(ev));
9200 break;
9201 case QEvent::DragLeave:
9202 dragLeaveEvent(event: static_cast<QDragLeaveEvent*>(ev));
9203 break;
9204 case QEvent::DragMove:
9205 dragMoveEvent(event: static_cast<QDragMoveEvent*>(ev));
9206 break;
9207 case QEvent::Drop:
9208 dropEvent(event: static_cast<QDropEvent*>(ev));
9209 break;
9210#endif // quick_draganddrop
9211#if QT_CONFIG(gestures)
9212 case QEvent::NativeGesture:
9213 ev->ignore();
9214 break;
9215#endif // gestures
9216 case QEvent::LanguageChange:
9217 case QEvent::LocaleChange:
9218 for (QQuickItem *item : std::as_const(t&: d->childItems))
9219 QCoreApplication::sendEvent(receiver: item, event: ev);
9220 break;
9221 case QEvent::WindowActivate:
9222 case QEvent::WindowDeactivate:
9223 if (d->providesPalette())
9224 d->setCurrentColorGroup();
9225 for (QQuickItem *item : std::as_const(t&: d->childItems))
9226 QCoreApplication::sendEvent(receiver: item, event: ev);
9227 break;
9228 case QEvent::ApplicationPaletteChange:
9229 for (QQuickItem *item : std::as_const(t&: d->childItems))
9230 QCoreApplication::sendEvent(receiver: item, event: ev);
9231 break;
9232 case QEvent::ContextMenu:
9233 // ### Qt 7: add virtual contextMenuEvent (and to QWindow?)
9234 d->handleContextMenuEvent(event: static_cast<QContextMenuEvent*>(ev));
9235 break;
9236 default:
9237 return QObject::event(event: ev);
9238 }
9239
9240 return true;
9241}
9242
9243#ifndef QT_NO_DEBUG_STREAM
9244QDebug operator<<(QDebug debug,
9245#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
9246 const
9247#endif
9248 QQuickItem *item)
9249{
9250 QDebugStateSaver saver(debug);
9251 debug.nospace();
9252 if (!item) {
9253 debug << "QQuickItem(nullptr)";
9254 return debug;
9255 }
9256
9257 const QRectF rect(item->position(), QSizeF(item->width(), item->height()));
9258
9259 debug << item->metaObject()->className() << '(' << static_cast<void *>(item);
9260
9261 // Deferred properties will cause recursion when calling nameForObject
9262 // before the component is completed, so guard against this situation.
9263 if (item->isComponentComplete() && !QQmlData::wasDeleted(object: item)) {
9264 if (QQmlContext *context = qmlContext(item)) {
9265 const auto objectId = context->nameForObject(item);
9266 if (!objectId.isEmpty())
9267 debug << ", id=" << objectId;
9268 }
9269 }
9270 if (!item->objectName().isEmpty())
9271 debug << ", name=" << item->objectName();
9272 debug << ", parent=" << static_cast<void *>(item->parentItem())
9273 << ", geometry=";
9274 QtDebugUtils::formatQRect(debug, rect);
9275 if (const qreal z = item->z())
9276 debug << ", z=" << z;
9277 if (item->flags().testFlag(flag: QQuickItem::ItemIsViewport))
9278 debug << " \U0001f5bc"; // frame with picture
9279 if (item->flags().testFlag(flag: QQuickItem::ItemObservesViewport))
9280 debug << " \u23ff"; // observer eye
9281 debug << ')';
9282 return debug;
9283}
9284#endif // QT_NO_DEBUG_STREAM
9285
9286/*!
9287 \fn bool QQuickItem::isTextureProvider() const
9288
9289 Returns true if this item is a texture provider. The default
9290 implementation returns false.
9291
9292 This function can be called from any thread.
9293 */
9294
9295bool QQuickItem::isTextureProvider() const
9296{
9297#if QT_CONFIG(quick_shadereffect)
9298 Q_D(const QQuickItem);
9299 return d->extra.isAllocated() && d->extra->layer && d->extra->layer->effectSource() ?
9300 d->extra->layer->effectSource()->isTextureProvider() : false;
9301#else
9302 return false;
9303#endif
9304}
9305
9306/*!
9307 \fn QSGTextureProvider *QQuickItem::textureProvider() const
9308
9309 Returns the texture provider for an item. The default implementation
9310 returns \nullptr.
9311
9312 This function may only be called on the rendering thread.
9313 */
9314
9315QSGTextureProvider *QQuickItem::textureProvider() const
9316{
9317#if QT_CONFIG(quick_shadereffect)
9318 Q_D(const QQuickItem);
9319 return d->extra.isAllocated() && d->extra->layer && d->extra->layer->effectSource() ?
9320 d->extra->layer->effectSource()->textureProvider() : nullptr;
9321#else
9322 return 0;
9323#endif
9324}
9325
9326/*!
9327 \since 6.0
9328 \qmlproperty Palette QtQuick::Item::palette
9329
9330 This property holds the palette currently set for the item.
9331
9332 This property describes the item's requested palette. The palette is used by the item's style
9333 when rendering all controls, and is available as a means to ensure that custom controls can
9334 maintain consistency with the native platform's native look and feel. It's common that
9335 different platforms, or different styles, define different palettes for an application.
9336
9337 The default palette depends on the system environment. ApplicationWindow maintains a
9338 system/theme palette which serves as a default for all controls. There may also be special
9339 palette defaults for certain types of controls. You can also set the default palette for
9340 controls by either:
9341
9342 \list
9343 \li passing a custom palette to QGuiApplication::setPalette(), before loading any QML; or
9344 \li specifying the colors in the \l {Qt Quick Controls 2 Configuration File}
9345 {qtquickcontrols2.conf file}.
9346 \endlist
9347
9348 Items propagate explicit palette properties from parents to children. If you change a specific
9349 property on a items's palette, that property propagates to all of the item's children,
9350 overriding any system defaults for that property.
9351
9352 \code
9353 Item {
9354 palette {
9355 buttonText: "maroon"
9356 button: "lavender"
9357 }
9358
9359 Button {
9360 text: "Click Me"
9361 }
9362 }
9363 \endcode
9364
9365 \sa Window::palette, Popup::palette, ColorGroup, Palette, SystemPalette
9366*/
9367
9368#if QT_CONFIG(quick_shadereffect)
9369/*!
9370 \property QQuickItem::layer
9371 \internal
9372 */
9373QQuickItemLayer *QQuickItemPrivate::layer() const
9374{
9375 if (!extra.isAllocated() || !extra->layer) {
9376 extra.value().layer = new QQuickItemLayer(const_cast<QQuickItem *>(q_func()));
9377 if (!componentComplete)
9378 extra->layer->classBegin();
9379 }
9380 return extra->layer;
9381}
9382#endif
9383
9384/*!
9385 \internal
9386 Create a modified copy of the given \a event intended for delivery to this
9387 item, containing pointers to only the QEventPoint instances that are
9388 relevant to this item, and transforming their positions to this item's
9389 coordinate system.
9390
9391 Returns an invalid event with type \l QEvent::None if all points are
9392 stationary; or there are no points inside the item; or none of the points
9393 were pressed inside, neither the item nor any of its handlers is grabbing
9394 any of them, and \a isFiltering is false.
9395
9396 When \a isFiltering is true, it is assumed that the item cares about all
9397 points which are inside its bounds, because most filtering items need to
9398 monitor eventpoint movements until a drag threshold is exceeded or the
9399 requirements for a gesture to be recognized are met in some other way.
9400*/
9401void QQuickItemPrivate::localizedTouchEvent(const QTouchEvent *event, bool isFiltering, QMutableTouchEvent *localized)
9402{
9403 Q_Q(QQuickItem);
9404 QList<QEventPoint> touchPoints;
9405 QEventPoint::States eventStates;
9406
9407 bool anyPressOrReleaseInside = false;
9408 bool anyGrabber = false;
9409 for (auto &p : event->points()) {
9410 if (p.isAccepted())
9411 continue;
9412
9413 // include points where item is the grabber, or if any of its handlers is the grabber while some parent is filtering
9414 auto pointGrabber = event->exclusiveGrabber(point: p);
9415 bool isGrabber = (pointGrabber == q);
9416 if (!isGrabber && pointGrabber && isFiltering) {
9417 auto handlerGrabber = qmlobject_cast<QQuickPointerHandler *>(object: pointGrabber);
9418 if (handlerGrabber && handlerGrabber->parentItem() == q)
9419 isGrabber = true;
9420 }
9421 if (isGrabber)
9422 anyGrabber = true;
9423
9424 // include points inside the bounds if no other item is the grabber or if the item is filtering
9425 const auto localPos = q->mapFromScene(point: p.scenePosition());
9426 bool isInside = q->contains(point: localPos);
9427 bool hasAnotherGrabber = pointGrabber && pointGrabber != q;
9428 // if there's no exclusive grabber, look for passive grabbers during filtering
9429 if (isFiltering && !pointGrabber) {
9430 const auto pg = event->passiveGrabbers(point: p);
9431 if (!pg.isEmpty()) {
9432 // It seems unlikely to have multiple passive grabbers of one eventpoint with different grandparents.
9433 // So hopefully if we start from one passive grabber and go up the parent chain from there,
9434 // we will find any filtering parent items that exist.
9435 auto handler = qmlobject_cast<QQuickPointerHandler *>(object: pg.constFirst());
9436 if (handler)
9437 pointGrabber = handler->parentItem();
9438 }
9439 }
9440
9441 // filtering: (childMouseEventFilter) include points that are grabbed by children of the target item
9442 bool grabberIsChild = false;
9443 auto parent = qobject_cast<QQuickItem*>(o: pointGrabber);
9444 while (isFiltering && parent) {
9445 if (parent == q) {
9446 grabberIsChild = true;
9447 break;
9448 }
9449 parent = parent->parentItem();
9450 }
9451
9452 bool filterRelevant = isFiltering && grabberIsChild;
9453 if (!(isGrabber || (isInside && (!hasAnotherGrabber || isFiltering)) || filterRelevant))
9454 continue;
9455 if ((p.state() == QEventPoint::State::Pressed || p.state() == QEventPoint::State::Released) && isInside)
9456 anyPressOrReleaseInside = true;
9457 QEventPoint pCopy(p);
9458 eventStates |= p.state();
9459 if (p.state() == QEventPoint::State::Released)
9460 QMutableEventPoint::detach(p&: pCopy);
9461 QMutableEventPoint::setPosition(p&: pCopy, arg: localPos);
9462 touchPoints.append(t: std::move(pCopy));
9463 }
9464
9465 // Now touchPoints will have only points which are inside the item.
9466 // But if none of them were just pressed inside, and the item has no other reason to care, ignore them anyway.
9467 if (touchPoints.isEmpty() || (!anyPressOrReleaseInside && !anyGrabber && !isFiltering)) {
9468 *localized = QMutableTouchEvent(QEvent::None);
9469 return;
9470 }
9471
9472 // if all points have the same state, set the event type accordingly
9473 QEvent::Type eventType = event->type();
9474 switch (eventStates) {
9475 case QEventPoint::State::Pressed:
9476 eventType = QEvent::TouchBegin;
9477 break;
9478 case QEventPoint::State::Released:
9479 eventType = QEvent::TouchEnd;
9480 break;
9481 default:
9482 eventType = QEvent::TouchUpdate;
9483 break;
9484 }
9485
9486 QMutableTouchEvent ret(eventType, event->pointingDevice(), event->modifiers(), touchPoints);
9487 ret.setTarget(q);
9488 ret.setTimestamp(event->timestamp());
9489 ret.accept();
9490 *localized = ret;
9491}
9492
9493bool QQuickItemPrivate::hasPointerHandlers() const
9494{
9495 return extra.isAllocated() && !extra->pointerHandlers.isEmpty();
9496}
9497
9498bool QQuickItemPrivate::hasEnabledHoverHandlers() const
9499{
9500 if (!hasPointerHandlers())
9501 return false;
9502 for (QQuickPointerHandler *h : extra->pointerHandlers)
9503 if (auto *hh = qmlobject_cast<QQuickHoverHandler *>(object: h); hh && hh->enabled())
9504 return true;
9505 return false;
9506}
9507
9508void QQuickItemPrivate::addPointerHandler(QQuickPointerHandler *h)
9509{
9510 Q_ASSERT(h);
9511 Q_Q(QQuickItem);
9512 // Accept all buttons, and leave filtering to pointerEvent() and/or user JS,
9513 // because there can be multiple handlers...
9514 extra.value().acceptedMouseButtons = Qt::AllButtons;
9515 auto &handlers = extra.value().pointerHandlers;
9516 if (!handlers.contains(t: h))
9517 handlers.prepend(t: h);
9518 auto &res = extra.value().resourcesList;
9519 if (!res.contains(t: h)) {
9520 res.append(t: h);
9521 QObject::connect(sender: h, signal: &QObject::destroyed, context: q, slot: [this](QObject *o) {
9522 _q_resourceObjectDeleted(object: o);
9523 });
9524 }
9525}
9526
9527void QQuickItemPrivate::removePointerHandler(QQuickPointerHandler *h)
9528{
9529 Q_ASSERT(h);
9530 Q_Q(QQuickItem);
9531 auto &handlers = extra.value().pointerHandlers;
9532 handlers.removeOne(t: h);
9533 auto &res = extra.value().resourcesList;
9534 res.removeOne(t: h);
9535 QObject::disconnect(sender: h, signal: &QObject::destroyed, receiver: q, zero: nullptr);
9536 if (handlers.isEmpty())
9537 extra.value().acceptedMouseButtons = extra.value().acceptedMouseButtonsWithoutHandlers;
9538}
9539
9540/*! \internal
9541 Replaces any existing context menu with the given \a menu,
9542 and returns the one that was already set before, or \c nullptr.
9543*/
9544QObject *QQuickItemPrivate::setContextMenu(QObject *menu)
9545{
9546 QObject *ret = (extra.isAllocated() ? extra->contextMenu : nullptr);
9547 extra.value().contextMenu = menu;
9548 return ret;
9549}
9550
9551#if QT_CONFIG(quick_shadereffect)
9552QQuickItemLayer::QQuickItemLayer(QQuickItem *item)
9553 : m_item(item)
9554 , m_enabled(false)
9555 , m_mipmap(false)
9556 , m_smooth(false)
9557 , m_live(true)
9558 , m_componentComplete(true)
9559 , m_wrapMode(QQuickShaderEffectSource::ClampToEdge)
9560 , m_format(QQuickShaderEffectSource::RGBA8)
9561 , m_name("source")
9562 , m_effectComponent(nullptr)
9563 , m_effect(nullptr)
9564 , m_effectSource(nullptr)
9565 , m_textureMirroring(QQuickShaderEffectSource::MirrorVertically)
9566 , m_samples(0)
9567{
9568}
9569
9570QQuickItemLayer::~QQuickItemLayer()
9571{
9572 delete m_effectSource;
9573 delete m_effect;
9574}
9575
9576/*!
9577 \qmlproperty bool QtQuick::Item::layer.enabled
9578
9579 Holds whether the item is layered or not. Layering is disabled by default.
9580
9581 A layered item is rendered into an offscreen surface and cached until
9582 it is changed. Enabling layering for complex QML item hierarchies can
9583 sometimes be an optimization.
9584
9585 None of the other layer properties have any effect when the layer
9586 is disabled.
9587
9588 \sa {Item Layers}
9589 */
9590void QQuickItemLayer::setEnabled(bool e)
9591{
9592 if (e == m_enabled)
9593 return;
9594 m_enabled = e;
9595 if (m_componentComplete) {
9596 if (m_enabled)
9597 activate();
9598 else
9599 deactivate();
9600 }
9601
9602 emit enabledChanged(enabled: e);
9603}
9604
9605void QQuickItemLayer::classBegin()
9606{
9607 Q_ASSERT(!m_effectSource);
9608 Q_ASSERT(!m_effect);
9609 m_componentComplete = false;
9610}
9611
9612void QQuickItemLayer::componentComplete()
9613{
9614 Q_ASSERT(!m_componentComplete);
9615 m_componentComplete = true;
9616 if (m_enabled)
9617 activate();
9618}
9619
9620void QQuickItemLayer::activate()
9621{
9622 Q_ASSERT(!m_effectSource);
9623 m_effectSource = new QQuickShaderEffectSource();
9624 QQuickItemPrivate::get(item: m_effectSource)->setTransparentForPositioner(true);
9625
9626 QQuickItem *parentItem = m_item->parentItem();
9627 if (parentItem) {
9628 m_effectSource->setParentItem(parentItem);
9629 m_effectSource->stackAfter(sibling: m_item);
9630 }
9631
9632 m_effectSource->setSourceItem(m_item);
9633 m_effectSource->setHideSource(true);
9634 m_effectSource->setSmooth(m_smooth);
9635 m_effectSource->setLive(m_live);
9636 m_effectSource->setTextureSize(m_size);
9637 m_effectSource->setSourceRect(m_sourceRect);
9638 m_effectSource->setMipmap(m_mipmap);
9639 m_effectSource->setWrapMode(m_wrapMode);
9640 m_effectSource->setFormat(m_format);
9641 m_effectSource->setTextureMirroring(m_textureMirroring);
9642 m_effectSource->setSamples(m_samples);
9643
9644 if (m_effectComponent)
9645 activateEffect();
9646
9647 m_effectSource->setVisible(m_item->isVisible() && !m_effect);
9648
9649 updateZ();
9650 updateGeometry();
9651 updateOpacity();
9652 updateMatrix();
9653
9654 QQuickItemPrivate *id = QQuickItemPrivate::get(item: m_item);
9655 id->addItemChangeListener(listener: this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Opacity | QQuickItemPrivate::Parent | QQuickItemPrivate::Visibility | QQuickItemPrivate::SiblingOrder);
9656}
9657
9658void QQuickItemLayer::deactivate()
9659{
9660 Q_ASSERT(m_effectSource);
9661
9662 if (m_effectComponent)
9663 deactivateEffect();
9664
9665 delete m_effectSource;
9666 m_effectSource = nullptr;
9667
9668 QQuickItemPrivate *id = QQuickItemPrivate::get(item: m_item);
9669 id->removeItemChangeListener(listener: this, types: QQuickItemPrivate::Geometry | QQuickItemPrivate::Opacity | QQuickItemPrivate::Parent | QQuickItemPrivate::Visibility | QQuickItemPrivate::SiblingOrder);
9670}
9671
9672void QQuickItemLayer::activateEffect()
9673{
9674 Q_ASSERT(m_effectSource);
9675 Q_ASSERT(m_effectComponent);
9676 Q_ASSERT(!m_effect);
9677
9678 QObject *created = m_effectComponent->beginCreate(m_effectComponent->creationContext());
9679 m_effect = qobject_cast<QQuickItem *>(o: created);
9680 if (!m_effect) {
9681 qWarning(msg: "Item: layer.effect is not a QML Item.");
9682 m_effectComponent->completeCreate();
9683 delete created;
9684 return;
9685 }
9686 QQuickItem *parentItem = m_item->parentItem();
9687 if (parentItem) {
9688 m_effect->setParentItem(parentItem);
9689 m_effect->stackAfter(sibling: m_effectSource);
9690 }
9691 m_effect->setVisible(m_item->isVisible());
9692 m_effect->setProperty(name: m_name, value: QVariant::fromValue<QObject *>(value: m_effectSource));
9693 QQuickItemPrivate::get(item: m_effect)->setTransparentForPositioner(true);
9694 m_effectComponent->completeCreate();
9695}
9696
9697void QQuickItemLayer::deactivateEffect()
9698{
9699 Q_ASSERT(m_effectSource);
9700 Q_ASSERT(m_effectComponent);
9701
9702 delete m_effect;
9703 m_effect = nullptr;
9704}
9705
9706
9707/*!
9708 \qmlproperty Component QtQuick::Item::layer.effect
9709
9710 Holds the effect that is applied to this layer.
9711
9712 The effect is typically a \l ShaderEffect component, although any \l Item component can be
9713 assigned. The effect should have a source texture property with a name matching \l layer.samplerName.
9714
9715 \sa layer.samplerName, {Item Layers}
9716 */
9717
9718void QQuickItemLayer::setEffect(QQmlComponent *component)
9719{
9720 if (component == m_effectComponent)
9721 return;
9722
9723 bool updateNeeded = false;
9724 if (m_effectSource && m_effectComponent) {
9725 deactivateEffect();
9726 updateNeeded = true;
9727 }
9728
9729 m_effectComponent = component;
9730
9731 if (m_effectSource && m_effectComponent) {
9732 activateEffect();
9733 updateNeeded = true;
9734 }
9735
9736 if (updateNeeded) {
9737 updateZ();
9738 updateGeometry();
9739 updateOpacity();
9740 updateMatrix();
9741 m_effectSource->setVisible(m_item->isVisible() && !m_effect);
9742 }
9743
9744 emit effectChanged(component);
9745}
9746
9747
9748/*!
9749 \qmlproperty bool QtQuick::Item::layer.mipmap
9750
9751 If this property is true, mipmaps are generated for the texture.
9752
9753 \note Some OpenGL ES 2 implementations do not support mipmapping of
9754 non-power-of-two textures.
9755
9756 \sa {Item Layers}
9757 */
9758
9759void QQuickItemLayer::setMipmap(bool mipmap)
9760{
9761 if (mipmap == m_mipmap)
9762 return;
9763 m_mipmap = mipmap;
9764
9765 if (m_effectSource)
9766 m_effectSource->setMipmap(m_mipmap);
9767
9768 emit mipmapChanged(mipmap);
9769}
9770
9771
9772/*!
9773 \qmlproperty enumeration QtQuick::Item::layer.format
9774
9775 This property defines the format of the backing texture.
9776 Modifying this property makes most sense when the \a layer.effect is also
9777 specified.
9778
9779 \value ShaderEffectSource.RGBA8
9780 \value ShaderEffectSource.RGBA16F
9781 \value ShaderEffectSource.RGBA32F
9782 \value ShaderEffectSource.Alpha Starting with Qt 6.0, this value is not in use and has the same effect as \c RGBA8 in practice.
9783 \value ShaderEffectSource.RGB Starting with Qt 6.0, this value is not in use and has the same effect as \c RGBA8 in practice.
9784 \value ShaderEffectSource.RGBA Starting with Qt 6.0, this value is not in use and has the same effect as \c RGBA8 in practice.
9785
9786 \sa {Item Layers}
9787 */
9788
9789void QQuickItemLayer::setFormat(QQuickShaderEffectSource::Format f)
9790{
9791 if (f == m_format)
9792 return;
9793 m_format = f;
9794
9795 if (m_effectSource)
9796 m_effectSource->setFormat(m_format);
9797
9798 emit formatChanged(format: m_format);
9799}
9800
9801
9802/*!
9803 \qmlproperty rect QtQuick::Item::layer.sourceRect
9804
9805 This property defines the rectangular area of the item that should be
9806 rendered into the texture. The source rectangle can be larger than
9807 the item itself. If the rectangle is null, which is the default,
9808 then the whole item is rendered to the texture.
9809
9810 \sa {Item Layers}
9811 */
9812
9813void QQuickItemLayer::setSourceRect(const QRectF &sourceRect)
9814{
9815 if (sourceRect == m_sourceRect)
9816 return;
9817 m_sourceRect = sourceRect;
9818
9819 if (m_effectSource)
9820 m_effectSource->setSourceRect(m_sourceRect);
9821
9822 emit sourceRectChanged(sourceRect);
9823}
9824
9825/*!
9826 \qmlproperty bool QtQuick::Item::layer.smooth
9827
9828 Holds whether the layer is smoothly transformed. When enabled, sampling the
9829 layer's texture is performed using \c linear interpolation, while
9830 non-smooth results in using the \c nearest filtering mode.
9831
9832 By default, this property is set to \c false.
9833
9834 \sa {Item Layers}
9835 */
9836
9837void QQuickItemLayer::setSmooth(bool s)
9838{
9839 if (m_smooth == s)
9840 return;
9841 m_smooth = s;
9842
9843 if (m_effectSource)
9844 m_effectSource->setSmooth(m_smooth);
9845
9846 emit smoothChanged(smooth: s);
9847}
9848
9849/*!
9850 \qmlproperty bool QtQuick::Item::layer.live
9851 \since 6.5
9852
9853 When this property is true the layer texture is updated whenever the
9854 item updates. Otherwise it will always be a frozen image.
9855
9856 By default, this property is set to \c true.
9857
9858 \sa {Item Layers}
9859 */
9860
9861void QQuickItemLayer::setLive(bool live)
9862{
9863 if (m_live == live)
9864 return;
9865 m_live = live;
9866
9867 if (m_effectSource)
9868 m_effectSource->setLive(m_live);
9869
9870 emit liveChanged(live);
9871}
9872
9873/*!
9874 \qmlproperty size QtQuick::Item::layer.textureSize
9875
9876 This property holds the requested pixel size of the layers texture. If it is empty,
9877 which is the default, the size of the item is used.
9878
9879 \note Some platforms have a limit on how small framebuffer objects can be,
9880 which means the actual texture size might be larger than the requested
9881 size.
9882
9883 \sa {Item Layers}
9884 */
9885
9886void QQuickItemLayer::setSize(const QSize &size)
9887{
9888 if (size == m_size)
9889 return;
9890 m_size = size;
9891
9892 if (m_effectSource)
9893 m_effectSource->setTextureSize(size);
9894
9895 emit sizeChanged(size);
9896}
9897
9898/*!
9899 \qmlproperty enumeration QtQuick::Item::layer.wrapMode
9900
9901 This property defines the wrap modes associated with the texture.
9902 Modifying this property makes most sense when the \a layer.effect is
9903 specified.
9904
9905 \value ShaderEffectSource.ClampToEdge GL_CLAMP_TO_EDGE both horizontally and vertically
9906 \value ShaderEffectSource.RepeatHorizontally GL_REPEAT horizontally, GL_CLAMP_TO_EDGE vertically
9907 \value ShaderEffectSource.RepeatVertically GL_CLAMP_TO_EDGE horizontally, GL_REPEAT vertically
9908 \value ShaderEffectSource.Repeat GL_REPEAT both horizontally and vertically
9909
9910 \note Some OpenGL ES 2 implementations do not support the GL_REPEAT
9911 wrap mode with non-power-of-two textures.
9912
9913 \sa {Item Layers}
9914 */
9915
9916void QQuickItemLayer::setWrapMode(QQuickShaderEffectSource::WrapMode mode)
9917{
9918 if (mode == m_wrapMode)
9919 return;
9920 m_wrapMode = mode;
9921
9922 if (m_effectSource)
9923 m_effectSource->setWrapMode(m_wrapMode);
9924
9925 emit wrapModeChanged(mode);
9926}
9927
9928/*!
9929 \qmlproperty enumeration QtQuick::Item::layer.textureMirroring
9930 \since 5.6
9931
9932 This property defines how the generated texture should be mirrored.
9933 The default value is \c{ShaderEffectSource.MirrorVertically}.
9934 Custom mirroring can be useful if the generated texture is directly accessed by custom shaders,
9935 such as those specified by ShaderEffect. If no effect is specified for the layered
9936 item, mirroring has no effect on the UI representation of the item.
9937
9938 \value ShaderEffectSource.NoMirroring No mirroring
9939 \value ShaderEffectSource.MirrorHorizontally The generated texture is flipped along X-axis.
9940 \value ShaderEffectSource.MirrorVertically The generated texture is flipped along Y-axis.
9941 */
9942
9943void QQuickItemLayer::setTextureMirroring(QQuickShaderEffectSource::TextureMirroring mirroring)
9944{
9945 if (mirroring == m_textureMirroring)
9946 return;
9947 m_textureMirroring = mirroring;
9948
9949 if (m_effectSource)
9950 m_effectSource->setTextureMirroring(m_textureMirroring);
9951
9952 emit textureMirroringChanged(mirroring);
9953}
9954
9955/*!
9956 \qmlproperty enumeration QtQuick::Item::layer.samples
9957 \since 5.10
9958
9959 This property allows requesting multisampled rendering in the layer.
9960
9961 By default multisampling is enabled whenever multisampling is
9962 enabled for the entire window, assuming the scenegraph renderer in
9963 use and the underlying graphics API supports this.
9964
9965 By setting the value to 2, 4, etc. multisampled rendering can be requested
9966 for a part of the scene without enabling multisampling for the entire
9967 scene. This way multisampling is applied only to a given subtree, which can
9968 lead to significant performance gains since multisampling is not applied to
9969 other parts of the scene.
9970
9971 \note Enabling multisampling can be potentially expensive regardless of the
9972 layer's size, as it incurs a hardware and driver dependent performance and
9973 memory cost.
9974
9975 \note This property is only functional when support for multisample
9976 renderbuffers and framebuffer blits is available. Otherwise the value is
9977 silently ignored.
9978 */
9979
9980void QQuickItemLayer::setSamples(int count)
9981{
9982 if (m_samples == count)
9983 return;
9984
9985 m_samples = count;
9986
9987 if (m_effectSource)
9988 m_effectSource->setSamples(m_samples);
9989
9990 emit samplesChanged(count);
9991}
9992
9993/*!
9994 \qmlproperty string QtQuick::Item::layer.samplerName
9995
9996 Holds the name of the effect's source texture property.
9997
9998 This value must match the name of the effect's source texture property
9999 so that the Item can pass the layer's offscreen surface to the effect correctly.
10000
10001 \sa layer.effect, ShaderEffect, {Item Layers}
10002 */
10003
10004void QQuickItemLayer::setName(const QByteArray &name) {
10005 if (m_name == name)
10006 return;
10007 if (m_effect) {
10008 m_effect->setProperty(name: m_name, value: QVariant());
10009 m_effect->setProperty(name, value: QVariant::fromValue<QObject *>(value: m_effectSource));
10010 }
10011 m_name = name;
10012 emit nameChanged(name);
10013}
10014
10015void QQuickItemLayer::itemOpacityChanged(QQuickItem *item)
10016{
10017 Q_UNUSED(item);
10018 updateOpacity();
10019}
10020
10021void QQuickItemLayer::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
10022{
10023 updateGeometry();
10024}
10025
10026void QQuickItemLayer::itemParentChanged(QQuickItem *item, QQuickItem *parent)
10027{
10028 Q_UNUSED(item);
10029 Q_ASSERT(item == m_item);
10030 Q_ASSERT(parent != m_effectSource);
10031 Q_ASSERT(parent == nullptr || parent != m_effect);
10032
10033 m_effectSource->setParentItem(parent);
10034 if (parent)
10035 m_effectSource->stackAfter(sibling: m_item);
10036
10037 if (m_effect) {
10038 m_effect->setParentItem(parent);
10039 if (parent)
10040 m_effect->stackAfter(sibling: m_effectSource);
10041 }
10042}
10043
10044void QQuickItemLayer::itemSiblingOrderChanged(QQuickItem *)
10045{
10046 m_effectSource->stackAfter(sibling: m_item);
10047 if (m_effect)
10048 m_effect->stackAfter(sibling: m_effectSource);
10049}
10050
10051void QQuickItemLayer::itemVisibilityChanged(QQuickItem *)
10052{
10053 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
10054 if (!l)
10055 return;
10056 l->setVisible(m_item->isVisible());
10057}
10058
10059void QQuickItemLayer::updateZ()
10060{
10061 if (!m_componentComplete || !m_enabled)
10062 return;
10063 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
10064 if (!l)
10065 return;
10066 l->setZ(m_item->z());
10067}
10068
10069void QQuickItemLayer::updateOpacity()
10070{
10071 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
10072 if (!l)
10073 return;
10074 l->setOpacity(m_item->opacity());
10075}
10076
10077void QQuickItemLayer::updateGeometry()
10078{
10079 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
10080 if (!l)
10081 return;
10082 // Avoid calling QQuickImage::boundingRect() or other overrides
10083 // which may not be up-to-date at this time (QTBUG-104442, 104536)
10084 QRectF bounds = m_item->QQuickItem::boundingRect();
10085 l->setSize(bounds.size());
10086 l->setPosition(bounds.topLeft() + m_item->position());
10087}
10088
10089void QQuickItemLayer::updateMatrix()
10090{
10091 // Called directly from transformChanged(), so needs some extra
10092 // checks.
10093 if (!m_componentComplete || !m_enabled)
10094 return;
10095 QQuickItem *l = m_effect ? (QQuickItem *) m_effect : (QQuickItem *) m_effectSource;
10096 if (!l)
10097 return;
10098 QQuickItemPrivate *ld = QQuickItemPrivate::get(item: l);
10099 l->setScale(m_item->scale());
10100 l->setRotation(m_item->rotation());
10101 ld->transforms = QQuickItemPrivate::get(item: m_item)->transforms;
10102 if (ld->origin() != QQuickItemPrivate::get(item: m_item)->origin())
10103 ld->extra.value().origin = QQuickItemPrivate::get(item: m_item)->origin();
10104 ld->dirty(type: QQuickItemPrivate::Transform);
10105}
10106#endif // quick_shadereffect
10107
10108QQuickItemPrivate::ExtraData::ExtraData()
10109: z(0), scale(1), rotation(0), opacity(1),
10110 contents(nullptr), screenAttached(nullptr), layoutDirectionAttached(nullptr),
10111 enterKeyAttached(nullptr),
10112 keyHandler(nullptr), contextMenu(nullptr),
10113#if QT_CONFIG(quick_shadereffect)
10114 layer(nullptr),
10115#endif
10116 effectRefCount(0), hideRefCount(0),
10117 recursiveEffectRefCount(0),
10118 opacityNode(nullptr), clipNode(nullptr), rootNode(nullptr),
10119 origin(QQuickItem::Center),
10120 transparentForPositioner(false)
10121{
10122}
10123
10124
10125#if QT_CONFIG(accessibility)
10126QAccessible::Role QQuickItemPrivate::effectiveAccessibleRole() const
10127{
10128 Q_Q(const QQuickItem);
10129 auto *attached = qmlAttachedPropertiesObject<QQuickAccessibleAttached>(obj: q, create: false);
10130 auto role = QAccessible::NoRole;
10131 if (auto *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(object: attached))
10132 role = accessibleAttached->role();
10133 if (role == QAccessible::NoRole)
10134 role = accessibleRole();
10135 return role;
10136}
10137
10138QAccessible::Role QQuickItemPrivate::accessibleRole() const
10139{
10140 return QAccessible::NoRole;
10141}
10142#endif
10143
10144// helper code to let a visual parent mark its visual children for the garbage collector
10145
10146namespace QV4 {
10147namespace Heap {
10148struct QQuickItemWrapper : public QObjectWrapper {
10149 static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack);
10150};
10151}
10152}
10153
10154struct QQuickItemWrapper : public QV4::QObjectWrapper {
10155 V4_OBJECT2(QQuickItemWrapper, QV4::QObjectWrapper)
10156};
10157
10158DEFINE_OBJECT_VTABLE(QQuickItemWrapper);
10159
10160void QV4::Heap::QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack)
10161{
10162 QObjectWrapper *This = static_cast<QObjectWrapper *>(that);
10163 if (QQuickItem *item = static_cast<QQuickItem*>(This->object())) {
10164 for (QQuickItem *child : std::as_const(t&: QQuickItemPrivate::get(item)->childItems))
10165 QV4::QObjectWrapper::markWrapper(object: child, markStack);
10166 }
10167 QObjectWrapper::markObjects(that, markStack);
10168}
10169
10170quint64 QQuickItemPrivate::_q_createJSWrapper(QQmlV4ExecutionEnginePtr engine)
10171{
10172 return (engine->memoryManager->allocate<QQuickItemWrapper>(args: q_func()))->asReturnedValue();
10173}
10174
10175QDebug operator<<(QDebug debug, const QQuickItemPrivate::ChangeListener &listener)
10176{
10177 QDebugStateSaver stateSaver(debug);
10178 debug.nospace() << "ChangeListener listener=" << listener.listener << " types=" << listener.types;
10179 return debug;
10180}
10181
10182//! \internal
10183QPointF QQuickItem::mapFromItem(const QQuickItem *item, qreal x, qreal y)
10184{ return mapFromItem(item, point: QPointF(x, y) ); }
10185
10186//! \internal
10187QRectF QQuickItem::mapFromItem(const QQuickItem *item, const QRectF &rect) const
10188{ return mapRectFromItem(item, rect); }
10189
10190//! \internal
10191QRectF QQuickItem::mapFromItem(const QQuickItem *item, qreal x, qreal y, qreal width, qreal height) const
10192{ return mapFromItem(item, rect: QRectF(x, y, width, height)); }
10193
10194//! \internal
10195QPointF QQuickItem::mapToItem(const QQuickItem *item, qreal x, qreal y)
10196{ return mapToItem(item, point: QPointF(x, y)); }
10197
10198//! \internal
10199QRectF QQuickItem::mapToItem(const QQuickItem *item, const QRectF &rect) const
10200{ return mapRectToItem(item, rect); }
10201
10202//! \internal
10203QRectF QQuickItem::mapToItem(const QQuickItem *item, qreal x, qreal y, qreal width, qreal height) const
10204{ return mapToItem(item, rect: QRectF(x, y, width, height)); }
10205
10206//! \internal
10207QPointF QQuickItem::mapToGlobal(qreal x, qreal y) const
10208{ return mapToGlobal(point: QPointF(x, y)); }
10209
10210//! \internal
10211QPointF QQuickItem::mapFromGlobal(qreal x, qreal y) const
10212{ return mapFromGlobal(point: QPointF(x, y)); }
10213
10214//! \internal
10215QQuickItemChangeListener::~QQuickItemChangeListener() = default;
10216
10217QT_END_NAMESPACE
10218
10219#include <moc_qquickitem.cpp>
10220
10221#include "moc_qquickitem_p.cpp"
10222

source code of qtdeclarative/src/quick/items/qquickitem.cpp