Get rid of QOpenGLContext dependency in WaylandCompositor constructor.
[profile/ivi/qtwayland.git] / examples / qwindow-compositor / qwindowcompositor.cpp
1 #include "qwindowcompositor.h"
2 #include <QMouseEvent>
3 #include <QKeyEvent>
4 #include <QTouchEvent>
5
6 QWindowCompositor::QWindowCompositor(QOpenGLWindow *window)
7     : WaylandCompositor(window)
8     , m_window(window)
9 {
10     m_backgroundImage = QImage(QLatin1String(":/background.jpg"));
11     m_renderer = new SurfaceRenderer(m_window->context(), m_window);
12     m_backgroundTexture = m_renderer->textureFromImage(m_backgroundImage);
13
14     window->installEventFilter(this);
15
16     render();
17 }
18
19 void QWindowCompositor::surfaceDestroyed(QObject *object)
20 {
21     WaylandSurface *surface = static_cast<WaylandSurface *>(object);
22     m_surfaces.removeOne(surface);
23     if (inputFocus() == surface || !inputFocus()) // typically reset to 0 already in Compositor::surfaceDestroyed()
24         setInputFocus(m_surfaces.isEmpty() ? 0 : m_surfaces.last());
25     render();
26 }
27
28 void QWindowCompositor::surfaceMapped(const QSize &size)
29 {
30     WaylandSurface *surface = qobject_cast<WaylandSurface *>(sender());
31     QPoint pos;
32     if (!m_surfaces.contains(surface)) {
33         uint px = 1 + (qrand() % (m_window->width() - size.width() - 2));
34         uint py = 1 + (qrand() % (m_window->height() - size.height() - 2));
35         pos = QPoint(px, py);
36         surface->setGeometry(QRect(pos, size));
37     } else {
38         surface->setGeometry(QRect(window()->geometry().topLeft(),size));
39         m_surfaces.removeOne(surface);
40     }
41     m_surfaces.append(surface);
42     setInputFocus(surface);
43     render();
44 }
45
46 void QWindowCompositor::surfaceDamaged(const QRect &rect)
47 {
48     WaylandSurface *surface = qobject_cast<WaylandSurface *>(sender());
49     surfaceDamaged(surface, rect);
50 }
51
52 void QWindowCompositor::surfaceDamaged(WaylandSurface *surface, const QRect &rect)
53 {
54     Q_UNUSED(surface)
55     Q_UNUSED(rect)
56     render();
57 }
58
59 void QWindowCompositor::surfaceCreated(WaylandSurface *surface)
60 {
61     connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *)));
62     connect(surface, SIGNAL(mapped(const QSize &)), this, SLOT(surfaceMapped(const QSize &)));
63     connect(surface, SIGNAL(damaged(const QRect &)), this, SLOT(surfaceDamaged(const QRect &)));
64     render();
65 }
66
67 QPointF QWindowCompositor::toSurface(WaylandSurface *surface, const QPointF &pos) const
68 {
69     return pos - surface->geometry().topLeft();
70 }
71
72 WaylandSurface *QWindowCompositor::surfaceAt(const QPoint &point, QPoint *local)
73 {
74     for (int i = m_surfaces.size() - 1; i >= 0; --i) {
75         if (m_surfaces.at(i)->geometry().contains(point)) {
76             if (local)
77                 *local = toSurface(m_surfaces.at(i), point).toPoint();
78             return m_surfaces.at(i);
79         }
80     }
81     return 0;
82 }
83
84 void QWindowCompositor::render()
85 {
86     m_window->makeCurrent();
87
88     //Draw the background Image texture
89     int w = m_window->width();
90     int h = m_window->height();
91     int iw = m_backgroundImage.width();
92     int ih = m_backgroundImage.height();
93     for (int y = 0; y < h; y += ih) {
94         for (int x = 0; x < w; x += iw) {
95             m_renderer->drawTexture(m_backgroundTexture, QRect(QPoint(x, y), QSize(iw, ih)), 0);
96         }
97     }
98
99     //Iterate all surfaces in m_surfaces
100     //If type == WaylandSurface::Texture draw textureId at geometry
101     foreach (WaylandSurface *surface, m_surfaces) {
102         if (surface->type() == WaylandSurface::Texture)
103             m_renderer->drawTexture(surface->texture(QOpenGLContext::currentContext()), surface->geometry(), 1); //depth argument should be dynamic (focused should be top).
104         else if (surface->type() == WaylandSurface::Shm)
105             m_renderer->drawImage(surface->image(), surface->geometry());
106     }
107     frameFinished();
108     glFinish();
109     m_window->swapBuffers();
110     m_window->context()->doneCurrent();
111 }
112
113 bool QWindowCompositor::eventFilter(QObject *obj, QEvent *event)
114 {
115     if (obj != m_window)
116         return false;
117
118     switch (event->type()) {
119     case QEvent::MouseButtonPress: {
120         QPoint local;
121         QMouseEvent *me = static_cast<QMouseEvent *>(event);
122         WaylandSurface *targetSurface = surfaceAt(me->pos(), &local);
123         if (targetSurface) {
124             if (inputFocus() != targetSurface) {
125                 setInputFocus(targetSurface);
126                 m_surfaces.removeOne(targetSurface);
127                 m_surfaces.append(targetSurface);
128                 render();
129             }
130             targetSurface->sendMousePressEvent(local, me->button());
131         }
132         break;
133     }
134     case QEvent::MouseButtonRelease: {
135         WaylandSurface *targetSurface = inputFocus();
136         if (targetSurface) {
137             QMouseEvent *me = static_cast<QMouseEvent *>(event);
138             targetSurface->sendMouseReleaseEvent(toSurface(targetSurface, me->pos()).toPoint(), me->button());
139         }
140         break;
141     }
142     case QEvent::KeyPress: {
143         QKeyEvent *ke = static_cast<QKeyEvent *>(event);
144         WaylandSurface *targetSurface = inputFocus();
145         if (targetSurface)
146             targetSurface->sendKeyPressEvent(ke->nativeScanCode());
147         break;
148     }
149     case QEvent::KeyRelease: {
150         QKeyEvent *ke = static_cast<QKeyEvent *>(event);
151         WaylandSurface *targetSurface = inputFocus();
152         if (targetSurface)
153             targetSurface->sendKeyReleaseEvent(ke->nativeScanCode());
154         break;
155     }
156     case QEvent::TouchBegin:
157     case QEvent::TouchUpdate:
158     case QEvent::TouchEnd:
159     {
160         QSet<WaylandSurface *> targets;
161         QTouchEvent *te = static_cast<QTouchEvent *>(event);
162         QList<QTouchEvent::TouchPoint> points = te->touchPoints();
163         for (int i = 0; i < points.count(); ++i) {
164             const QTouchEvent::TouchPoint &tp(points.at(i));
165             QPoint local;
166             WaylandSurface *targetSurface = surfaceAt(tp.pos().toPoint(), &local);
167             if (targetSurface) {
168                 targetSurface->sendTouchPointEvent(tp.id(), local.x(), local.y(), tp.state());
169                 targets.insert(targetSurface);
170             }
171         }
172         foreach (WaylandSurface *surface, targets)
173             surface->sendTouchFrameEvent();
174         break;
175     }
176     default:
177         break;
178     }
179     return false;
180 }