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