ca94570a3ce5718ee60e4af52220228f7e1c29dd
[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     \qmltype Window
779     \instantiates QQuickWindow
780     \inqmlmodule QtQuick.Window 2
781     \ingroup qtquick-visual
782     \brief Creates a new top-level window
783
784     The Window object creates a new top-level window for a QtQuick scene. It automatically sets up the
785     window for use with QtQuick 2.0 graphical types.
786
787     To use this type, you will need to import the module with the following line:
788     \code
789     import QtQuick.Window 2.0
790     \endcode
791
792     Restricting this import will allow you to have a QML environment without access to window system features.
793 */
794 /*!
795     \class QQuickWindow
796     \since QtQuick 2.0
797
798     \inmodule QtQuick
799
800     \brief The QQuickWindow class provides the window for displaying a graphical QML scene
801
802     QQuickWindow provides the graphical scene management needed to interact with and display
803     a scene of QQuickItems.
804
805     A QQuickWindow always has a single invisible root item. To add items to this window,
806     reparent the items to the root item or to an existing item in the scene.
807
808     For easily displaying a scene from a QML file, see \l{QQuickView}.
809
810     \section1 Scene Graph and Rendering
811
812     The QQuickWindow uses a scene graph on top of OpenGL to render. This scene graph is disconnected
813     from the QML scene and potentially lives in another thread, depending on the platform
814     implementation. Since the rendering scene graph lives independently from the QML scene, it can
815     also be completely released without affecting the state of the QML scene.
816
817     The sceneGraphInitialized() signal is emitted on the rendering thread before the QML scene is
818     rendered to the screen for the first time. If the rendering scene graph has been released
819     the signal will be emitted again before the next frame is rendered.
820
821     The rendering of each frame is broken down into the following
822     steps, in the given order:
823
824     \list 1
825
826     \li The QQuickWindow::beforeSynchronizing() signal is emitted.
827     Applications can make direct connections (Qt::DirectConnection)
828     to this signal to do any preparation required before calls to
829     QQuickItem::updatePaintNode().
830
831     \li Synchronization of the QML state into the scene graph. This is
832     done by calling the QQuickItem::updatePaintNode() function on all
833     items that have changed since the previous frame. When a dedicated
834     rendering thread is used, the GUI thread is blocked during this
835     synchroniation. This is the only time the QML items and the nodes
836     in the scene graph interact.
837
838     \li The window to be rendered is made current using
839     QOpenGLContext::makeCurrent().
840
841     \li The QQuickWindow::beforeRendering() signal is
842     emitted. Applications can make direct connections
843     (Qt::DirectConnection) to this signal to use custom OpenGL calls
844     which will then stack visually beneath the QML scene.
845
846     \li Items that have specified QSGNode::UsesPreprocess, will have their
847     QSGNode::preprocess() function invoked.
848
849     \li The QQuickWindow is cleared according to what is specified
850     using QQuickWindow::setClearBeforeRendering() and
851     QQuickWindow::setClearColor().
852
853     \li The scene graph is rendered.
854
855     \li The QQuickWindow::afterRendering() signal is
856     emitted. Applications can make direct connections
857     (Qt::DirectConnection) to this signal to use custom OpenGL calls
858     which will then stack visually over the QML scene.
859
860     \li The rendered frame is swapped and QQuickWindow::frameSwapped()
861     is emitted.
862
863     \endlist
864
865     All of the above happen on the rendering thread, when applicable.
866
867     While the scene graph is being rendered on the rendering thread, the GUI will process animations
868     for the next frame. This means that as long as users are not using scene graph API
869     directly, the added complexity of a rendering thread can be completely ignored.
870
871     When a QQuickWindow is programatically hidden with hide() or setVisible(false), it will
872     stop rendering and its scene graph and OpenGL context might be released. The
873     sceneGraphInvalidated() signal will be emitted when this happens.
874
875     \warning It is crucial that OpenGL operations and interaction with the scene graph happens
876     exclusively on the rendering thread, primarily during the updatePaintNode() phase.
877
878     \warning As signals related to rendering might be emitted from the rendering thread,
879     connections should be made using Qt::DirectConnection
880
881
882     \section2 Resource Management
883
884     QML will typically try to cache images, scene graph nodes, etc to improve performance, but in
885     some low-memory scenarios it might be required to aggressively release these resources. The
886     releaseResources() can be used to force clean up of certain resources. Calling releaseResources()
887     may result in the entire scene graph and its OpenGL context being deleted. The
888     sceneGraphInvalidated() signal will be emitted when this happens.
889
890     \sa {OpenGL Under QML Example}
891
892 */
893 QQuickWindow::QQuickWindow(QWindow *parent)
894     : QWindow(*(new QQuickWindowPrivate), parent)
895 {
896     Q_D(QQuickWindow);
897     d->init(this);
898 }
899
900 QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent)
901     : QWindow(dd, parent)
902 {
903     Q_D(QQuickWindow);
904     d->init(this);
905 }
906
907 QQuickWindow::~QQuickWindow()
908 {
909     Q_D(QQuickWindow);
910
911     d->windowManager->windowDestroyed(this);
912
913     QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
914     delete d->incubationController; d->incubationController = 0;
915
916     delete d->rootItem; d->rootItem = 0;
917 }
918
919
920
921 /*!
922     This function tries to release redundant resources currently held by the QML scene.
923
924     Calling this function might result in the scene graph and the OpenGL context used
925     for rendering being released to release graphics memory. If this happens, the
926     sceneGraphInvalidated() signal will be called, allowing users to clean up their
927     own graphics resources. The setPersistentOpenGLContext() and setPersistentSceneGraph()
928     functions can be used to prevent this from happening, if handling the cleanup is
929     not feasible in the application, at the cost of higher memory usage.
930
931     \sa sceneGraphInvalidated(), setPersistentOpenGLContext(), setPersistentSceneGraph()
932  */
933
934 void QQuickWindow::releaseResources()
935 {
936     Q_D(QQuickWindow);
937     d->windowManager->releaseResources();
938     QQuickPixmap::purgeCache();
939 }
940
941
942
943 /*!
944     Controls whether the OpenGL context can be released as a part of a call to
945     releaseResources().
946
947     The OpenGL context might still be released when the user makes an explicit
948     call to hide().
949
950     \sa setPersistentSceneGraph()
951  */
952
953 void QQuickWindow::setPersistentOpenGLContext(bool persistent)
954 {
955     Q_D(QQuickWindow);
956     d->persistentGLContext = persistent;
957 }
958
959
960 /*!
961     Returns whether the OpenGL context can be released as a part of a call to
962     releaseResources().
963  */
964
965 bool QQuickWindow::isPersistentOpenGLContext() const
966 {
967     Q_D(const QQuickWindow);
968     return d->persistentGLContext;
969 }
970
971
972
973 /*!
974     Controls whether the scene graph nodes and resources can be released as a
975     part of a call to releaseResources().
976
977     The scene graph nodes and resources might still be released when the user
978     makes an explicit call to hide().
979
980     \sa setPersistentOpenGLContext()
981  */
982
983 void QQuickWindow::setPersistentSceneGraph(bool persistent)
984 {
985     Q_D(QQuickWindow);
986     d->persistentSceneGraph = persistent;
987 }
988
989
990
991 /*!
992     Returns whether the scene graph nodes and resources can be released as a part
993     of a call to releaseResources().
994  */
995
996 bool QQuickWindow::isPersistentSceneGraph() const
997 {
998     Q_D(const QQuickWindow);
999     return d->persistentSceneGraph;
1000 }
1001
1002
1003
1004
1005
1006 /*!
1007   Returns the invisible root item of the scene.
1008
1009   A QQuickWindow always has a single invisible root item containing all of its content.
1010   To add items to this window, reparent the items to the contentItem or to an existing
1011   item in the scene.
1012 */
1013 QQuickItem *QQuickWindow::contentItem() const
1014 {
1015     Q_D(const QQuickWindow);
1016
1017     return d->rootItem;
1018 }
1019
1020 /*!
1021   Returns the item which currently has active focus.
1022 */
1023 QQuickItem *QQuickWindow::activeFocusItem() const
1024 {
1025     Q_D(const QQuickWindow);
1026
1027     return d->activeFocusItem;
1028 }
1029
1030 /*!
1031   \internal
1032   \reimp
1033 */
1034 QObject *QQuickWindow::focusObject() const
1035 {
1036     Q_D(const QQuickWindow);
1037
1038     if (d->activeFocusItem)
1039         return d->activeFocusItem;
1040     return const_cast<QQuickWindow*>(this);
1041 }
1042
1043
1044 /*!
1045   Returns the item which currently has the mouse grab.
1046 */
1047 QQuickItem *QQuickWindow::mouseGrabberItem() const
1048 {
1049     Q_D(const QQuickWindow);
1050
1051     return d->mouseGrabberItem;
1052 }
1053
1054
1055 /*!
1056     \qmlproperty color QtQuick.Window2::Window::color
1057
1058     The background color for the window.
1059
1060     Setting this property is more efficient than using a separate Rectangle.
1061 */
1062
1063 bool QQuickWindowPrivate::clearHover()
1064 {
1065     Q_Q(QQuickWindow);
1066     if (hoverItems.isEmpty())
1067         return false;
1068
1069     QPointF pos = q->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition.toPoint());
1070
1071     bool accepted = false;
1072     foreach (QQuickItem* item, hoverItems)
1073         accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), true) || accepted;
1074     hoverItems.clear();
1075     return accepted;
1076 }
1077
1078 /*! \reimp */
1079 bool QQuickWindow::event(QEvent *e)
1080 {
1081     Q_D(QQuickWindow);
1082
1083     switch (e->type()) {
1084
1085     case QEvent::TouchBegin:
1086     case QEvent::TouchUpdate:
1087     case QEvent::TouchEnd: {
1088         QTouchEvent *touch = static_cast<QTouchEvent*>(e);
1089         d->translateTouchEvent(touch);
1090         // return in order to avoid the QWindow::event below
1091         return d->deliverTouchEvent(touch);
1092     }
1093         break;
1094     case QEvent::TouchCancel:
1095         // return in order to avoid the QWindow::event below
1096         return d->deliverTouchCancelEvent(static_cast<QTouchEvent*>(e));
1097         break;
1098     case QEvent::Leave:
1099         d->clearHover();
1100         d->lastMousePosition = QPoint();
1101         break;
1102 #ifndef QT_NO_DRAGANDDROP
1103     case QEvent::DragEnter:
1104     case QEvent::DragLeave:
1105     case QEvent::DragMove:
1106     case QEvent::Drop:
1107         d->deliverDragEvent(&d->dragGrabber, e);
1108         break;
1109 #endif
1110     case QEvent::WindowDeactivate:
1111         rootItem()->windowDeactivateEvent();
1112         break;
1113     case QEvent::FocusAboutToChange:
1114         if (d->activeFocusItem)
1115             qGuiApp->inputMethod()->commit();
1116         break;
1117     default:
1118         break;
1119     }
1120
1121     return QWindow::event(e);
1122 }
1123
1124 /*! \reimp */
1125 void QQuickWindow::keyPressEvent(QKeyEvent *e)
1126 {
1127     Q_D(QQuickWindow);
1128
1129     if (d->activeFocusItem)
1130         sendEvent(d->activeFocusItem, e);
1131 }
1132
1133 /*! \reimp */
1134 void QQuickWindow::keyReleaseEvent(QKeyEvent *e)
1135 {
1136     Q_D(QQuickWindow);
1137
1138     if (d->activeFocusItem)
1139         sendEvent(d->activeFocusItem, e);
1140 }
1141
1142 QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos)
1143 {
1144     int caps = QGuiApplicationPrivate::mouseEventCaps(event);
1145     QVector2D velocity = QGuiApplicationPrivate::mouseEventVelocity(event);
1146     QMouseEvent *me = new QMouseEvent(event->type(),
1147                                       transformedLocalPos ? *transformedLocalPos : event->localPos(),
1148                                       event->windowPos(), event->screenPos(),
1149                                       event->button(), event->buttons(), event->modifiers());
1150     QGuiApplicationPrivate::setMouseEventCapsAndVelocity(me, caps, velocity);
1151     me->setTimestamp(event->timestamp());
1152     return me;
1153 }
1154
1155 bool QQuickWindowPrivate::deliverInitialMousePressEvent(QQuickItem *item, QMouseEvent *event)
1156 {
1157     Q_Q(QQuickWindow);
1158
1159     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1160
1161     if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1162         QPointF p = item->mapFromScene(event->windowPos());
1163         if (!item->contains(p))
1164             return false;
1165     }
1166
1167     QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1168     for (int ii = children.count() - 1; ii >= 0; --ii) {
1169         QQuickItem *child = children.at(ii);
1170         if (!child->isVisible() || !child->isEnabled())
1171             continue;
1172         if (deliverInitialMousePressEvent(child, event))
1173             return true;
1174     }
1175
1176     if (itemPrivate->acceptedMouseButtons() & event->button()) {
1177         QPointF localPos = item->mapFromScene(event->windowPos());
1178         if (item->contains(localPos)) {
1179             QScopedPointer<QMouseEvent> me(cloneMouseEvent(event, &localPos));
1180             me->accept();
1181             item->grabMouse();
1182             q->sendEvent(item, me.data());
1183             event->setAccepted(me->isAccepted());
1184             if (me->isAccepted())
1185                 return true;
1186             if (mouseGrabberItem && !event->buttons())
1187                 mouseGrabberItem->ungrabMouse();
1188         }
1189     }
1190
1191     return false;
1192 }
1193
1194 bool QQuickWindowPrivate::deliverMouseEvent(QMouseEvent *event)
1195 {
1196     Q_Q(QQuickWindow);
1197
1198     lastMousePosition = event->windowPos();
1199
1200     if (!mouseGrabberItem &&
1201          event->type() == QEvent::MouseButtonPress &&
1202          (event->buttons() & event->button()) == event->buttons()) {
1203         if (deliverInitialMousePressEvent(rootItem, event))
1204             event->accept();
1205         else
1206             event->ignore();
1207         return event->isAccepted();
1208     }
1209
1210     if (mouseGrabberItem) {
1211         QPointF localPos = mouseGrabberItem->mapFromScene(event->windowPos());
1212         QScopedPointer<QMouseEvent> me(cloneMouseEvent(event, &localPos));
1213         me->accept();
1214         q->sendEvent(mouseGrabberItem, me.data());
1215         event->setAccepted(me->isAccepted());
1216         if (me->isAccepted())
1217             return true;
1218     }
1219
1220     return false;
1221 }
1222
1223 /*! \reimp */
1224 void QQuickWindow::mousePressEvent(QMouseEvent *event)
1225 {
1226     Q_D(QQuickWindow);
1227 #ifdef MOUSE_DEBUG
1228     qWarning() << "QQuickWindow::mousePressEvent()" << event->localPos() << event->button() << event->buttons();
1229 #endif
1230
1231     d->deliverMouseEvent(event);
1232 }
1233
1234 /*! \reimp */
1235 void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
1236 {
1237     Q_D(QQuickWindow);
1238 #ifdef MOUSE_DEBUG
1239     qWarning() << "QQuickWindow::mouseReleaseEvent()" << event->localPos() << event->button() << event->buttons();
1240 #endif
1241
1242     if (!d->mouseGrabberItem) {
1243         QWindow::mouseReleaseEvent(event);
1244         return;
1245     }
1246
1247     d->deliverMouseEvent(event);
1248     if (d->mouseGrabberItem && !event->buttons())
1249         d->mouseGrabberItem->ungrabMouse();
1250 }
1251
1252 /*! \reimp */
1253 void QQuickWindow::mouseDoubleClickEvent(QMouseEvent *event)
1254 {
1255     Q_D(QQuickWindow);
1256 #ifdef MOUSE_DEBUG
1257     qWarning() << "QQuickWindow::mouseDoubleClickEvent()" << event->localPos() << event->button() << event->buttons();
1258 #endif
1259
1260     if (!d->mouseGrabberItem && (event->buttons() & event->button()) == event->buttons()) {
1261         if (d->deliverInitialMousePressEvent(d->rootItem, event))
1262             event->accept();
1263         else
1264             event->ignore();
1265         return;
1266     }
1267
1268     d->deliverMouseEvent(event);
1269 }
1270
1271 bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
1272                                       const QPointF &scenePos, const QPointF &lastScenePos,
1273                                       Qt::KeyboardModifiers modifiers, bool accepted)
1274 {
1275     Q_Q(QQuickWindow);
1276     const QTransform transform = QQuickItemPrivate::get(item)->windowToItemTransform();
1277
1278     //create copy of event
1279     QHoverEvent hoverEvent(type, transform.map(scenePos), transform.map(lastScenePos), modifiers);
1280     hoverEvent.setAccepted(accepted);
1281
1282     q->sendEvent(item, &hoverEvent);
1283
1284     return hoverEvent.isAccepted();
1285 }
1286
1287 /*! \reimp */
1288 void QQuickWindow::mouseMoveEvent(QMouseEvent *event)
1289 {
1290     Q_D(QQuickWindow);
1291 #ifdef MOUSE_DEBUG
1292     qWarning() << "QQuickWindow::mouseMoveEvent()" << event->localPos() << event->button() << event->buttons();
1293 #endif
1294
1295 #ifndef QT_NO_CURSOR
1296     d->updateCursor(event->windowPos());
1297 #endif
1298
1299     if (!d->mouseGrabberItem) {
1300         if (d->lastMousePosition.isNull())
1301             d->lastMousePosition = event->windowPos();
1302         QPointF last = d->lastMousePosition;
1303         d->lastMousePosition = event->windowPos();
1304
1305         bool accepted = event->isAccepted();
1306         bool delivered = d->deliverHoverEvent(d->rootItem, event->windowPos(), last, event->modifiers(), accepted);
1307         if (!delivered) {
1308             //take care of any exits
1309             accepted = d->clearHover();
1310         }
1311         event->setAccepted(accepted);
1312         return;
1313     }
1314
1315     d->deliverMouseEvent(event);
1316 }
1317
1318 bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &scenePos, const QPointF &lastScenePos,
1319                                          Qt::KeyboardModifiers modifiers, bool &accepted)
1320 {
1321     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1322
1323     if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1324         QPointF p = item->mapFromScene(scenePos);
1325         if (!item->contains(p))
1326             return false;
1327     }
1328
1329     QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1330     for (int ii = children.count() - 1; ii >= 0; --ii) {
1331         QQuickItem *child = children.at(ii);
1332         if (!child->isVisible() || !child->isEnabled())
1333             continue;
1334         if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, accepted))
1335             return true;
1336     }
1337
1338     if (itemPrivate->hoverEnabled) {
1339         QPointF p = item->mapFromScene(scenePos);
1340         if (item->contains(p)) {
1341             if (!hoverItems.isEmpty() && hoverItems[0] == item) {
1342                 //move
1343                 accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
1344             } else {
1345                 QList<QQuickItem *> itemsToHover;
1346                 QQuickItem* parent = item;
1347                 itemsToHover << item;
1348                 while ((parent = parent->parentItem()))
1349                     itemsToHover << parent;
1350
1351                 // Leaving from previous hovered items until we reach the item or one of its ancestors.
1352                 while (!hoverItems.isEmpty() && !itemsToHover.contains(hoverItems[0])) {
1353                     sendHoverEvent(QEvent::HoverLeave, hoverItems[0], scenePos, lastScenePos, modifiers, accepted);
1354                     hoverItems.removeFirst();
1355                 }
1356
1357                 if (!hoverItems.isEmpty() && hoverItems[0] == item){//Not entering a new Item
1358                     // ### Shouldn't we send moves for the parent items as well?
1359                     accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted);
1360                 } else {
1361                     // Enter items that are not entered yet.
1362                     int startIdx = -1;
1363                     if (!hoverItems.isEmpty())
1364                         startIdx = itemsToHover.indexOf(hoverItems[0]) - 1;
1365                     if (startIdx == -1)
1366                         startIdx = itemsToHover.count() - 1;
1367
1368                     for (int i = startIdx; i >= 0; i--) {
1369                         QQuickItem *itemToHover = itemsToHover[i];
1370                         if (QQuickItemPrivate::get(itemToHover)->hoverEnabled) {
1371                             hoverItems.prepend(itemToHover);
1372                             sendHoverEvent(QEvent::HoverEnter, itemToHover, scenePos, lastScenePos, modifiers, accepted);
1373                         }
1374                     }
1375                 }
1376             }
1377             return true;
1378         }
1379     }
1380
1381     return false;
1382 }
1383
1384 bool QQuickWindowPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event)
1385 {
1386     Q_Q(QQuickWindow);
1387     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1388
1389     if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1390         QPointF p = item->mapFromScene(event->posF());
1391         if (!item->contains(p))
1392             return false;
1393     }
1394
1395     QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1396     for (int ii = children.count() - 1; ii >= 0; --ii) {
1397         QQuickItem *child = children.at(ii);
1398         if (!child->isVisible() || !child->isEnabled())
1399             continue;
1400         if (deliverWheelEvent(child, event))
1401             return true;
1402     }
1403
1404     QPointF p = item->mapFromScene(event->posF());
1405
1406     if (item->contains(p)) {
1407         QWheelEvent wheel(p, p, event->pixelDelta(), event->angleDelta(), event->delta(),
1408                           event->orientation(), event->buttons(), event->modifiers());
1409         wheel.accept();
1410         q->sendEvent(item, &wheel);
1411         if (wheel.isAccepted()) {
1412             event->accept();
1413             return true;
1414         }
1415     }
1416
1417     return false;
1418 }
1419
1420 #ifndef QT_NO_WHEELEVENT
1421 /*! \reimp */
1422 void QQuickWindow::wheelEvent(QWheelEvent *event)
1423 {
1424     Q_D(QQuickWindow);
1425 #ifdef MOUSE_DEBUG
1426     qWarning() << "QQuickWindow::wheelEvent()" << event->pixelDelta() << event->angleDelta();
1427 #endif
1428
1429     //if the actual wheel event was accepted, accept the compatability wheel event and return early
1430     if (d->lastWheelEventAccepted && event->angleDelta().isNull())
1431         return;
1432
1433     event->ignore();
1434     d->deliverWheelEvent(d->rootItem, event);
1435     d->lastWheelEventAccepted = event->isAccepted();
1436 }
1437 #endif // QT_NO_WHEELEVENT
1438
1439
1440 bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event)
1441 {
1442 #ifdef TOUCH_DEBUG
1443     qWarning("touchCancelEvent");
1444 #endif
1445     Q_Q(QQuickWindow);
1446     // A TouchCancel event will typically not contain any points.
1447     // Deliver it to all items that have active touches.
1448     QSet<QQuickItem *> cancelDelivered;
1449     foreach (QQuickItem *item, itemForTouchPointId) {
1450         if (cancelDelivered.contains(item))
1451             continue;
1452         cancelDelivered.insert(item);
1453         q->sendEvent(item, event);
1454     }
1455     touchMouseId = -1;
1456     if (mouseGrabberItem)
1457         mouseGrabberItem->ungrabMouse();
1458     // The next touch event can only be a TouchBegin so clean up.
1459     itemForTouchPointId.clear();
1460     return true;
1461 }
1462
1463 // check what kind of touch we have (begin/update) and
1464 // call deliverTouchPoints to actually dispatch the points
1465 bool QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event)
1466 {
1467 #ifdef TOUCH_DEBUG
1468     if (event->type() == QEvent::TouchBegin)
1469         qWarning() << "touchBeginEvent";
1470     else if (event->type() == QEvent::TouchUpdate)
1471         qWarning() << "touchUpdateEvent points";
1472     else if (event->type() == QEvent::TouchEnd)
1473         qWarning("touchEndEvent");
1474 #endif
1475
1476     // List of all items that received an event before
1477     // When we have TouchBegin this is and will stay empty
1478     QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > updatedPoints;
1479
1480     // Figure out who accepted a touch point last and put it in updatedPoints
1481     // Add additional item to newPoints
1482     const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
1483     QList<QTouchEvent::TouchPoint> newPoints;
1484     for (int i=0; i<touchPoints.count(); i++) {
1485         const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
1486         if (touchPoint.state() == Qt::TouchPointPressed) {
1487             newPoints << touchPoint;
1488         } else {
1489             // TouchPointStationary is relevant only to items which
1490             // are also receiving touch points with some other state.
1491             // But we have not yet decided which points go to which item,
1492             // so for now we must include all non-new points in updatedPoints.
1493             if (itemForTouchPointId.contains(touchPoint.id())) {
1494                 QQuickItem *item = itemForTouchPointId.value(touchPoint.id());
1495                 if (item)
1496                     updatedPoints[item].append(touchPoint);
1497             }
1498         }
1499     }
1500
1501     // Deliver the event, but only if there is at least one new point
1502     // or some item accepted a point and should receive an update
1503     if (newPoints.count() > 0 || updatedPoints.count() > 0) {
1504         QSet<int> acceptedNewPoints;
1505         event->setAccepted(deliverTouchPoints(rootItem, event, newPoints, &acceptedNewPoints, &updatedPoints));
1506     } else
1507         event->ignore();
1508
1509     // Remove released points from itemForTouchPointId
1510     if (event->touchPointStates() & Qt::TouchPointReleased) {
1511         for (int i=0; i<touchPoints.count(); i++) {
1512             if (touchPoints[i].state() == Qt::TouchPointReleased) {
1513                 itemForTouchPointId.remove(touchPoints[i].id());
1514                 if (touchPoints[i].id() == touchMouseId)
1515                     touchMouseId = -1;
1516             }
1517         }
1518     }
1519
1520     if (event->type() == QEvent::TouchEnd) {
1521         Q_ASSERT(itemForTouchPointId.isEmpty());
1522     }
1523
1524     return event->isAccepted();
1525 }
1526
1527 // This function recurses and sends the events to the individual items
1528 bool QQuickWindowPrivate::deliverTouchPoints(QQuickItem *item, QTouchEvent *event, const QList<QTouchEvent::TouchPoint> &newPoints, QSet<int> *acceptedNewPoints, QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > *updatedPoints)
1529 {
1530     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1531
1532     if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1533         for (int i=0; i<newPoints.count(); i++) {
1534             QPointF p = item->mapFromScene(newPoints[i].scenePos());
1535             if (!item->contains(p))
1536                 return false;
1537         }
1538     }
1539
1540     // Check if our children want the event (or parts of it)
1541     // This is the only point where touch event delivery recurses!
1542     QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1543     for (int ii = children.count() - 1; ii >= 0; --ii) {
1544         QQuickItem *child = children.at(ii);
1545         if (!child->isEnabled() || !child->isVisible())
1546             continue;
1547         if (deliverTouchPoints(child, event, newPoints, acceptedNewPoints, updatedPoints))
1548             return true;
1549     }
1550
1551     // None of the children accepted the event, so check the given item itself.
1552     // First, construct matchingPoints as a list of TouchPoints which the
1553     // given item might be interested in.  Any newly-pressed point which is
1554     // inside the item's bounds will be interesting, and also any updated point
1555     // which was already accepted by that item when it was first pressed.
1556     // (A point which was already accepted is effectively "grabbed" by the item.)
1557
1558     // set of IDs of "interesting" new points
1559     QSet<int> matchingNewPoints;
1560     // set of points which this item has previously accepted, for starters
1561     QList<QTouchEvent::TouchPoint> matchingPoints = (*updatedPoints)[item];
1562     // now add the new points which are inside this item's bounds
1563     if (newPoints.count() > 0 && acceptedNewPoints->count() < newPoints.count()) {
1564         for (int i = 0; i < newPoints.count(); i++) {
1565             if (acceptedNewPoints->contains(newPoints[i].id()))
1566                 continue;
1567             QPointF p = item->mapFromScene(newPoints[i].scenePos());
1568             if (item->contains(p)) {
1569                 matchingNewPoints.insert(newPoints[i].id());
1570                 matchingPoints << newPoints[i];
1571             }
1572         }
1573     }
1574     // If there are no matching new points, and the existing points are all stationary,
1575     // there's no need to send an event to this item.  This is required by a test in
1576     // tst_qquickwindow::touchEvent_basic:
1577     // a single stationary press on an item shouldn't cause an event
1578     if (matchingNewPoints.isEmpty()) {
1579         bool stationaryOnly = true;
1580         Q_FOREACH (QTouchEvent::TouchPoint tp, matchingPoints)
1581             if (tp.state() != Qt::TouchPointStationary)
1582                 stationaryOnly = false;
1583         if (stationaryOnly)
1584             matchingPoints.clear();
1585     }
1586
1587     if (!matchingPoints.isEmpty()) {
1588         // Now we know this item might be interested in the event. Copy and send it, but
1589         // with only the subset of TouchPoints which are relevant to that item: that's matchingPoints.
1590         QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1591         transformTouchPoints(matchingPoints, itemPrivate->windowToItemTransform());
1592         deliverMatchingPointsToItem(item, event, acceptedNewPoints, matchingNewPoints, matchingPoints);
1593     }
1594
1595     // record the fact that this item has been visited already
1596     updatedPoints->remove(item);
1597
1598     // recursion is done only if ALL touch points have been delivered
1599     return (acceptedNewPoints->count() == newPoints.count() && updatedPoints->isEmpty());
1600 }
1601
1602 // touchEventForItemBounds has no means to generate a touch event that contains
1603 // only the points that are relevant for this item.  Thus the need for
1604 // matchingPoints to already be that set of interesting points.
1605 // They are all pre-transformed, too.
1606 bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet<int> *acceptedNewPoints, const QSet<int> &matchingNewPoints, const QList<QTouchEvent::TouchPoint> &matchingPoints)
1607 {
1608     QScopedPointer<QTouchEvent> touchEvent(touchEventWithPoints(*event, matchingPoints));
1609     touchEvent.data()->setTarget(item);
1610     bool touchEventAccepted = false;
1611
1612     // First check whether the parent wants to be a filter,
1613     // and if the parent accepts the event we are done.
1614     if (sendFilteredTouchEvent(item->parentItem(), item, event)) {
1615         event->accept();
1616         return true;
1617     }
1618
1619     // Since it can change in sendEvent, update itemForTouchPointId now
1620     foreach (int id, matchingNewPoints)
1621         itemForTouchPointId[id] = item;
1622
1623     // Deliver the touch event to the given item
1624     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1625     itemPrivate->deliverTouchEvent(touchEvent.data());
1626     touchEventAccepted = touchEvent->isAccepted();
1627
1628     // If the touch event wasn't accepted, synthesize a mouse event and see if the item wants it.
1629     if (!touchEventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton)) {
1630         //  send mouse event
1631         event->setAccepted(translateTouchToMouse(item, event));
1632         if (event->isAccepted()) {
1633             touchEventAccepted = true;
1634         }
1635     }
1636
1637     if (touchEventAccepted) {
1638         // If the touch was accepted (regardless by whom or in what form),
1639         // update acceptedNewPoints.
1640         foreach (int id, matchingNewPoints)
1641             acceptedNewPoints->insert(id);
1642     } else {
1643         // But if the event was not accepted then we know this item
1644         // will not be interested in further updates for those touchpoint IDs either.
1645         foreach (int id, matchingNewPoints)
1646             if (itemForTouchPointId[id] == item)
1647                 itemForTouchPointId.remove(id);
1648     }
1649
1650     return touchEventAccepted;
1651 }
1652
1653 QTouchEvent *QQuickWindowPrivate::touchEventForItemBounds(QQuickItem *target, const QTouchEvent &originalEvent)
1654 {
1655     const QList<QTouchEvent::TouchPoint> &touchPoints = originalEvent.touchPoints();
1656     QList<QTouchEvent::TouchPoint> pointsInBounds;
1657     // if all points are stationary, the list of points should be empty to signal a no-op
1658     if (originalEvent.touchPointStates() != Qt::TouchPointStationary) {
1659         for (int i = 0; i < touchPoints.count(); ++i) {
1660             const QTouchEvent::TouchPoint &tp = touchPoints.at(i);
1661             if (tp.state() == Qt::TouchPointPressed) {
1662                 QPointF p = target->mapFromScene(tp.scenePos());
1663                 if (target->contains(p))
1664                     pointsInBounds.append(tp);
1665             } else {
1666                 pointsInBounds.append(tp);
1667             }
1668         }
1669         transformTouchPoints(pointsInBounds, QQuickItemPrivate::get(target)->windowToItemTransform());
1670     }
1671
1672     QTouchEvent* touchEvent = touchEventWithPoints(originalEvent, pointsInBounds);
1673     touchEvent->setTarget(target);
1674     return touchEvent;
1675 }
1676
1677 QTouchEvent *QQuickWindowPrivate::touchEventWithPoints(const QTouchEvent &event, const QList<QTouchEvent::TouchPoint> &newPoints)
1678 {
1679     Qt::TouchPointStates eventStates;
1680     for (int i=0; i<newPoints.count(); i++)
1681         eventStates |= newPoints[i].state();
1682     // if all points have the same state, set the event type accordingly
1683     QEvent::Type eventType = event.type();
1684     switch (eventStates) {
1685         case Qt::TouchPointPressed:
1686             eventType = QEvent::TouchBegin;
1687             break;
1688         case Qt::TouchPointReleased:
1689             eventType = QEvent::TouchEnd;
1690             break;
1691         default:
1692             eventType = QEvent::TouchUpdate;
1693             break;
1694     }
1695
1696     QTouchEvent *touchEvent = new QTouchEvent(eventType);
1697     touchEvent->setWindow(event.window());
1698     touchEvent->setTarget(event.target());
1699     touchEvent->setDevice(event.device());
1700     touchEvent->setModifiers(event.modifiers());
1701     touchEvent->setTouchPoints(newPoints);
1702     touchEvent->setTouchPointStates(eventStates);
1703     touchEvent->setTimestamp(event.timestamp());
1704     touchEvent->accept();
1705     return touchEvent;
1706 }
1707
1708 #ifndef QT_NO_DRAGANDDROP
1709 void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *event)
1710 {
1711     Q_Q(QQuickWindow);
1712     grabber->resetTarget();
1713     QQuickDragGrabber::iterator grabItem = grabber->begin();
1714     if (grabItem != grabber->end()) {
1715         Q_ASSERT(event->type() != QEvent::DragEnter);
1716         if (event->type() == QEvent::Drop) {
1717             QDropEvent *e = static_cast<QDropEvent *>(event);
1718             for (e->setAccepted(false); !e->isAccepted() && grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
1719                 QPointF p = (**grabItem)->mapFromScene(e->pos());
1720                 QDropEvent translatedEvent(
1721                         p.toPoint(),
1722                         e->possibleActions(),
1723                         e->mimeData(),
1724                         e->mouseButtons(),
1725                         e->keyboardModifiers());
1726                 QQuickDropEventEx::copyActions(&translatedEvent, *e);
1727                 q->sendEvent(**grabItem, &translatedEvent);
1728                 e->setAccepted(translatedEvent.isAccepted());
1729                 e->setDropAction(translatedEvent.dropAction());
1730                 grabber->setTarget(**grabItem);
1731             }
1732         }
1733         if (event->type() != QEvent::DragMove) {    // Either an accepted drop or a leave.
1734             QDragLeaveEvent leaveEvent;
1735             for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem))
1736                 q->sendEvent(**grabItem, &leaveEvent);
1737             return;
1738         } else for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
1739             QDragMoveEvent *moveEvent = static_cast<QDragMoveEvent *>(event);
1740             if (deliverDragEvent(grabber, **grabItem, moveEvent)) {
1741                 moveEvent->setAccepted(true);
1742                 for (++grabItem; grabItem != grabber->end();) {
1743                     QPointF p = (**grabItem)->mapFromScene(moveEvent->pos());
1744                     if ((**grabItem)->contains(p)) {
1745                         QDragMoveEvent translatedEvent(
1746                                 p.toPoint(),
1747                                 moveEvent->possibleActions(),
1748                                 moveEvent->mimeData(),
1749                                 moveEvent->mouseButtons(),
1750                                 moveEvent->keyboardModifiers());
1751                         QQuickDropEventEx::copyActions(&translatedEvent, *moveEvent);
1752                         q->sendEvent(**grabItem, &translatedEvent);
1753                         ++grabItem;
1754                     } else {
1755                         QDragLeaveEvent leaveEvent;
1756                         q->sendEvent(**grabItem, &leaveEvent);
1757                         grabItem = grabber->release(grabItem);
1758                     }
1759                 }
1760                 return;
1761             } else {
1762                 QDragLeaveEvent leaveEvent;
1763                 q->sendEvent(**grabItem, &leaveEvent);
1764             }
1765         }
1766     }
1767     if (event->type() == QEvent::DragEnter || event->type() == QEvent::DragMove) {
1768         QDragMoveEvent *e = static_cast<QDragMoveEvent *>(event);
1769         QDragEnterEvent enterEvent(
1770                 e->pos(),
1771                 e->possibleActions(),
1772                 e->mimeData(),
1773                 e->mouseButtons(),
1774                 e->keyboardModifiers());
1775         QQuickDropEventEx::copyActions(&enterEvent, *e);
1776         event->setAccepted(deliverDragEvent(grabber, rootItem, &enterEvent));
1777     }
1778 }
1779
1780 bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickItem *item, QDragMoveEvent *event)
1781 {
1782     Q_Q(QQuickWindow);
1783     bool accepted = false;
1784     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1785     if (!item->isVisible() || !item->isEnabled())
1786         return false;
1787
1788     QPointF p = item->mapFromScene(event->pos());
1789     if (item->contains(p)) {
1790         if (event->type() == QEvent::DragMove || itemPrivate->flags & QQuickItem::ItemAcceptsDrops) {
1791             QDragMoveEvent translatedEvent(
1792                     p.toPoint(),
1793                     event->possibleActions(),
1794                     event->mimeData(),
1795                     event->mouseButtons(),
1796                     event->keyboardModifiers(),
1797                     event->type());
1798             QQuickDropEventEx::copyActions(&translatedEvent, *event);
1799             q->sendEvent(item, &translatedEvent);
1800             if (event->type() == QEvent::DragEnter) {
1801                 if (translatedEvent.isAccepted()) {
1802                     grabber->grab(item);
1803                     accepted = true;
1804                 }
1805             } else {
1806                 accepted = true;
1807             }
1808         }
1809     } else if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1810         return false;
1811     }
1812
1813     QDragEnterEvent enterEvent(
1814             event->pos(),
1815             event->possibleActions(),
1816             event->mimeData(),
1817             event->mouseButtons(),
1818             event->keyboardModifiers());
1819     QQuickDropEventEx::copyActions(&enterEvent, *event);
1820     QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1821     for (int ii = children.count() - 1; ii >= 0; --ii) {
1822         if (deliverDragEvent(grabber, children.at(ii), &enterEvent))
1823             return true;
1824     }
1825
1826     return accepted;
1827 }
1828 #endif // QT_NO_DRAGANDDROP
1829
1830 #ifndef QT_NO_CURSOR
1831 void QQuickWindowPrivate::updateCursor(const QPointF &scenePos)
1832 {
1833     Q_Q(QQuickWindow);
1834
1835     QQuickItem *oldCursorItem = cursorItem;
1836     cursorItem = findCursorItem(rootItem, scenePos);
1837
1838     if (cursorItem != oldCursorItem) {
1839         if (cursorItem)
1840             q->setCursor(cursorItem->cursor());
1841         else
1842             q->unsetCursor();
1843     }
1844 }
1845
1846 QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF &scenePos)
1847 {
1848     QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1849     if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1850         QPointF p = item->mapFromScene(scenePos);
1851         if (!item->contains(p))
1852             return 0;
1853     }
1854
1855     QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1856     for (int ii = children.count() - 1; ii >= 0; --ii) {
1857         QQuickItem *child = children.at(ii);
1858         if (!child->isVisible() || !child->isEnabled())
1859             continue;
1860         if (QQuickItem *cursorItem = findCursorItem(child, scenePos))
1861             return cursorItem;
1862     }
1863
1864     if (itemPrivate->hasCursor) {
1865         QPointF p = item->mapFromScene(scenePos);
1866         if (item->contains(p))
1867             return item;
1868     }
1869     return 0;
1870 }
1871 #endif
1872
1873 bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem *item, QTouchEvent *event)
1874 {
1875     if (!target)
1876         return false;
1877
1878     QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
1879     if (targetPrivate->filtersChildMouseEvents) {
1880         QScopedPointer<QTouchEvent> targetEvent(touchEventForItemBounds(target, *event));
1881         if (!targetEvent->touchPoints().isEmpty()) {
1882             QVector<int> touchIds;
1883             for (int i = 0; i < event->touchPoints().size(); ++i)
1884                 touchIds.append(event->touchPoints().at(i).id());
1885             if (target->childMouseEventFilter(item, targetEvent.data())) {
1886                 target->grabTouchPoints(touchIds);
1887                 if (mouseGrabberItem) {
1888                     mouseGrabberItem->ungrabMouse();
1889                     touchMouseId = -1;
1890                 }
1891                 return true;
1892             }
1893
1894             // Only offer a mouse event to the filter if we have one point
1895             if (targetEvent->touchPoints().count() == 1) {
1896                 QEvent::Type t;
1897                 const QTouchEvent::TouchPoint &tp = targetEvent->touchPoints().first();
1898                 switch (tp.state()) {
1899                 case Qt::TouchPointPressed:
1900                     t = QEvent::MouseButtonPress;
1901                     break;
1902                 case Qt::TouchPointReleased:
1903                     t = QEvent::MouseButtonRelease;
1904                     break;
1905                 default:
1906                     // move or stationary
1907                     t = QEvent::MouseMove;
1908                     break;
1909                 }
1910
1911                 // targetEvent is already transformed wrt local position, velocity, etc.
1912                 QScopedPointer<QMouseEvent> mouseEvent(touchToMouseEvent(t, targetEvent->touchPoints().first(), event, item, false));
1913                 if (target->childMouseEventFilter(item, mouseEvent.data())) {
1914                     itemForTouchPointId[tp.id()] = target;
1915                     touchMouseId = tp.id();
1916                     target->grabMouse();
1917                     return true;
1918                 }
1919             }
1920         }
1921     }
1922
1923     return sendFilteredTouchEvent(target->parentItem(), item, event);
1924 }
1925
1926 bool QQuickWindowPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem *item, QEvent *event)
1927 {
1928     if (!target)
1929         return false;
1930
1931     QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
1932     if (targetPrivate->filtersChildMouseEvents)
1933         if (target->childMouseEventFilter(item, event))
1934             return true;
1935
1936     if (sendFilteredMouseEvent(target->parentItem(), item, event))
1937         return true;
1938
1939     return false;
1940 }
1941
1942 bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event)
1943 {
1944     QStyleHints *styleHints = qApp->styleHints();
1945     int caps = QGuiApplicationPrivate::mouseEventCaps(event);
1946     bool dragVelocityLimitAvailable = (caps & QTouchDevice::Velocity)
1947         && styleHints->startDragVelocity();
1948     bool overThreshold = qAbs(d) > styleHints->startDragDistance();
1949     if (dragVelocityLimitAvailable) {
1950         QVector2D velocityVec = QGuiApplicationPrivate::mouseEventVelocity(event);
1951         qreal velocity = axis == Qt::XAxis ? velocityVec.x() : velocityVec.y();
1952         overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
1953     }
1954     return overThreshold;
1955 }
1956
1957 /*!
1958     Propagates an event to a QQuickItem on the window
1959 */
1960 bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e)
1961 {
1962     Q_D(QQuickWindow);
1963
1964     if (!item) {
1965         qWarning("QQuickWindow::sendEvent: Cannot send event to a null item");
1966         return false;
1967     }
1968
1969     Q_ASSERT(e);
1970
1971     switch (e->type()) {
1972     case QEvent::KeyPress:
1973     case QEvent::KeyRelease:
1974         e->accept();
1975         QQuickItemPrivate::get(item)->deliverKeyEvent(static_cast<QKeyEvent *>(e));
1976         while (!e->isAccepted() && (item = item->parentItem())) {
1977             e->accept();
1978             QQuickItemPrivate::get(item)->deliverKeyEvent(static_cast<QKeyEvent *>(e));
1979         }
1980         break;
1981     case QEvent::FocusIn:
1982     case QEvent::FocusOut:
1983         QQuickItemPrivate::get(item)->deliverFocusEvent(static_cast<QFocusEvent *>(e));
1984         break;
1985     case QEvent::MouseButtonPress:
1986     case QEvent::MouseButtonRelease:
1987     case QEvent::MouseButtonDblClick:
1988     case QEvent::MouseMove:
1989         // XXX todo - should sendEvent be doing this?  how does it relate to forwarded events?
1990         if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) {
1991             // accept because qml items by default accept and have to explicitly opt out of accepting
1992             e->accept();
1993             QQuickItemPrivate::get(item)->deliverMouseEvent(static_cast<QMouseEvent *>(e));
1994         }
1995         break;
1996     case QEvent::UngrabMouse:
1997         if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) {
1998             e->accept();
1999             item->mouseUngrabEvent();
2000         }
2001         break;
2002     case QEvent::Wheel:
2003         QQuickItemPrivate::get(item)->deliverWheelEvent(static_cast<QWheelEvent *>(e));
2004         break;
2005     case QEvent::HoverEnter:
2006     case QEvent::HoverLeave:
2007     case QEvent::HoverMove:
2008         QQuickItemPrivate::get(item)->deliverHoverEvent(static_cast<QHoverEvent *>(e));
2009         break;
2010     case QEvent::TouchBegin:
2011     case QEvent::TouchUpdate:
2012     case QEvent::TouchEnd:
2013         d->sendFilteredTouchEvent(item->parentItem(), item, static_cast<QTouchEvent *>(e));
2014         break;
2015     case QEvent::TouchCancel:
2016         QQuickItemPrivate::get(item)->deliverTouchEvent(static_cast<QTouchEvent *>(e));
2017         break;
2018 #ifndef QT_NO_DRAGANDDROP
2019     case QEvent::DragEnter:
2020     case QEvent::DragMove:
2021     case QEvent::DragLeave:
2022     case QEvent::Drop:
2023         QQuickItemPrivate::get(item)->deliverDragEvent(e);
2024         break;
2025 #endif
2026     default:
2027         break;
2028     }
2029
2030     return false;
2031 }
2032
2033 void QQuickWindowPrivate::cleanupNodes()
2034 {
2035     for (int ii = 0; ii < cleanupNodeList.count(); ++ii)
2036         delete cleanupNodeList.at(ii);
2037     cleanupNodeList.clear();
2038 }
2039
2040 void QQuickWindowPrivate::cleanupNodesOnShutdown(QQuickItem *item)
2041 {
2042     QQuickItemPrivate *p = QQuickItemPrivate::get(item);
2043     if (p->itemNodeInstance) {
2044         delete p->itemNodeInstance;
2045         p->itemNodeInstance = 0;
2046
2047         if (p->extra.isAllocated()) {
2048             p->extra->opacityNode = 0;
2049             p->extra->clipNode = 0;
2050             p->extra->rootNode = 0;
2051         }
2052
2053         p->groupNode = 0;
2054         p->paintNode = 0;
2055     }
2056
2057     for (int ii = 0; ii < p->childItems.count(); ++ii)
2058         cleanupNodesOnShutdown(p->childItems.at(ii));
2059 }
2060
2061 // This must be called from the render thread, with the main thread frozen
2062 void QQuickWindowPrivate::cleanupNodesOnShutdown()
2063 {
2064     Q_Q(QQuickWindow);
2065     cleanupNodes();
2066     cleanupNodesOnShutdown(rootItem);
2067     QSet<QQuickItem *>::const_iterator it = parentlessItems.begin();
2068     for (; it != parentlessItems.end(); ++it)
2069         cleanupNodesOnShutdown(*it);
2070     q->cleanupSceneGraph();
2071 }
2072
2073 void QQuickWindowPrivate::updateDirtyNodes()
2074 {
2075 #ifdef DIRTY_DEBUG
2076     qWarning() << "QQuickWindowPrivate::updateDirtyNodes():";
2077 #endif
2078
2079     cleanupNodes();
2080
2081     QQuickItem *updateList = dirtyItemList;
2082     dirtyItemList = 0;
2083     if (updateList) QQuickItemPrivate::get(updateList)->prevDirtyItem = &updateList;
2084
2085     while (updateList) {
2086         QQuickItem *item = updateList;
2087         QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
2088         itemPriv->removeFromDirtyList();
2089
2090 #ifdef DIRTY_DEBUG
2091         qWarning() << "   QSGNode:" << item << qPrintable(itemPriv->dirtyToString());
2092 #endif
2093         updateDirtyNode(item);
2094     }
2095 }
2096
2097 void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
2098 {
2099 #ifdef QML_RUNTIME_TESTING
2100     bool didFlash = false;
2101 #endif
2102
2103     QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
2104     quint32 dirty = itemPriv->dirtyAttributes;
2105     itemPriv->dirtyAttributes = 0;
2106
2107     if ((dirty & QQuickItemPrivate::TransformUpdateMask) ||
2108         (dirty & QQuickItemPrivate::Size && itemPriv->origin() != QQuickItem::TopLeft &&
2109          (itemPriv->scale() != 1. || itemPriv->rotation() != 0.))) {
2110
2111         QMatrix4x4 matrix;
2112
2113         if (itemPriv->x != 0. || itemPriv->y != 0.)
2114             matrix.translate(itemPriv->x, itemPriv->y);
2115
2116         for (int ii = itemPriv->transforms.count() - 1; ii >= 0; --ii)
2117             itemPriv->transforms.at(ii)->applyTo(&matrix);
2118
2119         if (itemPriv->scale() != 1. || itemPriv->rotation() != 0.) {
2120             QPointF origin = item->transformOriginPoint();
2121             matrix.translate(origin.x(), origin.y());
2122             if (itemPriv->scale() != 1.)
2123                 matrix.scale(itemPriv->scale(), itemPriv->scale());
2124             if (itemPriv->rotation() != 0.)
2125                 matrix.rotate(itemPriv->rotation(), 0, 0, 1);
2126             matrix.translate(-origin.x(), -origin.y());
2127         }
2128
2129         itemPriv->itemNode()->setMatrix(matrix);
2130     }
2131
2132     bool clipEffectivelyChanged = (dirty & (QQuickItemPrivate::Clip | QQuickItemPrivate::Window)) &&
2133                                   ((item->clip() == false) != (itemPriv->clipNode() == 0));
2134     int effectRefCount = itemPriv->extra.isAllocated()?itemPriv->extra->effectRefCount:0;
2135     bool effectRefEffectivelyChanged = (dirty & (QQuickItemPrivate::EffectReference | QQuickItemPrivate::Window)) &&
2136                                   ((effectRefCount == 0) != (itemPriv->rootNode() == 0));
2137
2138     if (clipEffectivelyChanged) {
2139         QSGNode *parent = itemPriv->opacityNode() ? (QSGNode *) itemPriv->opacityNode() :
2140                                                     (QSGNode *)itemPriv->itemNode();
2141         QSGNode *child = itemPriv->rootNode() ? (QSGNode *)itemPriv->rootNode() :
2142                                                 (QSGNode *)itemPriv->groupNode;
2143
2144         if (item->clip()) {
2145             Q_ASSERT(itemPriv->clipNode() == 0);
2146             itemPriv->extra.value().clipNode = new QQuickDefaultClipNode(item->clipRect());
2147             itemPriv->clipNode()->update();
2148
2149             if (child)
2150                 parent->removeChildNode(child);
2151             parent->appendChildNode(itemPriv->clipNode());
2152             if (child)
2153                 itemPriv->clipNode()->appendChildNode(child);
2154
2155         } else {
2156             Q_ASSERT(itemPriv->clipNode() != 0);
2157             parent->removeChildNode(itemPriv->clipNode());
2158             if (child)
2159                 itemPriv->clipNode()->removeChildNode(child);
2160             delete itemPriv->clipNode();
2161             itemPriv->extra->clipNode = 0;
2162             if (child)
2163                 parent->appendChildNode(child);
2164         }
2165     }
2166
2167     if (dirty & QQuickItemPrivate::ChildrenUpdateMask)
2168         itemPriv->childContainerNode()->removeAllChildNodes();
2169
2170     if (effectRefEffectivelyChanged) {
2171         QSGNode *parent = itemPriv->clipNode();
2172         if (!parent)
2173             parent = itemPriv->opacityNode();
2174         if (!parent)
2175             parent = itemPriv->itemNode();
2176         QSGNode *child = itemPriv->groupNode;
2177
2178         if (itemPriv->extra.isAllocated() && itemPriv->extra->effectRefCount) {
2179             Q_ASSERT(itemPriv->rootNode() == 0);
2180             itemPriv->extra->rootNode = new QSGRootNode;
2181
2182             if (child)
2183                 parent->removeChildNode(child);
2184             parent->appendChildNode(itemPriv->rootNode());
2185             if (child)
2186                 itemPriv->rootNode()->appendChildNode(child);
2187         } else {
2188             Q_ASSERT(itemPriv->rootNode() != 0);
2189             parent->removeChildNode(itemPriv->rootNode());
2190             if (child)
2191                 itemPriv->rootNode()->removeChildNode(child);
2192             delete itemPriv->rootNode();
2193             itemPriv->extra->rootNode = 0;
2194             if (child)
2195                 parent->appendChildNode(child);
2196         }
2197     }
2198
2199     if (dirty & QQuickItemPrivate::ChildrenUpdateMask) {
2200         QSGNode *groupNode = itemPriv->groupNode;
2201         if (groupNode)
2202             groupNode->removeAllChildNodes();
2203
2204         QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
2205         int ii = 0;
2206
2207         for (; ii < orderedChildren.count() && orderedChildren.at(ii)->z() < 0; ++ii) {
2208             QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
2209             if (!childPrivate->explicitVisible &&
2210                 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2211                 continue;
2212             if (childPrivate->itemNode()->parent())
2213                 childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
2214
2215             itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
2216         }
2217
2218         QSGNode *beforePaintNode = itemPriv->groupNode ? itemPriv->groupNode->lastChild() : 0;
2219         if (beforePaintNode || itemPriv->extra.isAllocated())
2220             itemPriv->extra.value().beforePaintNode = beforePaintNode;
2221
2222         if (itemPriv->paintNode)
2223             itemPriv->childContainerNode()->appendChildNode(itemPriv->paintNode);
2224
2225         for (; ii < orderedChildren.count(); ++ii) {
2226             QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
2227             if (!childPrivate->explicitVisible &&
2228                 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2229                 continue;
2230             if (childPrivate->itemNode()->parent())
2231                 childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
2232
2233             itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
2234         }
2235     }
2236
2237     if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode()) {
2238         itemPriv->clipNode()->setRect(item->clipRect());
2239         itemPriv->clipNode()->update();
2240     }
2241
2242     if (dirty & (QQuickItemPrivate::OpacityValue | QQuickItemPrivate::Visible
2243                  | QQuickItemPrivate::HideReference | QQuickItemPrivate::Window))
2244     {
2245         qreal opacity = itemPriv->explicitVisible && (!itemPriv->extra.isAllocated() || itemPriv->extra->hideRefCount == 0)
2246                       ? itemPriv->opacity() : qreal(0);
2247
2248         if (opacity != 1 && !itemPriv->opacityNode()) {
2249             itemPriv->extra.value().opacityNode = new QSGOpacityNode;
2250
2251             QSGNode *parent = itemPriv->itemNode();
2252             QSGNode *child = itemPriv->clipNode();
2253             if (!child)
2254                 child = itemPriv->rootNode();
2255             if (!child)
2256                 child = itemPriv->groupNode;
2257
2258             if (child)
2259                 parent->removeChildNode(child);
2260             parent->appendChildNode(itemPriv->opacityNode());
2261             if (child)
2262                 itemPriv->opacityNode()->appendChildNode(child);
2263         }
2264         if (itemPriv->opacityNode())
2265             itemPriv->opacityNode()->setOpacity(opacity);
2266     }
2267
2268     if (dirty & QQuickItemPrivate::ContentUpdateMask) {
2269
2270         if (itemPriv->flags & QQuickItem::ItemHasContents) {
2271             updatePaintNodeData.transformNode = itemPriv->itemNode();
2272             itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
2273
2274             Q_ASSERT(itemPriv->paintNode == 0 ||
2275                      itemPriv->paintNode->parent() == 0 ||
2276                      itemPriv->paintNode->parent() == itemPriv->childContainerNode());
2277
2278             if (itemPriv->paintNode && itemPriv->paintNode->parent() == 0) {
2279                 if (itemPriv->extra.isAllocated() && itemPriv->extra->beforePaintNode)
2280                     itemPriv->childContainerNode()->insertChildNodeAfter(itemPriv->paintNode, itemPriv->extra->beforePaintNode);
2281                 else
2282                     itemPriv->childContainerNode()->prependChildNode(itemPriv->paintNode);
2283             }
2284         } else if (itemPriv->paintNode) {
2285             delete itemPriv->paintNode;
2286             itemPriv->paintNode = 0;
2287         }
2288     }
2289
2290 #ifndef QT_NO_DEBUG
2291     // Check consistency.
2292     const QSGNode *nodeChain[] = {
2293         itemPriv->itemNodeInstance,
2294         itemPriv->opacityNode(),
2295         itemPriv->clipNode(),
2296         itemPriv->rootNode(),
2297         itemPriv->groupNode,
2298         itemPriv->paintNode,
2299     };
2300
2301     int ip = 0;
2302     for (;;) {
2303         while (ip < 5 && nodeChain[ip] == 0)
2304             ++ip;
2305         if (ip == 5)
2306             break;
2307         int ic = ip + 1;
2308         while (ic < 5 && nodeChain[ic] == 0)
2309             ++ic;
2310         const QSGNode *parent = nodeChain[ip];
2311         const QSGNode *child = nodeChain[ic];
2312         if (child == 0) {
2313             Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 0);
2314         } else {
2315             Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 1);
2316             Q_ASSERT(child->parent() == parent);
2317             bool containsChild = false;
2318             for (QSGNode *n = parent->firstChild(); n; n = n->nextSibling())
2319                 containsChild |= (n == child);
2320             Q_ASSERT(containsChild);
2321         }
2322         ip = ic;
2323     }
2324 #endif
2325
2326 #ifdef QML_RUNTIME_TESTING
2327     if (itemPriv->sceneGraphContext()->isFlashModeEnabled()) {
2328         QSGFlashNode *flash = new QSGFlashNode();
2329         flash->setRect(item->boundingRect());
2330         itemPriv->childContainerNode()->appendChildNode(flash);
2331         didFlash = true;
2332     }
2333     Q_Q(QQuickWindow);
2334     if (didFlash) {
2335         q->maybeUpdate();
2336     }
2337 #endif
2338
2339 }
2340
2341 void QQuickWindow::maybeUpdate()
2342 {
2343     Q_D(QQuickWindow);
2344     d->windowManager->maybeUpdate(this);
2345 }
2346
2347 void QQuickWindow::cleanupSceneGraph()
2348 {
2349     Q_D(QQuickWindow);
2350
2351     if (!d->renderer)
2352         return;
2353
2354     delete d->renderer->rootNode();
2355     delete d->renderer;
2356
2357     d->renderer = 0;
2358 }
2359
2360 /*!
2361     Returns the opengl context used for rendering.
2362
2363     If the scene graph is not ready, this function will return 0.
2364
2365     \sa sceneGraphInitialized(), sceneGraphInvalidated()
2366  */
2367
2368 QOpenGLContext *QQuickWindow::openglContext() const
2369 {
2370     Q_D(const QQuickWindow);
2371     if (d->context->isReady())
2372         return d->context->glContext();
2373     return 0;
2374 }
2375
2376
2377 /*!
2378     \fn void QSGContext::sceneGraphInitialized()
2379
2380     This signal is emitted when the scene graph has been initialized.
2381
2382     This signal will be emitted from the scene graph rendering thread.
2383
2384  */
2385
2386
2387 /*!
2388     \fn void QSGContext::sceneGraphInvalidated()
2389
2390     This signal is emitted when the scene graph has been invalidated.
2391
2392     This signal implies that the opengl rendering context used
2393     has been invalidated and all user resources tied to that context
2394     should be released.
2395
2396     This signal will be emitted from the scene graph rendering thread.
2397  */
2398
2399
2400 /*!
2401     Sets the render target for this window to be \a fbo.
2402
2403     The specified fbo must be created in the context of the window
2404     or one that shares with it.
2405
2406     \warning
2407     This function can only be called from the thread doing
2408     the rendering.
2409  */
2410
2411 void QQuickWindow::setRenderTarget(QOpenGLFramebufferObject *fbo)
2412 {
2413     Q_D(QQuickWindow);
2414     if (d->context && d->context && QThread::currentThread() != d->context->thread()) {
2415         qWarning("QQuickWindow::setRenderThread: Cannot set render target from outside the rendering thread");
2416         return;
2417     }
2418
2419     d->renderTarget = fbo;
2420     if (fbo) {
2421         d->renderTargetId = fbo->handle();
2422         d->renderTargetSize = fbo->size();
2423     } else {
2424         d->renderTargetId = 0;
2425         d->renderTargetSize = QSize();
2426     }
2427 }
2428
2429 /*!
2430     \overload
2431  */
2432 void QQuickWindow::setRenderTarget(uint fboId, const QSize &size)
2433 {
2434     Q_D(QQuickWindow);
2435     if (d->context && d->context && QThread::currentThread() != d->context->thread()) {
2436         qWarning("QQuickWindow::setRenderThread: Cannot set render target from outside the rendering thread");
2437         return;
2438     }
2439
2440     d->renderTargetId = fboId;
2441     d->renderTargetSize = size;
2442
2443     // Unset any previously set instance...
2444     d->renderTarget = 0;
2445 }
2446
2447
2448 /*!
2449     Returns the FBO id of the render target when set; otherwise returns 0.
2450  */
2451 uint QQuickWindow::renderTargetId() const
2452 {
2453     Q_D(const QQuickWindow);
2454     return d->renderTargetId;
2455 }
2456
2457 /*!
2458     Returns the size of the currently set render target; otherwise returns an enpty size.
2459  */
2460 QSize QQuickWindow::renderTargetSize() const
2461 {
2462     Q_D(const QQuickWindow);
2463     return d->renderTargetSize;
2464 }
2465
2466
2467
2468
2469 /*!
2470     Returns the render target for this window.
2471
2472     The default is to render to the surface of the window, in which
2473     case the render target is 0.
2474  */
2475 QOpenGLFramebufferObject *QQuickWindow::renderTarget() const
2476 {
2477     Q_D(const QQuickWindow);
2478     return d->renderTarget;
2479 }
2480
2481
2482 /*!
2483     Grabs the contents of the window and returns it as an image.
2484
2485     This function might not work if the window is not visible.
2486
2487     \warning Calling this function will cause performance problems.
2488
2489     \warning This function can only be called from the GUI thread.
2490  */
2491 QImage QQuickWindow::grabWindow()
2492 {
2493     Q_D(QQuickWindow);
2494     return d->windowManager->grab(this);
2495 }
2496
2497 /*!
2498     Returns an incubation controller that splices incubation between frames
2499     for this window. QQuickView automatically installs this controller for you,
2500     otherwise you will need to install it yourself using \l{QQmlEngine::setIncubationController()}.
2501
2502     The controller is owned by the window and will be destroyed when the window
2503     is deleted.
2504 */
2505 QQmlIncubationController *QQuickWindow::incubationController() const
2506 {
2507     Q_D(const QQuickWindow);
2508
2509     if (!d->incubationController)
2510         d->incubationController = new QQuickWindowIncubationController(const_cast<QQuickWindowPrivate *>(d));
2511     return d->incubationController;
2512 }
2513
2514
2515
2516 /*!
2517     \enum QQuickWindow::CreateTextureOption
2518
2519     The CreateTextureOption enums are used to customize a texture is wrapped.
2520
2521     \value TextureHasAlphaChannel The texture has an alpha channel and should
2522     be drawn using blending.
2523
2524     \value TextureHasMipmaps The texture has mipmaps and can be drawn with
2525     mipmapping enabled.
2526
2527     \value TextureOwnsGLTexture The texture object owns the texture id and
2528     will delete the GL texture when the texture object is deleted.
2529  */
2530
2531 /*!
2532     \fn void QQuickWindow::beforeRendering()
2533
2534     This signal is emitted before the scene starts rendering.
2535
2536     Combined with the modes for clearing the background, this option
2537     can be used to paint using raw GL under QML content.
2538
2539     The GL context used for rendering the scene graph will be bound
2540     at this point.
2541
2542     \warning Since this signal is emitted from the scene graph rendering thread, the
2543     receiver should be on the scene graph thread or the connection should be Qt::DirectConnection.
2544
2545     \warning Make very sure that a signal handler for beforeRendering leaves the GL
2546     context in the same state as it was when the signal handler was entered. Failing to
2547     do so can result in the scene not rendering properly.
2548 */
2549
2550 /*!
2551     \fn void QQuickWindow::afterRendering()
2552
2553     This signal is emitted after the scene has completed rendering, before swapbuffers is called.
2554
2555     This signal can be used to paint using raw GL on top of QML content,
2556     or to do screen scraping of the current frame buffer.
2557
2558     The GL context used for rendering the scene graph will be bound at this point.
2559
2560     \warning Since this signal is emitted from the scene graph rendering thread, the
2561     receiver should be on the scene graph thread or the connection should be Qt::DirectConnection.
2562
2563     \warning Make very sure that a signal handler for afterRendering() leaves the GL
2564     context in the same state as it was when the signal handler was entered. Failing to
2565     do so can result in the scene not rendering properly.
2566  */
2567
2568
2569
2570 /*!
2571     Sets weither the scene graph rendering of QML should clear the color buffer
2572     before it starts rendering to \a enbled.
2573
2574     By disabling clearing of the color buffer, it is possible to do GL painting
2575     under the scene graph.
2576
2577     The color buffer is cleared by default.
2578
2579     \sa beforeRendering()
2580  */
2581
2582 void QQuickWindow::setClearBeforeRendering(bool enabled)
2583 {
2584     Q_D(QQuickWindow);
2585     d->clearBeforeRendering = enabled;
2586 }
2587
2588
2589
2590 /*!
2591     Returns weither clearing of the color buffer is done before rendering or not.
2592  */
2593
2594 bool QQuickWindow::clearBeforeRendering() const
2595 {
2596     Q_D(const QQuickWindow);
2597     return d->clearBeforeRendering;
2598 }
2599
2600
2601
2602 /*!
2603     Creates a new QSGTexture from the supplied \a image. If the image has an
2604     alpha channel, the corresponding texture will have an alpha channel.
2605
2606     The caller of the function is responsible for deleting the returned texture.
2607     The actual GL texture will be deleted when the texture object is deleted.
2608
2609     Depending on the underlying implementation of the scene graph, the returned
2610     texture may be part of an atlas. For code to be portable across implementations
2611     one should always use the texture coordinates returned from
2612     QSGTexture::normalizedTextureSubRect() when building geometry.
2613
2614     \warning This function will return 0 if the scene graph has not yet been
2615     initialized.
2616
2617     \warning The returned texture is not memory managed by the scene graph and
2618     must be explicitely deleted by the caller on the rendering thread.
2619     This is acheived by deleting the texture from a QSGNode destructor
2620     or by using deleteLater() in the case where the texture already has affinity
2621     to the rendering thread.
2622
2623     This function can be called from any thread.
2624
2625     \sa sceneGraphInitialized()
2626  */
2627
2628 QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const
2629 {
2630     Q_D(const QQuickWindow);
2631     if (d->context && d->context->isReady())
2632         return d->context->createTexture(image);
2633     else
2634         return 0;
2635 }
2636
2637
2638
2639 /*!
2640     Creates a new QSGTexture object from an existing GL texture \a id.
2641
2642     The caller of the function is responsible for deleting the returned texture.
2643
2644     Use \a options to customize the texture attributes.
2645
2646     \warning This function will return 0 if the scenegraph has not yet been
2647     initialized.
2648
2649     \sa sceneGraphInitialized()
2650  */
2651 QSGTexture *QQuickWindow::createTextureFromId(uint id, const QSize &size, CreateTextureOptions options) const
2652 {
2653     Q_D(const QQuickWindow);
2654     if (d->context && d->context->isReady()) {
2655         QSGPlainTexture *texture = new QSGPlainTexture();
2656         texture->setTextureId(id);
2657         texture->setHasAlphaChannel(options & TextureHasAlphaChannel);
2658         texture->setHasMipmaps(options & TextureHasMipmaps);
2659         texture->setOwnsTexture(options & TextureOwnsGLTexture);
2660         texture->setTextureSize(size);
2661         return texture;
2662     }
2663     return 0;
2664 }
2665
2666
2667 /*!
2668     Sets the color used to clear the opengl context to \a color.
2669
2670     Setting the clear color has no effect when clearing is disabled.
2671
2672     \sa setClearBeforeRendering()
2673  */
2674
2675 void QQuickWindow::setColor(const QColor &color)
2676 {
2677     Q_D(QQuickWindow);
2678     if (color == d->clearColor)
2679         return;
2680
2681     d->clearColor = color;
2682     emit colorChanged(color);
2683 }
2684
2685
2686
2687 /*!
2688     Returns the color used to clear the opengl context.
2689  */
2690
2691 QColor QQuickWindow::color() const
2692 {
2693     return d_func()->clearColor;
2694 }
2695
2696
2697
2698 #include "moc_qquickwindow.cpp"
2699
2700 QT_END_NAMESPACE