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

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