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