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