Initial import from qtquick2.
[profile/ivi/qtdeclarative.git] / src / declarative / items / qsgcanvas.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qsgcanvas.h"
43 #include "qsgcanvas_p.h"
44
45 #include "qsgitem.h"
46 #include "qsgitem_p.h"
47
48 #include <private/qsgrenderer_p.h>
49 #include <private/qsgflashnode_p.h>
50
51 #include <QtGui/qpainter.h>
52 #include <QtGui/qgraphicssceneevent.h>
53 #include <QtGui/qmatrix4x4.h>
54 #include <QtGui/qinputcontext.h>
55 #include <QtCore/qvarlengtharray.h>
56 #include <QtCore/qabstractanimation.h>
57
58 #include <private/qdeclarativedebugtrace_p.h>
59
60 QT_BEGIN_NAMESPACE
61
62 DEFINE_BOOL_CONFIG_OPTION(qmlThreadedRenderer, QML_THREADED_RENDERER)
63
64 /*
65 Focus behavior
66 ==============
67
68 Prior to being added to a valid canvas items can set and clear focus with no 
69 effect.  Only once items are added to a canvas (by way of having a parent set that
70 already belongs to a canvas) do the focus rules apply.  Focus goes back to 
71 having no effect if an item is removed from a canvas.
72
73 When an item is moved into a new focus scope (either being added to a canvas
74 for the first time, or having its parent changed), if the focus scope already has 
75 a scope focused item that takes precedence over the item being added.  Otherwise,
76 the focus of the added tree is used.  In the case of of a tree of items being 
77 added to a canvas for the first time, which may have a conflicted focus state (two
78 or more items in one scope having focus set), the same rule is applied item by item - 
79 thus the first item that has focus will get it (assuming the scope doesn't already 
80 have a scope focused item), and the other items will have their focus cleared.
81 */
82
83 // #define FOCUS_DEBUG
84 // #define MOUSE_DEBUG
85 // #define TOUCH_DEBUG
86 // #define DIRTY_DEBUG
87 // #define THREAD_DEBUG
88
89 // #define FRAME_TIMING
90
91 #ifdef FRAME_TIMING
92 static QTime frameTimer;
93 int sceneGraphRenderTime;
94 int readbackTime;
95 #endif
96
97
98 class QSGAnimationDriver : public QAnimationDriver
99 {
100 public:
101     QSGAnimationDriver(QWidget *w, QObject *parent)
102         : QAnimationDriver(parent), widget(w)
103     {
104         Q_ASSERT(w);
105     }
106
107     void started()
108     {
109         widget->update();
110     }
111
112     QWidget *widget;
113 };
114
115 QSGItem::UpdatePaintNodeData::UpdatePaintNodeData()
116 : transformNode(0)
117 {
118 }
119
120 QSGRootItem::QSGRootItem()
121 {
122 }
123
124 QSGThreadedRendererAnimationDriver::QSGThreadedRendererAnimationDriver(QSGCanvasPrivate *r, QObject *parent)
125     : QAnimationDriver(parent)
126     , renderer(r)
127 {
128 }
129
130 void QSGThreadedRendererAnimationDriver::started()
131 {
132 #ifdef THREAD_DEBUG
133     qWarning("AnimationDriver: Main Thread: started");
134 #endif
135     renderer->mutex.lock();
136     renderer->animationRunning = true;
137     if (renderer->idle)
138         renderer->wait.wakeOne();
139     renderer->mutex.unlock();
140
141
142 }
143
144 void QSGThreadedRendererAnimationDriver::stopped()
145 {
146 #ifdef THREAD_DEBUG
147     qWarning("AnimationDriver: Main Thread: stopped");
148 #endif
149     renderer->mutex.lock();
150     renderer->animationRunning = false;
151     renderer->mutex.unlock();
152 }
153
154 void QSGCanvas::paintEvent(QPaintEvent *)
155 {
156     Q_D(QSGCanvas);
157
158     if (!d->threadedRendering) {
159 #ifdef FRAME_TIMING
160         int lastFrame = frameTimer.restart();
161 #endif
162
163         if (d->animationDriver->isRunning())
164             d->animationDriver->advance();
165
166 #ifdef FRAME_TIMING
167         int animationTime = frameTimer.elapsed();
168 #endif
169
170         Q_ASSERT(d->context);
171
172         d->polishItems();
173
174         QDeclarativeDebugTrace::addEvent(QDeclarativeDebugTrace::FramePaint);
175         QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Painting);
176
177 #ifdef FRAME_TIMING
178         int polishTime = frameTimer.elapsed();
179 #endif
180
181         makeCurrent();
182
183 #ifdef FRAME_TIMING
184         int makecurrentTime = frameTimer.elapsed();
185 #endif
186
187         d->syncSceneGraph();
188
189 #ifdef FRAME_TIMING
190         int syncTime = frameTimer.elapsed();
191 #endif
192
193         d->renderSceneGraph();
194
195 #ifdef FRAME_TIMING
196         printf("FrameTimes, last=%d, animations=%d, polish=%d, makeCurrent=%d, sync=%d, sgrender=%d, readback=%d, total=%d\n",
197                lastFrame,
198                animationTime,
199                polishTime - animationTime,
200                makecurrentTime - polishTime,
201                syncTime - makecurrentTime,
202                sceneGraphRenderTime - syncTime,
203                readbackTime - sceneGraphRenderTime,
204                frameTimer.elapsed());
205 #endif
206
207         QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Painting);
208
209         if (d->animationDriver->isRunning())
210             update();
211     }
212 }
213
214 void QSGCanvas::resizeEvent(QResizeEvent *e)
215 {
216     Q_D(QSGCanvas);
217     if (d->threadedRendering) {
218         d->mutex.lock();
219         QGLWidget::resizeEvent(e);
220         d->widgetSize = e->size();
221         d->mutex.unlock();
222     } else {
223         d->widgetSize = e->size();
224         d->viewportSize = d->widgetSize;
225         QGLWidget::resizeEvent(e);
226     }
227 }
228
229 void QSGCanvas::showEvent(QShowEvent *e)
230 {
231     Q_D(QSGCanvas);
232
233     QGLWidget::showEvent(e);
234
235     if (d->threadedRendering) {
236         d->contextInThread = true;
237         doneCurrent();
238         if (!d->animationDriver)
239             d->animationDriver = new QSGThreadedRendererAnimationDriver(d, this);
240         d->animationDriver->install();
241         d->mutex.lock();
242         d->thread->start();
243         d->wait.wait(&d->mutex);
244         d->mutex.unlock();
245     } else {
246         makeCurrent();
247
248         if (!d->context || !d->context->isReady()) {
249             d->initializeSceneGraph();
250             d->animationDriver = new QSGAnimationDriver(this, this);
251         }
252
253         d->animationDriver->install();
254     }
255 }
256
257 void QSGCanvas::hideEvent(QHideEvent *e)
258 {
259     Q_D(QSGCanvas);
260
261     if (d->threadedRendering) {
262         d->mutex.lock();
263         d->exitThread = true;
264         d->wait.wakeOne();
265         d->wait.wait(&d->mutex);
266         d->exitThread = false;
267         d->mutex.unlock();
268         d->thread->wait();
269     }
270
271     d->animationDriver->uninstall();
272
273     QGLWidget::hideEvent(e);
274 }
275
276
277 void QSGCanvasPrivate::initializeSceneGraph()
278 {
279     if (!context)
280         context = QSGContext::createDefaultContext();
281
282     if (context->isReady())
283         return;
284
285     QGLContext *glctx = const_cast<QGLContext *>(QGLContext::currentContext());
286     context->initialize(glctx);
287
288     if (!threadedRendering) {
289         Q_Q(QSGCanvas);
290         QObject::connect(context->renderer(), SIGNAL(sceneGraphChanged()), q, SLOT(maybeUpdate()),
291                          Qt::DirectConnection);
292     }
293
294     if (!QSGItemPrivate::get(rootItem)->itemNode()->parent()) {
295         context->rootNode()->appendChildNode(QSGItemPrivate::get(rootItem)->itemNode());
296     }
297
298     emit q_func()->sceneGraphInitialized();
299 }
300
301 void QSGCanvasPrivate::polishItems()
302 {
303     while (!itemsToPolish.isEmpty()) {
304         QSet<QSGItem *>::Iterator iter = itemsToPolish.begin();
305         QSGItem *item = *iter;
306         itemsToPolish.erase(iter);
307         QSGItemPrivate::get(item)->polishScheduled = false;
308         item->updatePolish();
309     }
310 }
311
312
313 void QSGCanvasPrivate::syncSceneGraph()
314 {
315     updateDirtyNodes();
316 }
317
318
319 void QSGCanvasPrivate::renderSceneGraph()
320 {
321     QGLContext *glctx = const_cast<QGLContext *>(QGLContext::currentContext());
322
323     context->renderer()->setDeviceRect(QRect(QPoint(0, 0), viewportSize));
324     context->renderer()->setViewportRect(QRect(QPoint(0, 0), viewportSize));
325     context->renderer()->setProjectMatrixToDeviceRect();
326
327     context->renderNextFrame();
328
329 #ifdef FRAME_TIMING
330     sceneGraphRenderTime = frameTimer.elapsed();
331 #endif
332
333
334 #ifdef FRAME_TIMING
335     int pixel;
336     glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
337     readbackTime = frameTimer.elapsed();
338 #endif
339
340     glctx->swapBuffers();
341 }
342
343
344 void QSGCanvas::sceneGraphChanged()
345 {
346     Q_D(QSGCanvas);
347     d->needsRepaint = true;
348 }
349
350
351 void QSGCanvasPrivate::runThread()
352 {
353 #ifdef THREAD_DEBUG
354     qWarning("QSGRenderer: Render thread running");
355 #endif
356     Q_Q(QSGCanvas);
357
358     printf("QSGCanvas::runThread(), rendering in a thread...\n");
359
360     q->makeCurrent();
361     initializeSceneGraph();
362
363     QObject::connect(context->renderer(), SIGNAL(sceneGraphChanged()),
364                       q, SLOT(sceneGraphChanged()),
365                       Qt::DirectConnection);
366
367     mutex.lock();
368     wait.wakeOne(); // Wake the main thread waiting for us to start
369
370     while (true) {
371         QSize s;
372         s = widgetSize;
373
374         if (exitThread)
375             break;
376
377         if (s != viewportSize) {
378             glViewport(0, 0, s.width(), s.height());
379             viewportSize = s;
380         }
381
382 #ifdef THREAD_DEBUG
383         qWarning("QSGRenderer: Render Thread: Waiting for main thread to stop");
384 #endif
385         QCoreApplication::postEvent(q, new QEvent(QEvent::User));
386         wait.wait(&mutex);
387
388         if (exitThread) {
389 #ifdef THREAD_DEBUG
390             qWarning("QSGRenderer: Render Thread: Shutting down...");
391 #endif
392             break;
393         }
394
395 #ifdef THREAD_DEBUG
396         qWarning("QSGRenderer: Render Thread: Main thread has stopped, syncing scene");
397 #endif
398
399         // Do processing while main thread is frozen
400         syncSceneGraph();
401
402 #ifdef THREAD_DEBUG
403         qWarning("QSGRenderer: Render Thread: Resuming main thread");
404 #endif
405
406         // Read animationRunning while inside the locked section
407         bool continous = animationRunning;
408
409         wait.wakeOne();
410         mutex.unlock();
411
412         bool enterIdle = false;
413         if (needsRepaint) {
414 #ifdef THREAD_DEBUG
415             qWarning("QSGRenderer: Render Thread: rendering scene");
416 #endif
417             renderSceneGraph();
418             needsRepaint = false;
419         } else if (continous) {
420 #ifdef THREAD_DEBUG
421             qWarning("QSGRenderer: Render Thread: waiting a while...");
422 #endif
423             MyThread::doWait();
424         } else {
425             enterIdle = true;
426         }
427
428         mutex.lock();
429
430         if (enterIdle) {
431 #ifdef THREAD_DEBUG
432             qWarning("QSGRenderer: Render Thread: Nothing has changed, going idle...");
433 #endif
434             idle = true;
435             wait.wait(&mutex);
436             idle = false;
437 #ifdef THREAD_DEBUG
438             qWarning("QSGRenderer: Render Thread: waking up from idle");
439 #endif
440         }
441
442     }
443
444
445 #ifdef THREAD_DEBUG
446     qWarning("QSGRenderer: Render Thread: shutting down, waking up main thread");
447 #endif
448     wait.wakeOne();
449     mutex.unlock();
450
451     q->doneCurrent();
452 }
453
454 QSGCanvasPrivate::QSGCanvasPrivate()
455     : rootItem(0)
456     , activeFocusItem(0)
457     , mouseGrabberItem(0)
458     , hoverItem(0)
459     , dirtyItemList(0)
460     , context(0)
461     , contextInThread(false)
462     , threadedRendering(false)
463     , exitThread(false)
464     , animationRunning(false)
465     , idle(false)
466     , needsRepaint(true)
467     , renderThreadAwakened(false)
468     , thread(new MyThread(this))
469     , animationDriver(0)
470 {
471     threadedRendering = qmlThreadedRenderer();
472 }
473
474 QSGCanvasPrivate::~QSGCanvasPrivate()
475 {
476 }
477
478 void QSGCanvasPrivate::init(QSGCanvas *c)
479 {
480     q_ptr = c;
481
482     Q_Q(QSGCanvas);
483
484     q->setAttribute(Qt::WA_AcceptTouchEvents);
485     q->setFocusPolicy(Qt::StrongFocus);
486
487     rootItem = new QSGRootItem;
488     QSGItemPrivate *rootItemPrivate = QSGItemPrivate::get(rootItem);
489     rootItemPrivate->canvas = q;
490     rootItemPrivate->flags |= QSGItem::ItemIsFocusScope;
491     rootItemPrivate->focus = true;
492     rootItemPrivate->activeFocus = true;
493     activeFocusItem = rootItem;
494
495     context = QSGContext::createDefaultContext();
496 }
497
498 void QSGCanvasPrivate::sceneMouseEventForTransform(QGraphicsSceneMouseEvent &sceneEvent,
499                                                    const QTransform &transform)
500 {
501     sceneEvent.setPos(transform.map(sceneEvent.scenePos()));
502     sceneEvent.setLastPos(transform.map(sceneEvent.lastScenePos()));
503     for (int ii = 0; ii < 5; ++ii) {
504         if (sceneEvent.buttons() & (1 << ii)) {
505             sceneEvent.setButtonDownPos((Qt::MouseButton)(1 << ii), 
506                                         transform.map(sceneEvent.buttonDownScenePos((Qt::MouseButton)(1 << ii))));
507         }
508     }
509 }
510
511 void QSGCanvasPrivate::transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform)
512 {
513     for (int i=0; i<touchPoints.count(); i++) {
514         QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
515         touchPoint.setRect(transform.mapRect(touchPoint.sceneRect()));
516         touchPoint.setStartPos(transform.map(touchPoint.startScenePos()));
517         touchPoint.setLastPos(transform.map(touchPoint.lastScenePos()));
518     }
519 }
520
521 QEvent::Type QSGCanvasPrivate::sceneMouseEventTypeFromMouseEvent(QMouseEvent *event)
522 {
523     switch(event->type()) {
524     default:
525         Q_ASSERT(!"Unknown event type");
526     case QEvent::MouseButtonPress:
527         return QEvent::GraphicsSceneMousePress;
528     case QEvent::MouseButtonRelease:
529         return QEvent::GraphicsSceneMouseRelease;
530     case QEvent::MouseButtonDblClick:
531         return QEvent::GraphicsSceneMouseDoubleClick;
532     case QEvent::MouseMove:
533         return QEvent::GraphicsSceneMouseMove;
534     }
535 }
536
537 /*!
538 Fill in the data in \a sceneEvent based on \a event.  This method leaves the item local positions in
539 \a sceneEvent untouched.  Use sceneMouseEventForTransform() to fill in those details.
540 */
541 void QSGCanvasPrivate::sceneMouseEventFromMouseEvent(QGraphicsSceneMouseEvent &sceneEvent, QMouseEvent *event)
542 {
543     Q_Q(QSGCanvas);
544
545     Q_ASSERT(event);
546
547     if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) {
548         if ((event->button() & event->buttons()) == event->buttons()) {
549             lastMousePosition = event->pos();
550         }
551
552         switch (event->button()) {
553         default:
554             Q_ASSERT(!"Unknown button");
555         case Qt::LeftButton:
556             buttonDownPositions[0] = event->pos();
557             break;
558         case Qt::RightButton:
559             buttonDownPositions[1] = event->pos();
560             break;
561         case Qt::MiddleButton:
562             buttonDownPositions[2] = event->pos();
563             break;
564         case Qt::XButton1:
565             buttonDownPositions[3] = event->pos();
566             break;
567         case Qt::XButton2:
568             buttonDownPositions[4] = event->pos();
569             break;
570         }
571     }
572
573     sceneEvent.setScenePos(event->pos());
574     sceneEvent.setScreenPos(event->globalPos());
575     sceneEvent.setLastScenePos(lastMousePosition);
576     sceneEvent.setLastScreenPos(q->mapToGlobal(lastMousePosition));
577     sceneEvent.setButtons(event->buttons());
578     sceneEvent.setButton(event->button());
579     sceneEvent.setModifiers(event->modifiers());
580     sceneEvent.setWidget(q);
581
582     for (int ii = 0; ii < 5; ++ii) {
583         if (sceneEvent.buttons() & (1 << ii)) {
584             sceneEvent.setButtonDownScenePos((Qt::MouseButton)(1 << ii), buttonDownPositions[ii]);
585             sceneEvent.setButtonDownScreenPos((Qt::MouseButton)(1 << ii), q->mapToGlobal(buttonDownPositions[ii]));
586         }
587     }
588
589     lastMousePosition = event->pos();
590 }
591
592 /*!
593 Fill in the data in \a hoverEvent based on \a mouseEvent.  This method leaves the item local positions in
594 \a hoverEvent untouched (these are filled in later).
595 */
596 void QSGCanvasPrivate::sceneHoverEventFromMouseEvent(QGraphicsSceneHoverEvent &hoverEvent, QMouseEvent *mouseEvent)
597 {
598     Q_Q(QSGCanvas);
599     hoverEvent.setWidget(q);
600     hoverEvent.setScenePos(mouseEvent->pos());
601     hoverEvent.setScreenPos(mouseEvent->globalPos());
602     if (lastMousePosition.isNull()) lastMousePosition = mouseEvent->pos();
603     hoverEvent.setLastScenePos(lastMousePosition);
604     hoverEvent.setLastScreenPos(q->mapToGlobal(lastMousePosition));
605     hoverEvent.setModifiers(mouseEvent->modifiers());
606     hoverEvent.setAccepted(mouseEvent->isAccepted());
607
608     lastMousePosition = mouseEvent->pos();
609 }
610
611 /*!
612 Translates the data in \a touchEvent to this canvas.  This method leaves the item local positions in
613 \a touchEvent untouched (these are filled in later).
614 */
615 void QSGCanvasPrivate::translateTouchEvent(QTouchEvent *touchEvent)
616 {
617     Q_Q(QSGCanvas);
618
619     touchEvent->setWidget(q);
620
621     QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
622     for (int i = 0; i < touchPoints.count(); ++i) {
623         QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
624
625         touchPoint.setScreenRect(touchPoint.sceneRect());
626         touchPoint.setStartScreenPos(touchPoint.startScenePos());
627         touchPoint.setLastScreenPos(touchPoint.lastScenePos());
628
629         touchPoint.setSceneRect(touchPoint.rect());
630         touchPoint.setStartScenePos(touchPoint.startPos());
631         touchPoint.setLastScenePos(touchPoint.lastPos());
632
633         if (touchPoint.isPrimary())
634             lastMousePosition = touchPoint.pos().toPoint();
635     }
636     touchEvent->setTouchPoints(touchPoints);
637 }
638
639 void QSGCanvasPrivate::setFocusInScope(QSGItem *scope, QSGItem *item, FocusOptions options)
640 {
641     Q_Q(QSGCanvas);
642
643     Q_ASSERT(item);
644     Q_ASSERT(scope);
645
646 #ifdef FOCUS_DEBUG
647     qWarning() << "QSGCanvasPrivate::setFocusInScope():";
648     qWarning() << "    scope:" << (QObject *)scope;
649     qWarning() << "    scopeSubFocusItem:" << (QObject *)QSGItemPrivate::get(scope)->subFocusItem;
650     qWarning() << "    item:" << (QObject *)item;
651     qWarning() << "    activeFocusItem:" << (QObject *)activeFocusItem;
652 #endif
653
654     QSGItemPrivate *scopePrivate = QSGItemPrivate::get(scope);
655     QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
656
657     QSGItem *oldActiveFocusItem = 0;
658     QSGItem *newActiveFocusItem = 0;
659
660     QVarLengthArray<QSGItem *, 20> changed;
661
662     // Does this change the active focus?
663     if (scopePrivate->activeFocus) {
664         oldActiveFocusItem = activeFocusItem;
665         newActiveFocusItem = item;
666         while (newActiveFocusItem->isFocusScope() && newActiveFocusItem->scopedFocusItem())
667             newActiveFocusItem = newActiveFocusItem->scopedFocusItem();
668
669         Q_ASSERT(oldActiveFocusItem);
670
671 #ifndef QT_NO_IM
672         if (QInputContext *ic = inputContext())
673             ic->reset();
674 #endif
675
676         activeFocusItem = 0;
677         QFocusEvent event(QEvent::FocusOut, Qt::OtherFocusReason);
678         q->sendEvent(oldActiveFocusItem, &event);
679
680         QSGItem *afi = oldActiveFocusItem;
681         while (afi != scope) {
682             if (QSGItemPrivate::get(afi)->activeFocus) {
683                 QSGItemPrivate::get(afi)->activeFocus = false;
684                 changed << afi;
685             }
686             afi = afi->parentItem();
687         }
688     }
689
690     QSGItem *oldSubFocusItem = scopePrivate->subFocusItem;
691     // Correct focus chain in scope
692     if (oldSubFocusItem) {
693         QSGItem *sfi = scopePrivate->subFocusItem->parentItem();
694         while (sfi != scope) {
695             QSGItemPrivate::get(sfi)->subFocusItem = 0;
696             sfi = sfi->parentItem();
697         }
698     }
699     {
700         scopePrivate->subFocusItem = item;
701         QSGItem *sfi = scopePrivate->subFocusItem->parentItem();
702         while (sfi != scope) {
703             QSGItemPrivate::get(sfi)->subFocusItem = item;
704             sfi = sfi->parentItem();
705         }
706     }
707
708     if (oldSubFocusItem) {
709         QSGItemPrivate::get(oldSubFocusItem)->focus = false;
710         changed << oldSubFocusItem;
711     }
712
713     if (!(options & DontChangeFocusProperty)) {
714         itemPrivate->focus = true;
715         changed << item;
716     }
717
718     if (newActiveFocusItem) {
719         activeFocusItem = newActiveFocusItem;
720
721         QSGItemPrivate::get(newActiveFocusItem)->activeFocus = true;
722         changed << newActiveFocusItem;
723
724         QSGItem *afi = newActiveFocusItem->parentItem();
725         while (afi != scope) {
726             if (afi->isFocusScope()) {
727                 QSGItemPrivate::get(afi)->activeFocus = true;
728                 changed << afi;
729             }
730             afi = afi->parentItem();
731         }
732
733         updateInputMethodData();
734
735         QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason);
736         q->sendEvent(newActiveFocusItem, &event); 
737     } else {
738         updateInputMethodData();
739     }
740
741     if (!changed.isEmpty()) 
742         notifyFocusChangesRecur(changed.data(), changed.count() - 1);
743 }
744
745 void QSGCanvasPrivate::clearFocusInScope(QSGItem *scope, QSGItem *item, FocusOptions options)
746 {
747     Q_Q(QSGCanvas);
748
749     Q_ASSERT(item);
750     Q_ASSERT(scope);
751
752 #ifdef FOCUS_DEBUG
753     qWarning() << "QSGCanvasPrivate::clearFocusInScope():";
754     qWarning() << "    scope:" << (QObject *)scope;
755     qWarning() << "    item:" << (QObject *)item;
756     qWarning() << "    activeFocusItem:" << (QObject *)activeFocusItem;
757 #endif
758
759     QSGItemPrivate *scopePrivate = QSGItemPrivate::get(scope);
760
761     QSGItem *oldActiveFocusItem = 0;
762     QSGItem *newActiveFocusItem = 0;
763
764     QVarLengthArray<QSGItem *, 20> changed;
765
766     Q_ASSERT(item == scopePrivate->subFocusItem);
767
768     // Does this change the active focus?
769     if (scopePrivate->activeFocus) {
770         oldActiveFocusItem = activeFocusItem;
771         newActiveFocusItem = scope;
772         
773         Q_ASSERT(oldActiveFocusItem);
774
775 #ifndef QT_NO_IM
776         if (QInputContext *ic = inputContext())
777             ic->reset();
778 #endif
779
780         activeFocusItem = 0;
781         QFocusEvent event(QEvent::FocusOut, Qt::OtherFocusReason);
782         q->sendEvent(oldActiveFocusItem, &event);
783
784         QSGItem *afi = oldActiveFocusItem;
785         while (afi != scope) {
786             if (QSGItemPrivate::get(afi)->activeFocus) {
787                 QSGItemPrivate::get(afi)->activeFocus = false;
788                 changed << afi;
789             }
790             afi = afi->parentItem();
791         }
792     }
793
794     QSGItem *oldSubFocusItem = scopePrivate->subFocusItem;
795     // Correct focus chain in scope
796     if (oldSubFocusItem) {
797         QSGItem *sfi = scopePrivate->subFocusItem->parentItem();
798         while (sfi != scope) {
799             QSGItemPrivate::get(sfi)->subFocusItem = 0;
800             sfi = sfi->parentItem();
801         }
802     }
803     scopePrivate->subFocusItem = 0;
804
805     if (oldSubFocusItem && !(options & DontChangeFocusProperty)) {
806         QSGItemPrivate::get(oldSubFocusItem)->focus = false;
807         changed << oldSubFocusItem;
808     }
809
810     if (newActiveFocusItem) {
811         Q_ASSERT(newActiveFocusItem == scope);
812         activeFocusItem = scope;
813
814         updateInputMethodData();
815
816         QFocusEvent event(QEvent::FocusIn, Qt::OtherFocusReason);
817         q->sendEvent(newActiveFocusItem, &event); 
818     } else {
819         updateInputMethodData();
820     }
821
822     if (!changed.isEmpty()) 
823         notifyFocusChangesRecur(changed.data(), changed.count() - 1);
824 }
825
826 void QSGCanvasPrivate::notifyFocusChangesRecur(QSGItem **items, int remaining)
827 {
828     QDeclarativeGuard<QSGItem> item(*items);
829
830     if (remaining)
831         notifyFocusChangesRecur(items + 1, remaining - 1);
832
833     if (item) {
834         QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
835
836         if (itemPrivate->notifiedFocus != itemPrivate->focus) {
837             itemPrivate->notifiedFocus = itemPrivate->focus;
838             emit item->focusChanged(itemPrivate->focus);
839         }
840
841         if (item && itemPrivate->notifiedActiveFocus != itemPrivate->activeFocus) {
842             itemPrivate->notifiedActiveFocus = itemPrivate->activeFocus;
843             itemPrivate->itemChange(QSGItem::ItemActiveFocusHasChanged, itemPrivate->activeFocus);
844             emit item->activeFocusChanged(itemPrivate->activeFocus);
845         }
846     } 
847 }
848
849 void QSGCanvasPrivate::updateInputMethodData()
850 {
851     Q_Q(QSGCanvas);
852     bool enabled = activeFocusItem
853                    && (QSGItemPrivate::get(activeFocusItem)->flags & QSGItem::ItemAcceptsInputMethod);
854     q->setAttribute(Qt::WA_InputMethodEnabled, enabled);
855     q->setInputMethodHints(enabled ? activeFocusItem->inputMethodHints() : Qt::ImhNone);
856 }
857
858 QVariant QSGCanvas::inputMethodQuery(Qt::InputMethodQuery query) const
859 {
860     Q_D(const QSGCanvas);
861     if (!d->activeFocusItem || !(QSGItemPrivate::get(d->activeFocusItem)->flags & QSGItem::ItemAcceptsInputMethod))
862         return QVariant();
863     QVariant value = d->activeFocusItem->inputMethodQuery(query);
864
865     //map geometry types
866     QVariant::Type type = value.type();
867     if (type == QVariant::RectF || type == QVariant::Rect) {
868         const QTransform transform = QSGItemPrivate::get(d->activeFocusItem)->itemToCanvasTransform();
869         value = transform.mapRect(value.toRectF());
870     } else if (type == QVariant::PointF || type == QVariant::Point) {
871         const QTransform transform = QSGItemPrivate::get(d->activeFocusItem)->itemToCanvasTransform();
872         value = transform.map(value.toPointF());
873     }
874     return value;
875 }
876
877 void QSGCanvasPrivate::dirtyItem(QSGItem *)
878 {
879     Q_Q(QSGCanvas);
880     q->maybeUpdate();
881 }
882
883 void QSGCanvasPrivate::cleanup(QSGNode *n)
884 {
885     Q_Q(QSGCanvas);
886
887     Q_ASSERT(!cleanupNodeList.contains(n));
888     cleanupNodeList.append(n);
889     q->maybeUpdate();
890 }
891
892 static QGLFormat tweakFormat(const QGLFormat &format = QGLFormat::defaultFormat())
893 {
894     QGLFormat f = format;
895     f.setSwapInterval(1);
896     return f;
897 }
898
899 QSGCanvas::QSGCanvas(QWidget *parent, Qt::WindowFlags f)
900     : QGLWidget(*(new QSGCanvasPrivate), tweakFormat(), parent, (QGLWidget *) 0, f)
901 {
902     Q_D(QSGCanvas);
903
904     d->init(this);
905 }
906
907 QSGCanvas::QSGCanvas(const QGLFormat &format, QWidget *parent, Qt::WindowFlags f)
908     : QGLWidget(*(new QSGCanvasPrivate), tweakFormat(format), parent, (QGLWidget *) 0, f)
909 {
910     Q_D(QSGCanvas);
911
912     d->init(this);
913 }
914
915 QSGCanvas::QSGCanvas(QSGCanvasPrivate &dd, QWidget *parent, Qt::WindowFlags f)
916 : QGLWidget(dd, tweakFormat(), parent, 0, f)
917 {
918     Q_D(QSGCanvas);
919
920     d->init(this);
921 }
922
923 QSGCanvas::QSGCanvas(QSGCanvasPrivate &dd, const QGLFormat &format, QWidget *parent, Qt::WindowFlags f)
924 : QGLWidget(dd, tweakFormat(format), parent, 0, f)
925 {
926     Q_D(QSGCanvas);
927
928     d->init(this);
929 }
930
931 QSGCanvas::~QSGCanvas()
932 {
933     Q_D(QSGCanvas);
934
935     // ### should we change ~QSGItem to handle this better?
936     // manually cleanup for the root item (item destructor only handles these when an item is parented)
937     QSGItemPrivate *rootItemPrivate = QSGItemPrivate::get(d->rootItem);
938     rootItemPrivate->removeFromDirtyList();
939     rootItemPrivate->canvas = 0;
940
941     delete d->rootItem; d->rootItem = 0;
942     d->cleanupNodes();
943
944     delete d->context;
945 }
946
947 QSGItem *QSGCanvas::rootItem() const
948 {
949     Q_D(const QSGCanvas);
950     
951     return d->rootItem;
952 }
953
954 QSGItem *QSGCanvas::activeFocusItem() const
955 {
956     Q_D(const QSGCanvas);
957     
958     return d->activeFocusItem;
959 }
960
961 QSGItem *QSGCanvas::mouseGrabberItem() const
962 {
963     Q_D(const QSGCanvas);
964     
965     return d->mouseGrabberItem;
966 }
967
968
969 void QSGCanvasPrivate::clearHover()
970 {
971     Q_Q(QSGCanvas);
972     if (!hoverItem)
973         return;
974
975     QGraphicsSceneHoverEvent hoverEvent;
976     hoverEvent.setWidget(q);
977
978     QPoint cursorPos = QCursor::pos();
979     hoverEvent.setScenePos(q->mapFromGlobal(cursorPos));
980     hoverEvent.setLastScenePos(hoverEvent.scenePos());
981     hoverEvent.setScreenPos(cursorPos);
982     hoverEvent.setLastScreenPos(hoverEvent.screenPos());
983
984     QSGItem *item = hoverItem;
985     hoverItem = 0;
986     sendHoverEvent(QEvent::GraphicsSceneHoverLeave, item, &hoverEvent);
987 }
988
989
990 bool QSGCanvas::event(QEvent *e)
991 {
992     Q_D(QSGCanvas);
993
994     if (e->type() == QEvent::User) {
995         Q_ASSERT(d->threadedRendering);
996
997         d->mutex.lock();
998 #ifdef THREAD_DEBUG
999         qWarning("QSGRenderer: Main Thread: Stopped");
1000 #endif
1001
1002         d->polishItems();
1003
1004         d->renderThreadAwakened = false;
1005
1006         d->wait.wakeOne();
1007
1008         // The thread is exited when the widget has been hidden. We then need to
1009         // skip the waiting, otherwise we would be waiting for a wakeup that never
1010         // comes.
1011         if (d->thread->isRunning())
1012             d->wait.wait(&d->mutex);
1013 #ifdef THREAD_DEBUG
1014         qWarning("QSGRenderer: Main Thread: Resumed");
1015 #endif
1016         d->mutex.unlock();
1017
1018         if (d->animationRunning)
1019             d->animationDriver->advance();
1020     }
1021
1022     switch (e->type()) {
1023
1024     case QEvent::TouchBegin:
1025     case QEvent::TouchUpdate:
1026     case QEvent::TouchEnd:
1027     {
1028         QTouchEvent *touch = static_cast<QTouchEvent *>(e);
1029         d->translateTouchEvent(touch);
1030         d->deliverTouchEvent(touch);
1031         if (!touch->isAccepted())
1032             return false;
1033     }
1034     case QEvent::Leave:
1035         d->clearHover();
1036         d->lastMousePosition = QPoint();
1037         break;
1038     default:
1039         break;
1040     }
1041
1042     return QGLWidget::event(e);
1043 }
1044
1045 void QSGCanvas::keyPressEvent(QKeyEvent *e)
1046 {
1047     Q_D(QSGCanvas);
1048     
1049     sendEvent(d->activeFocusItem, e);
1050 }
1051
1052 void QSGCanvas::keyReleaseEvent(QKeyEvent *e)
1053 {
1054     Q_D(QSGCanvas);
1055     
1056     sendEvent(d->activeFocusItem, e);
1057 }
1058
1059 void QSGCanvas::inputMethodEvent(QInputMethodEvent *e)
1060 {
1061     Q_D(QSGCanvas);
1062
1063     sendEvent(d->activeFocusItem, e);
1064 }
1065
1066 bool QSGCanvasPrivate::deliverInitialMousePressEvent(QSGItem *item, QGraphicsSceneMouseEvent *event)
1067 {
1068     Q_Q(QSGCanvas);
1069
1070     QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
1071     if (itemPrivate->opacity == 0.0)
1072         return false;
1073
1074     if (itemPrivate->flags & QSGItem::ItemClipsChildrenToShape) {
1075         QPointF p = item->mapFromScene(event->scenePos());
1076         if (!QRectF(0, 0, item->width(), item->height()).contains(p))
1077             return false;
1078     }
1079
1080     QList<QSGItem *> children = itemPrivate->paintOrderChildItems();
1081     for (int ii = children.count() - 1; ii >= 0; --ii) {
1082         QSGItem *child = children.at(ii);
1083         if (!child->isVisible() || !child->isEnabled())
1084             continue;
1085         if (deliverInitialMousePressEvent(child, event))
1086             return true;
1087     }
1088
1089     if (itemPrivate->acceptedMouseButtons & event->button()) {
1090         QPointF p = item->mapFromScene(event->scenePos());
1091         if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
1092             sceneMouseEventForTransform(*event, itemPrivate->canvasToItemTransform());
1093             event->accept();
1094             mouseGrabberItem = item;
1095             q->sendEvent(item, event);
1096             if (event->isAccepted()) 
1097                 return true;
1098             mouseGrabberItem->ungrabMouse();
1099             mouseGrabberItem = 0;
1100         }
1101     }
1102
1103     return false;
1104 }
1105
1106 bool QSGCanvasPrivate::deliverMouseEvent(QGraphicsSceneMouseEvent *sceneEvent)
1107 {
1108     Q_Q(QSGCanvas);
1109
1110     if (!mouseGrabberItem && 
1111          sceneEvent->type() == QEvent::GraphicsSceneMousePress &&
1112          (sceneEvent->button() & sceneEvent->buttons()) == sceneEvent->buttons()) {
1113         
1114         return deliverInitialMousePressEvent(rootItem, sceneEvent);
1115     }
1116
1117     if (mouseGrabberItem) {
1118         QSGItemPrivate *mgPrivate = QSGItemPrivate::get(mouseGrabberItem);
1119         sceneMouseEventForTransform(*sceneEvent, mgPrivate->canvasToItemTransform());
1120
1121         sceneEvent->accept();
1122         q->sendEvent(mouseGrabberItem, sceneEvent);
1123         if (sceneEvent->isAccepted())
1124             return true;
1125     }
1126
1127     return false;
1128 }
1129
1130 void QSGCanvas::mousePressEvent(QMouseEvent *event)
1131 {
1132     Q_D(QSGCanvas);
1133     
1134 #ifdef MOUSE_DEBUG
1135     qWarning() << "QSGCanvas::mousePressEvent()" << event->pos() << event->button() << event->buttons();
1136 #endif
1137
1138     QGraphicsSceneMouseEvent sceneEvent(d->sceneMouseEventTypeFromMouseEvent(event));
1139     d->sceneMouseEventFromMouseEvent(sceneEvent, event);
1140
1141     d->deliverMouseEvent(&sceneEvent);
1142     event->setAccepted(sceneEvent.isAccepted());
1143 }
1144
1145 void QSGCanvas::mouseReleaseEvent(QMouseEvent *event)
1146 {
1147     Q_D(QSGCanvas);
1148     
1149 #ifdef MOUSE_DEBUG
1150     qWarning() << "QSGCanvas::mouseReleaseEvent()" << event->pos() << event->button() << event->buttons();
1151 #endif
1152
1153     if (!d->mouseGrabberItem) {
1154         QGLWidget::mouseReleaseEvent(event);
1155         return;
1156     }
1157
1158     QGraphicsSceneMouseEvent sceneEvent(d->sceneMouseEventTypeFromMouseEvent(event));
1159     d->sceneMouseEventFromMouseEvent(sceneEvent, event);
1160
1161     d->deliverMouseEvent(&sceneEvent);
1162     event->setAccepted(sceneEvent.isAccepted());
1163
1164     d->mouseGrabberItem = 0;
1165 }
1166
1167 void QSGCanvas::mouseDoubleClickEvent(QMouseEvent *event)
1168 {
1169     Q_D(QSGCanvas);
1170     
1171 #ifdef MOUSE_DEBUG
1172     qWarning() << "QSGCanvas::mouseDoubleClickEvent()" << event->pos() << event->button() << event->buttons();
1173 #endif
1174
1175     QGraphicsSceneMouseEvent sceneEvent(d->sceneMouseEventTypeFromMouseEvent(event));
1176     d->sceneMouseEventFromMouseEvent(sceneEvent, event);
1177
1178     if (!d->mouseGrabberItem && (event->button() & event->buttons()) == event->buttons()) {
1179         if (d->deliverInitialMousePressEvent(d->rootItem, &sceneEvent))
1180             event->accept();
1181         else
1182             event->ignore();
1183         return;
1184     } 
1185
1186     d->deliverMouseEvent(&sceneEvent);
1187     event->setAccepted(sceneEvent.isAccepted());
1188 }
1189
1190 void QSGCanvasPrivate::sendHoverEvent(QEvent::Type type, QSGItem *item,
1191                                       QGraphicsSceneHoverEvent *event)
1192 {
1193     Q_Q(QSGCanvas);
1194     const QTransform transform = QSGItemPrivate::get(item)->canvasToItemTransform();
1195
1196     //create copy of event
1197     QGraphicsSceneHoverEvent hoverEvent(type);
1198     hoverEvent.setWidget(event->widget());
1199     hoverEvent.setPos(transform.map(event->scenePos()));
1200     hoverEvent.setScenePos(event->scenePos());
1201     hoverEvent.setScreenPos(event->screenPos());
1202     hoverEvent.setLastPos(transform.map(event->lastScenePos()));
1203     hoverEvent.setLastScenePos(event->lastScenePos());
1204     hoverEvent.setLastScreenPos(event->lastScreenPos());
1205     hoverEvent.setModifiers(event->modifiers());
1206     hoverEvent.setAccepted(event->isAccepted());
1207
1208     q->sendEvent(item, &hoverEvent);
1209 }
1210
1211 void QSGCanvas::mouseMoveEvent(QMouseEvent *event)
1212 {
1213     Q_D(QSGCanvas);
1214     
1215 #ifdef MOUSE_DEBUG
1216     qWarning() << "QSGCanvas::mouseMoveEvent()" << event->pos() << event->button() << event->buttons();
1217 #endif
1218
1219     if (!d->mouseGrabberItem) {
1220         QGraphicsSceneHoverEvent hoverEvent;
1221         d->sceneHoverEventFromMouseEvent(hoverEvent, event);
1222
1223         bool delivered = d->deliverHoverEvent(d->rootItem, &hoverEvent);
1224         if (!delivered) {
1225             //take care of any exits
1226             if (d->hoverItem) {
1227                 QSGItem *item = d->hoverItem;
1228                 d->hoverItem = 0;
1229                 d->sendHoverEvent(QEvent::GraphicsSceneHoverLeave, item, &hoverEvent);
1230             }
1231         }
1232         event->setAccepted(hoverEvent.isAccepted());
1233         return;
1234     }
1235
1236     QGraphicsSceneMouseEvent sceneEvent(d->sceneMouseEventTypeFromMouseEvent(event));
1237     d->sceneMouseEventFromMouseEvent(sceneEvent, event);
1238
1239     d->deliverMouseEvent(&sceneEvent);
1240     event->setAccepted(sceneEvent.isAccepted());
1241 }
1242
1243 bool QSGCanvasPrivate::deliverHoverEvent(QSGItem *item, QGraphicsSceneHoverEvent *event)
1244 {
1245     QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
1246     if (itemPrivate->opacity == 0.0)
1247         return false;
1248
1249     if (itemPrivate->flags & QSGItem::ItemClipsChildrenToShape) {
1250         QPointF p = item->mapFromScene(event->scenePos());
1251         if (!QRectF(0, 0, item->width(), item->height()).contains(p))
1252             return false;
1253     }
1254
1255     QList<QSGItem *> children = itemPrivate->paintOrderChildItems();
1256     for (int ii = children.count() - 1; ii >= 0; --ii) {
1257         QSGItem *child = children.at(ii);
1258         if (!child->isEnabled())
1259             continue;
1260         if (deliverHoverEvent(child, event))
1261             return true;
1262     }
1263
1264     if (itemPrivate->hoverEnabled) {
1265         QPointF p = item->mapFromScene(event->scenePos());
1266         if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
1267             if (hoverItem == item) {
1268                 //move
1269                 sendHoverEvent(QEvent::GraphicsSceneHoverMove, item, event);
1270             } else {
1271                 //exit from previous
1272                 if (hoverItem) {
1273                     QSGItem *item = hoverItem;
1274                     hoverItem = 0;
1275                     sendHoverEvent(QEvent::GraphicsSceneHoverLeave, item, event);
1276                 }
1277
1278                 //enter new item
1279                 hoverItem = item;
1280                 sendHoverEvent(QEvent::GraphicsSceneHoverEnter, item, event);
1281             }
1282             return true;
1283         }
1284     }
1285
1286     return false;
1287 }
1288
1289 bool QSGCanvasPrivate::deliverWheelEvent(QSGItem *item, QGraphicsSceneWheelEvent *event)
1290 {
1291     Q_Q(QSGCanvas);
1292     QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
1293     if (itemPrivate->opacity == 0.0)
1294         return false;
1295
1296     if (itemPrivate->flags & QSGItem::ItemClipsChildrenToShape) {
1297         QPointF p = item->mapFromScene(event->scenePos());
1298         if (!QRectF(0, 0, item->width(), item->height()).contains(p))
1299             return false;
1300     }
1301
1302     QList<QSGItem *> children = itemPrivate->paintOrderChildItems();
1303     for (int ii = children.count() - 1; ii >= 0; --ii) {
1304         QSGItem *child = children.at(ii);
1305         if (!child->isEnabled())
1306             continue;
1307         if (deliverWheelEvent(child, event))
1308             return true;
1309     }
1310
1311     QPointF p = item->mapFromScene(event->scenePos());
1312     if (QRectF(0, 0, item->width(), item->height()).contains(p)) {
1313         event->setPos(itemPrivate->canvasToItemTransform().map(event->scenePos()));
1314         event->accept();
1315         q->sendEvent(item, event);
1316         if (event->isAccepted())
1317             return true;
1318     }
1319
1320     return false;
1321 }
1322
1323 #ifndef QT_NO_WHEELEVENT
1324 void QSGCanvas::wheelEvent(QWheelEvent *event)
1325 {
1326     Q_D(QSGCanvas);
1327 #ifdef MOUSE_DEBUG
1328     qWarning() << "QSGCanvas::wheelEvent()" << event->pos() << event->delta() << event->orientation();
1329 #endif
1330     QGraphicsSceneWheelEvent wheelEvent(QEvent::GraphicsSceneWheel);
1331     wheelEvent.setWidget(this);
1332     wheelEvent.setScenePos(event->pos());
1333     wheelEvent.setScreenPos(event->globalPos());
1334     wheelEvent.setButtons(event->buttons());
1335     wheelEvent.setModifiers(event->modifiers());
1336     wheelEvent.setDelta(event->delta());
1337     wheelEvent.setOrientation(event->orientation());
1338     wheelEvent.setAccepted(false);
1339
1340     d->deliverWheelEvent(d->rootItem, &wheelEvent);
1341     event->setAccepted(wheelEvent.isAccepted());
1342 }
1343 #endif // QT_NO_WHEELEVENT
1344
1345 bool QSGCanvasPrivate::deliverTouchEvent(QTouchEvent *event)
1346 {
1347 #ifdef TOUCH_DEBUG
1348     if (event->type() == QEvent::TouchBegin)
1349         qWarning("touchBeginEvent");
1350     else if (event->type() == QEvent::TouchUpdate)
1351         qWarning("touchUpdateEvent");
1352     else if (event->type() == QEvent::TouchEnd)
1353         qWarning("touchEndEvent");
1354 #endif
1355
1356     QHash<QSGItem *, QList<QTouchEvent::TouchPoint> > updatedPoints;
1357
1358     if (event->type() == QTouchEvent::TouchBegin) {     // all points are new touch points
1359         QSet<int> acceptedNewPoints;
1360         deliverTouchPoints(rootItem, event, event->touchPoints(), &acceptedNewPoints, &updatedPoints);
1361         if (acceptedNewPoints.count() > 0)
1362             event->accept();
1363         return event->isAccepted();
1364     }
1365
1366     const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
1367     QList<QTouchEvent::TouchPoint> newPoints;
1368     QSGItem *item = 0;
1369     for (int i=0; i<touchPoints.count(); i++) {
1370         const QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
1371         switch (touchPoint.state()) {
1372             case Qt::TouchPointPressed:
1373                 newPoints << touchPoint;
1374                 break;
1375             case Qt::TouchPointMoved:
1376             case Qt::TouchPointStationary:
1377             case Qt::TouchPointReleased:
1378                 if (itemForTouchPointId.contains(touchPoint.id())) {
1379                     item = itemForTouchPointId[touchPoint.id()];
1380                     if (item)
1381                         updatedPoints[item].append(touchPoint);
1382                 }
1383                 break;
1384             default:
1385                 break;
1386         }
1387     }
1388
1389     if (newPoints.count() > 0 || updatedPoints.count() > 0) {
1390         QSet<int> acceptedNewPoints;
1391         int prevCount = updatedPoints.count();
1392         deliverTouchPoints(rootItem, event, newPoints, &acceptedNewPoints, &updatedPoints);
1393         if (acceptedNewPoints.count() > 0 || updatedPoints.count() != prevCount)
1394             event->accept();
1395     }
1396
1397     if (event->touchPointStates() & Qt::TouchPointReleased) {
1398         for (int i=0; i<touchPoints.count(); i++) {
1399             if (touchPoints[i].state() == Qt::TouchPointReleased)
1400                 itemForTouchPointId.remove(touchPoints[i].id());
1401         }
1402     }
1403
1404     return event->isAccepted();
1405 }
1406
1407 bool QSGCanvasPrivate::deliverTouchPoints(QSGItem *item, QTouchEvent *event, const QList<QTouchEvent::TouchPoint> &newPoints, QSet<int> *acceptedNewPoints, QHash<QSGItem *, QList<QTouchEvent::TouchPoint> > *updatedPoints)
1408 {
1409     Q_Q(QSGCanvas);
1410     QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
1411
1412     if (itemPrivate->opacity == 0.0)
1413         return false;
1414
1415     if (itemPrivate->flags & QSGItem::ItemClipsChildrenToShape) {
1416         QRectF bounds(0, 0, item->width(), item->height());
1417         for (int i=0; i<newPoints.count(); i++) {
1418             QPointF p = item->mapFromScene(newPoints[i].scenePos());
1419             if (!bounds.contains(p))
1420                 return false;
1421         }
1422     }
1423
1424     QList<QSGItem *> children = itemPrivate->paintOrderChildItems();
1425     for (int ii = children.count() - 1; ii >= 0; --ii) {
1426         QSGItem *child = children.at(ii);
1427         if (!child->isEnabled())
1428             continue;
1429         if (deliverTouchPoints(child, event, newPoints, acceptedNewPoints, updatedPoints))
1430             return true;
1431     }
1432
1433     QList<QTouchEvent::TouchPoint> matchingPoints;
1434     if (newPoints.count() > 0 && acceptedNewPoints->count() < newPoints.count()) {
1435         QRectF bounds(0, 0, item->width(), item->height());
1436         for (int i=0; i<newPoints.count(); i++) {
1437             if (acceptedNewPoints->contains(newPoints[i].id()))
1438                 continue;
1439             QPointF p = item->mapFromScene(newPoints[i].scenePos());
1440             if (bounds.contains(p))
1441                 matchingPoints << newPoints[i];
1442         }
1443     }
1444
1445     if (matchingPoints.count() > 0 || (*updatedPoints)[item].count() > 0) {
1446         QList<QTouchEvent::TouchPoint> &eventPoints = (*updatedPoints)[item];
1447         eventPoints.append(matchingPoints);
1448         transformTouchPoints(eventPoints, itemPrivate->canvasToItemTransform());
1449
1450         Qt::TouchPointStates eventStates;
1451         for (int i=0; i<eventPoints.count(); i++)
1452             eventStates |= eventPoints[i].state();
1453         // if all points have the same state, set the event type accordingly
1454         QEvent::Type eventType;
1455         switch (eventStates) {
1456             case Qt::TouchPointPressed:
1457                 eventType = QEvent::TouchBegin;
1458                 break;
1459             case Qt::TouchPointReleased:
1460                 eventType = QEvent::TouchEnd;
1461                 break;
1462             default:
1463                 eventType = QEvent::TouchUpdate;
1464                 break;
1465         }
1466
1467         if (eventStates != Qt::TouchPointStationary) {
1468             QTouchEvent touchEvent(eventType);
1469             touchEvent.setWidget(q);
1470             touchEvent.setDeviceType(event->deviceType());
1471             touchEvent.setModifiers(event->modifiers());
1472             touchEvent.setTouchPointStates(eventStates);
1473             touchEvent.setTouchPoints(eventPoints);
1474
1475             touchEvent.accept();
1476             q->sendEvent(item, &touchEvent);
1477
1478             if (touchEvent.isAccepted()) {
1479                 for (int i=0; i<matchingPoints.count(); i++) {
1480                     itemForTouchPointId[matchingPoints[i].id()] = item;
1481                     acceptedNewPoints->insert(matchingPoints[i].id());
1482                 }
1483             }
1484         }
1485     }
1486
1487     updatedPoints->remove(item);
1488     if (acceptedNewPoints->count() == newPoints.count() && updatedPoints->isEmpty())
1489         return true;
1490
1491     return false;
1492 }
1493
1494 bool QSGCanvasPrivate::sendFilteredMouseEvent(QSGItem *target, QSGItem *item, QGraphicsSceneMouseEvent *event)
1495 {
1496     if (!target)
1497         return false;
1498
1499     if (sendFilteredMouseEvent(target->parentItem(), item, event))
1500         return true;
1501
1502     QSGItemPrivate *targetPrivate = QSGItemPrivate::get(target);
1503     if (targetPrivate->filtersChildMouseEvents) 
1504         if (target->childMouseEventFilter(item, event))
1505             return true;
1506
1507     return false;
1508 }
1509
1510 bool QSGCanvas::sendEvent(QSGItem *item, QEvent *e) 
1511
1512     Q_D(QSGCanvas);
1513     
1514     if (!item) {
1515         qWarning("QSGCanvas::sendEvent: Cannot send event to a null item");
1516         return false;
1517     }
1518
1519     Q_ASSERT(e);
1520
1521     switch (e->type()) {
1522     case QEvent::KeyPress:
1523     case QEvent::KeyRelease:
1524         QSGItemPrivate::get(item)->deliverKeyEvent(static_cast<QKeyEvent *>(e));
1525         while (!e->isAccepted() && (item = item->parentItem())) {
1526             e->accept();
1527             QSGItemPrivate::get(item)->deliverKeyEvent(static_cast<QKeyEvent *>(e));
1528         }
1529         break;
1530     case QEvent::InputMethod:
1531         QSGItemPrivate::get(item)->deliverInputMethodEvent(static_cast<QInputMethodEvent *>(e));
1532         while (!e->isAccepted() && (item = item->parentItem())) {
1533             e->accept();
1534             QSGItemPrivate::get(item)->deliverInputMethodEvent(static_cast<QInputMethodEvent *>(e));
1535         }
1536         break;
1537     case QEvent::FocusIn:
1538     case QEvent::FocusOut:
1539         QSGItemPrivate::get(item)->deliverFocusEvent(static_cast<QFocusEvent *>(e));
1540         break;
1541     case QEvent::GraphicsSceneMousePress:
1542     case QEvent::GraphicsSceneMouseRelease:
1543     case QEvent::GraphicsSceneMouseDoubleClick:
1544     case QEvent::GraphicsSceneMouseMove:
1545         // XXX todo - should sendEvent be doing this?  how does it relate to forwarded events? 
1546         {
1547             QGraphicsSceneMouseEvent *se = static_cast<QGraphicsSceneMouseEvent *>(e);
1548             if (!d->sendFilteredMouseEvent(item->parentItem(), item, se)) {
1549                 se->accept();
1550                 QSGItemPrivate::get(item)->deliverMouseEvent(se);
1551             }
1552         }
1553         break;
1554     case QEvent::GraphicsSceneWheel:
1555         QSGItemPrivate::get(item)->deliverWheelEvent(static_cast<QGraphicsSceneWheelEvent *>(e));
1556         break;
1557     case QEvent::GraphicsSceneHoverEnter:
1558     case QEvent::GraphicsSceneHoverLeave:
1559     case QEvent::GraphicsSceneHoverMove:
1560         QSGItemPrivate::get(item)->deliverHoverEvent(static_cast<QGraphicsSceneHoverEvent *>(e));
1561         break;
1562     case QEvent::TouchBegin:
1563     case QEvent::TouchUpdate:
1564     case QEvent::TouchEnd:
1565         QSGItemPrivate::get(item)->deliverTouchEvent(static_cast<QTouchEvent *>(e));
1566         break;
1567     default:
1568         break;
1569     }
1570
1571     return false; 
1572 }
1573
1574 void QSGCanvasPrivate::cleanupNodes()
1575 {
1576     for (int ii = 0; ii < cleanupNodeList.count(); ++ii)
1577         delete cleanupNodeList.at(ii);
1578     cleanupNodeList.clear();
1579 }
1580
1581 void QSGCanvasPrivate::updateDirtyNodes()
1582 {
1583 #ifdef DIRTY_DEBUG
1584     qWarning() << "QSGCanvasPrivate::updateDirtyNodes():";
1585 #endif
1586
1587     cleanupNodes();
1588
1589     QSGItem *updateList = dirtyItemList;
1590     dirtyItemList = 0;
1591     if (updateList) QSGItemPrivate::get(updateList)->prevDirtyItem = &updateList;
1592
1593     while (updateList) {
1594         QSGItem *item = updateList;
1595         QSGItemPrivate *itemPriv = QSGItemPrivate::get(item);
1596         itemPriv->removeFromDirtyList();
1597
1598 #ifdef DIRTY_DEBUG
1599         qWarning() << "   QSGNode:" << item << qPrintable(itemPriv->dirtyToString());
1600 #endif
1601         updateDirtyNode(item);
1602     }
1603 }
1604
1605 void QSGCanvasPrivate::updateDirtyNode(QSGItem *item)
1606 {
1607 #ifdef QML_RUNTIME_TESTING
1608     bool didFlash = false;
1609 #endif
1610
1611     QSGItemPrivate *itemPriv = QSGItemPrivate::get(item);
1612     quint32 dirty = itemPriv->dirtyAttributes;
1613     itemPriv->dirtyAttributes = 0;
1614
1615     if ((dirty & QSGItemPrivate::TransformUpdateMask) ||
1616         (dirty & QSGItemPrivate::Size && itemPriv->origin != QSGItem::TopLeft && 
1617          (itemPriv->scale != 1. || itemPriv->rotation != 0.))) {
1618
1619         QMatrix4x4 matrix;
1620
1621         if (itemPriv->x != 0. || itemPriv->y != 0.) 
1622             matrix.translate(itemPriv->x, itemPriv->y);
1623
1624         if (dirty & QSGItemPrivate::ComplexTransformUpdateMask) {
1625             for (int ii = itemPriv->transforms.count() - 1; ii >= 0; --ii)
1626                 itemPriv->transforms.at(ii)->applyTo(&matrix);
1627         }
1628
1629         if (itemPriv->scale != 1. || itemPriv->rotation != 0.) {
1630             QPointF origin = itemPriv->computeTransformOrigin();
1631             matrix.translate(origin.x(), origin.y());
1632             if (itemPriv->scale != 1.)
1633                 matrix.scale(itemPriv->scale, itemPriv->scale);
1634             if (itemPriv->rotation != 0.)
1635                 matrix.rotate(itemPriv->rotation, 0, 0, 1);
1636             matrix.translate(-origin.x(), -origin.y());
1637         }
1638
1639         itemPriv->itemNode()->setMatrix(matrix);
1640     }
1641
1642     bool clipEffectivelyChanged = dirty & QSGItemPrivate::Clip &&
1643                                   ((item->clip() == false) != (itemPriv->clipNode == 0));
1644     bool effectRefEffectivelyChanged = dirty & QSGItemPrivate::EffectReference &&
1645                                   ((itemPriv->effectRefCount == 0) != (itemPriv->rootNode == 0));
1646
1647     if (clipEffectivelyChanged) {
1648         QSGNode *parent = itemPriv->opacityNode ? (QSGNode *) itemPriv->opacityNode : (QSGNode *)itemPriv->itemNode();
1649         QSGNode *child = itemPriv->rootNode ? (QSGNode *)itemPriv->rootNode : (QSGNode *)itemPriv->groupNode;
1650
1651         if (item->clip()) {
1652             Q_ASSERT(itemPriv->clipNode == 0);
1653             itemPriv->clipNode = new QSGDefaultClipNode(QRectF(0, 0, itemPriv->width, itemPriv->height));
1654
1655             if (child)
1656                 parent->removeChildNode(child);
1657             parent->appendChildNode(itemPriv->clipNode);
1658             if (child)
1659                 itemPriv->clipNode->appendChildNode(child);
1660
1661         } else {
1662             Q_ASSERT(itemPriv->clipNode != 0);
1663             parent->removeChildNode(itemPriv->clipNode);
1664             if (child)
1665                 itemPriv->clipNode->removeChildNode(child);
1666             delete itemPriv->clipNode;
1667             itemPriv->clipNode = 0;
1668             if (child)
1669                 parent->appendChildNode(child);
1670         }
1671     }
1672
1673     if (dirty & QSGItemPrivate::ChildrenUpdateMask) {
1674         while (itemPriv->childContainerNode()->childCount())
1675             itemPriv->childContainerNode()->removeChildNode(itemPriv->childContainerNode()->childAtIndex(0));
1676     }
1677
1678     if (effectRefEffectivelyChanged) {
1679         QSGNode *parent = itemPriv->clipNode;
1680         if (!parent)
1681             parent = itemPriv->opacityNode;
1682         if (!parent)
1683             parent = itemPriv->itemNode();
1684         QSGNode *child = itemPriv->groupNode;
1685
1686         if (itemPriv->effectRefCount) {
1687             Q_ASSERT(itemPriv->rootNode == 0);
1688             itemPriv->rootNode = new QSGRootNode;
1689
1690             if (child)
1691                 parent->removeChildNode(child);
1692             parent->appendChildNode(itemPriv->rootNode);
1693             if (child)
1694                 itemPriv->rootNode->appendChildNode(child);
1695         } else {
1696             Q_ASSERT(itemPriv->rootNode != 0);
1697             parent->removeChildNode(itemPriv->rootNode);
1698             if (child)
1699                 itemPriv->rootNode->removeChildNode(child);
1700             delete itemPriv->rootNode;
1701             itemPriv->rootNode = 0;
1702             if (child)
1703                 parent->appendChildNode(child);
1704         }
1705     }
1706
1707     if (dirty & QSGItemPrivate::ChildrenUpdateMask) {
1708         QSGNode *groupNode = itemPriv->groupNode;
1709         if (groupNode) {
1710             for (int count = groupNode->childCount(); count; --count)
1711                 groupNode->removeChildNode(groupNode->childAtIndex(0));
1712         }
1713
1714         QList<QSGItem *> orderedChildren = itemPriv->paintOrderChildItems();
1715         int ii = 0;
1716
1717         itemPriv->paintNodeIndex = 0;
1718         for (; ii < orderedChildren.count() && orderedChildren.at(ii)->z() < 0; ++ii) {
1719             QSGItemPrivate *childPrivate = QSGItemPrivate::get(orderedChildren.at(ii));
1720             if (!childPrivate->explicitVisible && !childPrivate->effectRefCount)
1721                 continue;
1722             if (childPrivate->itemNode()->parent())
1723                 childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
1724
1725             itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
1726             itemPriv->paintNodeIndex++;
1727         }
1728
1729         if (itemPriv->paintNode)
1730             itemPriv->childContainerNode()->appendChildNode(itemPriv->paintNode);
1731
1732         for (; ii < orderedChildren.count(); ++ii) {
1733             QSGItemPrivate *childPrivate = QSGItemPrivate::get(orderedChildren.at(ii));
1734             if (!childPrivate->explicitVisible && !childPrivate->effectRefCount)
1735                 continue;
1736             if (childPrivate->itemNode()->parent())
1737                 childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
1738
1739             itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
1740         }
1741     }
1742
1743     if ((dirty & QSGItemPrivate::Size || clipEffectivelyChanged) && itemPriv->clipNode) {
1744         itemPriv->clipNode->setRect(QRectF(0, 0, itemPriv->width, itemPriv->height));
1745         itemPriv->clipNode->update();
1746     }
1747
1748     if (dirty & (QSGItemPrivate::OpacityValue | QSGItemPrivate::Visible | QSGItemPrivate::HideReference)) {
1749         qreal opacity = itemPriv->explicitVisible && itemPriv->hideRefCount == 0
1750                       ? itemPriv->opacity : qreal(0);
1751
1752         if (opacity != 1 && !itemPriv->opacityNode) {
1753             itemPriv->opacityNode = new QSGOpacityNode;
1754
1755             QSGNode *parent = itemPriv->itemNode();
1756             QSGNode *child = itemPriv->clipNode;
1757             if (!child)
1758                 child = itemPriv->rootNode;
1759             if (!child)
1760                 child = itemPriv->groupNode;
1761
1762             if (child)
1763                 parent->removeChildNode(child);
1764             parent->appendChildNode(itemPriv->opacityNode);
1765             if (child)
1766                 itemPriv->opacityNode->appendChildNode(child);
1767         }
1768         if (itemPriv->opacityNode)
1769             itemPriv->opacityNode->setOpacity(opacity);
1770     }
1771
1772     if (dirty & QSGItemPrivate::ContentUpdateMask) {
1773
1774         if (itemPriv->flags & QSGItem::ItemHasContents) {
1775             updatePaintNodeData.transformNode = itemPriv->itemNode(); 
1776             itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
1777
1778             Q_ASSERT(itemPriv->paintNode == 0 || 
1779                      itemPriv->paintNode->parent() == 0 ||
1780                      itemPriv->paintNode->parent() == itemPriv->childContainerNode());
1781
1782             if (itemPriv->paintNode && itemPriv->paintNode->parent() == 0) {
1783                 if (itemPriv->childContainerNode()->childCount() == itemPriv->paintNodeIndex)
1784                     itemPriv->childContainerNode()->appendChildNode(itemPriv->paintNode);
1785                 else 
1786                     itemPriv->childContainerNode()->insertChildNodeBefore(itemPriv->paintNode, itemPriv->childContainerNode()->childAtIndex(itemPriv->paintNodeIndex));
1787             }
1788         } else if (itemPriv->paintNode) {
1789             delete itemPriv->paintNode;
1790         }
1791     }
1792
1793 #ifndef QT_NO_DEBUG
1794     // Check consistency.
1795     const QSGNode *nodeChain[] = {
1796         itemPriv->itemNodeInstance,
1797         itemPriv->opacityNode,
1798         itemPriv->clipNode,
1799         itemPriv->rootNode,
1800         itemPriv->groupNode,
1801         itemPriv->paintNode,
1802     };
1803
1804     int ip = 0;
1805     for (;;) {
1806         while (ip < 5 && nodeChain[ip] == 0)
1807             ++ip;
1808         if (ip == 5)
1809             break;
1810         int ic = ip + 1;
1811         while (ic < 5 && nodeChain[ic] == 0)
1812             ++ic;
1813         const QSGNode *parent = nodeChain[ip];
1814         const QSGNode *child = nodeChain[ic];
1815         if (child == 0) {
1816             Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 0);
1817         } else {
1818             Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 1);
1819             Q_ASSERT(child->parent() == parent);
1820             bool containsChild = false;
1821             for (int i = 0; i < parent->childCount(); ++i)
1822                 containsChild |= (parent->childAtIndex(i) == child);
1823             Q_ASSERT(containsChild);
1824         }
1825         ip = ic;
1826     }
1827 #endif
1828
1829 #ifdef QML_RUNTIME_TESTING
1830     if (itemPriv->sceneGraphContext()->isFlashModeEnabled()) {
1831         QSGFlashNode *flash = new QSGFlashNode();
1832         flash->setRect(item->boundingRect());
1833         itemPriv->childContainerNode()->appendChildNode(flash);
1834         didFlash = true;
1835     }
1836     Q_Q(QSGCanvas);
1837     if (didFlash) {
1838         q->maybeUpdate();
1839     }
1840 #endif
1841
1842 }
1843
1844 void QSGCanvas::maybeUpdate()
1845 {
1846     Q_D(QSGCanvas);
1847
1848     if (d->threadedRendering) {
1849         if (!d->renderThreadAwakened) {
1850             d->renderThreadAwakened = true;
1851             bool locked = d->mutex.tryLock();
1852             if (d->idle && locked) {
1853 #ifdef THREAD_DEBUG
1854                 qWarning("QSGRenderer: now maybe I should update...");
1855 #endif
1856                 d->wait.wakeOne();
1857             }
1858             if (locked)
1859                 d->mutex.unlock();
1860         }
1861     } else if (!d->animationDriver || !d->animationDriver->isRunning()) {
1862         update();
1863     }
1864 }
1865
1866 /*!
1867     \fn void QSGEngine::sceneGraphInitialized();
1868
1869     This signal is emitted when the scene graph has been initialized.
1870
1871     This signal will be emitted from the scene graph rendering thread.
1872  */
1873
1874 /*!
1875     Returns the QSGEngine used for this scene.
1876
1877     The engine will only be available once the scene graph has been
1878     initialized. Register for the sceneGraphEngine() signal to get
1879     notification about this.
1880  */
1881
1882 QSGEngine *QSGCanvas::sceneGraphEngine() const
1883 {
1884     Q_D(const QSGCanvas);
1885     if (d->context->isReady())
1886         return d->context->engine();
1887     return 0;
1888 }
1889
1890 QT_END_NAMESPACE