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