Avoid direct GL calls in Quick
[qt:qtdeclarative.git] / src / quick / items / qquickwindow.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtQuick module of the Qt Toolkit.
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 Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquickwindow.h"
43 #include "qquickwindow_p.h"
44
45 #include "qquickitem.h"
46 #include "qquickitem_p.h"
47 #include "qquickevents_p_p.h"
48
49 #include <private/qquickdrag_p.h>
50
51 #include <QtQuick/private/qsgrenderer_p.h>
52 #include <QtQuick/private/qsgtexture_p.h>
53 #include <private/qsgrenderloop_p.h>
54 #include <private/qquickrendercontrol_p.h>
55 #include <private/qquickanimatorcontroller_p.h>
56
57 #include <private/qguiapplication_p.h>
58 #include <QtGui/QInputMethod>
59
60 #include <private/qabstractanimation_p.h>
61
62 #include <QtGui/qpainter.h>
63 #include <QtGui/qevent.h>
64 #include <QtGui/qmatrix4x4.h>
65 #include <QtGui/qstylehints.h>
66 #include <QtCore/qvarlengtharray.h>
67 #include <QtCore/qabstractanimation.h>
68 #include <QtCore/QLibraryInfo>
69 #include <QtQml/qqmlincubator.h>
70
71 #include <QtQuick/private/qquickpixmapcache_p.h>
72
73 #include <private/qqmlprofilerservice_p.h>
74 #include <private/qqmlmemoryprofiler_p.h>
75
76 QT_BEGIN_NAMESPACE
77
78 Q_LOGGING_CATEGORY(DBG_TOUCH, "qt.quick.touch");
79 Q_LOGGING_CATEGORY(DBG_MOUSE, "qt.quick.mouse");
80 Q_LOGGING_CATEGORY(DBG_FOCUS, "qt.quick.focus");
81 Q_LOGGING_CATEGORY(DBG_DIRTY, "qt.quick.dirty");
82
83 extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
84
85 bool QQuickWindowPrivate::defaultAlphaBuffer = false;
86 bool QQuickWindowPrivate::defaultFormatInitialized = false;
87 QSurfaceFormat QQuickWindowPrivate::defaultFormat;
88
89 void QQuickWindowPrivate::updateFocusItemTransform()
90 {
91     Q_Q(QQuickWindow);
92 #ifndef QT_NO_IM
93     QQuickItem *focus = q->activeFocusItem();
94     if (focus && qApp->focusObject() == focus) {
95         QQuickItemPrivate *focusPrivate = QQuickItemPrivate::get(focus);
96         qApp->inputMethod()->setInputItemTransform(focusPrivate->itemToWindowTransform());
97         qApp->inputMethod()->setInputItemRectangle(QRectF(0, 0, focusPrivate->width, focusPrivate->height));
98     }
99 #endif
100 }
101
102 class QQuickWindowIncubationController : public QObject, public QQmlIncubationController
103 {
104     Q_OBJECT
105
106 public:
107     QQuickWindowIncubationController(QSGRenderLoop *loop)
108         : m_renderLoop(loop), m_timer(0)
109     {
110         // Allow incubation for 1/3 of a frame.
111         m_incubation_time = qMax(1, int(1000 / QGuiApplication::primaryScreen()->refreshRate()) / 3);
112
113         QAnimationDriver *animationDriver = m_renderLoop->animationDriver();
114         if (animationDriver) {
115             connect(animationDriver, SIGNAL(stopped()), this, SLOT(animationStopped()));
116             connect(m_renderLoop, SIGNAL(timeToIncubate()), this, SLOT(incubate()));
117         }
118     }
119
120 protected:
121     void timerEvent(QTimerEvent *)
122     {
123         killTimer(m_timer);
124         m_timer = 0;
125         incubate();
126     }
127
128     void incubateAgain() {
129         if (m_timer == 0) {
130             // Wait for a while before processing the next batch. Using a
131             // timer to avoid starvation of system events.
132             m_timer = startTimer(m_incubation_time);
133         }
134     }
135
136 public slots:
137     void incubate() {
138         if (incubatingObjectCount()) {
139             if (m_renderLoop->interleaveIncubation()) {
140                 incubateFor(m_incubation_time);
141             } else {
142                 incubateFor(m_incubation_time * 2);
143                 if (incubatingObjectCount())
144                     incubateAgain();
145             }
146         }
147     }
148
149     void animationStopped() { incubate(); }
150
151 protected:
152     virtual void incubatingObjectCountChanged(int count)
153     {
154         if (count && !m_renderLoop->interleaveIncubation())
155             incubateAgain();
156     }
157
158 private:
159     QSGRenderLoop *m_renderLoop;
160     int m_incubation_time;
161     int m_timer;
162 };
163
164 #include "qquickwindow.moc"
165
166
167 #ifndef QT_NO_ACCESSIBILITY
168 /*!
169     Returns an accessibility interface for this window, or 0 if such an
170     interface cannot be created.
171 */
172 QAccessibleInterface *QQuickWindow::accessibleRoot() const
173 {
174     return QAccessible::queryAccessibleInterface(const_cast<QQuickWindow*>(this));
175 }
176 #endif
177
178
179 /*
180 Focus behavior
181 ==============
182
183 Prior to being added to a valid window items can set and clear focus with no
184 effect.  Only once items are added to a window (by way of having a parent set that
185 already belongs to a window) do the focus rules apply.  Focus goes back to
186 having no effect if an item is removed from a window.
187
188 When an item is moved into a new focus scope (either being added to a window
189 for the first time, or having its parent changed), if the focus scope already has
190 a scope focused item that takes precedence over the item being added.  Otherwise,
191 the focus of the added tree is used.  In the case of of a tree of items being
192 added to a window for the first time, which may have a conflicted focus state (two
193 or more items in one scope having focus set), the same rule is applied item by item -
194 thus the first item that has focus will get it (assuming the scope doesn't already
195 have a scope focused item), and the other items will have their focus cleared.
196 */
197
198 QQuickItem::UpdatePaintNodeData::UpdatePaintNodeData()
199 : transformNode(0)
200 {
201 }
202
203 QQuickRootItem::QQuickRootItem()
204 {
205 }
206
207 /*! \reimp */
208 void QQuickWindow::exposeEvent(QExposeEvent *)
209 {
210     Q_D(QQuickWindow);
211     if (d->windowManager)
212         d->windowManager->exposureChanged(this);
213 }
214
215 /*! \reimp */
216 void QQuickWindow::resizeEvent(QResizeEvent *ev)
217 {
218     Q_D(QQuickWindow);
219     if (d->contentItem)
220         d->contentItem->setSize(ev->size());
221     if (d->windowManager)
222         d->windowManager->resize(this);
223 }
224
225 /*! \reimp */
226 void QQuickWindow::showEvent(QShowEvent *)
227 {
228     Q_D(QQuickWindow);
229     if (d->windowManager)
230         d->windowManager->show(this);
231 }
232
233 /*! \reimp */
234 void QQuickWindow::hideEvent(QHideEvent *)
235 {
236     Q_D(QQuickWindow);
237     if (d->windowManager)
238         d->windowManager->hide(this);
239 }
240
241 /*! \reimp */
242 void QQuickWindow::focusOutEvent(QFocusEvent *ev)
243 {
244     Q_D(QQuickWindow);
245     d->contentItem->setFocus(false, ev->reason());
246 }
247
248 /*! \reimp */
249 void QQuickWindow::focusInEvent(QFocusEvent *ev)
250 {
251     Q_D(QQuickWindow);
252     d->contentItem->setFocus(true, ev->reason());
253     d->updateFocusItemTransform();
254 }
255
256 void QQuickWindowPrivate::polishItems()
257 {
258     int maxPolishCycles = 100000;
259
260     while (!itemsToPolish.isEmpty() && --maxPolishCycles > 0) {
261         QSet<QQuickItem *> itms = itemsToPolish;
262         itemsToPolish.clear();
263
264         for (QSet<QQuickItem *>::iterator it = itms.begin(); it != itms.end(); ++it) {
265             QQuickItem *item = *it;
266             QQuickItemPrivate::get(item)->polishScheduled = false;
267             item->updatePolish();
268         }
269     }
270
271     if (maxPolishCycles == 0)
272         qWarning("QQuickWindow: possible QQuickItem::polish() loop");
273
274     updateFocusItemTransform();
275 }
276
277 /*!
278  * Schedules the window to render another frame.
279  *
280  * Calling QQuickWindow::update() differs from QQuickItem::update() in that
281  * it always triggers a repaint, regardless of changes in the underlying
282  * scene graph or not.
283  */
284 void QQuickWindow::update()
285 {
286     Q_D(QQuickWindow);
287     if (d->windowManager)
288         d->windowManager->update(this);
289     else if (d->renderControl)
290         d->renderControl->update();
291 }
292
293 void forcePolishHelper(QQuickItem *item)
294 {
295     if (item->flags() & QQuickItem::ItemHasContents) {
296         item->polish();
297     }
298
299     QList <QQuickItem *> items = item->childItems();
300     for (int i=0; i<items.size(); ++i)
301         forcePolishHelper(items.at(i));
302 }
303
304 /*!
305     Schedules polish events on all items in the scene.
306 */
307 void QQuickWindow::forcePolish()
308 {
309     Q_D(QQuickWindow);
310     if (!screen())
311         return;
312     forcePolishHelper(d->contentItem);
313 }
314
315 void forceUpdate(QQuickItem *item)
316 {
317     if (item->flags() & QQuickItem::ItemHasContents)
318         item->update();
319     QQuickItemPrivate::get(item)->dirty(QQuickItemPrivate::ChildrenUpdateMask);
320
321     QList <QQuickItem *> items = item->childItems();
322     for (int i=0; i<items.size(); ++i)
323         forceUpdate(items.at(i));
324 }
325
326 void QQuickWindowPrivate::syncSceneGraph()
327 {
328     QML_MEMORY_SCOPE_STRING("SceneGraph");
329     Q_Q(QQuickWindow);
330
331     animationController->beforeNodeSync();
332
333     emit q->beforeSynchronizing();
334     if (!renderer) {
335         forceUpdate(contentItem);
336
337         QSGRootNode *rootNode = new QSGRootNode;
338         rootNode->appendChildNode(QQuickItemPrivate::get(contentItem)->itemNode());
339         renderer = context->createRenderer();
340         renderer->setRootNode(rootNode);
341     }
342
343     updateDirtyNodes();
344
345     animationController->afterNodeSync();
346
347     // Copy the current state of clearing from window into renderer.
348     renderer->setClearColor(clearColor);
349     QSGRenderer::ClearMode mode = QSGRenderer::ClearStencilBuffer | QSGRenderer::ClearDepthBuffer;
350     if (clearBeforeRendering)
351         mode |= QSGRenderer::ClearColorBuffer;
352     renderer->setClearMode(mode);
353
354     renderer->setCustomRenderMode(customRenderMode);
355
356     emit q->afterSynchronizing();
357     context->endSync();
358 }
359
360
361 void QQuickWindowPrivate::renderSceneGraph(const QSize &size)
362 {
363     QML_MEMORY_SCOPE_STRING("SceneGraph");
364     Q_Q(QQuickWindow);
365     if (!renderer)
366         return;
367
368     animationController->advance();
369     emit q->beforeRendering();
370     int fboId = 0;
371     const qreal devicePixelRatio = q->devicePixelRatio();
372     renderer->setDeviceRect(QRect(QPoint(0, 0), size * devicePixelRatio));
373     if (renderTargetId) {
374         fboId = renderTargetId;
375         renderer->setViewportRect(QRect(QPoint(0, 0), renderTargetSize));
376     } else {
377         renderer->setViewportRect(QRect(QPoint(0, 0), size * devicePixelRatio));
378     }
379     renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size));
380     renderer->setDevicePixelRatio(q->devicePixelRatio());
381
382     context->renderNextFrame(renderer, fboId);
383     emit q->afterRendering();
384 }
385
386 QQuickWindowPrivate::QQuickWindowPrivate()
387     : contentItem(0)
388     , activeFocusItem(0)
389     , mouseGrabberItem(0)
390 #ifndef QT_NO_CURSOR
391     , cursorItem(0)
392 #endif
393 #ifndef QT_NO_DRAGANDDROP
394     , dragGrabber(0)
395 #endif
396     , touchMouseId(-1)
397     , touchMousePressTimestamp(0)
398     , dirtyItemList(0)
399     , context(0)
400     , renderer(0)
401     , windowManager(0)
402     , renderControl(0)
403     , touchRecursionGuard(0)
404     , clearColor(Qt::white)
405     , clearBeforeRendering(true)
406     , persistentGLContext(true)
407     , persistentSceneGraph(true)
408     , lastWheelEventAccepted(false)
409     , componentCompleted(true)
410     , lastFocusReason(Qt::OtherFocusReason)
411     , renderTarget(0)
412     , renderTargetId(0)
413     , incubationController(0)
414 {
415 #ifndef QT_NO_DRAGANDDROP
416     dragGrabber = new QQuickDragGrabber;
417 #endif
418 }
419
420 QQuickWindowPrivate::~QQuickWindowPrivate()
421 {
422 }
423
424 void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
425 {
426     q_ptr = c;
427
428     Q_Q(QQuickWindow);
429
430     contentItem = new QQuickRootItem;
431     QQmlEngine::setObjectOwnership(contentItem, QQmlEngine::CppOwnership);
432     QQuickItemPrivate *contentItemPrivate = QQuickItemPrivate::get(contentItem);
433     contentItemPrivate->window = q;
434     contentItemPrivate->windowRefCount = 1;
435     contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
436     contentItem->setSize(q->size());
437
438     customRenderMode = qgetenv("QSG_VISUALIZE");
439     renderControl = control;
440     if (renderControl)
441         renderControl->setWindow(q);
442
443     if (!renderControl)
444         windowManager = QSGRenderLoop::instance();
445
446     Q_ASSERT(windowManager || renderControl);
447
448     QSGContext *sg;
449     if (renderControl) {
450         sg = renderControl->sceneGraphContext();
451         context = renderControl->renderContext(sg);
452     } else {
453         windowManager->addWindow(q);
454         sg = windowManager->sceneGraphContext();
455         context = windowManager->createRenderContext(sg);
456     }
457
458     q->setSurfaceType(QWindow::OpenGLSurface);
459     q->setFormat(q->defaultFormat());
460
461     animationController = new QQuickAnimatorController();
462     animationController->m_window = q;
463
464     delayedTouch = 0;
465
466     QObject::connect(context, SIGNAL(initialized()), q, SIGNAL(sceneGraphInitialized()), Qt::DirectConnection);
467     QObject::connect(context, SIGNAL(invalidated()), q, SIGNAL(sceneGraphInvalidated()), Qt::DirectConnection);
468     QObject::connect(context, SIGNAL(invalidated()), q, SLOT(cleanupSceneGraph()), Qt::DirectConnection);
469
470     QObject::connect(q, SIGNAL(focusObjectChanged(QObject*)), q, SIGNAL(activeFocusItemChanged()));
471     QObject::connect(q, SIGNAL(screenChanged(QScreen*)), q, SLOT(forcePolish()));
472 }
473
474 /*!
475     \property QQuickWindow::data
476     \internal
477 */
478
479 QQmlListProperty<QObject> QQuickWindowPrivate::data()
480 {
481     return QQmlListProperty<QObject>(q_func(), 0, QQuickWindowPrivate::data_append,
482                                              QQuickWindowPrivate::data_count,
483                                              QQuickWindowPrivate::data_at,
484                                              QQuickWindowPrivate::data_clear);
485 }
486
487 static QMouseEvent *touchToMouseEvent(QEvent::Type type, const QTouchEvent::TouchPoint &p, QTouchEvent *event, QQuickItem *item, bool transformNeeded = true)
488 {
489     // The touch point local position and velocity are not yet transformed.
490     QMouseEvent *me = new QMouseEvent(type, transformNeeded ? item->mapFromScene(p.scenePos()) : p.pos(), p.scenePos(), p.screenPos(),
491                                       Qt::LeftButton, (type == QEvent::MouseButtonRelease ? Qt::NoButton : Qt::LeftButton), event->modifiers());
492     me->setAccepted(true);
493     me->setTimestamp(event->timestamp());
494     QVector2D transformedVelocity = p.velocity();
495     if (transformNeeded) {
496         QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
497         QMatrix4x4 transformMatrix(itemPrivate->windowToItemTransform());
498         transformedVelocity = transformMatrix.mapVector(p.velocity()).toVector2D();
499     }
500     QGuiApplicationPrivate::setMouseEventCapsAndVelocity(me, event->device()->capabilities(), transformedVelocity);
501     QGuiApplicationPrivate::setMouseEventSource(me, Qt::MouseEventSynthesizedByQt);
502     return me;
503 }
504
505 bool QQuickWindowPrivate::checkIfDoubleClicked(ulong newPressEventTimestamp)
506 {
507     bool doubleClicked;
508
509     if (touchMousePressTimestamp == 0) {
510         // just initialize the variable
511         touchMousePressTimestamp = newPressEventTimestamp;
512         doubleClicked = false;
513     } else {
514         ulong timeBetweenPresses = newPressEventTimestamp - touchMousePressTimestamp;
515         ulong doubleClickInterval = static_cast<ulong>(qApp->styleHints()->
516                 mouseDoubleClickInterval());
517         doubleClicked = timeBetweenPresses < doubleClickInterval;
518         if (doubleClicked) {
519             touchMousePressTimestamp = 0;
520         } else {
521             touchMousePressTimestamp = newPressEventTimestamp;
522         }
523     }
524
525     return doubleClicked;
526 }
527
528 bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *event)
529 {
530     // For each point, check if it is accepted, if not, try the next point.
531     // Any of the fingers can become the mouse one.
532     // This can happen because a mouse area might not accept an event at some point but another.
533     for (int i = 0; i < event->touchPoints().count(); ++i) {
534         const QTouchEvent::TouchPoint &p = event->touchPoints().at(i);
535         // A new touch point
536         if (touchMouseId == -1 && p.state() & Qt::TouchPointPressed) {
537             QPointF pos = item->mapFromScene(p.scenePos());
538
539             // probably redundant, we check bounds in the calling function (matchingNewPoints)
540             if (!item->contains(pos))
541                 break;
542
543             // Store the id already here and restore it to -1 if the event does not get
544             // accepted. Cannot defer setting the new value because otherwise if the event
545             // handler spins the event loop all subsequent moves and releases get lost.
546             touchMouseId = p.id();
547             itemForTouchPointId[touchMouseId] = item;
548             QScopedPointer<QMouseEvent> mousePress(touchToMouseEvent(QEvent::MouseButtonPress, p, event, item));
549
550             // Send a single press and see if that's accepted
551             if (!mouseGrabberItem)
552                 item->grabMouse();
553             item->grabTouchPoints(QVector<int>() << touchMouseId);
554
555             QCoreApplication::sendEvent(item, mousePress.data());
556             event->setAccepted(mousePress->isAccepted());
557             if (!mousePress->isAccepted()) {
558                 touchMouseId = -1;
559                 if (itemForTouchPointId.value(p.id()) == item)
560                     itemForTouchPointId.remove(p.id());
561
562                 if (mouseGrabberItem == item)
563                     item->ungrabMouse();
564             }
565
566             if (mousePress->isAccepted() && checkIfDoubleClicked(event->timestamp())) {
567                 QScopedPointer<QMouseEvent> mouseDoubleClick(touchToMouseEvent(QEvent::MouseButtonDblClick, p, event, item));
568                 QCoreApplication::sendEvent(item, mouseDoubleClick.data());
569                 event->setAccepted(mouseDoubleClick->isAccepted());
570                 if (mouseDoubleClick->isAccepted()) {
571                     return true;
572                 } else {
573                     touchMouseId = -1;
574                 }
575             }
576             // The event was accepted, we are done.
577             if (mousePress->isAccepted())
578                 return true;
579             // The event was not accepted but touchMouseId was set.
580             if (touchMouseId != -1)
581                 return false;
582             // try the next point
583
584         // Touch point was there before and moved
585         } else if (p.id() == touchMouseId) {
586             if (p.state() & Qt::TouchPointMoved) {
587                 if (mouseGrabberItem) {
588                     QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event, mouseGrabberItem));
589                     QCoreApplication::sendEvent(item, me.data());
590                     event->setAccepted(me->isAccepted());
591                     if (me->isAccepted()) {
592                         itemForTouchPointId[p.id()] = mouseGrabberItem; // N.B. the mouseGrabberItem may be different after returning from sendEvent()
593                         return true;
594                     }
595                 } else {
596                     // no grabber, check if we care about mouse hover
597                     // FIXME: this should only happen once, not recursively... I'll ignore it just ignore hover now.
598                     // hover for touch???
599                     QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event, item));
600                     if (lastMousePosition.isNull())
601                         lastMousePosition = me->windowPos();
602                     QPointF last = lastMousePosition;
603                     lastMousePosition = me->windowPos();
604
605                     bool accepted = me->isAccepted();
606                     bool delivered = deliverHoverEvent(contentItem, me->windowPos(), last, me->modifiers(), accepted);
607                     if (!delivered) {
608                         //take care of any exits
609                         accepted = clearHover();
610                     }
611                     me->setAccepted(accepted);
612                     break;
613                 }
614             } else if (p.state() & Qt::TouchPointReleased) {
615                 // currently handled point was released
616                 touchMouseId = -1;
617                 if (mouseGrabberItem) {
618                     QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseButtonRelease, p, event, mouseGrabberItem));
619                     QCoreApplication::sendEvent(item, me.data());
620                     if (mouseGrabberItem) // might have ungrabbed due to event
621                         mouseGrabberItem->ungrabMouse();
622                     return me->isAccepted();
623                 }
624             }
625             break;
626         }
627     }
628     return false;
629 }
630
631 void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
632 {
633     Q_Q(QQuickWindow);
634     if (mouseGrabberItem == grabber)
635         return;
636
637     QQuickItem *oldGrabber = mouseGrabberItem;
638     mouseGrabberItem = grabber;
639
640     if (touchMouseId != -1) {
641         // update the touch item for mouse touch id to the new grabber
642         itemForTouchPointId.remove(touchMouseId);
643         if (grabber)
644             itemForTouchPointId[touchMouseId] = grabber;
645     }
646
647     if (oldGrabber) {
648         QEvent ev(QEvent::UngrabMouse);
649         q->sendEvent(oldGrabber, &ev);
650     }
651 }
652
653 void QQuickWindowPrivate::transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform)
654 {
655     QMatrix4x4 transformMatrix(transform);
656     for (int i=0; i<touchPoints.count(); i++) {
657         QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
658         touchPoint.setRect(transform.mapRect(touchPoint.sceneRect()));
659         touchPoint.setStartPos(transform.map(touchPoint.startScenePos()));
660         touchPoint.setLastPos(transform.map(touchPoint.lastScenePos()));
661         touchPoint.setVelocity(transformMatrix.mapVector(touchPoint.velocity()).toVector2D());
662     }
663 }
664
665
666 /*!
667 Translates the data in \a touchEvent to this window.  This method leaves the item local positions in
668 \a touchEvent untouched (these are filled in later).
669 */
670 void QQuickWindowPrivate::translateTouchEvent(QTouchEvent *touchEvent)
671 {
672     QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
673     for (int i = 0; i < touchPoints.count(); ++i) {
674         QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
675
676         touchPoint.setScreenRect(touchPoint.sceneRect());
677         touchPoint.setStartScreenPos(touchPoint.startScenePos());
678         touchPoint.setLastScreenPos(touchPoint.lastScenePos());
679
680         touchPoint.setSceneRect(touchPoint.rect());
681         touchPoint.setStartScenePos(touchPoint.startPos());
682         touchPoint.setLastScenePos(touchPoint.lastPos());
683
684         if (i == 0)
685             lastMousePosition = touchPoint.pos().toPoint();
686     }
687     touchEvent->setTouchPoints(touchPoints);
688 }
689
690
691 static inline bool windowHasFocus(QQuickWindow *win)
692 {
693     const QWindow *focusWindow = QGuiApplication::focusWindow();
694     return win == focusWindow || QQuickRenderControl::renderWindowFor(win) == focusWindow;
695 }
696
697 /*!
698 Set the focus inside \a scope to be \a item.
699 If the scope contains the active focus item, it will be changed to \a item.
700 Calls notifyFocusChangesRecur for all changed items.
701 */
702 void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions options)
703 {
704     Q_Q(QQuickWindow);
705
706     Q_ASSERT(item);
707     Q_ASSERT(scope || item == contentItem);
708
709     qCDebug(DBG_FOCUS) << "QQuickWindowPrivate::setFocusInScope():";
710     qCDebug(DBG_FOCUS) << "    scope:" << (QObject *)scope;
711     if (scope)
712         qCDebug(DBG_FOCUS) << "    scopeSubFocusItem:" << (QObject *)QQuickItemPrivate::get(scope)->subFocusItem;
713     qCDebug(DBG_FOCUS) << "    item:" << (QObject *)item;
714     qCDebug(DBG_FOCUS) << "    activeFocusItem:" << (QObject *)activeFocusItem;
715
716     QQuickItemPrivate *scopePrivate = scope ? QQuickItemPrivate::get(scope) : 0;
717     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
718
719     QQuickItem *currentActiveFocusItem = activeFocusItem;
720     QQuickItem *newActiveFocusItem = 0;
721
722     lastFocusReason = reason;
723
724     QVarLengthArray<QQuickItem *, 20> changed;
725
726     // Does this change the active focus?
727     if (item == contentItem || scopePrivate->activeFocus) {
728         QQuickItem *oldActiveFocusItem = 0;
729         oldActiveFocusItem = activeFocusItem;
730         if (item->isEnabled()) {
731             newActiveFocusItem = item;
732             while (newActiveFocusItem->isFocusScope()
733                    && newActiveFocusItem->scopedFocusItem()
734                    && newActiveFocusItem->scopedFocusItem()->isEnabled()) {
735                 newActiveFocusItem = newActiveFocusItem->scopedFocusItem();
736             }
737         } else {
738             newActiveFocusItem = scope;
739         }
740
741         if (oldActiveFocusItem) {
742 #ifndef QT_NO_IM
743             qApp->inputMethod()->commit();
744 #endif
745
746             activeFocusItem = 0;
747             QFocusEvent event(QEvent::FocusOut, reason);
748             q->sendEvent(oldActiveFocusItem, &event);
749
750             QQuickItem *afi = oldActiveFocusItem;
751             while (afi && afi != scope) {
752                 if (QQuickItemPrivate::get(afi)->activeFocus) {
753                     QQuickItemPrivate::get(afi)->activeFocus = false;
754                     changed << afi;
755                 }
756                 afi = afi->parentItem();
757             }
758         }
759     }
760
761     if (item != contentItem && !(options & DontChangeSubFocusItem)) {
762         QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem;
763         if (oldSubFocusItem) {
764             QQuickItemPrivate::get(oldSubFocusItem)->focus = false;
765             changed << oldSubFocusItem;
766         }
767
768         QQuickItemPrivate::get(item)->updateSubFocusItem(scope, true);
769     }
770
771     if (!(options & DontChangeFocusProperty)) {
772         if (item != contentItem || windowHasFocus(q)) {
773             itemPrivate->focus = true;
774             changed << item;
775         }
776     }
777
778     if (newActiveFocusItem && contentItem->hasFocus()) {
779         activeFocusItem = newActiveFocusItem;
780
781         QQuickItemPrivate::get(newActiveFocusItem)->activeFocus = true;
782         changed << newActiveFocusItem;
783
784         QQuickItem *afi = newActiveFocusItem->parentItem();
785         while (afi && afi != scope) {
786             if (afi->isFocusScope()) {
787                 QQuickItemPrivate::get(afi)->activeFocus = true;
788                 changed << afi;
789             }
790             afi = afi->parentItem();
791         }
792         updateFocusItemTransform();
793
794         QFocusEvent event(QEvent::FocusIn, reason);
795         q->sendEvent(newActiveFocusItem, &event);
796     }
797
798     if (activeFocusItem != currentActiveFocusItem)
799         emit q->focusObjectChanged(activeFocusItem);
800
801     if (!changed.isEmpty())
802         notifyFocusChangesRecur(changed.data(), changed.count() - 1);
803 }
804
805 void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions options)
806 {
807     Q_Q(QQuickWindow);
808
809     Q_ASSERT(item);
810     Q_ASSERT(scope || item == contentItem);
811
812     qCDebug(DBG_FOCUS) << "QQuickWindowPrivate::clearFocusInScope():";
813     qCDebug(DBG_FOCUS) << "    scope:" << (QObject *)scope;
814     qCDebug(DBG_FOCUS) << "    item:" << (QObject *)item;
815     qCDebug(DBG_FOCUS) << "    activeFocusItem:" << (QObject *)activeFocusItem;
816
817     QQuickItemPrivate *scopePrivate = 0;
818     if (scope) {
819         scopePrivate = QQuickItemPrivate::get(scope);
820         if ( !scopePrivate->subFocusItem )
821             return;//No focus, nothing to do.
822     }
823
824     QQuickItem *currentActiveFocusItem = activeFocusItem;
825     QQuickItem *oldActiveFocusItem = 0;
826     QQuickItem *newActiveFocusItem = 0;
827
828     lastFocusReason = reason;
829
830     QVarLengthArray<QQuickItem *, 20> changed;
831
832     Q_ASSERT(item == contentItem || item == scopePrivate->subFocusItem);
833
834     // Does this change the active focus?
835     if (item == contentItem || scopePrivate->activeFocus) {
836         oldActiveFocusItem = activeFocusItem;
837         newActiveFocusItem = scope;
838
839 #ifndef QT_NO_IM
840         qApp->inputMethod()->commit();
841 #endif
842
843         activeFocusItem = 0;
844
845         if (oldActiveFocusItem) {
846             QFocusEvent event(QEvent::FocusOut, reason);
847             q->sendEvent(oldActiveFocusItem, &event);
848
849             QQuickItem *afi = oldActiveFocusItem;
850             while (afi && afi != scope) {
851                 if (QQuickItemPrivate::get(afi)->activeFocus) {
852                     QQuickItemPrivate::get(afi)->activeFocus = false;
853                     changed << afi;
854                 }
855                 afi = afi->parentItem();
856             }
857         }
858     }
859
860     if (item != contentItem && !(options & DontChangeSubFocusItem)) {
861         QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem;
862         if (oldSubFocusItem && !(options & DontChangeFocusProperty)) {
863             QQuickItemPrivate::get(oldSubFocusItem)->focus = false;
864             changed << oldSubFocusItem;
865         }
866
867         QQuickItemPrivate::get(item)->updateSubFocusItem(scope, false);
868
869     } else if (!(options & DontChangeFocusProperty)) {
870         QQuickItemPrivate::get(item)->focus = false;
871         changed << item;
872     }
873
874     if (newActiveFocusItem) {
875         Q_ASSERT(newActiveFocusItem == scope);
876         activeFocusItem = scope;
877         updateFocusItemTransform();
878
879         QFocusEvent event(QEvent::FocusIn, reason);
880         q->sendEvent(newActiveFocusItem, &event);
881     }
882
883     if (activeFocusItem != currentActiveFocusItem)
884         emit q->focusObjectChanged(activeFocusItem);
885
886     if (!changed.isEmpty())
887         notifyFocusChangesRecur(changed.data(), changed.count() - 1);
888 }
889
890 void QQuickWindowPrivate::clearFocusObject()
891 {
892     if (activeFocusItem)
893         activeFocusItem->setFocus(false, Qt::OtherFocusReason);
894 }
895
896 void QQuickWindowPrivate::notifyFocusChangesRecur(QQuickItem **items, int remaining)
897 {
898     QPointer<QQuickItem> item(*items);
899
900     if (remaining)
901         notifyFocusChangesRecur(items + 1, remaining - 1);
902
903     if (item) {
904         QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
905
906         if (itemPrivate->notifiedFocus != itemPrivate->focus) {
907             itemPrivate->notifiedFocus = itemPrivate->focus;
908             emit item->focusChanged(itemPrivate->focus);
909         }
910
911         if (item && itemPrivate->notifiedActiveFocus != itemPrivate->activeFocus) {
912             itemPrivate->notifiedActiveFocus = itemPrivate->activeFocus;
913             itemPrivate->itemChange(QQuickItem::ItemActiveFocusHasChanged, itemPrivate->activeFocus);
914             emit item->activeFocusChanged(itemPrivate->activeFocus);
915         }
916     }
917 }
918
919 void QQuickWindowPrivate::dirtyItem(QQuickItem *)
920 {
921     Q_Q(QQuickWindow);
922     q->maybeUpdate();
923 }
924
925 void QQuickWindowPrivate::cleanup(QSGNode *n)
926 {
927     Q_Q(QQuickWindow);
928
929     Q_ASSERT(!cleanupNodeList.contains(n));
930     cleanupNodeList.append(n);
931     q->maybeUpdate();
932 }
933
934 /*!
935     \qmltype Window
936     \instantiates QQuickWindow
937     \inqmlmodule QtQuick.Window
938     \ingroup qtquick-visual
939     \brief Creates a new top-level window
940
941     The Window object creates a new top-level window for a Qt Quick scene. It automatically sets up the
942     window for use with \c {QtQuick 2.x} graphical types.
943
944     To use this type, you will need to import the module with the following line:
945     \code
946     import QtQuick.Window 2.1
947     \endcode
948
949     Omitting this import will allow you to have a QML environment without
950     access to window system features.
951
952     A Window can be declared inside an Item or inside another Window; in that
953     case the inner Window will automatically become "transient for" the outer
954     Window: that is, most platforms will show it centered upon the outer window
955     by default, and there may be other platform-dependent behaviors, depending
956     also on the \l flags. If the nested window is intended to be a dialog in
957     your application, you should also set \l flags to Qt.Dialog, because some
958     window managers will not provide the centering behavior without that flag.
959     You can also declare multiple windows inside a top-level \l QtObject, in which
960     case the windows will have no transient relationship.
961
962     Alternatively you can set or bind \l x and \l y to position the Window
963     explicitly on the screen.
964
965     When the user attempts to close a window, the \a closing signal will be
966     emitted. You can force the window to stay open (for example to prompt the
967     user to save changes) by writing an onClosing handler and setting
968     close.accepted = false.
969 */
970 /*!
971     \class QQuickWindow
972     \since 5.0
973
974     \inmodule QtQuick
975
976     \brief The QQuickWindow class provides the window for displaying a graphical QML scene
977
978     QQuickWindow provides the graphical scene management needed to interact with and display
979     a scene of QQuickItems.
980
981     A QQuickWindow always has a single invisible root item. To add items to this window,
982     reparent the items to the root item or to an existing item in the scene.
983
984     For easily displaying a scene from a QML file, see \l{QQuickView}.
985
986     \section1 Rendering
987
988     QQuickWindow uses a scene graph on top of OpenGL to
989     render. This scene graph is disconnected from the QML scene and
990     potentially lives in another thread, depending on the platform
991     implementation. Since the rendering scene graph lives
992     independently from the QML scene, it can also be completely
993     released without affecting the state of the QML scene.
994
995     The sceneGraphInitialized() signal is emitted on the rendering
996     thread before the QML scene is rendered to the screen for the
997     first time. If the rendering scene graph has been released, the
998     signal will be emitted again before the next frame is rendered.
999
1000
1001     \section2 Integration with OpenGL
1002
1003     It is possible to integrate OpenGL calls directly into the
1004     QQuickWindow using the same OpenGL context as the Qt Quick Scene
1005     Graph. This is done by connecting to the
1006     QQuickWindow::beforeRendering() or QQuickWindow::afterRendering()
1007     signal.
1008
1009     \note When using QQuickWindow::beforeRendering(), make sure to
1010     disable clearing before rendering with
1011     QQuickWindow::setClearBeforeRendering().
1012
1013
1014     \section2 Exposure and Visibility
1015
1016     When a QQuickWindow instance is deliberately hidden with hide() or
1017     setVisible(false), it will stop rendering and its scene graph and
1018     OpenGL context might be released. The sceneGraphInvalidated()
1019     signal will be emitted when this happens.
1020
1021     \warning It is crucial that OpenGL operations and interaction with
1022     the scene graph happens exclusively on the rendering thread,
1023     primarily during the updatePaintNode() phase.
1024
1025     \warning As signals related to rendering might be emitted from the
1026     rendering thread, connections should be made using
1027     Qt::DirectConnection.
1028
1029
1030     \section2 Resource Management
1031
1032     QML will try to cache images and scene graph nodes to
1033     improve performance, but in some low-memory scenarios it might be
1034     required to aggressively release these resources. The
1035     releaseResources() can be used to force the clean up of certain
1036     resources. Calling releaseResources() may result in the entire
1037     scene graph and its OpenGL context being deleted. The
1038     sceneGraphInvalidated() signal will be emitted when this happens.
1039
1040     \note All classes with QSG prefix should be used solely on the scene graph's
1041     rendering thread. See \l {Scene Graph and Rendering} for more information.
1042
1043     \sa {Scene Graph - OpenGL Under QML}
1044
1045 */
1046
1047 /*!
1048     Constructs a window for displaying a QML scene with parent window \a parent.
1049 */
1050 QQuickWindow::QQuickWindow(QWindow *parent)
1051     : QWindow(*(new QQuickWindowPrivate), parent)
1052 {
1053     Q_D(QQuickWindow);
1054     d->init(this);
1055 }
1056
1057
1058
1059 /*!
1060     \internal
1061 */
1062 QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent)
1063     : QWindow(dd, parent)
1064 {
1065     Q_D(QQuickWindow);
1066     d->init(this);
1067 }
1068
1069 /*!
1070     \internal
1071 */
1072 QQuickWindow::QQuickWindow(QQuickRenderControl *control)
1073     : QWindow(*(new QQuickWindowPrivate), 0)
1074 {
1075     Q_D(QQuickWindow);
1076     d->init(this, control);
1077 }
1078
1079
1080
1081 /*!
1082     Destroys the window.
1083 */
1084 QQuickWindow::~QQuickWindow()
1085 {
1086     Q_D(QQuickWindow);
1087
1088     d->animationController->deleteLater();
1089     if (d->renderControl) {
1090         d->renderControl->windowDestroyed();
1091     } else if (d->windowManager) {
1092         d->windowManager->removeWindow(this);
1093         d->windowManager->windowDestroyed(this);
1094     }
1095
1096     QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1097     delete d->incubationController; d->incubationController = 0;
1098 #ifndef QT_NO_DRAGANDDROP
1099     delete d->dragGrabber; d->dragGrabber = 0;
1100 #endif
1101     delete d->contentItem; d->contentItem = 0;
1102 }
1103
1104 /*!
1105     This function tries to release redundant resources currently held by the QML scene.
1106
1107     Calling this function might result in the scene graph and the OpenGL context used
1108     for rendering being released to release graphics memory. If this happens, the
1109     sceneGraphInvalidated() signal will be called, allowing users to clean up their
1110     own graphics resources. The setPersistentOpenGLContext() and setPersistentSceneGraph()
1111     functions can be used to prevent this from happening, if handling the cleanup is
1112     not feasible in the application, at the cost of higher memory usage.
1113
1114     \sa sceneGraphInvalidated(), setPersistentOpenGLContext(), setPersistentSceneGraph()
1115  */
1116
1117 void QQuickWindow::releaseResources()
1118 {
1119     Q_D(QQuickWindow);
1120     if (d->windowManager)
1121         d->windowManager->releaseResources(this);
1122     QQuickPixmap::purgeCache();
1123 }
1124
1125
1126
1127 /*!
1128     Sets whether the OpenGL context can be released to \a
1129     persistent. The default value is true.
1130
1131     The OpenGL context can be released to free up graphics resources
1132     when the window is obscured, hidden or not rendering. When this
1133     happens is implementation specific.
1134
1135     The QOpenGLContext::aboutToBeDestroyed() signal is emitted from
1136     the QQuickWindow::openglContext() when the OpenGL context is about
1137     to be released.  The QQuickWindow::sceneGraphInitialized() signal
1138     is emitted when a new OpenGL context is created for this
1139     window. Make a Qt::DirectConnection to these signals to be
1140     notified.
1141
1142     The OpenGL context is still released when the last QQuickWindow is
1143     deleted.
1144
1145     \sa setPersistentSceneGraph(),
1146     QOpenGLContext::aboutToBeDestroyed(), sceneGraphInitialized()
1147  */
1148
1149 void QQuickWindow::setPersistentOpenGLContext(bool persistent)
1150 {
1151     Q_D(QQuickWindow);
1152     d->persistentGLContext = persistent;
1153 }
1154
1155
1156
1157 /*!
1158     Returns whether the OpenGL context can be released during the
1159     lifetime of the QQuickWindow.
1160
1161     \note This is a hint. When and how this happens is implementation
1162     specific.
1163  */
1164
1165 bool QQuickWindow::isPersistentOpenGLContext() const
1166 {
1167     Q_D(const QQuickWindow);
1168     return d->persistentGLContext;
1169 }
1170
1171
1172
1173 /*!
1174     Sets whether the scene graph nodes and resources can be released
1175     to \a persistent.  The default value is true.
1176
1177     The scene graph nodes and resources can be released to free up
1178     graphics resources when the window is obscured, hidden or not
1179     rendering. When this happens is implementation specific.
1180
1181     The QQuickWindow::sceneGraphInvalidated() signal is emitted when
1182     cleanup occurs. The QQuickWindow::sceneGraphInitialized() signal
1183     is emitted when a new scene graph is recreated for this
1184     window. Make a Qt::DirectConnection to these signals to be
1185     notified.
1186
1187     The scene graph nodes and resources are still released when the
1188     last QQuickWindow is deleted.
1189
1190     \sa setPersistentOpenGLContext(),
1191     sceneGraphInvalidated(), sceneGraphInitialized()
1192  */
1193
1194 void QQuickWindow::setPersistentSceneGraph(bool persistent)
1195 {
1196     Q_D(QQuickWindow);
1197     d->persistentSceneGraph = persistent;
1198 }
1199
1200
1201
1202 /*!
1203     Returns whether the scene graph nodes and resources can be
1204     released during the lifetime of this QQuickWindow.
1205
1206     \note This is a hint. When and how this happens is implementation
1207     specific.
1208  */
1209
1210 bool QQuickWindow::isPersistentSceneGraph() const
1211 {
1212     Q_D(const QQuickWindow);
1213     return d->persistentSceneGraph;
1214 }
1215
1216
1217
1218
1219
1220 /*!
1221     \property QQuickWindow::contentItem
1222     \brief The invisible root item of the scene.
1223
1224   A QQuickWindow always has a single invisible root item containing all of its content.
1225   To add items to this window, reparent the items to the contentItem or to an existing
1226   item in the scene.
1227 */
1228 QQuickItem *QQuickWindow::contentItem() const
1229 {
1230     Q_D(const QQuickWindow);
1231
1232     return d->contentItem;
1233 }
1234
1235 /*!
1236     \property QQuickWindow::activeFocusItem
1237
1238     \brief The item which currently has active focus or \c null if there is
1239     no item with active focus.
1240 */
1241 QQuickItem *QQuickWindow::activeFocusItem() const
1242 {
1243     Q_D(const QQuickWindow);
1244
1245     return d->activeFocusItem;
1246 }
1247
1248 /*!
1249   \internal
1250   \reimp
1251 */
1252 QObject *QQuickWindow::focusObject() const
1253 {
1254     Q_D(const QQuickWindow);
1255
1256     if (d->activeFocusItem)
1257         return d->activeFocusItem;
1258     return const_cast<QQuickWindow*>(this);
1259 }
1260
1261
1262 /*!
1263   Returns the item which currently has the mouse grab.
1264 */
1265 QQuickItem *QQuickWindow::mouseGrabberItem() const
1266 {
1267     Q_D(const QQuickWindow);
1268
1269     return d->mouseGrabberItem;
1270 }
1271
1272
1273 bool QQuickWindowPrivate::clearHover()
1274 {
1275     Q_Q(QQuickWindow);
1276     if (hoverItems.isEmpty())
1277         return false;
1278
1279     QPointF pos = q->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition.toPoint());
1280
1281     bool accepted = false;
1282     foreach (QQuickItem* item, hoverItems)
1283         accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), true) || accepted;
1284     hoverItems.clear();
1285     return accepted;
1286 }
1287
1288 /*! \reimp */
1289 bool QQuickWindow::event(QEvent *e)
1290 {
1291     Q_D(QQuickWindow);
1292
1293     switch (e->type()) {
1294
1295     case QEvent::TouchBegin:
1296     case QEvent::TouchUpdate:
1297     case QEvent::TouchEnd: {
1298         QTouchEvent *touch = static_cast<QTouchEvent*>(e);
1299         d->translateTouchEvent(touch);
1300         d->deliverTouchEvent(touch);
1301         if (Q_LIKELY(qApp->testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents))) {
1302             // we consume all touch events ourselves to avoid duplicate
1303             // mouse delivery by QtGui mouse synthesis
1304             e->accept();
1305         }
1306         return true;
1307     }
1308         break;
1309     case QEvent::TouchCancel:
1310         // return in order to avoid the QWindow::event below
1311         return d->deliverTouchCancelEvent(static_cast<QTouchEvent*>(e));
1312         break;
1313     case QEvent::Leave:
1314         d->clearHover();
1315         d->lastMousePosition = QPoint();
1316         break;
1317 #ifndef QT_NO_DRAGANDDROP
1318     case QEvent::DragEnter:
1319     case QEvent::DragLeave:
1320     case QEvent::DragMove:
1321     case QEvent::Drop:
1322         d->deliverDragEvent(d->dragGrabber, e);
1323         break;
1324 #endif
1325     case QEvent::WindowDeactivate:
1326         contentItem()->windowDeactivateEvent();
1327         break;
1328     case QEvent::Close: {
1329         // TOOD Qt 6 (binary incompatible)
1330         // closeEvent(static_cast<QCloseEvent *>(e));
1331         QQuickCloseEvent qev;
1332         qev.setAccepted(e->isAccepted());
1333         emit closing(&qev);
1334         e->setAccepted(qev.isAccepted());
1335         } break;
1336     case QEvent::FocusAboutToChange:
1337 #ifndef QT_NO_IM
1338         if (d->activeFocusItem)
1339             qGuiApp->inputMethod()->commit();
1340 #endif
1341         if (d->mouseGrabberItem)
1342             d->mouseGrabberItem->ungrabMouse();
1343         break;
1344     default:
1345         break;
1346     }
1347
1348     return QWindow::event(e);
1349 }
1350
1351 /*! \reimp */
1352 void QQuickWindow::keyPressEvent(QKeyEvent *e)
1353 {
1354     Q_D(QQuickWindow);
1355     d->deliverKeyEvent(e);
1356 }
1357
1358 /*! \reimp */
1359 void QQuickWindow::keyReleaseEvent(QKeyEvent *e)
1360 {
1361     Q_D(QQuickWindow);
1362     d->deliverKeyEvent(e);
1363 }
1364
1365 void QQuickWindowPrivate::deliverKeyEvent(QKeyEvent *e)
1366 {
1367     Q_Q(QQuickWindow);
1368
1369 #ifndef QT_NO_SHORTCUT
1370     // Try looking for a Shortcut before sending key events
1371     if (e->type() == QEvent::KeyPress
1372         && QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(q->focusObject(), e))
1373         return;
1374 #endif
1375
1376     if (activeFocusItem)
1377         q->sendEvent(activeFocusItem, e);
1378 #ifdef Q_OS_MAC
1379     else {
1380         // This is the case for popup windows on Mac, where popup windows get focus
1381         // in Qt (after exposure) but they are not "key windows" in the Cocoa sense.
1382         // Therefore, the will never receive key events from Cocoa. Instead, the
1383         // toplevel non-popup window (the application current "key window") will
1384         // receive them. (QWidgetWindow does something similar for widgets, by keeping
1385         // a list of popup windows, and forwarding the key event to the top-most popup.)
1386         QWindow *focusWindow = qApp->focusWindow();
1387         if (focusWindow && focusWindow != q
1388             && (focusWindow->flags() & Qt::Popup) == Qt::Popup)
1389             QGuiApplication::sendEvent(focusWindow, e);
1390     }
1391 #endif
1392 }
1393
1394 QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos)
1395 {
1396     int caps = QGuiApplicationPrivate::mouseEventCaps(event);
1397     QVector2D velocity = QGuiApplicationPrivate::mouseEventVelocity(event);
1398     QMouseEvent *me = new QMouseEvent(event->type(),
1399                                       transformedLocalPos ? *transformedLocalPos : event->localPos(),
1400                                       event->windowPos(), event->screenPos(),
1401                                       event->button(), event->buttons(), event->modifiers());
1402     QGuiApplicationPrivate::setMouseEventCapsAndVelocity(me, caps, velocity);
1403     QGuiApplicationPrivate::setMouseEventSource(me, QGuiApplicationPrivate::mouseEventSource(event));
1404     me->setTimestamp(event->timestamp());
1405     return me;
1406 }
1407
1408 bool QQuickWindowPrivate::deliverInitialMousePressEvent(QQuickItem *item, QMouseEvent *event)
1409 {
1410     Q_Q(QQuickWindow);
1411
1412     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1413
1414     if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1415         QPointF p = item->mapFromScene(event->windowPos());
1416         if (!item->contains(p))
1417             return false;
1418     }
1419
1420     QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1421     for (int ii = children.count() - 1; ii >= 0; --ii) {
1422         QQuickItem *child = children.at(ii);
1423         if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
1424             continue;
1425         if (deliverInitialMousePressEvent(child, event))
1426             return true;
1427     }
1428
1429     if (itemPrivate->acceptedMouseButtons() & event->button()) {
1430         QPointF localPos = item->mapFromScene(event->windowPos());
1431         if (item->contains(localPos)) {
1432             QScopedPointer<QMouseEvent> me(cloneMouseEvent(event, &localPos));
1433             me->accept();
1434             item->grabMouse();
1435             q->sendEvent(item, me.data());
1436             event->setAccepted(me->isAccepted());
1437             if (me->isAccepted())
1438                 return true;
1439             if (mouseGrabberItem)
1440                 mouseGrabberItem->ungrabMouse();
1441         }
1442     }
1443
1444     return false;
1445 }
1446
1447 bool QQuickWindowPrivate::deliverMouseEvent(QMouseEvent *event)
1448 {
1449     Q_Q(QQuickWindow);
1450
1451     lastMousePosition = event->windowPos();
1452
1453     if (!mouseGrabberItem &&
1454          event->type() == QEvent::MouseButtonPress &&
1455          (event->buttons() & event->button()) == event->buttons()) {
1456         if (deliverInitialMousePressEvent(contentItem, event))
1457             event->accept();
1458         else
1459             event->ignore();
1460         return event->isAccepted();
1461     }
1462
1463     if (mouseGrabberItem) {
1464         QPointF localPos = mouseGrabberItem->mapFromScene(event->windowPos());
1465         QScopedPointer<QMouseEvent> me(cloneMouseEvent(event, &localPos));
1466         me->accept();
1467         q->sendEvent(mouseGrabberItem, me.data());
1468         event->setAccepted(me->isAccepted());
1469         if (me->isAccepted())
1470             return true;
1471     }
1472
1473     return false;
1474 }
1475
1476 /*! \reimp */
1477 void QQuickWindow::mousePressEvent(QMouseEvent *event)
1478 {
1479     Q_D(QQuickWindow);
1480
1481     if (event->source() == Qt::MouseEventSynthesizedBySystem) {
1482         event->accept();
1483         return;
1484     }
1485
1486     qCDebug(DBG_MOUSE) << "QQuickWindow::mousePressEvent()" << event->localPos() << event->button() << event->buttons();
1487     d->deliverMouseEvent(event);
1488 }
1489
1490 /*! \reimp */
1491 void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
1492 {
1493     Q_D(QQuickWindow);
1494
1495     if (event->source() == Qt::MouseEventSynthesizedBySystem) {
1496         event->accept();
1497         return;
1498     }
1499
1500     qCDebug(DBG_MOUSE) << "QQuickWindow::mouseReleaseEvent()" << event->localPos() << event->button() << event->buttons();
1501
1502     if (!d->mouseGrabberItem) {
1503         QWindow::mouseReleaseEvent(event);
1504         return;
1505     }
1506
1507     d->deliverMouseEvent(event);
1508     if (d->mouseGrabberItem && !event->buttons())
1509         d->mouseGrabberItem->ungrabMouse();
1510 }
1511
1512 /*! \reimp */
1513 void QQuickWindow::mouseDoubleClickEvent(QMouseEvent *event)
1514 {
1515     Q_D(QQuickWindow);
1516
1517     if (event->source() == Qt::MouseEventSynthesizedBySystem) {
1518         event->accept();
1519         return;
1520     }
1521
1522     qCDebug(DBG_MOUSE) << "QQuickWindow::mouseDoubleClickEvent()" << event->localPos() << event->button() << event->buttons();
1523
1524     if (!d->mouseGrabberItem && (event->buttons() & event->button()) == event->buttons()) {
1525         if (d->deliverInitialMousePressEvent(d->contentItem, event))
1526             event->accept();
1527         else
1528             event->ignore();
1529         return;
1530     }
1531
1532     d->deliverMouseEvent(event);
1533 }
1534
1535 bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
1536                                       const QPointF &scenePos, const QPointF &lastScenePos,
1537                                       Qt::KeyboardModifiers modifiers, bool accepted)
1538 {
1539     Q_Q(QQuickWindow);
1540     const QTransform transform = QQuickItemPrivate::get(item)->windowToItemTransform();
1541
1542     //create copy of event
1543     QHoverEvent hoverEvent(type, transform.map(scenePos), transform.map(lastScenePos), modifiers);
1544     hoverEvent.setAccepted(accepted);
1545
1546     q->sendEvent(item, &hoverEvent);
1547
1548     return hoverEvent.isAccepted();
1549 }
1550
1551 /*! \reimp */
1552 void QQuickWindow::mouseMoveEvent(QMouseEvent *event)
1553 {
1554     Q_D(QQuickWindow);
1555
1556     if (event->source() == Qt::MouseEventSynthesizedBySystem) {
1557         event->accept();
1558         return;
1559     }
1560
1561     qCDebug(DBG_MOUSE) << "QQuickWindow::mouseMoveEvent()" << event->localPos() << event->button() << event->buttons();
1562
1563 #ifndef QT_NO_CURSOR
1564     d->updateCursor(event->windowPos());
1565 #endif
1566
1567     if (!d->mouseGrabberItem) {
1568         if (d->lastMousePosition.isNull())
1569             d->lastMousePosition = event->windowPos();
1570         QPointF last = d->lastMousePosition;
1571         d->lastMousePosition = event->windowPos();
1572
1573         bool accepted = event->isAccepted();
1574         bool delivered = d->deliverHoverEvent(d->contentItem, event->windowPos(), last, event->modifiers(), accepted);
1575         if (!delivered) {
1576             //take care of any exits
1577             accepted = d->clearHover();
1578         }
1579         event->setAccepted(accepted);
1580         return;
1581     }
1582
1583     d->deliverMouseEvent(event);
1584 }
1585
1586 bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &scenePos, const QPointF &lastScenePos,
1587                                          Qt::KeyboardModifiers modifiers, bool &accepted)
1588 {
1589     Q_Q(QQuickWindow);
1590     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1591
1592     if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1593         QPointF p = item->mapFromScene(scenePos);
1594         if (!item->contains(p))
1595             return false;
1596     }
1597
1598     QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1599     for (int ii = children.count() - 1; ii >= 0; --ii) {
1600         QQuickItem *child = children.at(ii);
1601         if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
1602             continue;
1603         if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, accepted))
1604             return true;
1605     }
1606
1607     if (itemPrivate->hoverEnabled) {
1608         QPointF p = item->mapFromScene(scenePos);
1609         if (item->contains(p)) {
1610             if (!hoverItems.isEmpty() && hoverItems[0] == item) {
1611                 //move
1612                 accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
1613             } else {
1614                 QList<QQuickItem *> itemsToHover;
1615                 QQuickItem* parent = item;
1616                 itemsToHover << item;
1617                 while ((parent = parent->parentItem()))
1618                     itemsToHover << parent;
1619
1620                 // Leaving from previous hovered items until we reach the item or one of its ancestors.
1621                 while (!hoverItems.isEmpty() && !itemsToHover.contains(hoverItems[0])) {
1622                     sendHoverEvent(QEvent::HoverLeave, hoverItems[0], scenePos, lastScenePos, modifiers, accepted);
1623                     hoverItems.removeFirst();
1624                 }
1625
1626                 if (!hoverItems.isEmpty() && hoverItems[0] == item){//Not entering a new Item
1627                     // ### Shouldn't we send moves for the parent items as well?
1628                     accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
1629                 } else {
1630                     // Enter items that are not entered yet.
1631                     int startIdx = -1;
1632                     if (!hoverItems.isEmpty())
1633                         startIdx = itemsToHover.indexOf(hoverItems[0]) - 1;
1634                     if (startIdx == -1)
1635                         startIdx = itemsToHover.count() - 1;
1636
1637                     for (int i = startIdx; i >= 0; i--) {
1638                         QQuickItem *itemToHover = itemsToHover[i];
1639                         QQuickItemPrivate *itemToHoverPrivate = QQuickItemPrivate::get(itemToHover);
1640                         // The item may be about to be deleted or reparented to another window
1641                         // due to another hover event delivered in this function. If that is the
1642                         // case, sending a hover event here will cause a crash or other bad
1643                         // behavior when the leave event is generated. Checking
1644                         // itemToHoverPrivate->window here prevents that case.
1645                         if (itemToHoverPrivate->window == q && itemToHoverPrivate->hoverEnabled) {
1646                             hoverItems.prepend(itemToHover);
1647                             sendHoverEvent(QEvent::HoverEnter, itemToHover, scenePos, lastScenePos, modifiers, accepted);
1648                         }
1649                     }
1650                 }
1651             }
1652             return true;
1653         }
1654     }
1655
1656     return false;
1657 }
1658
1659 #ifndef QT_NO_WHEELEVENT
1660 bool QQuickWindowPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event)
1661 {
1662     Q_Q(QQuickWindow);
1663     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1664
1665     if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1666         QPointF p = item->mapFromScene(event->posF());
1667         if (!item->contains(p))
1668             return false;
1669     }
1670
1671     QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1672     for (int ii = children.count() - 1; ii >= 0; --ii) {
1673         QQuickItem *child = children.at(ii);
1674         if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
1675             continue;
1676         if (deliverWheelEvent(child, event))
1677             return true;
1678     }
1679
1680     QPointF p = item->mapFromScene(event->posF());
1681
1682     if (item->contains(p)) {
1683         QWheelEvent wheel(p, p, event->pixelDelta(), event->angleDelta(), event->delta(),
1684                           event->orientation(), event->buttons(), event->modifiers(), event->phase());
1685         wheel.accept();
1686         q->sendEvent(item, &wheel);
1687         if (wheel.isAccepted()) {
1688             event->accept();
1689             return true;
1690         }
1691     }
1692
1693     return false;
1694 }
1695
1696 /*! \reimp */
1697 void QQuickWindow::wheelEvent(QWheelEvent *event)
1698 {
1699     Q_D(QQuickWindow);
1700     qCDebug(DBG_MOUSE) << "QQuickWindow::wheelEvent()" << event->pixelDelta() << event->angleDelta();
1701
1702     //if the actual wheel event was accepted, accept the compatibility wheel event and return early
1703     if (d->lastWheelEventAccepted && event->angleDelta().isNull() && event->phase() == Qt::ScrollUpdate)
1704         return;
1705
1706     event->ignore();
1707     d->deliverWheelEvent(d->contentItem, event);
1708     d->lastWheelEventAccepted = event->isAccepted();
1709 }
1710 #endif // QT_NO_WHEELEVENT
1711
1712
1713 bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event)
1714 {
1715     qCDebug(DBG_TOUCH) << event;
1716     Q_Q(QQuickWindow);
1717     // A TouchCancel event will typically not contain any points.
1718     // Deliver it to all items that have active touches.
1719     QSet<QQuickItem *> cancelDelivered;
1720     foreach (QQuickItem *item, itemForTouchPointId) {
1721         if (cancelDelivered.contains(item))
1722             continue;
1723         cancelDelivered.insert(item);
1724         q->sendEvent(item, event);
1725     }
1726     touchMouseId = -1;
1727     if (mouseGrabberItem)
1728         mouseGrabberItem->ungrabMouse();
1729     // The next touch event can only be a TouchBegin so clean up.
1730     itemForTouchPointId.clear();
1731     return true;
1732 }
1733
1734 static bool qquickwindow_no_touch_compression = qEnvironmentVariableIsSet("QML_NO_TOUCH_COMPRESSION");
1735
1736 // check what kind of touch we have (begin/update) and
1737 // call deliverTouchPoints to actually dispatch the points
1738 void QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event)
1739 {
1740     qCDebug(DBG_TOUCH) << event;
1741     Q_Q(QQuickWindow);
1742
1743     if (qquickwindow_no_touch_compression || touchRecursionGuard) {
1744         reallyDeliverTouchEvent(event);
1745         return;
1746     }
1747
1748     Qt::TouchPointStates states = event->touchPointStates();
1749     if (((states & (Qt::TouchPointMoved | Qt::TouchPointStationary)) != 0)
1750         && ((states & (Qt::TouchPointPressed | Qt::TouchPointReleased)) == 0)) {
1751         // we can only compress something that isn't a press or release
1752         if (!delayedTouch) {
1753             delayedTouch = new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints());
1754             delayedTouch->setTimestamp(event->timestamp());
1755             if (windowManager)
1756                 windowManager->maybeUpdate(q);
1757             return;
1758         } else {
1759             // check if this looks like the last touch event
1760             if (delayedTouch->type() == event->type() &&
1761                 delayedTouch->device() == event->device() &&
1762                 delayedTouch->modifiers() == event->modifiers() &&
1763                 delayedTouch->touchPoints().count() == event->touchPoints().count())
1764             {
1765                 // possible match.. is it really the same?
1766                 bool mismatch = false;
1767
1768                 QList<QTouchEvent::TouchPoint> tpts = event->touchPoints();
1769                 Qt::TouchPointStates states;
1770                 for (int i = 0; i < event->touchPoints().count(); ++i) {
1771                     const QTouchEvent::TouchPoint &tp = tpts.at(i);
1772                     const QTouchEvent::TouchPoint &tp2 = delayedTouch->touchPoints().at(i);
1773                     if (tp.id() != tp2.id()) {
1774                         mismatch = true;
1775                         break;
1776                     }
1777
1778                     if (tp2.state() == Qt::TouchPointMoved && tp.state() == Qt::TouchPointStationary)
1779                         tpts[i].setState(Qt::TouchPointMoved);
1780
1781                     states |= tpts.at(i).state();
1782                 }
1783
1784                 // same touch event? then merge if so
1785                 if (!mismatch) {
1786                     delayedTouch->setTouchPoints(tpts);
1787                     delayedTouch->setTimestamp(event->timestamp());
1788                     return;
1789                 }
1790             }
1791
1792             // otherwise; we need to deliver the delayed event first, and
1793             // then delay this one..
1794             reallyDeliverTouchEvent(delayedTouch);
1795             delete delayedTouch;
1796             delayedTouch = new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints());
1797             delayedTouch->setTimestamp(event->timestamp());
1798             return;
1799         }
1800     } else {
1801         if (delayedTouch) {
1802             // deliver the delayed touch first
1803             reallyDeliverTouchEvent(delayedTouch);
1804             delete delayedTouch;
1805             delayedTouch = 0;
1806         }
1807         reallyDeliverTouchEvent(event);
1808     }
1809 }
1810
1811 void QQuickWindowPrivate::flushDelayedTouchEvent()
1812 {
1813     if (delayedTouch) {
1814         reallyDeliverTouchEvent(delayedTouch);
1815         delete delayedTouch;
1816         delayedTouch = 0;
1817
1818         // To flush pending meta-calls triggered from the recently flushed touch events.
1819         // This is safe because flushDelayedEvent is only called from eventhandlers.
1820         QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1821     }
1822 }
1823
1824 void QQuickWindowPrivate::reallyDeliverTouchEvent(QTouchEvent *event)
1825 {
1826     qCDebug(DBG_TOUCH) << " - delivering" << event;
1827
1828     // If users spin the eventloop as a result of touch delivery, we disable
1829     // touch compression and send events directly. This is because we consider
1830     // the usecase a bit evil, but we at least don't want to lose events.
1831     ++touchRecursionGuard;
1832
1833     // List of all items that received an event before
1834     // When we have TouchBegin this is and will stay empty
1835     QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > updatedPoints;
1836
1837     // Figure out who accepted a touch point last and put it in updatedPoints
1838     // Add additional item to newPoints
1839     const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
1840     QList<QTouchEvent::TouchPoint> newPoints;
1841     for (int i=0; i<touchPoints.count(); i++) {
1842         const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
1843         if (touchPoint.state() == Qt::TouchPointPressed) {
1844             newPoints << touchPoint;
1845         } else {
1846             // TouchPointStationary is relevant only to items which
1847             // are also receiving touch points with some other state.
1848             // But we have not yet decided which points go to which item,
1849             // so for now we must include all non-new points in updatedPoints.
1850             if (itemForTouchPointId.contains(touchPoint.id())) {
1851                 QQuickItem *item = itemForTouchPointId.value(touchPoint.id());
1852                 if (item)
1853                     updatedPoints[item].append(touchPoint);
1854             }
1855         }
1856     }
1857
1858     // Deliver the event, but only if there is at least one new point
1859     // or some item accepted a point and should receive an update
1860     if (newPoints.count() > 0 || updatedPoints.count() > 0) {
1861         QSet<int> acceptedNewPoints;
1862         event->setAccepted(deliverTouchPoints(contentItem, event, newPoints, &acceptedNewPoints, &updatedPoints));
1863     } else
1864         event->ignore();
1865
1866     // Remove released points from itemForTouchPointId
1867     if (event->touchPointStates() & Qt::TouchPointReleased) {
1868         for (int i=0; i<touchPoints.count(); i++) {
1869             if (touchPoints[i].state() == Qt::TouchPointReleased) {
1870                 itemForTouchPointId.remove(touchPoints[i].id());
1871                 if (touchPoints[i].id() == touchMouseId)
1872                     touchMouseId = -1;
1873             }
1874         }
1875     }
1876
1877     if (event->type() == QEvent::TouchEnd) {
1878         Q_ASSERT(itemForTouchPointId.isEmpty());
1879     }
1880
1881     --touchRecursionGuard;
1882 }
1883
1884 // This function recurses and sends the events to the individual items
1885 bool QQuickWindowPrivate::deliverTouchPoints(QQuickItem *item, QTouchEvent *event, const QList<QTouchEvent::TouchPoint> &newPoints, QSet<int> *acceptedNewPoints, QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > *updatedPoints)
1886 {
1887     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1888
1889     if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1890         for (int i=0; i<newPoints.count(); i++) {
1891             QPointF p = item->mapFromScene(newPoints[i].scenePos());
1892             if (!item->contains(p))
1893                 return false;
1894         }
1895     }
1896
1897     // Check if our children want the event (or parts of it)
1898     // This is the only point where touch event delivery recurses!
1899     QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1900     for (int ii = children.count() - 1; ii >= 0; --ii) {
1901         QQuickItem *child = children.at(ii);
1902         if (!child->isEnabled() || !child->isVisible() || QQuickItemPrivate::get(child)->culled)
1903             continue;
1904         if (deliverTouchPoints(child, event, newPoints, acceptedNewPoints, updatedPoints))
1905             return true;
1906     }
1907
1908     // None of the children accepted the event, so check the given item itself.
1909     // First, construct matchingPoints as a list of TouchPoints which the
1910     // given item might be interested in.  Any newly-pressed point which is
1911     // inside the item's bounds will be interesting, and also any updated point
1912     // which was already accepted by that item when it was first pressed.
1913     // (A point which was already accepted is effectively "grabbed" by the item.)
1914
1915     // set of IDs of "interesting" new points
1916     QSet<int> matchingNewPoints;
1917     // set of points which this item has previously accepted, for starters
1918     QList<QTouchEvent::TouchPoint> matchingPoints = (*updatedPoints)[item];
1919     // now add the new points which are inside this item's bounds
1920     if (newPoints.count() > 0 && acceptedNewPoints->count() < newPoints.count()) {
1921         for (int i = 0; i < newPoints.count(); i++) {
1922             if (acceptedNewPoints->contains(newPoints[i].id()))
1923                 continue;
1924             QPointF p = item->mapFromScene(newPoints[i].scenePos());
1925             if (item->contains(p)) {
1926                 matchingNewPoints.insert(newPoints[i].id());
1927                 matchingPoints << newPoints[i];
1928             }
1929         }
1930     }
1931     // If there are no matching new points, and the existing points are all stationary,
1932     // there's no need to send an event to this item.  This is required by a test in
1933     // tst_qquickwindow::touchEvent_basic:
1934     // a single stationary press on an item shouldn't cause an event
1935     if (matchingNewPoints.isEmpty()) {
1936         bool stationaryOnly = true;
1937
1938         foreach (const QTouchEvent::TouchPoint &tp, matchingPoints) {
1939             if (tp.state() != Qt::TouchPointStationary) {
1940                 stationaryOnly = false;
1941                 break;
1942             }
1943         }
1944
1945         if (stationaryOnly)
1946             matchingPoints.clear();
1947     }
1948
1949     if (!matchingPoints.isEmpty()) {
1950         // Now we know this item might be interested in the event. Copy and send it, but
1951         // with only the subset of TouchPoints which are relevant to that item: that's matchingPoints.
1952         QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1953         transformTouchPoints(matchingPoints, itemPrivate->windowToItemTransform());
1954         deliverMatchingPointsToItem(item, event, acceptedNewPoints, matchingNewPoints, matchingPoints);
1955     }
1956
1957     // record the fact that this item has been visited already
1958     updatedPoints->remove(item);
1959
1960     // recursion is done only if ALL touch points have been delivered
1961     return (acceptedNewPoints->count() == newPoints.count() && updatedPoints->isEmpty());
1962 }
1963
1964 // touchEventForItemBounds has no means to generate a touch event that contains
1965 // only the points that are relevant for this item.  Thus the need for
1966 // matchingPoints to already be that set of interesting points.
1967 // They are all pre-transformed, too.
1968 bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet<int> *acceptedNewPoints, const QSet<int> &matchingNewPoints, const QList<QTouchEvent::TouchPoint> &matchingPoints)
1969 {
1970     QScopedPointer<QTouchEvent> touchEvent(touchEventWithPoints(*event, matchingPoints));
1971     touchEvent.data()->setTarget(item);
1972     bool touchEventAccepted = false;
1973
1974     // First check whether the parent wants to be a filter,
1975     // and if the parent accepts the event we are done.
1976     if (sendFilteredTouchEvent(item->parentItem(), item, event)) {
1977         // If the touch was accepted (regardless by whom or in what form),
1978         // update acceptedNewPoints
1979         foreach (int id, matchingNewPoints)
1980             acceptedNewPoints->insert(id);
1981         return true;
1982     }
1983
1984     // Since it can change in sendEvent, update itemForTouchPointId now
1985     foreach (int id, matchingNewPoints)
1986         itemForTouchPointId[id] = item;
1987
1988     // Deliver the touch event to the given item
1989     QCoreApplication::sendEvent(item, touchEvent.data());
1990     touchEventAccepted = touchEvent->isAccepted();
1991
1992     // If the touch event wasn't accepted, synthesize a mouse event and see if the item wants it.
1993     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1994     if (!touchEventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton)) {
1995         //  send mouse event
1996         event->setAccepted(translateTouchToMouse(item, event));
1997         if (event->isAccepted()) {
1998             touchEventAccepted = true;
1999         }
2000     }
2001
2002     if (touchEventAccepted) {
2003         // If the touch was accepted (regardless by whom or in what form),
2004         // update acceptedNewPoints.
2005         foreach (int id, matchingNewPoints)
2006             acceptedNewPoints->insert(id);
2007     } else {
2008         // But if the event was not accepted then we know this item
2009         // will not be interested in further updates for those touchpoint IDs either.
2010         foreach (int id, matchingNewPoints)
2011             if (itemForTouchPointId[id] == item)
2012                 itemForTouchPointId.remove(id);
2013     }
2014
2015     return touchEventAccepted;
2016 }
2017
2018 QTouchEvent *QQuickWindowPrivate::touchEventForItemBounds(QQuickItem *target, const QTouchEvent &originalEvent)
2019 {
2020     const QList<QTouchEvent::TouchPoint> &touchPoints = originalEvent.touchPoints();
2021     QList<QTouchEvent::TouchPoint> pointsInBounds;
2022     // if all points are stationary, the list of points should be empty to signal a no-op
2023     if (originalEvent.touchPointStates() != Qt::TouchPointStationary) {
2024         for (int i = 0; i < touchPoints.count(); ++i) {
2025             const QTouchEvent::TouchPoint &tp = touchPoints.at(i);
2026             if (tp.state() == Qt::TouchPointPressed) {
2027                 QPointF p = target->mapFromScene(tp.scenePos());
2028                 if (target->contains(p))
2029                     pointsInBounds.append(tp);
2030             } else {
2031                 pointsInBounds.append(tp);
2032             }
2033         }
2034         transformTouchPoints(pointsInBounds, QQuickItemPrivate::get(target)->windowToItemTransform());
2035     }
2036
2037     QTouchEvent* touchEvent = touchEventWithPoints(originalEvent, pointsInBounds);
2038     touchEvent->setTarget(target);
2039     return touchEvent;
2040 }
2041
2042 QTouchEvent *QQuickWindowPrivate::touchEventWithPoints(const QTouchEvent &event, const QList<QTouchEvent::TouchPoint> &newPoints)
2043 {
2044     Qt::TouchPointStates eventStates;
2045     for (int i=0; i<newPoints.count(); i++)
2046         eventStates |= newPoints[i].state();
2047     // if all points have the same state, set the event type accordingly
2048     QEvent::Type eventType = event.type();
2049     switch (eventStates) {
2050         case Qt::TouchPointPressed:
2051             eventType = QEvent::TouchBegin;
2052             break;
2053         case Qt::TouchPointReleased:
2054             eventType = QEvent::TouchEnd;
2055             break;
2056         default:
2057             eventType = QEvent::TouchUpdate;
2058             break;
2059     }
2060
2061     QTouchEvent *touchEvent = new QTouchEvent(eventType);
2062     touchEvent->setWindow(event.window());
2063     touchEvent->setTarget(event.target());
2064     touchEvent->setDevice(event.device());
2065     touchEvent->setModifiers(event.modifiers());
2066     touchEvent->setTouchPoints(newPoints);
2067     touchEvent->setTouchPointStates(eventStates);
2068     touchEvent->setTimestamp(event.timestamp());
2069     touchEvent->accept();
2070     return touchEvent;
2071 }
2072
2073 #ifndef QT_NO_DRAGANDDROP
2074 void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *event)
2075 {
2076     Q_Q(QQuickWindow);
2077     grabber->resetTarget();
2078     QQuickDragGrabber::iterator grabItem = grabber->begin();
2079     if (grabItem != grabber->end()) {
2080         Q_ASSERT(event->type() != QEvent::DragEnter);
2081         if (event->type() == QEvent::Drop) {
2082             QDropEvent *e = static_cast<QDropEvent *>(event);
2083             for (e->setAccepted(false); !e->isAccepted() && grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
2084                 QPointF p = (**grabItem)->mapFromScene(e->pos());
2085                 QDropEvent translatedEvent(
2086                         p.toPoint(),
2087                         e->possibleActions(),
2088                         e->mimeData(),
2089                         e->mouseButtons(),
2090                         e->keyboardModifiers());
2091                 QQuickDropEventEx::copyActions(&translatedEvent, *e);
2092                 q->sendEvent(**grabItem, &translatedEvent);
2093                 e->setAccepted(translatedEvent.isAccepted());
2094                 e->setDropAction(translatedEvent.dropAction());
2095                 grabber->setTarget(**grabItem);
2096             }
2097         }
2098         if (event->type() != QEvent::DragMove) {    // Either an accepted drop or a leave.
2099             QDragLeaveEvent leaveEvent;
2100             for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem))
2101                 q->sendEvent(**grabItem, &leaveEvent);
2102             return;
2103         } else for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
2104             QDragMoveEvent *moveEvent = static_cast<QDragMoveEvent *>(event);
2105             if (deliverDragEvent(grabber, **grabItem, moveEvent)) {
2106                 moveEvent->setAccepted(true);
2107                 for (++grabItem; grabItem != grabber->end();) {
2108                     QPointF p = (**grabItem)->mapFromScene(moveEvent->pos());
2109                     if ((**grabItem)->contains(p)) {
2110                         QDragMoveEvent translatedEvent(
2111                                 p.toPoint(),
2112                                 moveEvent->possibleActions(),
2113                                 moveEvent->mimeData(),
2114                                 moveEvent->mouseButtons(),
2115                                 moveEvent->keyboardModifiers());
2116                         QQuickDropEventEx::copyActions(&translatedEvent, *moveEvent);
2117                         q->sendEvent(**grabItem, &translatedEvent);
2118                         ++grabItem;
2119                     } else {
2120                         QDragLeaveEvent leaveEvent;
2121                         q->sendEvent(**grabItem, &leaveEvent);
2122                         grabItem = grabber->release(grabItem);
2123                     }
2124                 }
2125                 return;
2126             } else {
2127                 QDragLeaveEvent leaveEvent;
2128                 q->sendEvent(**grabItem, &leaveEvent);
2129             }
2130         }
2131     }
2132     if (event->type() == QEvent::DragEnter || event->type() == QEvent::DragMove) {
2133         QDragMoveEvent *e = static_cast<QDragMoveEvent *>(event);
2134         QDragEnterEvent enterEvent(
2135                 e->pos(),
2136                 e->possibleActions(),
2137                 e->mimeData(),
2138                 e->mouseButtons(),
2139                 e->keyboardModifiers());
2140         QQuickDropEventEx::copyActions(&enterEvent, *e);
2141         event->setAccepted(deliverDragEvent(grabber, contentItem, &enterEvent));
2142     }
2143 }
2144
2145 bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickItem *item, QDragMoveEvent *event)
2146 {
2147     Q_Q(QQuickWindow);
2148     bool accepted = false;
2149     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
2150     if (!item->isVisible() || !item->isEnabled() || QQuickItemPrivate::get(item)->culled)
2151         return false;
2152
2153     QPointF p = item->mapFromScene(event->pos());
2154     if (item->contains(p)) {
2155         if (event->type() == QEvent::DragMove || itemPrivate->flags & QQuickItem::ItemAcceptsDrops) {
2156             QDragMoveEvent translatedEvent(
2157                     p.toPoint(),
2158                     event->possibleActions(),
2159                     event->mimeData(),
2160                     event->mouseButtons(),
2161                     event->keyboardModifiers(),
2162                     event->type());
2163             QQuickDropEventEx::copyActions(&translatedEvent, *event);
2164             q->sendEvent(item, &translatedEvent);
2165             if (event->type() == QEvent::DragEnter) {
2166                 if (translatedEvent.isAccepted()) {
2167                     grabber->grab(item);
2168                     accepted = true;
2169                 }
2170             } else {
2171                 accepted = true;
2172             }
2173         }
2174     } else if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
2175         return false;
2176     }
2177
2178     QDragEnterEvent enterEvent(
2179             event->pos(),
2180             event->possibleActions(),
2181             event->mimeData(),
2182             event->mouseButtons(),
2183             event->keyboardModifiers());
2184     QQuickDropEventEx::copyActions(&enterEvent, *event);
2185     QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
2186     for (int ii = children.count() - 1; ii >= 0; --ii) {
2187         if (deliverDragEvent(grabber, children.at(ii), &enterEvent))
2188             return true;
2189     }
2190
2191     return accepted;
2192 }
2193 #endif // QT_NO_DRAGANDDROP
2194
2195 #ifndef QT_NO_CURSOR
2196 void QQuickWindowPrivate::updateCursor(const QPointF &scenePos)
2197 {
2198     Q_Q(QQuickWindow);
2199
2200     QQuickItem *oldCursorItem = cursorItem;
2201     cursorItem = findCursorItem(contentItem, scenePos);
2202
2203     if (cursorItem != oldCursorItem) {
2204         if (cursorItem)
2205             q->setCursor(cursorItem->cursor());
2206         else
2207             q->unsetCursor();
2208     }
2209 }
2210
2211 QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF &scenePos)
2212 {
2213     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
2214     if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
2215         QPointF p = item->mapFromScene(scenePos);
2216         if (!item->contains(p))
2217             return 0;
2218     }
2219
2220     const int numCursorsInHierarchy = itemPrivate->extra.isAllocated() ? itemPrivate->extra.value().numItemsWithCursor : 0;
2221     const int numChildrenWithCursor = itemPrivate->hasCursor ? numCursorsInHierarchy-1 : numCursorsInHierarchy;
2222
2223     if (numChildrenWithCursor > 0) {
2224         QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
2225         for (int ii = children.count() - 1; ii >= 0; --ii) {
2226             QQuickItem *child = children.at(ii);
2227             if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
2228                 continue;
2229             if (QQuickItem *cursorItem = findCursorItem(child, scenePos))
2230                 return cursorItem;
2231         }
2232     }
2233
2234     if (itemPrivate->hasCursor) {
2235         QPointF p = item->mapFromScene(scenePos);
2236         if (item->contains(p))
2237             return item;
2238     }
2239     return 0;
2240 }
2241 #endif
2242
2243 bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem *item, QTouchEvent *event)
2244 {
2245     if (!target)
2246         return false;
2247
2248     QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
2249     if (targetPrivate->filtersChildMouseEvents) {
2250         QScopedPointer<QTouchEvent> targetEvent(touchEventForItemBounds(target, *event));
2251         if (!targetEvent->touchPoints().isEmpty()) {
2252             QVector<int> touchIds;
2253             for (int i = 0; i < event->touchPoints().size(); ++i)
2254                 touchIds.append(event->touchPoints().at(i).id());
2255             if (target->childMouseEventFilter(item, targetEvent.data())) {
2256                 target->grabTouchPoints(touchIds);
2257                 if (mouseGrabberItem) {
2258                     mouseGrabberItem->ungrabMouse();
2259                     touchMouseId = -1;
2260                 }
2261                 return true;
2262             }
2263
2264             // Only offer a mouse event to the filter if we have one point
2265             if (targetEvent->touchPoints().count() == 1) {
2266                 QEvent::Type t;
2267                 const QTouchEvent::TouchPoint &tp = targetEvent->touchPoints().first();
2268                 switch (tp.state()) {
2269                 case Qt::TouchPointPressed:
2270                     t = QEvent::MouseButtonPress;
2271                     break;
2272                 case Qt::TouchPointReleased:
2273                     t = QEvent::MouseButtonRelease;
2274                     break;
2275                 default:
2276                     // move or stationary
2277                     t = QEvent::MouseMove;
2278                     break;
2279                 }
2280
2281                 // targetEvent is already transformed wrt local position, velocity, etc.
2282                 QScopedPointer<QMouseEvent> mouseEvent(touchToMouseEvent(t, targetEvent->touchPoints().first(), event, item, false));
2283                 if (target->childMouseEventFilter(item, mouseEvent.data())) {
2284                     itemForTouchPointId[tp.id()] = target;
2285                     touchMouseId = tp.id();
2286                     target->grabMouse();
2287                     return true;
2288                 }
2289             }
2290         }
2291     }
2292
2293     return sendFilteredTouchEvent(target->parentItem(), item, event);
2294 }
2295
2296 bool QQuickWindowPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem *item, QEvent *event)
2297 {
2298     if (!target)
2299         return false;
2300
2301     QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
2302     if (targetPrivate->filtersChildMouseEvents)
2303         if (target->childMouseEventFilter(item, event))
2304             return true;
2305
2306     if (sendFilteredMouseEvent(target->parentItem(), item, event))
2307         return true;
2308
2309     return false;
2310 }
2311
2312 bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold)
2313 {
2314     QStyleHints *styleHints = qApp->styleHints();
2315     int caps = QGuiApplicationPrivate::mouseEventCaps(event);
2316     bool dragVelocityLimitAvailable = (caps & QTouchDevice::Velocity)
2317         && styleHints->startDragVelocity();
2318     bool overThreshold = qAbs(d) > (startDragThreshold >= 0 ? startDragThreshold : styleHints->startDragDistance());
2319     if (dragVelocityLimitAvailable) {
2320         QVector2D velocityVec = QGuiApplicationPrivate::mouseEventVelocity(event);
2321         qreal velocity = axis == Qt::XAxis ? velocityVec.x() : velocityVec.y();
2322         overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
2323     }
2324     return overThreshold;
2325 }
2326
2327 /*!
2328     \qmlproperty list<Object> Window::data
2329     \default
2330
2331     The data property allows you to freely mix visual children, resources
2332     and other Windows in a Window.
2333
2334     If you assign another Window to the data list, the nested window will
2335     become "transient for" the outer Window.
2336
2337     If you assign an \l Item to the data list, it becomes a child of the
2338     Window's \l contentItem, so that it appears inside the window. The item's
2339     parent will be the window's contentItem, which is the root of the Item
2340     ownership tree within that Window.
2341
2342     If you assign any other object type, it is added as a resource.
2343
2344     It should not generally be necessary to refer to the \c data property,
2345     as it is the default property for Window and thus all child items are
2346     automatically assigned to this property.
2347
2348     \sa QWindow::transientParent()
2349  */
2350
2351 void QQuickWindowPrivate::data_append(QQmlListProperty<QObject> *property, QObject *o)
2352 {
2353     if (!o)
2354         return;
2355     QQuickWindow *that = static_cast<QQuickWindow *>(property->object);
2356     if (QQuickWindow *window = qmlobject_cast<QQuickWindow *>(o))
2357         window->setTransientParent(that);
2358     QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(that->contentItem())->data();
2359     itemProperty.append(&itemProperty, o);
2360 }
2361
2362 int QQuickWindowPrivate::data_count(QQmlListProperty<QObject> *property)
2363 {
2364     QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
2365     if (!win || !win->contentItem() || !QQuickItemPrivate::get(win->contentItem())->data().count)
2366         return 0;
2367     QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
2368     return itemProperty.count(&itemProperty);
2369 }
2370
2371 QObject *QQuickWindowPrivate::data_at(QQmlListProperty<QObject> *property, int i)
2372 {
2373     QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
2374     QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
2375     return itemProperty.at(&itemProperty, i);
2376 }
2377
2378 void QQuickWindowPrivate::data_clear(QQmlListProperty<QObject> *property)
2379 {
2380     QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
2381     QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
2382     itemProperty.clear(&itemProperty);
2383 }
2384
2385 bool QQuickWindowPrivate::isRenderable() const
2386 {
2387     Q_Q(const QQuickWindow);
2388     return ((q->isExposed() && q->isVisible())) && q->geometry().isValid();
2389 }
2390
2391 void QQuickWindowPrivate::contextCreationFailureMessage(const QSurfaceFormat &format,
2392                                                         QString *translatedMessage,
2393                                                         QString *untranslatedMessage,
2394                                                         bool isEs)
2395 {
2396     const QString contextType = QLatin1String(isEs ? "EGL" : "OpenGL");
2397     QString formatStr;
2398     QDebug(&formatStr) << format;
2399 #if defined(Q_OS_WIN32)
2400     const bool isDebug = QLibraryInfo::isDebugBuild();
2401     const QString eglLibName = QLatin1String(isDebug ? "libEGLd.dll" : "libEGL.dll");
2402     const QString glesLibName = QLatin1String(isDebug ? "libGLESv2d.dll" : "libGLESv2.dll");
2403      //: %1 Context type (Open GL, EGL), %2 format, ANGLE %3, %4 library names
2404     const char msg[] = QT_TRANSLATE_NOOP("QQuickWindow",
2405         "Failed to create %1 context for format %2.\n"
2406         "This is most likely caused by not having the necessary graphics drivers installed.\n\n"
2407         "Install a driver providing OpenGL 2.0 or higher, or, if this is not possible, "
2408         "make sure the ANGLE Open GL ES 2.0 emulation libraries (%3, %4 and d3dcompiler_*.dll) "
2409         "are available in the application executable's directory or in a location listed in PATH.");
2410     *translatedMessage = QQuickWindow::tr(msg).arg(contextType, formatStr, eglLibName, glesLibName);
2411     *untranslatedMessage = QString::fromLatin1(msg).arg(contextType, formatStr, eglLibName, glesLibName);
2412 #else // Q_OS_WIN32
2413     //: %1 Context type (Open GL, EGL), %2 format specification
2414     const char msg[] = QT_TRANSLATE_NOOP("QQuickWindow",
2415                                          "Failed to create %1 context for format %2");
2416     *translatedMessage = QQuickWindow::tr(msg).arg(contextType, formatStr);
2417     *untranslatedMessage = QString::fromLatin1(msg).arg(contextType, formatStr);
2418 #endif // !Q_OS_WIN32
2419 }
2420
2421 /*!
2422     Propagates an event \a e to a QQuickItem \a item on the window.
2423
2424     The return value is currently not used.
2425 */
2426 bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e)
2427 {
2428     Q_D(QQuickWindow);
2429
2430     if (!item) {
2431         qWarning("QQuickWindow::sendEvent: Cannot send event to a null item");
2432         return false;
2433     }
2434
2435     Q_ASSERT(e);
2436
2437     switch (e->type()) {
2438     case QEvent::KeyPress:
2439     case QEvent::KeyRelease:
2440         e->accept();
2441         QCoreApplication::sendEvent(item, e);
2442         while (!e->isAccepted() && (item = item->parentItem())) {
2443             e->accept();
2444             QCoreApplication::sendEvent(item, e);
2445         }
2446         break;
2447     case QEvent::MouseButtonPress:
2448     case QEvent::MouseButtonRelease:
2449     case QEvent::MouseButtonDblClick:
2450     case QEvent::MouseMove:
2451         // XXX todo - should sendEvent be doing this?  how does it relate to forwarded events?
2452         if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) {
2453             // accept because qml items by default accept and have to explicitly opt out of accepting
2454             e->accept();
2455             QCoreApplication::sendEvent(item, e);
2456         }
2457         break;
2458     case QEvent::UngrabMouse:
2459         if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) {
2460             e->accept();
2461             item->mouseUngrabEvent();
2462         }
2463         break;
2464 #ifndef QT_NO_WHEELEVENT
2465     case QEvent::Wheel:
2466 #endif
2467 #ifndef QT_NO_DRAGANDDROP
2468     case QEvent::DragEnter:
2469     case QEvent::DragMove:
2470     case QEvent::DragLeave:
2471     case QEvent::Drop:
2472 #endif
2473     case QEvent::FocusIn:
2474     case QEvent::FocusOut:
2475     case QEvent::HoverEnter:
2476     case QEvent::HoverLeave:
2477     case QEvent::HoverMove:
2478     case QEvent::TouchCancel:
2479         QCoreApplication::sendEvent(item, e);
2480         break;
2481     case QEvent::TouchBegin:
2482     case QEvent::TouchUpdate:
2483     case QEvent::TouchEnd:
2484         d->sendFilteredTouchEvent(item->parentItem(), item, static_cast<QTouchEvent *>(e));
2485         break;
2486     default:
2487         break;
2488     }
2489
2490     return false;
2491 }
2492
2493 void QQuickWindowPrivate::cleanupNodes()
2494 {
2495     for (int ii = 0; ii < cleanupNodeList.count(); ++ii)
2496         delete cleanupNodeList.at(ii);
2497     cleanupNodeList.clear();
2498 }
2499
2500 void QQuickWindowPrivate::cleanupNodesOnShutdown(QQuickItem *item)
2501 {
2502     QQuickItemPrivate *p = QQuickItemPrivate::get(item);
2503     if (p->itemNodeInstance) {
2504         delete p->itemNodeInstance;
2505         p->itemNodeInstance = 0;
2506
2507         if (p->extra.isAllocated()) {
2508             p->extra->opacityNode = 0;
2509             p->extra->clipNode = 0;
2510             p->extra->rootNode = 0;
2511         }
2512
2513         p->groupNode = 0;
2514         p->paintNode = 0;
2515
2516         p->dirty(QQuickItemPrivate::Window);
2517     }
2518
2519     for (int ii = 0; ii < p->childItems.count(); ++ii)
2520         cleanupNodesOnShutdown(p->childItems.at(ii));
2521 }
2522
2523 // This must be called from the render thread, with the main thread frozen
2524 void QQuickWindowPrivate::cleanupNodesOnShutdown()
2525 {
2526     Q_Q(QQuickWindow);
2527     cleanupNodes();
2528     cleanupNodesOnShutdown(contentItem);
2529     QSet<QQuickItem *>::const_iterator it = parentlessItems.begin();
2530     for (; it != parentlessItems.end(); ++it)
2531         cleanupNodesOnShutdown(*it);
2532     animationController->windowNodesDestroyed();
2533     q->cleanupSceneGraph();
2534 }
2535
2536 void QQuickWindowPrivate::updateDirtyNodes()
2537 {
2538     qCDebug(DBG_DIRTY) << "QQuickWindowPrivate::updateDirtyNodes():";
2539
2540     cleanupNodes();
2541
2542     QQuickItem *updateList = dirtyItemList;
2543     dirtyItemList = 0;
2544     if (updateList) QQuickItemPrivate::get(updateList)->prevDirtyItem = &updateList;
2545
2546     while (updateList) {
2547         QQuickItem *item = updateList;
2548         QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
2549         itemPriv->removeFromDirtyList();
2550
2551         qCDebug(DBG_DIRTY) << "   QSGNode:" << item << qPrintable(itemPriv->dirtyToString());
2552         updateDirtyNode(item);
2553     }
2554 }
2555
2556 void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
2557 {
2558     QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
2559     quint32 dirty = itemPriv->dirtyAttributes;
2560     itemPriv->dirtyAttributes = 0;
2561
2562     if ((dirty & QQuickItemPrivate::TransformUpdateMask) ||
2563         (dirty & QQuickItemPrivate::Size && itemPriv->origin() != QQuickItem::TopLeft &&
2564          (itemPriv->scale() != 1. || itemPriv->rotation() != 0.))) {
2565
2566         QMatrix4x4 matrix;
2567
2568         if (itemPriv->x != 0. || itemPriv->y != 0.)
2569             matrix.translate(itemPriv->x, itemPriv->y);
2570
2571         for (int ii = itemPriv->transforms.count() - 1; ii >= 0; --ii)
2572             itemPriv->transforms.at(ii)->applyTo(&matrix);
2573
2574         if (itemPriv->scale() != 1. || itemPriv->rotation() != 0.) {
2575             QPointF origin = item->transformOriginPoint();
2576             matrix.translate(origin.x(), origin.y());
2577             if (itemPriv->scale() != 1.)
2578                 matrix.scale(itemPriv->scale(), itemPriv->scale());
2579             if (itemPriv->rotation() != 0.)
2580                 matrix.rotate(itemPriv->rotation(), 0, 0, 1);
2581             matrix.translate(-origin.x(), -origin.y());
2582         }
2583
2584         itemPriv->itemNode()->setMatrix(matrix);
2585     }
2586
2587     bool clipEffectivelyChanged = (dirty & (QQuickItemPrivate::Clip | QQuickItemPrivate::Window)) &&
2588                                   ((item->clip() == false) != (itemPriv->clipNode() == 0));
2589     int effectRefCount = itemPriv->extra.isAllocated()?itemPriv->extra->effectRefCount:0;
2590     bool effectRefEffectivelyChanged = (dirty & (QQuickItemPrivate::EffectReference | QQuickItemPrivate::Window)) &&
2591                                   ((effectRefCount == 0) != (itemPriv->rootNode() == 0));
2592
2593     if (clipEffectivelyChanged) {
2594         QSGNode *parent = itemPriv->opacityNode() ? (QSGNode *) itemPriv->opacityNode() :
2595                                                     (QSGNode *)itemPriv->itemNode();
2596         QSGNode *child = itemPriv->rootNode() ? (QSGNode *)itemPriv->rootNode() :
2597                                                 (QSGNode *)itemPriv->groupNode;
2598
2599         if (item->clip()) {
2600             Q_ASSERT(itemPriv->clipNode() == 0);
2601             itemPriv->extra.value().clipNode = new QQuickDefaultClipNode(item->clipRect());
2602             itemPriv->clipNode()->update();
2603
2604             if (child)
2605                 parent->removeChildNode(child);
2606             parent->appendChildNode(itemPriv->clipNode());
2607             if (child)
2608                 itemPriv->clipNode()->appendChildNode(child);
2609
2610         } else {
2611             Q_ASSERT(itemPriv->clipNode() != 0);
2612             parent->removeChildNode(itemPriv->clipNode());
2613             if (child)
2614                 itemPriv->clipNode()->removeChildNode(child);
2615             delete itemPriv->clipNode();
2616             itemPriv->extra->clipNode = 0;
2617             if (child)
2618                 parent->appendChildNode(child);
2619         }
2620     }
2621
2622     if (dirty & QQuickItemPrivate::ChildrenUpdateMask)
2623         itemPriv->childContainerNode()->removeAllChildNodes();
2624
2625     if (effectRefEffectivelyChanged) {
2626         QSGNode *parent = itemPriv->clipNode();
2627         if (!parent)
2628             parent = itemPriv->opacityNode();
2629         if (!parent)
2630             parent = itemPriv->itemNode();
2631         QSGNode *child = itemPriv->groupNode;
2632
2633         if (itemPriv->extra.isAllocated() && itemPriv->extra->effectRefCount) {
2634             Q_ASSERT(itemPriv->rootNode() == 0);
2635             itemPriv->extra->rootNode = new QSGRootNode;
2636
2637             if (child)
2638                 parent->removeChildNode(child);
2639             parent->appendChildNode(itemPriv->rootNode());
2640             if (child)
2641                 itemPriv->rootNode()->appendChildNode(child);
2642         } else {
2643             Q_ASSERT(itemPriv->rootNode() != 0);
2644             parent->removeChildNode(itemPriv->rootNode());
2645             if (child)
2646                 itemPriv->rootNode()->removeChildNode(child);
2647             delete itemPriv->rootNode();
2648             itemPriv->extra->rootNode = 0;
2649             if (child)
2650                 parent->appendChildNode(child);
2651         }
2652     }
2653
2654     if (dirty & QQuickItemPrivate::ChildrenUpdateMask) {
2655         QSGNode *groupNode = itemPriv->groupNode;
2656         if (groupNode)
2657             groupNode->removeAllChildNodes();
2658
2659         QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
2660         int ii = 0;
2661
2662         for (; ii < orderedChildren.count() && orderedChildren.at(ii)->z() < 0; ++ii) {
2663             QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
2664             if (!childPrivate->explicitVisible &&
2665                 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2666                 continue;
2667             if (childPrivate->itemNode()->parent())
2668                 childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
2669
2670             itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
2671         }
2672
2673         QSGNode *beforePaintNode = itemPriv->groupNode ? itemPriv->groupNode->lastChild() : 0;
2674         if (beforePaintNode || itemPriv->extra.isAllocated())
2675             itemPriv->extra.value().beforePaintNode = beforePaintNode;
2676
2677         if (itemPriv->paintNode)
2678             itemPriv->childContainerNode()->appendChildNode(itemPriv->paintNode);
2679
2680         for (; ii < orderedChildren.count(); ++ii) {
2681             QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
2682             if (!childPrivate->explicitVisible &&
2683                 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2684                 continue;
2685             if (childPrivate->itemNode()->parent())
2686                 childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
2687
2688             itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
2689         }
2690     }
2691
2692     if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode()) {
2693         itemPriv->clipNode()->setRect(item->clipRect());
2694         itemPriv->clipNode()->update();
2695     }
2696
2697     if (dirty & (QQuickItemPrivate::OpacityValue | QQuickItemPrivate::Visible
2698                  | QQuickItemPrivate::HideReference | QQuickItemPrivate::Window))
2699     {
2700         qreal opacity = itemPriv->explicitVisible && (!itemPriv->extra.isAllocated() || itemPriv->extra->hideRefCount == 0)
2701                       ? itemPriv->opacity() : qreal(0);
2702
2703         if (opacity != 1 && !itemPriv->opacityNode()) {
2704             itemPriv->extra.value().opacityNode = new QSGOpacityNode;
2705
2706             QSGNode *parent = itemPriv->itemNode();
2707             QSGNode *child = itemPriv->clipNode();
2708             if (!child)
2709                 child = itemPriv->rootNode();
2710             if (!child)
2711                 child = itemPriv->groupNode;
2712
2713             if (child)
2714                 parent->removeChildNode(child);
2715             parent->appendChildNode(itemPriv->opacityNode());
2716             if (child)
2717                 itemPriv->opacityNode()->appendChildNode(child);
2718         }
2719         if (itemPriv->opacityNode())
2720             itemPriv->opacityNode()->setOpacity(opacity);
2721     }
2722
2723     if (dirty & QQuickItemPrivate::ContentUpdateMask) {
2724
2725         if (itemPriv->flags & QQuickItem::ItemHasContents) {
2726             updatePaintNodeData.transformNode = itemPriv->itemNode();
2727             itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
2728
2729             Q_ASSERT(itemPriv->paintNode == 0 ||
2730                      itemPriv->paintNode->parent() == 0 ||
2731                      itemPriv->paintNode->parent() == itemPriv->childContainerNode());
2732
2733             if (itemPriv->paintNode && itemPriv->paintNode->parent() == 0) {
2734                 if (itemPriv->extra.isAllocated() && itemPriv->extra->beforePaintNode)
2735                     itemPriv->childContainerNode()->insertChildNodeAfter(itemPriv->paintNode, itemPriv->extra->beforePaintNode);
2736                 else
2737                     itemPriv->childContainerNode()->prependChildNode(itemPriv->paintNode);
2738             }
2739         } else if (itemPriv->paintNode) {
2740             delete itemPriv->paintNode;
2741             itemPriv->paintNode = 0;
2742         }
2743     }
2744
2745 #ifndef QT_NO_DEBUG
2746     // Check consistency.
2747     const QSGNode *nodeChain[] = {
2748         itemPriv->itemNodeInstance,
2749         itemPriv->opacityNode(),
2750         itemPriv->clipNode(),
2751         itemPriv->rootNode(),
2752         itemPriv->groupNode,
2753         itemPriv->paintNode,
2754     };
2755
2756     int ip = 0;
2757     for (;;) {
2758         while (ip < 5 && nodeChain[ip] == 0)
2759             ++ip;
2760         if (ip == 5)
2761             break;
2762         int ic = ip + 1;
2763         while (ic < 5 && nodeChain[ic] == 0)
2764             ++ic;
2765         const QSGNode *parent = nodeChain[ip];
2766         const QSGNode *child = nodeChain[ic];
2767         if (child == 0) {
2768             Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 0);
2769         } else {
2770             Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 1);
2771             Q_ASSERT(child->parent() == parent);
2772             bool containsChild = false;
2773             for (QSGNode *n = parent->firstChild(); n; n = n->nextSibling())
2774                 containsChild |= (n == child);
2775             Q_ASSERT(containsChild);
2776         }
2777         ip = ic;
2778     }
2779 #endif
2780
2781 }
2782
2783 bool QQuickWindowPrivate::emitError(QQuickWindow::SceneGraphError error, const QString &msg)
2784 {
2785     Q_Q(QQuickWindow);
2786     static const QMetaMethod errorSignal = QMetaMethod::fromSignal(&QQuickWindow::sceneGraphError);
2787     if (q->isSignalConnected(errorSignal)) {
2788         emit q->sceneGraphError(error, msg);
2789         return true;
2790     }
2791     return false;
2792 }
2793
2794 void QQuickWindow::maybeUpdate()
2795 {
2796     Q_D(QQuickWindow);
2797     if (d->renderControl)
2798         d->renderControl->maybeUpdate();
2799     else if (d->windowManager)
2800         d->windowManager->maybeUpdate(this);
2801 }
2802
2803 void QQuickWindow::cleanupSceneGraph()
2804 {
2805     Q_D(QQuickWindow);
2806
2807     if (!d->renderer)
2808         return;
2809
2810     delete d->renderer->rootNode();
2811     delete d->renderer;
2812
2813     d->renderer = 0;
2814 }
2815