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