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