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