1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the Qt Compositor.
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
14 ** * Redistributions of source code must retain the above copyright
15 ** notice, this list of conditions and the following disclaimer.
16 ** * Redistributions in binary form must reproduce the above copyright
17 ** notice, this list of conditions and the following disclaimer in
18 ** the documentation and/or other materials provided with the
20 ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
21 ** the names of its contributors may be used to endorse or promote
22 ** products derived from this software without specific prior written
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
39 ****************************************************************************/
41 #include "waylandsurfaceitem.h"
42 #include "waylandsurface.h"
43 #include "waylandcompositor.h"
44 #include "waylandinput.h"
46 #include "wlsurface.h"
47 #include "wlextendedsurface.h"
49 #include <QtGui/QKeyEvent>
50 #include <QtGui/QGuiApplication>
51 #include <QtGui/QScreen>
53 #include <QtQuick/QSGSimpleTextureNode>
54 #include <QtQuick/QSGSimpleRectNode>
55 #include <QtQuick/QQuickCanvas>
57 class WaylandSurfaceTextureProvider : public QSGTextureProvider
60 WaylandSurfaceTextureProvider() : t(0) { }
62 QSGTexture *texture() const {
64 t->setFiltering(smooth ? QSGTexture::Linear : QSGTexture::Nearest);
72 WaylandSurfaceItem::WaylandSurfaceItem(QQuickItem *parent)
77 , m_paintEnabled(true)
78 , m_useTextureAlpha(false)
79 , m_clientRenderingEnabled(false)
80 , m_touchEventsEnabled(false)
84 WaylandSurfaceItem::WaylandSurfaceItem(WaylandSurface *surface, QQuickItem *parent)
89 , m_paintEnabled(true)
90 , m_useTextureAlpha(false)
91 , m_clientRenderingEnabled(false)
92 , m_touchEventsEnabled(false)
97 void WaylandSurfaceItem::init(WaylandSurface *surface)
103 m_surface->setSurfaceItem(0);
107 m_surface->setSurfaceItem(this);
108 if (m_clientRenderingEnabled) {
109 m_surface->sendOnScreenVisibilityChange(m_clientRenderingEnabled);
112 setWidth(surface->size().width());
113 setHeight(surface->size().height());
116 setFlag(ItemHasContents);
117 setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
118 setAcceptHoverEvents(true);
119 connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped()));
120 connect(surface, SIGNAL(unmapped()), this, SLOT(surfaceUnmapped()));
121 connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *)));
122 connect(surface, SIGNAL(damaged(const QRect &)), this, SLOT(surfaceDamaged(const QRect &)));
123 connect(surface, SIGNAL(parentChanged(WaylandSurface*,WaylandSurface*)),
124 this, SLOT(parentChanged(WaylandSurface*,WaylandSurface*)));
125 connect(surface, SIGNAL(sizeChanged()), this, SLOT(updateSize()));
126 connect(surface, SIGNAL(posChanged()), this, SLOT(updatePosition()));
129 m_yInverted = surface ? surface->isYInverted() : true;
132 WaylandSurfaceItem::~WaylandSurfaceItem()
135 m_surface->setSurfaceItem(0);
137 m_texture->deleteLater();
140 void WaylandSurfaceItem::setSurface(WaylandSurface *surface)
142 if (surface == m_surface)
146 emit surfaceChanged();
149 bool WaylandSurfaceItem::isYInverted() const
154 QSGTextureProvider *WaylandSurfaceItem::textureProvider() const
157 m_provider = new WaylandSurfaceTextureProvider();
161 void WaylandSurfaceItem::mousePressEvent(QMouseEvent *event)
164 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
165 if (inputDevice->mouseFocus() != m_surface)
166 inputDevice->setMouseFocus(m_surface, event->pos(), event->globalPos());
167 inputDevice->sendMousePressEvent(event->button(), toSurface(event->pos()));
171 void WaylandSurfaceItem::mouseMoveEvent(QMouseEvent *event)
174 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
175 inputDevice->sendMouseMoveEvent(m_surface, toSurface(event->pos()));
179 void WaylandSurfaceItem::mouseReleaseEvent(QMouseEvent *event)
182 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
183 inputDevice->sendMouseReleaseEvent(event->button(), toSurface(event->pos()));
187 void WaylandSurfaceItem::keyPressEvent(QKeyEvent *event)
189 if (m_surface && hasFocus()) {
190 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
191 inputDevice->sendKeyPressEvent(event->nativeScanCode());
195 void WaylandSurfaceItem::keyReleaseEvent(QKeyEvent *event)
197 if (m_surface && hasFocus()) {
198 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
199 inputDevice->sendKeyReleaseEvent(event->nativeScanCode());
203 void WaylandSurfaceItem::touchEvent(QTouchEvent *event)
205 if (m_touchEventsEnabled && m_surface) {
206 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
208 if (inputDevice->mouseFocus() != m_surface) {
210 QList<QTouchEvent::TouchPoint> points = event->touchPoints();
211 if (!points.isEmpty())
212 pointPos = points.at(0).pos().toPoint();
213 inputDevice->setMouseFocus(m_surface, pointPos, pointPos);
215 inputDevice->sendFullTouchEvent(event);
221 void WaylandSurfaceItem::takeFocus()
226 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
227 inputDevice->setKeyboardFocus(m_surface);
231 QPoint WaylandSurfaceItem::toSurface(const QPointF &pos) const
233 return pos.toPoint();
236 void WaylandSurfaceItem::surfaceMapped()
238 setPaintEnabled(true);
241 void WaylandSurfaceItem::surfaceUnmapped()
243 setPaintEnabled(false);
246 void WaylandSurfaceItem::surfaceDestroyed(QObject *)
251 void WaylandSurfaceItem::setDamagedFlag(bool on)
257 void WaylandSurfaceItem::surfaceDamaged(const QRect &)
261 bool inverted = m_surface->isYInverted();
262 if (inverted != m_yInverted) {
263 m_yInverted = inverted;
264 emit yInvertedChanged();
267 emit textureChanged();
271 void WaylandSurfaceItem::parentChanged(WaylandSurface *newParent, WaylandSurface *oldParent)
275 WaylandSurfaceItem *item = newParent? newParent->surfaceItem():0;
279 setPaintEnabled(true);
286 void WaylandSurfaceItem::updateSize()
288 setSize(m_surface->size());
291 void WaylandSurfaceItem::updatePosition()
293 setPos(m_surface->pos());
296 bool WaylandSurfaceItem::paintEnabled() const
298 return m_paintEnabled;
301 void WaylandSurfaceItem::setPaintEnabled(bool enabled)
303 m_paintEnabled = enabled;
307 class WaylandSurfaceNode : public QSGSimpleTextureNode
310 WaylandSurfaceNode(WaylandSurfaceItem *item) : m_item(item) {
311 setFlag(UsePreprocess,true);
314 if (m_item->m_damaged)
315 m_item->updateNodeTexture(this);
318 WaylandSurfaceItem *m_item;
322 void WaylandSurfaceItem::updateNodeTexture(WaylandSurfaceNode *node)
325 QSGTexture *oldTexture = m_texture;
326 if (m_surface->type() == WaylandSurface::Texture) {
327 QOpenGLContext *context = QOpenGLContext::currentContext();
329 QQuickCanvas::CreateTextureOptions opt = useTextureAlpha() ? QQuickCanvas::TextureHasAlphaChannel : QQuickCanvas::CreateTextureOptions(0);
330 m_texture = canvas()->createTextureFromId(m_surface->texture(context),
334 m_texture = canvas()->createTextureFromImage(m_surface->image());
342 m_provider->t = m_texture;
343 m_provider->smooth = smooth();
346 node->setTexture(m_texture);
347 node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
351 QSGNode *WaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
353 if (!m_surface || !m_paintEnabled) {
358 WaylandSurfaceNode *node = static_cast<WaylandSurfaceNode *>(oldNode);
361 node = new WaylandSurfaceNode(this);
364 updateNodeTexture(node);
366 if (surface()->isYInverted()) {
367 node->setRect(0, height(), width(), -height());
369 node->setRect(0, 0, width(), height());
375 void WaylandSurfaceItem::setUseTextureAlpha(bool useTextureAlpha)
377 m_useTextureAlpha = useTextureAlpha;
379 if ((flags() & ItemHasContents) != 0) {
384 void WaylandSurfaceItem::setClientRenderingEnabled(bool enabled)
386 if (m_clientRenderingEnabled != enabled) {
387 m_clientRenderingEnabled = enabled;
390 m_surface->sendOnScreenVisibilityChange(enabled);
393 emit clientRenderingEnabledChanged();
397 void WaylandSurfaceItem::setTouchEventsEnabled(bool enabled)
399 if (m_touchEventsEnabled != enabled) {
400 m_touchEventsEnabled = enabled;
401 emit touchEventsEnabledChanged();