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