1 /****************************************************************************
3 ** This file is part of QtCompositor**
5 ** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies).
6 ** All rights reserved.
8 ** Contact: Nokia Corporation qt-info@nokia.com
10 ** You may use this file under the terms of the BSD license as follows:
12 ** Redistribution and use in source and binary forms, with or without
13 ** modification, are permitted provided that the following conditions are
16 ** Redistributions of source code must retain the above copyright
17 ** notice, this list of conditions and the following disclaimer.
19 ** Redistributions in binary form must reproduce the above copyright
20 ** notice, this list of conditions and the following disclaimer in the
21 ** documentation and/or other materials provided with the distribution.
23 ** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
24 ** names of its contributors may be used to endorse or promote products
25 ** derived from this software without specific prior written permission.
27 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 ** 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>
51 #include <QtQuick/QSGSimpleTextureNode>
52 #include <QtQuick/QSGSimpleRectNode>
53 #include <QtQuick/QQuickCanvas>
55 class WaylandSurfaceTextureProvider : public QSGTextureProvider
58 WaylandSurfaceTextureProvider() : t(0) { }
60 QSGTexture *texture() const {
62 t->setFiltering(smooth ? QSGTexture::Linear : QSGTexture::Nearest);
70 WaylandSurfaceItem::WaylandSurfaceItem(QQuickItem *parent)
75 , m_paintEnabled(true)
76 , m_touchEventsEnabled(false)
80 WaylandSurfaceItem::WaylandSurfaceItem(WaylandSurface *surface, QQuickItem *parent)
85 , m_paintEnabled(true)
86 , m_touchEventsEnabled(false)
91 void WaylandSurfaceItem::init(WaylandSurface *surface)
97 m_surface->setSurfaceItem(0);
101 m_surface->setSurfaceItem(this);
103 setWidth(surface->size().width());
104 setHeight(surface->size().height());
107 setFlag(ItemHasContents);
108 setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
109 connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped()));
110 connect(surface, SIGNAL(unmapped()), this, SLOT(surfaceUnmapped()));
111 connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *)));
112 connect(surface, SIGNAL(damaged(const QRect &)), this, SLOT(surfaceDamaged(const QRect &)));
113 connect(surface, SIGNAL(parentChanged(WaylandSurface*,WaylandSurface*)),
114 this, SLOT(parentChanged(WaylandSurface*,WaylandSurface*)));
115 connect(surface, SIGNAL(sizeChanged()), this, SLOT(updateSize()));
116 connect(surface, SIGNAL(posChanged()), this, SLOT(updatePosition()));
119 m_yInverted = surface ? surface->isYInverted() : true;
122 WaylandSurfaceItem::~WaylandSurfaceItem()
125 m_surface->setSurfaceItem(0);
127 m_texture->deleteLater();
130 void WaylandSurfaceItem::setSurface(WaylandSurface *surface)
135 bool WaylandSurfaceItem::isYInverted() const
140 QSGTextureProvider *WaylandSurfaceItem::textureProvider() const
143 m_provider = new WaylandSurfaceTextureProvider();
147 void WaylandSurfaceItem::mousePressEvent(QMouseEvent *event)
150 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
151 inputDevice->sendMousePressEvent(event->button(), toSurface(event->pos()));
155 void WaylandSurfaceItem::mouseMoveEvent(QMouseEvent *event)
158 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
159 inputDevice->sendMouseMoveEvent(m_surface, toSurface(event->pos()));
163 void WaylandSurfaceItem::mouseReleaseEvent(QMouseEvent *event)
166 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
167 inputDevice->sendMouseReleaseEvent(event->button(), toSurface(event->pos()));
171 void WaylandSurfaceItem::keyPressEvent(QKeyEvent *event)
173 if (m_surface && hasFocus()) {
174 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
175 inputDevice->sendKeyPressEvent(event->nativeScanCode());
179 void WaylandSurfaceItem::keyReleaseEvent(QKeyEvent *event)
181 if (m_surface && hasFocus()) {
182 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
183 inputDevice->sendKeyReleaseEvent(event->nativeScanCode());
187 void WaylandSurfaceItem::touchEvent(QTouchEvent *event)
189 if (m_touchEventsEnabled && m_surface) {
190 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
192 QList<QTouchEvent::TouchPoint> points = event->touchPoints();
193 if (!points.isEmpty()) {
194 for (int i = 0; i < points.count(); ++i) {
195 const QTouchEvent::TouchPoint &point(points.at(i));
196 // Wayland expects surface-relative coordinates.
197 inputDevice->sendTouchPointEvent(point.id(), point.pos().x(), point.pos().y(), point.state());
199 inputDevice->sendTouchFrameEvent();
206 void WaylandSurfaceItem::takeFocus()
211 WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
212 inputDevice->setKeyboardFocus(m_surface);
216 QPoint WaylandSurfaceItem::toSurface(const QPointF &pos) const
218 return pos.toPoint();
221 void WaylandSurfaceItem::surfaceMapped()
223 setPaintEnabled(true);
226 void WaylandSurfaceItem::surfaceUnmapped()
228 setPaintEnabled(false);
231 void WaylandSurfaceItem::surfaceDestroyed(QObject *)
236 void WaylandSurfaceItem::surfaceDamaged(const QRect &)
240 bool inverted = m_surface->isYInverted();
241 if (inverted != m_yInverted) {
242 m_yInverted = inverted;
243 emit yInvertedChanged();
246 emit textureChanged();
250 void WaylandSurfaceItem::parentChanged(WaylandSurface *newParent, WaylandSurface *oldParent)
254 WaylandSurfaceItem *item = newParent? newParent->surfaceItem():0;
258 setPaintEnabled(true);
265 void WaylandSurfaceItem::updateSize()
267 setSize(m_surface->size());
270 void WaylandSurfaceItem::updatePosition()
272 setPos(m_surface->pos());
275 bool WaylandSurfaceItem::paintEnabled() const
277 return m_paintEnabled;
280 void WaylandSurfaceItem::setPaintEnabled(bool enabled)
282 m_paintEnabled = enabled;
286 QSGNode *WaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
294 QSGTexture *oldTexture = m_texture;
295 if (m_surface->type() == WaylandSurface::Texture) {
296 QOpenGLContext *context = QOpenGLContext::currentContext();
298 QQuickCanvas::CreateTextureOptions opt = useTextureAlpha() ? QQuickCanvas::TextureHasAlphaChannel : QQuickCanvas::CreateTextureOptions(0);
299 m_texture = canvas()->createTextureFromId(m_surface->texture(context),
303 m_texture = canvas()->createTextureFromImage(m_surface->image());
311 m_provider->t = m_texture;
312 m_provider->smooth = smooth();
315 QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode);
316 if (!m_texture || !m_paintEnabled) {
322 node = new QSGSimpleTextureNode();
325 if (surface()->isYInverted()) {
326 node->setRect(0, height(), width(), -height());
328 node->setRect(0, 0, width(), height());
331 node->setTexture(m_texture);
332 node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
337 void WaylandSurfaceItem::setUseTextureAlpha(bool useTextureAlpha)
339 m_useTextureAlpha = useTextureAlpha;
341 if ((flags() & ItemHasContents) != 0) {
346 void WaylandSurfaceItem::setClientRenderingEnabled(bool enabled)
348 if (m_clientRenderingEnabled != enabled) {
349 m_clientRenderingEnabled = enabled;
352 m_surface->sendOnScreenVisibilityChange(enabled);
355 emit clientRenderingEnabledChanged();
359 void WaylandSurfaceItem::setTouchEventsEnabled(bool enabled)
361 if (m_touchEventsEnabled != enabled) {
362 m_touchEventsEnabled = enabled;
363 emit touchEventsEnabledChanged();