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