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