diff options
38 files changed, 1474 insertions, 655 deletions
diff --git a/examples/qml-compositor/WindowContainer.qml b/examples/qml-compositor/WindowContainer.qml index 701b46d24..77dd1d4dc 100644 --- a/examples/qml-compositor/WindowContainer.qml +++ b/examples/qml-compositor/WindowContainer.qml @@ -40,6 +40,7 @@ import QtQuick 2.0 import QtQuick.Window 2.0 +import QtCompositor 1.0 Item { id: container @@ -52,10 +53,20 @@ Item { visible: isFullscreen || !root.hasFullscreenWindow onVisibleChanged: { - child.clientRenderingEnabled = visible + child.surface.clientRenderingEnabled = visible console.log("visibility changed: " + visible); } + WaylandSurfaceItem { + id: surfaceItem + anchors.fill: parent + touchEventsEnabled: true + + onSurfaceDestroyed: { + destroyAnimation.start(); + } + } + opacity: 0 property real targetX @@ -64,7 +75,7 @@ Item { property real targetHeight property real targetScale - property variant child: null + property variant child: surfaceItem property variant chrome: null property bool animationsEnabled: false property bool isFullscreen: state === "fullscreen" @@ -168,11 +179,17 @@ Item { NumberAnimation { target: scaleTransform; property: "yScale"; easing.type: Easing.Linear; to: 0.01; duration: 200; } NumberAnimation { target: scaleTransform; property: "xScale"; easing.type: Easing.Linear; to: 0.01; duration: 150; } NumberAnimation { target: container; property: "opacity"; easing.type: Easing.Linear; to: 0.0; duration: 150; } - ScriptAction { script: container.parent.removeWindow(child); } + ScriptAction { script: container.parent.removeWindow(container) } + } + SequentialAnimation { + id: unmapAnimation + NumberAnimation { target: container; property: "opacity"; easing.type: Easing.Linear; to: 0.0; duration: 150; } + ScriptAction { script: container.parent.removeWindow(container) } } - function runDestroyAnimation() { - destroyAnimation.start(); + Connections { + target: container.child.surface + onUnmapped: unmapAnimation.start() } Image { diff --git a/examples/qml-compositor/main.cpp b/examples/qml-compositor/main.cpp index 93b23c0e3..7ebcb6c29 100644 --- a/examples/qml-compositor/main.cpp +++ b/examples/qml-compositor/main.cpp @@ -38,9 +38,8 @@ ** ****************************************************************************/ -#include "qwaylandcompositor.h" -#include "qwaylandsurface.h" -#include "qwaylandsurfaceitem.h" +#include "qwaylandquickcompositor.h" +#include "qwaylandquicksurface.h" #include <QGuiApplication> #include <QTimer> @@ -52,14 +51,14 @@ #include <QQuickItem> #include <QQuickView> -class QmlCompositor : public QQuickView, public QWaylandCompositor +class QmlCompositor : public QQuickView, public QWaylandQuickCompositor { Q_OBJECT - Q_PROPERTY(QWaylandSurface* fullscreenSurface READ fullscreenSurface WRITE setFullscreenSurface NOTIFY fullscreenSurfaceChanged) + Q_PROPERTY(QWaylandQuickSurface* fullscreenSurface READ fullscreenSurface WRITE setFullscreenSurface NOTIFY fullscreenSurfaceChanged) public: QmlCompositor() - : QWaylandCompositor(this, 0, DefaultExtensions | SubSurfaceExtension) + : QWaylandQuickCompositor(this, 0, DefaultExtensions | SubSurfaceExtension) , m_fullscreenSurface(0) { setSource(QUrl("main.qml")); @@ -67,11 +66,10 @@ public: setColor(Qt::black); winId(); - connect(this, SIGNAL(beforeSynchronizing()), this, SLOT(startFrame()), Qt::DirectConnection); connect(this, SIGNAL(afterRendering()), this, SLOT(sendCallbacks())); } - QWaylandSurface *fullscreenSurface() const + QWaylandQuickSurface *fullscreenSurface() const { return m_fullscreenSurface; } @@ -87,12 +85,7 @@ public slots: qvariant_cast<QObject *>(window)->deleteLater(); } - void destroyClientForWindow(QVariant window) { - QWaylandSurface *surface = qobject_cast<QWaylandSurfaceItem *>(qvariant_cast<QObject *>(window))->surface(); - destroyClientForSurface(surface); - } - - void setFullscreenSurface(QWaylandSurface *surface) { + void setFullscreenSurface(QWaylandQuickSurface *surface) { if (surface == m_fullscreenSurface) return; m_fullscreenSurface = surface; @@ -101,34 +94,25 @@ public slots: private slots: void surfaceMapped() { - QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); + QWaylandQuickSurface *surface = qobject_cast<QWaylandQuickSurface *>(sender()); //Ignore surface if it's not a window surface if (!surface->hasShellSurface()) return; - QWaylandSurfaceItem *item = surface->surfaceItem(); - //Create a WaylandSurfaceItem if we have not yet - if (!item) - item = new QWaylandSurfaceItem(surface, rootObject()); - - item->setTouchEventsEnabled(true); - //item->takeFocus(); - emit windowAdded(QVariant::fromValue(static_cast<QQuickItem *>(item))); + emit windowAdded(QVariant::fromValue(surface)); } void surfaceUnmapped() { - QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); + QWaylandQuickSurface *surface = qobject_cast<QWaylandQuickSurface *>(sender()); if (surface == m_fullscreenSurface) m_fullscreenSurface = 0; - QQuickItem *item = surface->surfaceItem(); - emit windowDestroyed(QVariant::fromValue(item)); + emit windowDestroyed(QVariant::fromValue(surface)); } void surfaceDestroyed(QObject *object) { - QWaylandSurface *surface = static_cast<QWaylandSurface *>(object); + QWaylandQuickSurface *surface = static_cast<QWaylandQuickSurface *>(object); if (surface == m_fullscreenSurface) m_fullscreenSurface = 0; - QQuickItem *item = surface->surfaceItem(); - emit windowDestroyed(QVariant::fromValue(item)); + emit windowDestroyed(QVariant::fromValue(surface)); } void sendCallbacks() { @@ -137,9 +121,6 @@ private slots: else sendFrameCallbacks(surfaces()); } - void startFrame() { - frameStarted(); - } protected: void resizeEvent(QResizeEvent *event) @@ -155,7 +136,7 @@ protected: } private: - QWaylandSurface *m_fullscreenSurface; + QWaylandQuickSurface *m_fullscreenSurface; }; int main(int argc, char *argv[]) @@ -170,7 +151,6 @@ int main(int argc, char *argv[]) compositor.rootContext()->setContextProperty("compositor", &compositor); QObject::connect(&compositor, SIGNAL(windowAdded(QVariant)), compositor.rootObject(), SLOT(windowAdded(QVariant))); - QObject::connect(&compositor, SIGNAL(windowDestroyed(QVariant)), compositor.rootObject(), SLOT(windowDestroyed(QVariant))); QObject::connect(&compositor, SIGNAL(windowResized(QVariant)), compositor.rootObject(), SLOT(windowResized(QVariant))); return app.exec(); diff --git a/examples/qml-compositor/main.qml b/examples/qml-compositor/main.qml index 7b152280e..120c92bdb 100644 --- a/examples/qml-compositor/main.qml +++ b/examples/qml-compositor/main.qml @@ -39,6 +39,7 @@ ****************************************************************************/ import QtQuick 2.0 +import QtCompositor 1.0 import "compositor.js" as CompositorLogic Item { @@ -84,15 +85,15 @@ Item { function windowAdded(window) { var windowContainerComponent = Qt.createComponent("WindowContainer.qml"); var windowContainer = windowContainerComponent.createObject(root); + console.log(windowContainerComponent.errorString()); - window.parent = windowContainer; + windowContainer.child.surface = window; - windowContainer.targetWidth = window.width; - windowContainer.targetHeight = window.height; - windowContainer.child = window; + windowContainer.targetWidth = window.size.width; + windowContainer.targetHeight = window.size.height; var windowChromeComponent = Qt.createComponent("WindowChrome.qml"); - var windowChrome = windowChromeComponent.createObject(window); + var windowChrome = windowChromeComponent.createObject(windowContainer.child); CompositorLogic.addWindow(windowContainer); @@ -102,25 +103,16 @@ Item { } function windowResized(window) { - var windowContainer = window.parent; - windowContainer.width = window.width; - windowContainer.height = window.height; + window.width = window.surface.size.width; + window.height = window.surface.size.height; CompositorLogic.relayout(); } - function windowDestroyed(window) { - var windowContainer = window.parent; - if (windowContainer.runDestroyAnimation) - windowContainer.runDestroyAnimation(); - } - function removeWindow(window) { - var windowContainer = window.parent; - CompositorLogic.removeWindow(windowContainer); - windowContainer.chrome.destroy(); - windowContainer.destroy(); - compositor.destroyWindow(window); + CompositorLogic.removeWindow(window); + window.chrome.destroy(); + window.destroy(); } onHeightChanged: CompositorLogic.relayout(); diff --git a/examples/qwindow-compositor/qwindowcompositor.cpp b/examples/qwindow-compositor/qwindowcompositor.cpp index e0f213aa4..aa6afd7aa 100644 --- a/examples/qwindow-compositor/qwindowcompositor.cpp +++ b/examples/qwindow-compositor/qwindowcompositor.cpp @@ -52,6 +52,55 @@ #include <QPainter> #include <QtCompositor/qwaylandinput.h> +#include <QtCompositor/qwaylandbufferref.h> + +static GLuint textureFromImage(const QImage &image) +{ + GLuint texture = 0; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + QImage tx = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tx.width(), tx.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tx.constBits()); + glBindTexture(GL_TEXTURE_2D, 0); + return texture; +} + +class BufferAttacher : public QWaylandBufferAttacher +{ +public: + void attach(const QWaylandBufferRef &ref) Q_DECL_OVERRIDE + { + if (bufferRef) { + if (ownTexture) + glDeleteTextures(1, &texture); + else + bufferRef.destroyTexture(); + } + + bufferRef = ref; + + if (bufferRef) { + if (bufferRef.isShm()) { + texture = textureFromImage(bufferRef.image()); + ownTexture = true; + } else { + texture = bufferRef.createTexture(); + ownTexture = false; + } + } + } + + QImage image() const + { + if (!bufferRef || !bufferRef.isShm()) + return QImage(); + return bufferRef.image(); + } + + QWaylandBufferRef bufferRef; + GLuint texture; + bool ownTexture; +}; QWindowCompositor::QWindowCompositor(QOpenGLWindow *window) : QWaylandCompositor(window, 0, DefaultExtensions | SubSurfaceExtension) @@ -118,9 +167,9 @@ void QWindowCompositor::ensureKeyboardFocusSurface(QWaylandSurface *oldSurface) defaultInputDevice()->setKeyboardFocus(m_surfaces.isEmpty() ? 0 : m_surfaces.last()); } -void QWindowCompositor::surfaceDestroyed(QObject *object) +void QWindowCompositor::surfaceDestroyed() { - QWaylandSurface *surface = static_cast<QWaylandSurface *>(object); + QWaylandSurface *surface = static_cast<QWaylandSurface *>(sender()); m_surfaces.removeOne(surface); ensureKeyboardFocusSurface(surface); m_renderScheduler.start(0); @@ -157,6 +206,7 @@ void QWindowCompositor::surfaceUnmapped() m_surfaces.insert(0, surface); ensureKeyboardFocusSurface(surface); + m_renderScheduler.start(0); } void QWindowCompositor::surfaceCommitted() @@ -178,13 +228,15 @@ void QWindowCompositor::surfaceCommitted(QWaylandSurface *surface) void QWindowCompositor::surfaceCreated(QWaylandSurface *surface) { - connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *))); + connect(surface, SIGNAL(surfaceDestroyed()), this, SLOT(surfaceDestroyed())); connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped())); connect(surface, SIGNAL(unmapped()), this, SLOT(surfaceUnmapped())); - connect(surface, SIGNAL(committed()), this, SLOT(surfaceCommitted())); + connect(surface, SIGNAL(redraw()), this, SLOT(surfaceCommitted())); connect(surface, SIGNAL(extendedSurfaceReady()), this, SLOT(sendExpose())); connect(surface, SIGNAL(posChanged()), this, SLOT(surfacePosChanged())); m_renderScheduler.start(0); + + surface->setBufferAttacher(new BufferAttacher); } void QWindowCompositor::sendExpose() @@ -197,7 +249,10 @@ void QWindowCompositor::updateCursor() { if (!m_cursorSurface) return; - QCursor cursor(QPixmap::fromImage(m_cursorSurface->image()), m_cursorHotspotX, m_cursorHotspotY); + + QImage image = static_cast<BufferAttacher *>(m_cursorSurface->bufferAttacher())->image(); + + QCursor cursor(QPixmap::fromImage(image), m_cursorHotspotX, m_cursorHotspotY); static bool cursorIsSet = false; if (cursorIsSet) { QGuiApplication::changeOverrideCursor(cursor); @@ -215,11 +270,13 @@ QPointF QWindowCompositor::toSurface(QWaylandSurface *surface, const QPointF &po void QWindowCompositor::setCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY) { if ((m_cursorSurface != surface) && surface) - connect(surface, SIGNAL(damaged(QRect)), this, SLOT(updateCursor())); + connect(surface, SIGNAL(configure()), this, SLOT(updateCursor())); m_cursorSurface = surface; m_cursorHotspotX = hotspotX; m_cursorHotspotY = hotspotY; + if (!m_cursorSurface->bufferAttacher()) + m_cursorSurface->setBufferAttacher(new BufferAttacher); } QWaylandSurface *QWindowCompositor::surfaceAt(const QPointF &point, QPointF *local) @@ -236,34 +293,14 @@ QWaylandSurface *QWindowCompositor::surfaceAt(const QPointF &point, QPointF *loc return 0; } -static GLuint textureFromImage(const QImage &image) -{ - GLuint texture = 0; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - QImage tx = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tx.width(), tx.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tx.constBits()); - glBindTexture(GL_TEXTURE_2D, 0); - return texture; -} - -GLuint QWindowCompositor::composeSurface(QWaylandSurface *surface, bool *textureOwned) +GLuint QWindowCompositor::composeSurface(QWaylandSurface *surface) { - GLuint texture = 0; - QSize windowSize = surface->size(); - surface->swapBuffers(); QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions(); functions->glBindFramebuffer(GL_FRAMEBUFFER, m_surface_fbo); - if (surface->type() == QWaylandSurface::Shm) { - texture = textureFromImage(surface->image()); - *textureOwned = true; - } else if (surface->type() == QWaylandSurface::Texture) { - texture = surface->texture(); - *textureOwned = false; - } + GLuint texture = static_cast<BufferAttacher *>(surface->bufferAttacher())->texture; functions->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); @@ -287,19 +324,11 @@ void QWindowCompositor::paintChildren(QWaylandSurface *surface, QWaylandSurface QWaylandSurface *subSurface = i.next(); QPointF p = subSurface->mapTo(window,QPointF(0,0)); QSize subSize = subSurface->size(); - subSurface->swapBuffers(); if (subSize.isValid()) { - GLuint texture = 0; - if (subSurface->type() == QWaylandSurface::Texture) { - texture = subSurface->texture(); - } else if (surface->type() == QWaylandSurface::Shm) { - texture = textureFromImage(subSurface->image()); - } + GLuint texture = static_cast<BufferAttacher *>(subSurface->bufferAttacher())->texture; QRect geo(p.toPoint(),subSize); if (texture > 0) m_textureBlitter->drawTexture(texture,geo,windowSize,0,window->isYInverted(),subSurface->isYInverted()); - if (surface->type() == QWaylandSurface::Shm) - glDeleteTextures(1, &texture); } paintChildren(subSurface,window,windowSize); } @@ -326,12 +355,9 @@ void QWindowCompositor::render() foreach (QWaylandSurface *surface, m_surfaces) { if (!surface->visible()) continue; - bool ownsTexture; - GLuint texture = composeSurface(surface, &ownsTexture); + GLuint texture = composeSurface(surface); QRect geo(surface->pos().toPoint(),surface->size()); m_textureBlitter->drawTexture(texture,geo,m_window->size(),0,false,surface->isYInverted()); - if (ownsTexture) - glDeleteTextures(1, &texture); } m_textureBlitter->release(); diff --git a/examples/qwindow-compositor/qwindowcompositor.h b/examples/qwindow-compositor/qwindowcompositor.h index e26a09ebc..3ecbdbc1a 100644 --- a/examples/qwindow-compositor/qwindowcompositor.h +++ b/examples/qwindow-compositor/qwindowcompositor.h @@ -58,7 +58,7 @@ public: ~QWindowCompositor(); private slots: - void surfaceDestroyed(QObject *object); + void surfaceDestroyed(); void surfaceMapped(); void surfaceUnmapped(); void surfaceCommitted(); @@ -71,7 +71,7 @@ protected: QWaylandSurface* surfaceAt(const QPointF &point, QPointF *local = 0); - GLuint composeSurface(QWaylandSurface *surface, bool *textureOwned); + GLuint composeSurface(QWaylandSurface *surface); void paintChildren(QWaylandSurface *surface, QWaylandSurface *window, const QSize &windowSize); diff --git a/examples/server-buffer/compositor/main.cpp b/examples/server-buffer/compositor/main.cpp index ff375a8c6..a30ea0895 100644 --- a/examples/server-buffer/compositor/main.cpp +++ b/examples/server-buffer/compositor/main.cpp @@ -38,9 +38,8 @@ ** ****************************************************************************/ -#include "qwaylandcompositor.h" +#include "qwaylandquickcompositor.h" #include "qwaylandsurface.h" -#include "qwaylandsurfaceitem.h" #include <QGuiApplication> #include <QTimer> @@ -63,14 +62,14 @@ class QmlCompositor : public QQuickView - , public QWaylandCompositor + , public QWaylandQuickCompositor , public QtWaylandServer::qt_share_buffer { Q_OBJECT public: QmlCompositor() - : QWaylandCompositor(this, 0, DefaultExtensions | SubSurfaceExtension) + : QWaylandQuickCompositor(this, 0, DefaultExtensions | SubSurfaceExtension) , QtWaylandServer::qt_share_buffer(QWaylandCompositor::handle()->wl_display()) , m_server_buffer_32_bit(0) , m_server_buffer_item_32_bit(0) @@ -83,7 +82,6 @@ public: create(); grabWindow(); - connect(this, SIGNAL(beforeSynchronizing()), this, SLOT(startFrame()), Qt::DirectConnection); connect(this, SIGNAL(afterRendering()), this, SLOT(sendCallbacks())); connect(this, SIGNAL(sceneGraphInitialized()), this, SLOT(initiateServerBuffer()),Qt::DirectConnection); @@ -98,38 +96,26 @@ signals: void serverBuffersCreated(); public slots: - void destroyWindow(QVariant window) - { - qvariant_cast<QObject *>(window)->deleteLater(); - } - void destroyClientForWindow(QVariant window) { - QWaylandSurface *surface = qobject_cast<QWaylandSurfaceItem *>(qvariant_cast<QObject *>(window))->surface(); + QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(qvariant_cast<QObject *>(window)); destroyClientForSurface(surface); } private slots: void surfaceMapped() { QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); - QQuickItem *item = surface->surfaceItem(); - emit windowAdded(QVariant::fromValue(static_cast<QQuickItem *>(item))); + emit windowAdded(QVariant::fromValue(surface)); } void surfaceUnmapped() { QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); - QQuickItem *item = surface->surfaceItem(); - emit windowDestroyed(QVariant::fromValue(item)); + emit windowDestroyed(QVariant::fromValue(surface)); } void surfaceDestroyed(QObject *object) { QWaylandSurface *surface = static_cast<QWaylandSurface *>(object); - QQuickItem *item = surface->surfaceItem(); - emit windowDestroyed(QVariant::fromValue(item)); - } - - void startFrame() { - frameStarted(); + emit windowDestroyed(QVariant::fromValue(surface)); } void sendCallbacks() { @@ -219,11 +205,6 @@ protected: } void surfaceCreated(QWaylandSurface *surface) { - QWaylandSurfaceItem *item = new QWaylandSurfaceItem(surface, rootObject()); - item->setUseTextureAlpha(true); - item->setTouchEventsEnabled(true); - - connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *))); connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped())); connect(surface,SIGNAL(unmapped()), this,SLOT(surfaceUnmapped())); } @@ -270,7 +251,6 @@ int main(int argc, char *argv[]) compositor.rootContext()->setContextProperty("compositor", &compositor); QObject::connect(&compositor, SIGNAL(windowAdded(QVariant)), compositor.rootObject(), SLOT(windowAdded(QVariant))); - QObject::connect(&compositor, SIGNAL(windowDestroyed(QVariant)), compositor.rootObject(), SLOT(windowDestroyed(QVariant))); QObject::connect(&compositor, SIGNAL(windowResized(QVariant)), compositor.rootObject(), SLOT(windowResized(QVariant))); QObject::connect(&compositor, SIGNAL(serverBufferItemCreated(QVariant)), compositor.rootObject(), SLOT(serverBufferItemCreated(QVariant))); diff --git a/examples/server-buffer/compositor/qml/main.qml b/examples/server-buffer/compositor/qml/main.qml index 231fb5169..1beddbf1d 100644 --- a/examples/server-buffer/compositor/qml/main.qml +++ b/examples/server-buffer/compositor/qml/main.qml @@ -39,6 +39,7 @@ ****************************************************************************/ import QtQuick 2.0 +import QtCompositor 1.0 Item { id: root @@ -58,15 +59,21 @@ Item { anchors.fill: parent } - function windowAdded(window) { - window.parent = root; + Component { + id: windowItem + WaylandSurfaceItem { + onSurfaceDestroyed: { + destroy(); + } + } } - function windowResized(window) { + function windowAdded(window) { + var item = windowItem.createObject(root); + item.surface = window; } - function windowDestroyed(window) { - compositor.destroyWindow(window); + function windowResized(window) { } function removeWindow(window) { diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri index 87d28003c..8e7fd3ace 100644 --- a/src/compositor/compositor_api/compositor_api.pri +++ b/src/compositor/compositor_api/compositor_api.pri @@ -2,29 +2,34 @@ INCLUDEPATH += compositor_api HEADERS += \ compositor_api/qwaylandcompositor.h \ + compositor_api/qwaylandcompositor_p.h \ compositor_api/qwaylandsurface.h \ + compositor_api/qwaylandsurface_p.h \ compositor_api/qwaylandinput.h \ compositor_api/qwaylandinputpanel.h \ - compositor_api/qwaylanddrag.h + compositor_api/qwaylanddrag.h \ + compositor_api/qwaylandbufferref.h SOURCES += \ compositor_api/qwaylandcompositor.cpp \ compositor_api/qwaylandsurface.cpp \ compositor_api/qwaylandinput.cpp \ compositor_api/qwaylandinputpanel.cpp \ - compositor_api/qwaylanddrag.cpp + compositor_api/qwaylanddrag.cpp \ + compositor_api/qwaylandbufferref.cpp QT += core-private qtHaveModule(quick) { SOURCES += \ + compositor_api/qwaylandquickcompositor.cpp \ + compositor_api/qwaylandquicksurface.cpp \ compositor_api/qwaylandsurfaceitem.cpp HEADERS += \ + compositor_api/qwaylandquickcompositor.h \ + compositor_api/qwaylandquicksurface.h \ compositor_api/qwaylandsurfaceitem.h - DEFINES += QT_COMPOSITOR_QUICK - QT += qml quick - QT += quick-private gui-private } diff --git a/src/compositor/compositor_api/qwaylandbufferref.cpp b/src/compositor/compositor_api/qwaylandbufferref.cpp new file mode 100644 index 000000000..67554c7cb --- /dev/null +++ b/src/compositor/compositor_api/qwaylandbufferref.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QDebug> +#include <QAtomicInt> + +#include "qwaylandbufferref.h" +#include "wayland_wrapper/qwlsurfacebuffer_p.h" + +QT_BEGIN_NAMESPACE + +class QWaylandBufferRefPrivate +{ +public: + QtWayland::SurfaceBuffer *buffer; +}; + +QWaylandBufferRef::QWaylandBufferRef() + : d(new QWaylandBufferRefPrivate) +{ + d->buffer = 0; +} + +QWaylandBufferRef::QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer) + : d(new QWaylandBufferRefPrivate) +{ + d->buffer = buffer; + if (buffer) + buffer->m_refCount.ref(); +} + +QWaylandBufferRef::QWaylandBufferRef(const QWaylandBufferRef &ref) + : d(new QWaylandBufferRefPrivate) +{ + d->buffer = 0; + *this = ref; +} + +QWaylandBufferRef::~QWaylandBufferRef() +{ + if (d->buffer && !d->buffer->m_refCount.deref()) + d->buffer->disown(); + delete d; +} + +QWaylandBufferRef &QWaylandBufferRef::operator=(const QWaylandBufferRef &ref) +{ + if (d->buffer && !d->buffer->m_refCount.deref()) + d->buffer->disown(); + + d->buffer = ref.d->buffer; + if (d->buffer) + d->buffer->m_refCount.ref(); + + return *this; +} + +QWaylandBufferRef::operator bool() const +{ + return d->buffer && d->buffer->waylandBufferHandle(); +} + +bool QWaylandBufferRef::isShm() const +{ + return d->buffer->isShmBuffer(); +} + +QImage QWaylandBufferRef::image() const +{ + if (d->buffer->isShmBuffer()) + return d->buffer->image(); + return QImage(); +} + +#ifdef QT_COMPOSITOR_WAYLAND_GL + +GLuint QWaylandBufferRef::createTexture() +{ + if (!d->buffer->isShmBuffer() && !d->buffer->textureCreated()) { + d->buffer->createTexture(); + } + return d->buffer->texture(); +} + +void QWaylandBufferRef::destroyTexture() +{ + if (!d->buffer->isShmBuffer() && d->buffer->textureCreated()) { + d->buffer->destroyTexture(); + } +} +#endif + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandbufferref.h b/src/compositor/compositor_api/qwaylandbufferref.h new file mode 100644 index 000000000..0d1573bbb --- /dev/null +++ b/src/compositor/compositor_api/qwaylandbufferref.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDBUFFERREF_H +#define QWAYLANDBUFFERREF_H + +#ifdef QT_COMPOSITOR_WAYLAND_GL +#include <QtGui/qopengl.h> +#endif + +#include <QtCompositor/qwaylandexport.h> + +QT_BEGIN_NAMESPACE + +namespace QtWayland +{ + class SurfaceBuffer; +} + +class Q_COMPOSITOR_EXPORT QWaylandBufferRef +{ +public: + QWaylandBufferRef(); + explicit QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer); + QWaylandBufferRef(const QWaylandBufferRef &ref); + ~QWaylandBufferRef(); + + QWaylandBufferRef &operator=(const QWaylandBufferRef &ref); + operator bool() const; + bool isShm() const; + + QImage image() const; +#ifdef QT_COMPOSITOR_WAYLAND_GL + /** + * There must be a GL context bound when calling this function. + * It is responsibility of the caller to call destroyTexture() later. + */ + GLuint createTexture(); + void destroyTexture(); +#endif + +private: + class QWaylandBufferRefPrivate *const d; + friend class QWaylandBufferRefPrivate; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index 342dce510..2135a0e94 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -55,33 +55,26 @@ #include <QDebug> -#ifdef QT_COMPOSITOR_QUICK -#include "qwaylandsurfaceitem.h" -#endif - QT_BEGIN_NAMESPACE QWaylandCompositor::QWaylandCompositor(QWindow *window, const char *socketName, ExtensionFlags extensions) - : m_compositor(0) + : m_compositor(new QtWayland::Compositor(this, extensions)) , m_toplevel_window(window) - , m_socket_name(socketName) { - QStringList arguments = QCoreApplication::instance()->arguments(); + m_compositor->m_socket_name = socketName; + m_compositor->init(); - int socketArg = arguments.indexOf(QLatin1String("--wayland-socket-name")); - if (socketArg != -1 && socketArg + 1 < arguments.size()) - m_socket_name = arguments.at(socketArg + 1).toLocal8Bit(); - - m_compositor = new QtWayland::Compositor(this, extensions); -#ifdef QT_COMPOSITOR_QUICK - qmlRegisterType<QWaylandSurfaceItem>("WaylandCompositor", 1, 0, "WaylandSurfaceItem"); - qmlRegisterType<QWaylandSurface>("WaylandCompositor", 1, 0, "WaylandSurface"); -#else - qRegisterMetaType<QWaylandSurface*>("WaylandSurface*"); +#if !defined(QT_NO_DEBUG) && !defined(QT_WAYLAND_NO_CLEANUP_WARNING) + qWarning("QWaylandCompositor::cleanupGraphicsResources() must be called manually"); #endif - m_compositor->initializeHardwareIntegration(); - m_compositor->initializeExtensions(); - m_compositor->initializeDefaultInputDevice(); +} + +QWaylandCompositor::QWaylandCompositor(QWindow *window, const char *socketName, QtWayland::Compositor *dptr) + : m_compositor(dptr) + , m_toplevel_window(window) +{ + m_compositor->m_socket_name = socketName; + m_compositor->init(); } QWaylandCompositor::~QWaylandCompositor() @@ -213,9 +206,9 @@ void QWaylandCompositor::setClientFullScreenHint(bool value) const char *QWaylandCompositor::socketName() const { - if (m_socket_name.isEmpty()) + if (m_compositor->m_socket_name.isEmpty()) return 0; - return m_socket_name.constData(); + return m_compositor->m_socket_name.constData(); } /*! diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h index 9009f4caa..85f10b281 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.h +++ b/src/compositor/compositor_api/qwaylandcompositor.h @@ -141,13 +141,14 @@ public: void configureTouchExtension(TouchExtensionFlags flags); protected: + QWaylandCompositor(QWindow *window, const char *socketName, QtWayland::Compositor *dptr); virtual void retainedSelectionReceived(QMimeData *mimeData); -private: friend class QtWayland::Compositor; QtWayland::Compositor *m_compositor; + +private: QWindow *m_toplevel_window; - QByteArray m_socket_name; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandCompositor::ExtensionFlags) diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp new file mode 100644 index 000000000..bc475f1c5 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QQuickWindow> + +#include <QtCompositor/private/qwlcompositor_p.h> + +#include "qwaylandquickcompositor.h" +#include "qwaylandquicksurface.h" +#include "qwaylandsurfaceitem.h" + +QT_BEGIN_NAMESPACE + +class QWaylandQuickCompositorPrivate : public QtWayland::Compositor +{ +public: + QWaylandQuickCompositorPrivate(QWaylandQuickCompositor *compositor, QWaylandCompositor::ExtensionFlags extensions) + : QtWayland::Compositor(compositor, extensions) + , updateScheduled(false) + { + } + + void compositor_create_surface(Resource *resource, uint32_t id) Q_DECL_OVERRIDE + { + QWaylandQuickSurface *surface = new QWaylandQuickSurface(resource->client(), id, static_cast<QWaylandQuickCompositor *>(m_qt_compositor)); + m_surfaces << surface->handle(); + //BUG: This may not be an on-screen window surface though + m_qt_compositor->surfaceCreated(surface); + } + + void updateStarted() + { + updateScheduled = false; + m_qt_compositor->frameStarted(); + m_qt_compositor->cleanupGraphicsResources(); + } + + bool updateScheduled; +}; + + +QWaylandQuickCompositor::QWaylandQuickCompositor(QQuickWindow *window, const char *socketName, ExtensionFlags extensions) + : QWaylandCompositor(window, socketName, new QWaylandQuickCompositorPrivate(this, extensions)) +{ + window->connect(window, &QQuickWindow::beforeSynchronizing, d_ptr(), &QWaylandQuickCompositorPrivate::updateStarted, Qt::DirectConnection); + + qmlRegisterType<QWaylandSurfaceItem>("QtCompositor", 1, 0, "WaylandSurfaceItem"); + qmlRegisterUncreatableType<QWaylandQuickSurface>("QtCompositor", 1, 0, "WaylandQuickSurface", QObject::tr("Cannot create instance of WaylandQuickSurface")); +} + +QWaylandQuickCompositorPrivate *QWaylandQuickCompositor::d_ptr() +{ + return static_cast<QWaylandQuickCompositorPrivate *>(m_compositor); +} + +void QWaylandQuickCompositor::update() +{ + if (!d_ptr()->updateScheduled) { + static_cast<QQuickWindow *>(window())->update(); + d_ptr()->updateScheduled = true; + } +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.h b/src/compositor/compositor_api/qwaylandquickcompositor.h new file mode 100644 index 000000000..c87585221 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquickcompositor.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDQUICKCOMPOSITOR_H +#define QWAYLANDQUICKCOMPOSITOR_H + +#include <QtCompositor/qwaylandcompositor.h> + +QT_BEGIN_NAMESPACE + +class QQuickWindow; +class QWaylandQuickCompositorPrivate; + +class Q_COMPOSITOR_EXPORT QWaylandQuickCompositor : public QWaylandCompositor +{ +public: + QWaylandQuickCompositor(QQuickWindow *window = 0, const char *socketName = 0, QWaylandCompositor::ExtensionFlags extensions = DefaultExtensions); + + void update(); + +private: + friend class QWaylandQuickCompositorPrivate; + QWaylandQuickCompositorPrivate *d_ptr(); +}; + +#endif diff --git a/src/compositor/compositor_api/qwaylandquicksurface.cpp b/src/compositor/compositor_api/qwaylandquicksurface.cpp new file mode 100644 index 000000000..e4a5f7732 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquicksurface.cpp @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QSGTexture> +#include <QOpenGLTexture> +#include <QQuickWindow> +#include <QDebug> +#include <QQmlPropertyMap> + +#include "qwaylandquicksurface.h" +#include "qwaylandquickcompositor.h" +#include "qwaylandsurfaceitem.h" +#include <QtCompositor/qwaylandbufferref.h> +#include <QtCompositor/private/qwaylandsurface_p.h> + +QT_BEGIN_NAMESPACE + +class BufferAttacher : public QWaylandBufferAttacher +{ +public: + BufferAttacher() + : surface(0) + , texture(0) + , update(false) + { + + } + + ~BufferAttacher() + { + if (texture) + texture->deleteLater(); + bufferRef = QWaylandBufferRef(); + nextBuffer = QWaylandBufferRef(); + } + + void attach(const QWaylandBufferRef &ref) Q_DECL_OVERRIDE + { + nextBuffer = ref; + update = true; + } + + void createTexture() + { + if (bufferRef) + bufferRef.destroyTexture(); + bufferRef = nextBuffer; + + QQuickWindow *window = static_cast<QQuickWindow *>(surface->compositor()->window()); + // If the next buffer is NULL do not delete the current texture. If the client called + // attach(0) the surface is going to be unmapped anyway, if instead the client attached + // a valid buffer but died before we got here we want to keep the old buffer around + // in case some destroy animation is run. + if (bufferRef) { + delete texture; + + if (bufferRef.isShm()) { + texture = window->createTextureFromImage(bufferRef.image()); + } else { + QQuickWindow::CreateTextureOptions opt = 0; + if (surface->useTextureAlpha()) { + opt |= QQuickWindow::TextureHasAlphaChannel; + } + texture = window->createTextureFromId(bufferRef.createTexture(), surface->size(), opt); + } + texture->bind(); + } + + update = false; + } + + void invalidateTexture() + { + delete texture; + texture = 0; + } + + QWaylandQuickSurface *surface; + QWaylandBufferRef bufferRef; + QWaylandBufferRef nextBuffer; + QSGTexture *texture; + bool update; +}; + + +class QWaylandQuickSurfacePrivate : public QWaylandSurfacePrivate +{ +public: + QWaylandQuickSurfacePrivate(wl_client *client, quint32 id, QWaylandQuickCompositor *c, QWaylandQuickSurface *surf) + : QWaylandSurfacePrivate(client, id, c, surf) + , buffer(new BufferAttacher) + , compositor(c) + , useTextureAlpha(true) + , windowPropertyMap(new QQmlPropertyMap) + , clientRenderingEnabled(true) + { + + } + + ~QWaylandQuickSurfacePrivate() + { + windowPropertyMap->deleteLater(); + // buffer is deleted automatically by ~Surface(), since it is the assigned attacher + } + + void surface_commit(Resource *resource) Q_DECL_OVERRIDE + { + if (m_pending.newlyAttached) { + buffer->update = true; + } + QWaylandSurfacePrivate::surface_commit(resource); + + compositor->update(); + } + + BufferAttacher *buffer; + QWaylandQuickCompositor *compositor; + bool useTextureAlpha; + QQmlPropertyMap *windowPropertyMap; + bool clientRenderingEnabled; +}; + +QWaylandQuickSurface::QWaylandQuickSurface(wl_client *client, quint32 id, QWaylandQuickCompositor *compositor) + : QWaylandSurface(new QWaylandQuickSurfacePrivate(client, id, compositor, this)) +{ + Q_D(QWaylandQuickSurface); + d->buffer->surface = this; + setBufferAttacher(d->buffer); + + QQuickWindow *window = static_cast<QQuickWindow *>(compositor->window()); + connect(window, &QQuickWindow::beforeSynchronizing, this, &QWaylandQuickSurface::updateTexture, Qt::DirectConnection); + connect(window, &QQuickWindow::sceneGraphInvalidated, this, &QWaylandQuickSurface::invalidateTexture, Qt::DirectConnection); + connect(this, &QWaylandSurface::windowPropertyChanged, d->windowPropertyMap, &QQmlPropertyMap::insert); + connect(d->windowPropertyMap, &QQmlPropertyMap::valueChanged, this, &QWaylandSurface::setWindowProperty); + +} + +QWaylandQuickSurface::~QWaylandQuickSurface() +{ + +} + +QSGTexture *QWaylandQuickSurface::texture() const +{ + Q_D(const QWaylandQuickSurface); + return d->buffer->texture; +} + +bool QWaylandQuickSurface::useTextureAlpha() const +{ + Q_D(const QWaylandQuickSurface); + return d->useTextureAlpha; +} + +void QWaylandQuickSurface::setUseTextureAlpha(bool useTextureAlpha) +{ + Q_D(QWaylandQuickSurface); + if (d->useTextureAlpha != useTextureAlpha) { + d->useTextureAlpha = useTextureAlpha; + emit useTextureAlphaChanged(); + emit configure(); + } +} + +QObject *QWaylandQuickSurface::windowPropertyMap() const +{ + Q_D(const QWaylandQuickSurface); + return d->windowPropertyMap; +} + + +void QWaylandQuickSurface::updateTexture() +{ + Q_D(QWaylandQuickSurface); + if (d->buffer->update) + d->buffer->createTexture(); +} + +void QWaylandQuickSurface::invalidateTexture() +{ + Q_D(QWaylandQuickSurface); + d->buffer->invalidateTexture(); +} + +bool QWaylandQuickSurface::clientRenderingEnabled() const +{ + Q_D(const QWaylandQuickSurface); + return d->clientRenderingEnabled; +} + +void QWaylandQuickSurface::setClientRenderingEnabled(bool enabled) +{ + Q_D(QWaylandQuickSurface); + if (d->clientRenderingEnabled != enabled) { + d->clientRenderingEnabled = enabled; + + sendOnScreenVisibilityChange(enabled); + + emit clientRenderingEnabledChanged(); + } +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquicksurface.h b/src/compositor/compositor_api/qwaylandquicksurface.h new file mode 100644 index 000000000..6c464ecd7 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquicksurface.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKWAYLANDSURFACE_H +#define QQUICKWAYLANDSURFACE_H + +#include <QSGTexture> +#include <QSGTextureProvider> + +#include "qwaylandsurface.h" + +struct wl_client; + +QT_BEGIN_NAMESPACE + +class QWaylandSurfaceItem; +class QWaylandQuickSurfacePrivate; +class QWaylandQuickCompositor; + +class Q_COMPOSITOR_EXPORT QWaylandQuickSurface : public QWaylandSurface +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandQuickSurface) + Q_PROPERTY(bool useTextureAlpha READ useTextureAlpha WRITE setUseTextureAlpha NOTIFY useTextureAlphaChanged) + Q_PROPERTY(bool clientRenderingEnabled READ clientRenderingEnabled WRITE setClientRenderingEnabled NOTIFY clientRenderingEnabledChanged) + Q_PROPERTY(QObject *windowProperties READ windowPropertyMap CONSTANT) +public: + QWaylandQuickSurface(wl_client *client, quint32 id, QWaylandQuickCompositor *compositor); + ~QWaylandQuickSurface(); + + QSGTexture *texture() const; + + bool useTextureAlpha() const; + void setUseTextureAlpha(bool useTextureAlpha); + + bool clientRenderingEnabled() const; + void setClientRenderingEnabled(bool enabled); + + QObject *windowPropertyMap() const; + +signals: + void useTextureAlphaChanged(); + void clientRenderingEnabledChanged(); + +private: + void updateTexture(); + void invalidateTexture(); + +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index 2b7d713c8..5fd7fabe9 100644 --- a/src/compositor/compositor_api/qwaylandsurface.cpp +++ b/src/compositor/compositor_api/qwaylandsurface.cpp @@ -53,74 +53,51 @@ #include "qwaylandcompositor.h" #include "waylandwindowmanagerintegration.h" +#include "qwaylandsurface_p.h" +#include "qwaylandbufferref.h" #include <QtGui/QGuiApplication> #include <QtGui/QScreen> -#ifdef QT_COMPOSITOR_QUICK -#include "qwaylandsurfaceitem.h" -#include <QtQml/QQmlPropertyMap> -#endif - QT_BEGIN_NAMESPACE -class QWaylandSurfacePrivate : public QObjectPrivate -{ -public: - QWaylandSurfacePrivate(QtWayland::Surface *srfc) - : surface(srfc) -#ifdef QT_COMPOSITOR_QUICK - , surface_item(0) - , windowPropertyMap(new QQmlPropertyMap) -#endif - {} - - ~QWaylandSurfacePrivate() - { -#ifdef QT_COMPOSITOR_QUICK - if (surface_item) - surface_item->setSurface(0); - if (windowPropertyMap) - windowPropertyMap->deleteLater(); -#endif - } +QWaylandSurfacePrivate::QWaylandSurfacePrivate(wl_client *client, quint32 id, QWaylandCompositor *compositor, QWaylandSurface *surface) + : QtWayland::Surface(client, id, compositor, surface) + , closing(false) + , refCount(1) +{} - QtWayland::Surface *surface; -#ifdef QT_COMPOSITOR_QUICK - QWaylandSurfaceItem *surface_item; - QQmlPropertyMap *windowPropertyMap; -#endif -}; -QWaylandSurface::QWaylandSurface(QtWayland::Surface *surface) - : QObject(*new QWaylandSurfacePrivate(surface)) + +QWaylandSurface::QWaylandSurface(wl_client *client, quint32 id, QWaylandCompositor *compositor) + : QObject(*new QWaylandSurfacePrivate(client, id, compositor, this)) { -#ifdef QT_COMPOSITOR_QUICK - Q_D(QWaylandSurface); - connect(this, &QWaylandSurface::windowPropertyChanged, - d->windowPropertyMap, &QQmlPropertyMap::insert); - connect(d->windowPropertyMap, &QQmlPropertyMap::valueChanged, - this, &QWaylandSurface::setWindowProperty); -#endif + } -void QWaylandSurface::swapBuffers() +QWaylandSurface::QWaylandSurface(QWaylandSurfacePrivate *dptr) + : QObject(*dptr) { - Q_D(const QWaylandSurface); - d->surface->swapBuffers(); + +} + +QWaylandSurface::~QWaylandSurface() +{ + Q_D(QWaylandSurface); + delete d->m_attacher; } WaylandClient *QWaylandSurface::client() const { Q_D(const QWaylandSurface); - return d->surface->resource()->client(); + return d->resource()->client(); } QWaylandSurface *QWaylandSurface::parentSurface() const { Q_D(const QWaylandSurface); - if (d->surface->subSurface() && d->surface->subSurface()->parent()) { - return d->surface->subSurface()->parent()->waylandSurface(); + if (d->subSurface() && d->subSurface()->parent()) { + return d->subSurface()->parent()->waylandSurface(); } return 0; } @@ -128,8 +105,8 @@ QWaylandSurface *QWaylandSurface::parentSurface() const QLinkedList<QWaylandSurface *> QWaylandSurface::subSurfaces() const { Q_D(const QWaylandSurface); - if (d->surface->subSurface()) { - return d->surface->subSurface()->subSurfaces(); + if (d->subSurface()) { + return d->subSurface()->subSurfaces(); } return QLinkedList<QWaylandSurface *>(); } @@ -137,13 +114,13 @@ QLinkedList<QWaylandSurface *> QWaylandSurface::subSurfaces() const QWaylandSurface::Type QWaylandSurface::type() const { Q_D(const QWaylandSurface); - return d->surface->type(); + return d->type(); } bool QWaylandSurface::isYInverted() const { Q_D(const QWaylandSurface); - return d->surface->isYInverted(); + return d->isYInverted(); } bool QWaylandSurface::visible() const @@ -154,110 +131,70 @@ bool QWaylandSurface::visible() const bool QWaylandSurface::isMapped() const { Q_D(const QWaylandSurface); - return d->surface->mapped(); + return d->mapped(); } QPointF QWaylandSurface::pos() const { Q_D(const QWaylandSurface); - return d->surface->pos(); + return d->pos(); } void QWaylandSurface::setPos(const QPointF &pos) { Q_D(QWaylandSurface); - d->surface->setPos(pos); + d->setPos(pos); } QSize QWaylandSurface::size() const { Q_D(const QWaylandSurface); - return d->surface->size(); + return d->size(); } void QWaylandSurface::requestSize(const QSize &size) { Q_D(QWaylandSurface); - if (d->surface->shellSurface()) - d->surface->shellSurface()->sendConfigure(WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT, size.width(), size.height()); + if (d->shellSurface()) + d->shellSurface()->sendConfigure(WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT, size.width(), size.height()); } Qt::ScreenOrientations QWaylandSurface::orientationUpdateMask() const { Q_D(const QWaylandSurface); - return d->surface->compositor()->orientationUpdateMaskForClient(static_cast<wl_client *>(client())); + return d->compositor()->orientationUpdateMaskForClient(static_cast<wl_client *>(client())); } Qt::ScreenOrientation QWaylandSurface::contentOrientation() const { Q_D(const QWaylandSurface); - if (!d->surface->extendedSurface()) + if (!d->extendedSurface()) return Qt::PrimaryOrientation; - return d->surface->extendedSurface()->contentOrientation(); + return d->extendedSurface()->contentOrientation(); } QWaylandSurface::WindowFlags QWaylandSurface::windowFlags() const { Q_D(const QWaylandSurface); - if (!d->surface->extendedSurface()) + if (!d->extendedSurface()) return QWaylandSurface::WindowFlags(0); - return d->surface->extendedSurface()->windowFlags(); + return d->extendedSurface()->windowFlags(); } QWaylandSurface::WindowType QWaylandSurface::windowType() const { Q_D(const QWaylandSurface); - if (d->surface->shellSurface()) - return d->surface->shellSurface()->windowType(); + if (d->shellSurface()) + return d->shellSurface()->windowType(); return QWaylandSurface::None; } -QImage QWaylandSurface::image() const -{ - Q_D(const QWaylandSurface); - return d->surface->image(); -} - -#ifdef QT_COMPOSITOR_WAYLAND_GL -GLuint QWaylandSurface::texture() const -{ - Q_D(const QWaylandSurface); - return d->surface->textureId(); -} -#else //QT_COMPOSITOR_WAYLAND_GL -uint QWaylandSurface::texture() const -{ - return 0; -} -#endif - -QtWayland::Surface * QWaylandSurface::handle() const -{ - Q_D(const QWaylandSurface); - return d->surface; -} - -#ifdef QT_COMPOSITOR_QUICK -QWaylandSurfaceItem *QWaylandSurface::surfaceItem() const -{ - Q_D(const QWaylandSurface); - return d->surface_item; -} - -void QWaylandSurface::setSurfaceItem(QWaylandSurfaceItem *surfaceItem) +QtWayland::Surface * QWaylandSurface::handle() { Q_D(QWaylandSurface); - d->surface_item = surfaceItem; + return d; } -QObject *QWaylandSurface::windowPropertyMap() const -{ - Q_D(const QWaylandSurface); - return d->windowPropertyMap; -} - -#endif //QT_COMPOSITOR_QUICK - qint64 QWaylandSurface::processId() const { struct wl_client *client = static_cast<struct wl_client *>(this->client()); @@ -269,19 +206,19 @@ qint64 QWaylandSurface::processId() const QVariantMap QWaylandSurface::windowProperties() const { Q_D(const QWaylandSurface); - if (!d->surface->extendedSurface()) + if (!d->extendedSurface()) return QVariantMap(); - return d->surface->extendedSurface()->windowProperties(); + return d->extendedSurface()->windowProperties(); } void QWaylandSurface::setWindowProperty(const QString &name, const QVariant &value) { Q_D(QWaylandSurface); - if (!d->surface->extendedSurface()) + if (!d->extendedSurface()) return; - d->surface->extendedSurface()->setWindowProperty(name, value); + d->extendedSurface()->setWindowProperty(name, value); } QPointF QWaylandSurface::mapToParent(const QPointF &pos) const @@ -307,22 +244,22 @@ QPointF QWaylandSurface::mapTo(QWaylandSurface *parent, const QPointF &pos) cons QWaylandCompositor *QWaylandSurface::compositor() const { Q_D(const QWaylandSurface); - return d->surface->compositor()->waylandCompositor(); + return d->compositor()->waylandCompositor(); } QWaylandSurface *QWaylandSurface::transientParent() const { Q_D(const QWaylandSurface); - if (d->surface->shellSurface() && d->surface->shellSurface()->transientParent()) - return d->surface->shellSurface()->transientParent()->surface()->waylandSurface(); + if (d->shellSurface() && d->shellSurface()->transientParent()) + return d->shellSurface()->transientParent()->surface()->waylandSurface(); return 0; } QWindow::Visibility QWaylandSurface::visibility() const { Q_D(const QWaylandSurface); - if (d->surface->extendedSurface()) - return d->surface->extendedSurface()->visibility(); + if (d->extendedSurface()) + return d->extendedSurface()->visibility(); return QWindow::AutomaticVisibility; } @@ -330,8 +267,8 @@ QWindow::Visibility QWaylandSurface::visibility() const void QWaylandSurface::setVisibility(QWindow::Visibility visibility) { Q_D(QWaylandSurface); - if (d->surface->extendedSurface()) - d->surface->extendedSurface()->setVisibility(visibility); + if (d->extendedSurface()) + d->extendedSurface()->setVisibility(visibility); } void QWaylandSurface::sendOnScreenVisibilityChange(bool visible) @@ -342,19 +279,19 @@ void QWaylandSurface::sendOnScreenVisibilityChange(bool visible) QString QWaylandSurface::className() const { Q_D(const QWaylandSurface); - return d->surface->className(); + return d->className(); } QString QWaylandSurface::title() const { Q_D(const QWaylandSurface); - return d->surface->title(); + return d->title(); } bool QWaylandSurface::hasShellSurface() const { Q_D(const QWaylandSurface); - if (d->surface->shellSurface()) + if (d->shellSurface()) return true; return false; @@ -364,7 +301,7 @@ bool QWaylandSurface::hasInputPanelSurface() const { Q_D(const QWaylandSurface); - return d->surface->inputPanelSurface() != 0; + return d->inputPanelSurface() != 0; } /*! @@ -373,14 +310,21 @@ bool QWaylandSurface::hasInputPanelSurface() const bool QWaylandSurface::transientInactive() const { Q_D(const QWaylandSurface); - return d->surface->transientInactive(); + return d->transientInactive(); +} + +void QWaylandSurface::destroy() +{ + Q_D(QWaylandSurface); + if (--d->refCount == 0) + compositor()->handle()->destroySurface(d); } void QWaylandSurface::destroySurface() { Q_D(QWaylandSurface); - if (d->surface->extendedSurface()) { - d->surface->extendedSurface()->send_close(); + if (d->extendedSurface()) { + d->extendedSurface()->send_close(); } else { destroySurfaceByForce(); } @@ -389,15 +333,15 @@ void QWaylandSurface::destroySurface() void QWaylandSurface::destroySurfaceByForce() { Q_D(QWaylandSurface); - wl_resource *surface_resource = d->surface->resource()->handle; + wl_resource *surface_resource = d->resource()->handle; wl_resource_destroy(surface_resource); } void QWaylandSurface::ping() { Q_D(QWaylandSurface); - if (d->surface->shellSurface()) - d->surface->shellSurface()->ping(); + if (d->shellSurface()) + d->shellSurface()->ping(); } /*! @@ -408,14 +352,32 @@ void QWaylandSurface::ping() void QWaylandSurface::updateSelection() { Q_D(QWaylandSurface); - const QtWayland::InputDevice *inputDevice = d->surface->compositor()->defaultInputDevice(); + const QtWayland::InputDevice *inputDevice = d->compositor()->defaultInputDevice(); if (inputDevice) { const QtWayland::DataDevice *dataDevice = inputDevice->dataDevice(); if (dataDevice) { - d->surface->compositor()->dataDeviceManager()->offerRetainedSelection( - dataDevice->resourceMap().value(d->surface->resource()->client())->handle); + d->compositor()->dataDeviceManager()->offerRetainedSelection( + dataDevice->resourceMap().value(d->resource()->client())->handle); } } } +void QWaylandSurface::ref() +{ + Q_D(QWaylandSurface); + ++d->refCount; +} + +void QWaylandSurface::setBufferAttacher(QWaylandBufferAttacher *attacher) +{ + Q_D(QWaylandSurface); + d->m_attacher = attacher; +} + +QWaylandBufferAttacher *QWaylandSurface::bufferAttacher() const +{ + Q_D(const QWaylandSurface); + return d->m_attacher; +} + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h index 2f7b70ce8..22deee5ae 100644 --- a/src/compositor/compositor_api/qwaylandsurface.h +++ b/src/compositor/compositor_api/qwaylandsurface.h @@ -48,19 +48,14 @@ #include <QtGui/QWindow> #include <QtCore/QVariantMap> -#ifdef QT_COMPOSITOR_WAYLAND_GL -#include <QtGui/qopengl.h> -#endif +struct wl_client; QT_BEGIN_NAMESPACE class QTouchEvent; class QWaylandSurfacePrivate; class QWaylandCompositor; - -#ifdef QT_COMPOSITOR_QUICK -class QWaylandSurfaceItem; -#endif +class QWaylandBufferRef; namespace QtWayland { class Surface; @@ -68,6 +63,17 @@ class SurfacePrivate; class ExtendedSurface; } +class Q_COMPOSITOR_EXPORT QWaylandBufferAttacher +{ +public: + virtual ~QWaylandBufferAttacher() {} + +protected: + virtual void attach(const QWaylandBufferRef &ref) = 0; + + friend class QtWayland::Surface; +}; + class Q_COMPOSITOR_EXPORT QWaylandSurface : public QObject { Q_OBJECT @@ -81,9 +87,7 @@ class Q_COMPOSITOR_EXPORT QWaylandSurface : public QObject Q_PROPERTY(QString title READ title NOTIFY titleChanged) Q_PROPERTY(Qt::ScreenOrientations orientationUpdateMask READ orientationUpdateMask NOTIFY orientationUpdateMaskChanged) Q_PROPERTY(QWindow::Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged) -#ifdef QT_COMPOSITOR_QUICK - Q_PROPERTY(QObject * windowProperties READ windowPropertyMap CONSTANT) -#endif + Q_PROPERTY(QSize size READ size NOTIFY sizeChanged) Q_ENUMS(WindowFlag WindowType) Q_FLAGS(WindowFlag WindowFlags) @@ -109,7 +113,8 @@ public: Texture }; - QWaylandSurface(QtWayland::Surface *surface = 0); + QWaylandSurface(wl_client *client, quint32 id, QWaylandCompositor *compositor); + virtual ~QWaylandSurface(); WaylandClient *client() const; @@ -134,27 +139,13 @@ public: WindowType windowType() const; - QImage image() const; -#ifdef QT_COMPOSITOR_WAYLAND_GL - GLuint texture() const; -#else - uint texture() const; -#endif - QWindow::Visibility visibility() const; void setVisibility(QWindow::Visibility visibility); Q_INVOKABLE void sendOnScreenVisibilityChange(bool visible); // Compat QWaylandSurface *transientParent() const; - QtWayland::Surface *handle() const; - -#ifdef QT_COMPOSITOR_QUICK - QWaylandSurfaceItem *surfaceItem() const; - void setSurfaceItem(QWaylandSurfaceItem *surfaceItem); - - QObject *windowPropertyMap() const; -#endif + QtWayland::Surface *handle(); qint64 processId() const; QByteArray authenticationToken() const; @@ -175,20 +166,26 @@ public: bool transientInactive() const; + Q_INVOKABLE void destroy(); Q_INVOKABLE void destroySurface(); Q_INVOKABLE void destroySurfaceByForce(); Q_INVOKABLE void ping(); - void swapBuffers(); + void ref(); + + void setBufferAttacher(QWaylandBufferAttacher *attacher); + QWaylandBufferAttacher *bufferAttacher() const; public slots: void updateSelection(); +protected: + QWaylandSurface(QWaylandSurfacePrivate *dptr); + signals: void mapped(); void unmapped(); void damaged(const QRegion &rect); - void committed(); void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent); void sizeChanged(); void posChanged(); @@ -204,6 +201,10 @@ signals: void lowerRequested(); void visibilityChanged(); void pong(); + void surfaceDestroyed(); + + void configure(); + void redraw(); }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h new file mode 100644 index 000000000..aff0a8758 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandsurface_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDSURFACE_P_H +#define QWAYLANDSURFACE_P_H + +#include <QtCompositor/qwaylandexport.h> +#include <private/qobject_p.h> + +#include <QtCompositor/private/qwlsurface_p.h> + +QT_BEGIN_NAMESPACE + +class QWaylandCompositor; +class QWaylandSurface; + +class Q_COMPOSITOR_EXPORT QWaylandSurfacePrivate : public QObjectPrivate, public QtWayland::Surface +{ +public: + QWaylandSurfacePrivate(wl_client *client, quint32 id, QWaylandCompositor *compositor, QWaylandSurface *surface); + + bool closing; + int refCount; + + friend class QWaylandSurface; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp index 57e5c2906..1a1dc7cdb 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp @@ -39,12 +39,9 @@ ****************************************************************************/ #include "qwaylandsurfaceitem.h" -#include "qwaylandsurface.h" -#include "qwaylandcompositor.h" -#include "qwaylandinput.h" - -#include "qwlsurface_p.h" -#include "qwlextendedsurface_p.h" +#include "qwaylandquicksurface.h" +#include <QtCompositor/qwaylandcompositor.h> +#include <QtCompositor/qwaylandinput.h> #include <QtGui/QKeyEvent> #include <QtGui/QGuiApplication> @@ -58,15 +55,15 @@ QT_BEGIN_NAMESPACE +QMutex *QWaylandSurfaceItem::mutex = 0; + class QWaylandSurfaceTextureProvider : public QSGTextureProvider { - Q_OBJECT - public: QWaylandSurfaceTextureProvider() : t(0) { } - ~QWaylandSurfaceTextureProvider() { delete t; } - QSGTexture *texture() const { + QSGTexture *texture() const Q_DECL_OVERRIDE + { if (t) t->setFiltering(smooth ? QSGTexture::Linear : QSGTexture::Nearest); return t; @@ -74,55 +71,45 @@ public: bool smooth; QSGTexture *t; - -public slots: - void invalidate() - { - delete t; - t = 0; - } }; -QMutex *QWaylandSurfaceItem::mutex = 0; - QWaylandSurfaceItem::QWaylandSurfaceItem(QQuickItem *parent) : QQuickItem(parent) , m_surface(0) , m_provider(0) , m_paintEnabled(true) - , m_useTextureAlpha(false) - , m_clientRenderingEnabled(true) , m_touchEventsEnabled(false) , m_resizeSurfaceToItem(false) + , m_newTexture(false) { if (!mutex) mutex = new QMutex; + + setFlag(ItemHasContents); } -QWaylandSurfaceItem::QWaylandSurfaceItem(QWaylandSurface *surface, QQuickItem *parent) +QWaylandSurfaceItem::QWaylandSurfaceItem(QWaylandQuickSurface *surface, QQuickItem *parent) : QQuickItem(parent) , m_surface(0) , m_provider(0) , m_paintEnabled(true) - , m_useTextureAlpha(false) - , m_clientRenderingEnabled(true) , m_touchEventsEnabled(false) , m_resizeSurfaceToItem(false) { init(surface); } -void QWaylandSurfaceItem::init(QWaylandSurface *surface) +void QWaylandSurfaceItem::init(QWaylandQuickSurface *surface) { + if (m_surface) + m_surface->destroy(); + if (!surface) return; - if (m_surface) { - m_surface->setSurfaceItem(0); - } - m_surface = surface; - m_surface->setSurfaceItem(this); + surface->ref(); + update(); if (m_resizeSurfaceToItem) { updateSurfaceSize(); @@ -134,7 +121,7 @@ void QWaylandSurfaceItem::init(QWaylandSurface *surface) updatePosition(); setSmooth(true); - setFlag(ItemHasContents); + setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton | Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::ExtraButton3 | Qt::ExtraButton4 | Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 | @@ -143,29 +130,29 @@ void QWaylandSurfaceItem::init(QWaylandSurface *surface) setAcceptHoverEvents(true); connect(surface, &QWaylandSurface::mapped, this, &QWaylandSurfaceItem::surfaceMapped); connect(surface, &QWaylandSurface::unmapped, this, &QWaylandSurfaceItem::surfaceUnmapped); - connect(surface, &QWaylandSurface::destroyed, this, &QWaylandSurfaceItem::surfaceDestroyed); - connect(surface, &QWaylandSurface::damaged, this, &QWaylandSurfaceItem::surfaceDamaged); - connect(surface, &QWaylandSurface::committed, this, &QQuickItem::update); + connect(surface, &QWaylandSurface::surfaceDestroyed, this, &QWaylandSurfaceItem::surfaceDestroyed); connect(surface, &QWaylandSurface::parentChanged, this, &QWaylandSurfaceItem::parentChanged); connect(surface, &QWaylandSurface::sizeChanged, this, &QWaylandSurfaceItem::updateSize); connect(surface, &QWaylandSurface::posChanged, this, &QWaylandSurfaceItem::updatePosition); + connect(surface, &QWaylandSurface::configure, this, &QWaylandSurfaceItem::updateBuffer); + connect(surface, &QWaylandSurface::redraw, this, &QQuickItem::update); connect(this, &QWaylandSurfaceItem::widthChanged, this, &QWaylandSurfaceItem::updateSurfaceSize); connect(this, &QWaylandSurfaceItem::heightChanged, this, &QWaylandSurfaceItem::updateSurfaceSize); - m_damaged = false; m_yInverted = surface ? surface->isYInverted() : true; + emit yInvertedChanged(); } QWaylandSurfaceItem::~QWaylandSurfaceItem() { QMutexLocker locker(mutex); if (m_surface) - m_surface->setSurfaceItem(0); + m_surface->destroy(); if (m_provider) m_provider->deleteLater(); } -void QWaylandSurfaceItem::setSurface(QWaylandSurface *surface) +void QWaylandSurfaceItem::setSurface(QWaylandQuickSurface *surface) { if (surface == m_surface) return; @@ -181,16 +168,9 @@ bool QWaylandSurfaceItem::isYInverted() const QSGTextureProvider *QWaylandSurfaceItem::textureProvider() const { - const_cast<QWaylandSurfaceItem *>(this)->ensureProvider(); - return m_provider; -} - -void QWaylandSurfaceItem::ensureProvider() -{ - if (!m_provider) { + if (!m_provider) m_provider = new QWaylandSurfaceTextureProvider(); - connect(window(), &QQuickWindow::sceneGraphInvalidated, m_provider, &QWaylandSurfaceTextureProvider::invalidate, Qt::DirectConnection); - } + return m_provider; } void QWaylandSurfaceItem::mousePressEvent(QMouseEvent *event) @@ -281,40 +261,10 @@ void QWaylandSurfaceItem::surfaceUnmapped() update(); } -void QWaylandSurfaceItem::surfaceDestroyed(QObject *) -{ - if (m_surface) - m_surface->setSurfaceItem(0); - - m_surface = 0; -} - -void QWaylandSurfaceItem::setDamagedFlag(bool on) -{ - m_damaged = on; -} - - -void QWaylandSurfaceItem::surfaceDamaged(const QRegion &) -{ - m_damaged = true; - if (m_surface) { - bool inverted = m_surface->isYInverted(); - if (inverted != m_yInverted) { - m_yInverted = inverted; - emit yInvertedChanged(); - } - } - emit textureChanged(); -} - void QWaylandSurfaceItem::parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent) { Q_UNUSED(oldParent); - QWaylandSurfaceItem *item = newParent? newParent->surfaceItem():0; - setParentItem(item); - if (newParent) { setPaintEnabled(true); setVisible(true); @@ -340,6 +290,14 @@ void QWaylandSurfaceItem::updatePosition() setPosition(m_surface->pos()); } +/*! + \qmlproperty bool QtWayland::QWaylandSurfaceItem::paintEnabled + + If this property is true, the \l item is hidden, though the texture + will still be updated. As opposed to hiding the \l item by + setting \l{Item::visible}{visible} to false, setting this property to true + will not prevent mouse or keyboard input from reaching \l item. +*/ bool QWaylandSurfaceItem::paintEnabled() const { return m_paintEnabled; @@ -351,29 +309,14 @@ void QWaylandSurfaceItem::setPaintEnabled(bool enabled) update(); } -void QWaylandSurfaceItem::updateTexture() +void QWaylandSurfaceItem::updateBuffer() { - ensureProvider(); - QSGTexture *texture = m_provider->t; - if (m_damaged) { - m_damaged = false; - QSGTexture *oldTexture = texture; - if (m_surface->type() == QWaylandSurface::Texture) { - QQuickWindow::CreateTextureOptions opt = 0; - if (useTextureAlpha()) { - opt |= QQuickWindow::TextureHasAlphaChannel; - } - texture = window()->createTextureFromId(m_surface->texture(), m_surface->size(), opt); - } else { - texture = window()->createTextureFromImage(m_surface->image()); - } - texture->bind(); - delete oldTexture; - } + bool inv = m_yInverted; + m_yInverted = surface()->isYInverted(); + if (inv != m_yInverted) + emit yInvertedChanged(); - m_provider->t = texture; - emit m_provider->textureChanged(); - m_provider->smooth = smooth(); + m_newTexture = true; } QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) @@ -383,14 +326,20 @@ QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeD return 0; } + if (!m_provider) + m_provider = new QWaylandSurfaceTextureProvider(); + // Order here is important, as the state of visible is that of the pending // buffer but will be replaced after we advance the buffer queue. bool mapped = m_surface->isMapped(); - surface()->swapBuffers(); if (mapped) - updateTexture(); + m_provider->t = surface()->texture(); + m_provider->smooth = smooth(); + if (m_newTexture) + emit m_provider->textureChanged(); + m_newTexture = false; - if (!mapped|| !m_provider || !m_provider->t || !m_paintEnabled) { + if (!mapped || !m_provider->t || !m_paintEnabled) { delete oldNode; return 0; } @@ -409,28 +358,6 @@ QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeD return node; } -void QWaylandSurfaceItem::setUseTextureAlpha(bool useTextureAlpha) -{ - m_useTextureAlpha = useTextureAlpha; - - if ((flags() & ItemHasContents) != 0) { - update(); - } -} - -void QWaylandSurfaceItem::setClientRenderingEnabled(bool enabled) -{ - if (m_clientRenderingEnabled != enabled) { - m_clientRenderingEnabled = enabled; - - if (m_surface) { - m_surface->sendOnScreenVisibilityChange(enabled); - } - - emit clientRenderingEnabledChanged(); - } -} - void QWaylandSurfaceItem::setTouchEventsEnabled(bool enabled) { if (m_touchEventsEnabled != enabled) { @@ -448,5 +375,3 @@ void QWaylandSurfaceItem::setResizeSurfaceToItem(bool enabled) } QT_END_NAMESPACE - -#include "qwaylandsurfaceitem.moc" diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.h b/src/compositor/compositor_api/qwaylandsurfaceitem.h index 8abd4bf2d..f1da27995 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.h +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.h @@ -42,38 +42,37 @@ #define QWAYLANDSURFACEITEM_H #include <QtCompositor/qwaylandexport.h> -#include <QtCompositor/qwaylandsurface.h> #include <QtQuick/QQuickItem> #include <QtQuick/qsgtexture.h> #include <QtQuick/qsgtextureprovider.h> +#include "qwaylandquicksurface.h" + QT_BEGIN_NAMESPACE class QWaylandSurfaceTextureProvider; class QMutex; -Q_DECLARE_METATYPE(QWaylandSurface*) +Q_DECLARE_METATYPE(QWaylandQuickSurface*) -class Q_COMPOSITOR_EXPORT QWaylandSurfaceItem : public QQuickItem +class QWaylandSurfaceItem : public QQuickItem { Q_OBJECT - Q_PROPERTY(QWaylandSurface* surface READ surface WRITE setSurface NOTIFY surfaceChanged) + Q_PROPERTY(QWaylandQuickSurface* surface READ surface WRITE setSurface NOTIFY surfaceChanged) Q_PROPERTY(bool paintEnabled READ paintEnabled WRITE setPaintEnabled) - Q_PROPERTY(bool useTextureAlpha READ useTextureAlpha WRITE setUseTextureAlpha NOTIFY useTextureAlphaChanged) - Q_PROPERTY(bool clientRenderingEnabled READ clientRenderingEnabled WRITE setClientRenderingEnabled NOTIFY clientRenderingEnabledChanged) Q_PROPERTY(bool touchEventsEnabled READ touchEventsEnabled WRITE setTouchEventsEnabled NOTIFY touchEventsEnabledChanged) Q_PROPERTY(bool isYInverted READ isYInverted NOTIFY yInvertedChanged) Q_PROPERTY(bool resizeSurfaceToItem READ resizeSurfaceToItem WRITE setResizeSurfaceToItem NOTIFY resizeSurfaceToItemChanged) public: QWaylandSurfaceItem(QQuickItem *parent = 0); - QWaylandSurfaceItem(QWaylandSurface *surface, QQuickItem *parent = 0); + QWaylandSurfaceItem(QWaylandQuickSurface *surface, QQuickItem *parent = 0); ~QWaylandSurfaceItem(); - void setSurface(QWaylandSurface *surface); - QWaylandSurface *surface() const {return m_surface; } + void setSurface(QWaylandQuickSurface *surface); + QWaylandQuickSurface *surface() const {return m_surface; } Q_INVOKABLE bool isYInverted() const; @@ -81,18 +80,12 @@ public: QSGTextureProvider *textureProvider() const; bool paintEnabled() const; - bool useTextureAlpha() const { return m_useTextureAlpha; } - bool clientRenderingEnabled() const { return m_clientRenderingEnabled; } bool touchEventsEnabled() const { return m_touchEventsEnabled; } bool resizeSurfaceToItem() const { return m_resizeSurfaceToItem; } - void setUseTextureAlpha(bool useTextureAlpha); - void setClientRenderingEnabled(bool enabled); void setTouchEventsEnabled(bool enabled); void setResizeSurfaceToItem(bool enabled); - void setDamagedFlag(bool on); - protected: void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); @@ -111,21 +104,18 @@ public slots: private slots: void surfaceMapped(); void surfaceUnmapped(); - void surfaceDestroyed(QObject *object); - void surfaceDamaged(const QRegion &); void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent); void updateSize(); void updateSurfaceSize(); void updatePosition(); + void updateBuffer(); signals: - void textureChanged(); - void useTextureAlphaChanged(); - void clientRenderingEnabledChanged(); void touchEventsEnabledChanged(); void yInvertedChanged(); void surfaceChanged(); void resizeSurfaceToItemChanged(); + void surfaceDestroyed(); protected: QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); @@ -133,20 +123,17 @@ protected: private: friend class QWaylandSurfaceNode; void updateTexture(); - void init(QWaylandSurface *); - void ensureProvider(); + void init(QWaylandQuickSurface *); static QMutex *mutex; - QWaylandSurface *m_surface; - QWaylandSurfaceTextureProvider *m_provider; + QWaylandQuickSurface *m_surface; + mutable QWaylandSurfaceTextureProvider *m_provider; bool m_paintEnabled; - bool m_useTextureAlpha; - bool m_clientRenderingEnabled; bool m_touchEventsEnabled; - bool m_damaged; bool m_yInverted; bool m_resizeSurfaceToItem; + bool m_newTexture; }; QT_END_NAMESPACE diff --git a/src/compositor/wayland_wrapper/qwlcompositor.cpp b/src/compositor/wayland_wrapper/qwlcompositor.cpp index da67c3cd2..a6ec62caa 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor.cpp +++ b/src/compositor/wayland_wrapper/qwlcompositor.cpp @@ -69,10 +69,6 @@ #include <QtCore/QAbstractEventDispatcher> #include <QtGui/private/qguiapplication_p.h> -#ifdef QT_COMPOSITOR_QUICK -#include <QtQuick/QQuickWindow> -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -131,6 +127,15 @@ Compositor::Compositor(QWaylandCompositor *qt_compositor, QWaylandCompositor::Ex { m_timer.start(); compositor = this; +} + +void Compositor::init() +{ + QStringList arguments = QCoreApplication::instance()->arguments(); + + int socketArg = arguments.indexOf(QLatin1String("--wayland-socket-name")); + if (socketArg != -1 && socketArg + 1 < arguments.size()) + m_socket_name = arguments.at(socketArg + 1).toLocal8Bit(); wl_compositor::init(m_display->handle()); @@ -147,7 +152,7 @@ Compositor::Compositor(QWaylandCompositor *qt_compositor, QWaylandCompositor::Ex m_shell, Shell::bind_func); - if (wl_display_add_socket(m_display->handle(), qt_compositor->socketName())) { + if (wl_display_add_socket(m_display->handle(), m_qt_compositor->socketName())) { fprintf(stderr, "Fatal: Failed to open server socket\n"); exit(EXIT_FAILURE); } @@ -163,18 +168,12 @@ Compositor::Compositor(QWaylandCompositor *qt_compositor, QWaylandCompositor::Ex connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(processWaylandEvents())); qRegisterMetaType<SurfaceBuffer*>("SurfaceBuffer*"); + qRegisterMetaType<QWaylandSurface*>("WaylandSurface*"); //initialize distancefieldglyphcache here -#ifdef QT_COMPOSITOR_QUICK - if (QQuickWindow *w = qobject_cast<QQuickWindow *>(qt_compositor->window())) { - connect(w, SIGNAL(beforeSynchronizing()), this, SLOT(cleanupGraphicsResources()), Qt::DirectConnection); - } else -#endif - { -#if !defined(QT_NO_DEBUG) && !defined(QT_WAYLAND_NO_CLEANUP_WARNING) - qWarning("QWaylandCompositor::cleanupGraphicsResources() must be called manually"); -#endif - } + initializeHardwareIntegration(); + initializeExtensions(); + initializeDefaultInputDevice(); } Compositor::~Compositor() @@ -216,44 +215,26 @@ void Compositor::processWaylandEvents() void Compositor::destroySurface(Surface *surface) { - InputDevice *dev = defaultInputDevice(); - if (dev->mouseFocus() == surface) { - dev->setMouseFocus(0, QPointF(), QPointF()); - // Make sure the surface is reset regardless of what the grabber - // interface's focus() does. (e.g. the default implementation does - // nothing when a button is down which would be disastrous here) - dev->pointerDevice()->setFocus(0, QPointF()); - } - if (dev->pointerDevice()->current() == surface) { - dev->pointerDevice()->setCurrent(0, QPointF()); - } - if (dev->keyboardFocus() == surface) - dev->setKeyboardFocus(0); - m_surfaces.removeOne(surface); waylandCompositor()->surfaceAboutToBeDestroyed(surface->waylandSurface()); surface->releaseSurfaces(); - m_destroyed_surfaces << surface; + m_destroyed_surfaces << surface->waylandSurface(); } void Compositor::cleanupGraphicsResources() { - foreach (SurfaceBuffer *s, m_destroyed_buffers) - s->bufferWasDestroyed(); - m_destroyed_buffers.clear(); - qDeleteAll(m_destroyed_surfaces); m_destroyed_surfaces.clear(); } void Compositor::compositor_create_surface(Resource *resource, uint32_t id) { - Surface *surface = new Surface(resource->client(), id, this); - m_surfaces << surface; + QWaylandSurface *surface = new QWaylandSurface(resource->client(), id, m_qt_compositor); + m_surfaces << surface->handle(); //BUG: This may not be an on-screen window surface though - m_qt_compositor->surfaceCreated(surface->waylandSurface()); + m_qt_compositor->surfaceCreated(surface); } void Compositor::compositor_create_region(Resource *resource, uint32_t id) diff --git a/src/compositor/wayland_wrapper/qwlcompositor_p.h b/src/compositor/wayland_wrapper/qwlcompositor_p.h index 450ee23ed..835fa1fd8 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor_p.h +++ b/src/compositor/wayland_wrapper/qwlcompositor_p.h @@ -90,7 +90,9 @@ public: Compositor(QWaylandCompositor *qt_compositor, QWaylandCompositor::ExtensionFlags extensions); ~Compositor(); + void init(); void sendFrameCallbacks(QList<QWaylandSurface *> visibleSurfaces); + void frameFinished(Surface *surface = 0); InputDevice *defaultInputDevice(); //we just have 1 default device for now (since QPA doesn't give us anything else) @@ -155,8 +157,6 @@ public: bool retainedSelectionEnabled() const; void overrideSelection(const QMimeData *data); void feedRetainedSelectionData(QMimeData *data); - - void bufferWasDestroyed(SurfaceBuffer *buffer) { m_destroyed_buffers << buffer; } public slots: void cleanupGraphicsResources(); @@ -166,13 +166,14 @@ protected: private slots: void processWaylandEvents(); -private: +protected: void loadClientBufferIntegration(); void loadServerBufferIntegration(); QWaylandCompositor::ExtensionFlags m_extensions; Display *m_display; + QByteArray m_socket_name; /* Input */ QWaylandInputDevice *m_default_wayland_input_device; @@ -186,8 +187,7 @@ private: QElapsedTimer m_timer; QList<Surface *> m_surfaces; - QSet<Surface *> m_destroyed_surfaces; - QSet<SurfaceBuffer *> m_destroyed_buffers; + QSet<QWaylandSurface *> m_destroyed_surfaces; /* Render state */ uint32_t m_current_frame; @@ -220,6 +220,8 @@ private: uint32_t version, uint32_t id); bool m_retainSelection; + + friend class ::QWaylandCompositor; }; } diff --git a/src/compositor/wayland_wrapper/qwlinputdevice.cpp b/src/compositor/wayland_wrapper/qwlinputdevice.cpp index 50ed377a6..0f3fce94f 100644 --- a/src/compositor/wayland_wrapper/qwlinputdevice.cpp +++ b/src/compositor/wayland_wrapper/qwlinputdevice.cpp @@ -260,7 +260,7 @@ Surface *InputDevice::keyboardFocus() const */ bool InputDevice::setKeyboardFocus(Surface *surface) { - if (surface && surface->transientInactive()) + if (surface && (surface->transientInactive() || surface->isDestroyed())) return false; m_keyboard->setFocus(surface); @@ -276,6 +276,9 @@ Surface *InputDevice::mouseFocus() const void InputDevice::setMouseFocus(Surface *surface, const QPointF &localPos, const QPointF &globalPos) { + if (surface && surface->isDestroyed()) + return; + m_pointer->setMouseFocus(surface, localPos, globalPos); // We have no separate touch focus management so make it match the pointer focus always. diff --git a/src/compositor/wayland_wrapper/qwlkeyboard.cpp b/src/compositor/wayland_wrapper/qwlkeyboard.cpp index 4c3aa8920..25e7155b0 100644 --- a/src/compositor/wayland_wrapper/qwlkeyboard.cpp +++ b/src/compositor/wayland_wrapper/qwlkeyboard.cpp @@ -75,6 +75,7 @@ Keyboard::Keyboard(Compositor *compositor, InputDevice *seat) #ifndef QT_NO_WAYLAND_XKB initXKB(); #endif + connect(&m_focusDestroyListener, &WlListener::fired, this, &Keyboard::focusDestroyed); } Keyboard::~Keyboard() @@ -93,6 +94,7 @@ void Keyboard::setFocus(Surface *surface) if (m_focusResource && m_focus != surface) { uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); send_leave(m_focusResource->handle, serial, m_focus->resource()->handle); + m_focusDestroyListener.reset(); } Resource *resource = surface ? resourceMap().value(surface->resource()->client()) : 0; @@ -101,6 +103,7 @@ void Keyboard::setFocus(Surface *surface) uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); send_modifiers(resource->handle, serial, m_modsDepressed, m_modsLatched, m_modsLocked, m_group); send_enter(resource->handle, serial, surface->resource()->handle, QByteArray::fromRawData((char *)m_keys.data(), m_keys.size() * sizeof(uint32_t))); + m_focusDestroyListener.listenForDestruction(surface->resource()->handle); } m_focusResource = resource; @@ -114,6 +117,15 @@ void Keyboard::setKeymap(const QWaylandKeymap &keymap) m_pendingKeymap = true; } +void Keyboard::focusDestroyed(void *data) +{ + Q_UNUSED(data) + m_focusDestroyListener.reset(); + + m_focus = 0; + m_focusResource = 0; +} + void Keyboard::sendKeyModifiers(wl_keyboard::Resource *resource, uint32_t serial) { send_modifiers(resource->handle, serial, m_modsDepressed, m_modsLatched, m_modsLocked, m_group); diff --git a/src/compositor/wayland_wrapper/qwlkeyboard_p.h b/src/compositor/wayland_wrapper/qwlkeyboard_p.h index b20fa97f7..6faf6ace2 100644 --- a/src/compositor/wayland_wrapper/qwlkeyboard_p.h +++ b/src/compositor/wayland_wrapper/qwlkeyboard_p.h @@ -54,6 +54,8 @@ #include <xkbcommon/xkbcommon.h> #endif +#include "qwllistener_p.h" + QT_BEGIN_NAMESPACE namespace QtWayland { @@ -91,6 +93,7 @@ private: void sendKeyEvent(uint code, uint32_t state); void updateModifierState(uint code, uint32_t state); void updateKeymap(); + void focusDestroyed(void *data); #ifndef QT_NO_WAYLAND_XKB void initXKB(); @@ -102,6 +105,7 @@ private: Surface *m_focus; Resource *m_focusResource; + WlListener m_focusDestroyListener; QVector<uint32_t> m_keys; uint32_t m_modsDepressed; diff --git a/src/compositor/wayland_wrapper/qwllistener.cpp b/src/compositor/wayland_wrapper/qwllistener.cpp new file mode 100644 index 000000000..a754981bf --- /dev/null +++ b/src/compositor/wayland_wrapper/qwllistener.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwllistener_p.h" + +QT_BEGIN_NAMESPACE + +WlListener::WlListener() +{ + m_listener.parent = this; + m_listener.listener.notify = handler; + wl_list_init(&m_listener.listener.link); +} + +void WlListener::listenForDestruction(::wl_resource *resource) +{ + wl_resource_add_destroy_listener(resource, &m_listener.listener); +} + +void WlListener::reset() +{ + wl_list_remove(&m_listener.listener.link); + wl_list_init(&m_listener.listener.link); +} + +void WlListener::handler(wl_listener *listener, void *data) +{ + WlListener *that = reinterpret_cast<Listener *>(listener)->parent; + emit that->fired(data); +} + +QT_END_NAMESPACE diff --git a/src/compositor/wayland_wrapper/qwllistener_p.h b/src/compositor/wayland_wrapper/qwllistener_p.h new file mode 100644 index 000000000..4c49b1433 --- /dev/null +++ b/src/compositor/wayland_wrapper/qwllistener_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTWAYLAND_QWLLISTENER_H +#define QTWAYLAND_QWLLISTENER_H + +#include <QObject> + +#include <wayland-server.h> + +QT_BEGIN_NAMESPACE + +class WlListener : public QObject +{ + Q_OBJECT +public: + WlListener(); + + void listenForDestruction(::wl_resource *resource); + void reset(); + +signals: + void fired(void *data); + +private: + static void handler(wl_listener *listener, void *data); + + struct Listener { + wl_listener listener; + WlListener *parent; + }; + Listener m_listener; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/compositor/wayland_wrapper/qwlpointer.cpp b/src/compositor/wayland_wrapper/qwlpointer.cpp index b459472a2..60082e325 100644 --- a/src/compositor/wayland_wrapper/qwlpointer.cpp +++ b/src/compositor/wayland_wrapper/qwlpointer.cpp @@ -96,6 +96,7 @@ Pointer::Pointer(Compositor *compositor, InputDevice *seat) , m_currentPoint() , m_buttonCount() { + connect(&m_focusDestroyListener, &WlListener::fired, this, &Pointer::focusDestroyed); } void Pointer::setFocus(Surface *surface, const QPointF &position) @@ -103,6 +104,7 @@ void Pointer::setFocus(Surface *surface, const QPointF &position) if (m_focusResource && m_focus != surface) { uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); send_leave(m_focusResource->handle, serial, m_focus->resource()->handle); + m_focusDestroyListener.reset(); } Resource *resource = surface ? resourceMap().value(surface->resource()->client()) : 0; @@ -117,12 +119,24 @@ void Pointer::setFocus(Surface *surface, const QPointF &position) } send_enter(resource->handle, serial, surface->resource()->handle, wl_fixed_from_double(position.x()), wl_fixed_from_double(position.y())); + + m_focusDestroyListener.listenForDestruction(surface->resource()->handle); } m_focusResource = resource; m_focus = surface; } +void Pointer::focusDestroyed(void *data) +{ + Q_UNUSED(data) + m_focusDestroyListener.reset(); + + m_focus = 0; + m_focusResource = 0; + setMouseFocus(0, QPointF(), QPointF()); +} + void Pointer::startGrab(PointerGrabber *grab) { m_grab = grab; diff --git a/src/compositor/wayland_wrapper/qwlpointer_p.h b/src/compositor/wayland_wrapper/qwlpointer_p.h index ed53b048c..e125ab323 100644 --- a/src/compositor/wayland_wrapper/qwlpointer_p.h +++ b/src/compositor/wayland_wrapper/qwlpointer_p.h @@ -46,11 +46,14 @@ #include <QtCore/QList> #include <QtCore/QPoint> +#include <QtCore/QObject> #include <QtCompositor/private/qwayland-server-wayland.h> #include <stdint.h> +#include "qwllistener_p.h" + QT_BEGIN_NAMESPACE namespace QtWayland { @@ -71,7 +74,7 @@ public: Pointer *m_pointer; }; -class Q_COMPOSITOR_EXPORT Pointer : public QtWaylandServer::wl_pointer, public PointerGrabber +class Q_COMPOSITOR_EXPORT Pointer : public QObject, public QtWaylandServer::wl_pointer, public PointerGrabber { public: Pointer(Compositor *compositor, InputDevice *seat); @@ -112,6 +115,8 @@ protected: void pointer_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; private: + void focusDestroyed(void *data); + Compositor *m_compositor; InputDevice *m_seat; @@ -129,6 +134,8 @@ private: QPointF m_currentPoint; int m_buttonCount; + + WlListener m_focusDestroyListener; }; } // namespace QtWayland diff --git a/src/compositor/wayland_wrapper/qwlsurface.cpp b/src/compositor/wayland_wrapper/qwlsurface.cpp index 5928bbb0f..98d494ac8 100644 --- a/src/compositor/wayland_wrapper/qwlsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlsurface.cpp @@ -41,10 +41,6 @@ #include "qwlsurface_p.h" #include "qwaylandsurface.h" -#ifdef QT_COMPOSITOR_QUICK -#include "qwaylandsurfaceitem.h" -#endif - #include "qwlcompositor_p.h" #include "qwlinputdevice_p.h" #include "qwlextendedsurface_p.h" @@ -58,11 +54,6 @@ #include <wayland-server.h> -#ifdef QT_COMPOSITOR_WAYLAND_GL -#include "hardware_integration/qwlclientbufferintegration_p.h" -#include <qpa/qplatformopenglcontext.h> -#endif - #ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT #include "waylandwindowmanagerintegration.h" #endif @@ -117,19 +108,20 @@ public: bool canSend; }; -Surface::Surface(struct wl_client *client, uint32_t id, Compositor *compositor) +Surface::Surface(struct wl_client *client, uint32_t id, QWaylandCompositor *compositor, QWaylandSurface *surface) : QtWaylandServer::wl_surface(client, id) - , m_compositor(compositor) - , m_waylandSurface(new QWaylandSurface(this)) - , m_backBuffer(0) - , m_frontBuffer(0) + , m_compositor(compositor->handle()) + , m_waylandSurface(surface) + , m_buffer(0) , m_surfaceMapped(false) + , m_attacher(0) , m_extendedSurface(0) , m_subSurface(0) , m_shellSurface(0) , m_inputPanelSurface(0) , m_transientInactive(false) , m_isCursorSurface(false) + , m_destroyed(false) { m_pending.buffer = 0; m_pending.newlyAttached = false; @@ -137,9 +129,10 @@ Surface::Surface(struct wl_client *client, uint32_t id, Compositor *compositor) Surface::~Surface() { - delete m_waylandSurface; delete m_subSurface; + m_bufferRef = QWaylandBufferRef(); + for (int i = 0; i < m_bufferPool.size(); i++) delete m_bufferPool[i]; @@ -151,10 +144,7 @@ Surface::~Surface() void Surface::releaseSurfaces() { - delete m_waylandSurface; - m_waylandSurface = 0; - delete m_subSurface; - m_subSurface = 0; + } Surface *Surface::fromResource(struct ::wl_resource *resource) @@ -164,9 +154,8 @@ Surface *Surface::fromResource(struct ::wl_resource *resource) QWaylandSurface::Type Surface::type() const { - SurfaceBuffer *surfaceBuffer = currentSurfaceBuffer(); - if (surfaceBuffer && surfaceBuffer->waylandBufferHandle()) { - if (surfaceBuffer->isShmBuffer()) { + if (m_buffer && m_buffer->waylandBufferHandle()) { + if (m_buffer->isShmBuffer()) { return QWaylandSurface::Shm; } else { return QWaylandSurface::Texture; @@ -177,27 +166,14 @@ QWaylandSurface::Type Surface::type() const bool Surface::isYInverted() const { - bool ret = false; - static bool negateReturn = qgetenv("QT_COMPOSITOR_NEGATE_INVERTED_Y").toInt(); - ClientBufferIntegration *clientBufferIntegration = m_compositor->clientBufferIntegration(); - -#ifdef QT_COMPOSITOR_WAYLAND_GL - SurfaceBuffer *surfacebuffer = currentSurfaceBuffer(); - if (!surfacebuffer) { - ret = false; - } else if (clientBufferIntegration && surfacebuffer->waylandBufferHandle() && type() != QWaylandSurface::Shm) { - ret = clientBufferIntegration->isYInverted(surfacebuffer->waylandBufferHandle()); - } else -#endif - ret = true; - - return ret != negateReturn; + if (m_buffer) + return m_buffer->isYInverted(); + return false; } bool Surface::mapped() const { - SurfaceBuffer *surfacebuffer = currentSurfaceBuffer(); - return surfacebuffer ? bool(surfacebuffer->waylandBufferHandle()) : false; + return m_buffer ? bool(m_buffer->waylandBufferHandle()) : false; } QPointF Surface::pos() const @@ -246,28 +222,6 @@ QRegion Surface::opaqueRegion() const return m_opaqueRegion; } -QImage Surface::image() const -{ - SurfaceBuffer *surfacebuffer = currentSurfaceBuffer(); - if (surfacebuffer && !surfacebuffer->isDestroyed() && type() == QWaylandSurface::Shm) { - return surfacebuffer->image(); - } - return QImage(); -} - -#ifdef QT_COMPOSITOR_WAYLAND_GL -GLuint Surface::textureId() const -{ - const SurfaceBuffer *surfacebuffer = m_frontBuffer; - - if (m_compositor->clientBufferIntegration() && type() == QWaylandSurface::Texture - && !surfacebuffer->textureCreated()) { - const_cast<SurfaceBuffer *>(surfacebuffer)->createTexture(); - } - return surfacebuffer->texture(); -} -#endif // QT_COMPOSITOR_WAYLAND_GL - void Surface::sendFrameCallback() { uint time = m_compositor->currentTimeMsecs(); @@ -342,25 +296,6 @@ Compositor *Surface::compositor() const return m_compositor; } -void Surface::swapBuffers() - { - SurfaceBuffer *front = m_frontBuffer; - - // Advance current back buffer to the front buffer. - if (m_backBuffer) { - if (m_backBuffer->isDestroyed()) { - m_backBuffer->disown(); - m_backBuffer = 0; - } - m_frontBuffer = m_backBuffer; - m_backBuffer = 0; - } - - // Release the old front buffer if we changed it. - if (front && front != m_frontBuffer) - front->disown(); -} - /*! * Sets the backbuffer for this surface. The back buffer is not yet on * screen and will become live during the next swapBuffers(). @@ -370,11 +305,11 @@ void Surface::swapBuffers() */ void Surface::setBackBuffer(SurfaceBuffer *buffer) { - m_backBuffer = buffer; + m_buffer = buffer; - if (m_backBuffer) { - bool valid = m_backBuffer->waylandBufferHandle() != 0; - setSize(valid ? m_backBuffer->size() : QSize()); + if (m_buffer) { + bool valid = m_buffer->waylandBufferHandle() != 0; + setSize(valid ? m_buffer->size() : QSize()); if ((!m_subSurface || !m_subSurface->parent()) && !m_surfaceMapped) { m_surfaceMapped = true; @@ -426,7 +361,9 @@ void Surface::surface_destroy_resource(Resource *) m_extendedSurface = 0; } - compositor()->destroySurface(this); + m_destroyed = true; + m_waylandSurface->destroy(); + emit m_waylandSurface->surfaceDestroyed(); } void Surface::surface_destroy(Resource *resource) @@ -469,14 +406,17 @@ void Surface::surface_commit(Resource *) m_damage = m_pending.damage; if (m_pending.buffer || m_pending.newlyAttached) { - if (m_backBuffer && m_backBuffer != m_pending.buffer) - m_backBuffer->disown(); - setBackBuffer(m_pending.buffer); - if (!m_backBuffer && m_surfaceMapped) { + if (!m_buffer && m_surfaceMapped) { m_surfaceMapped = false; emit m_waylandSurface->unmapped(); } + + m_bufferRef = QWaylandBufferRef(m_buffer); + + if (m_attacher) + m_attacher->attach(m_bufferRef); + emit m_waylandSurface->configure(); } m_pending.buffer = 0; @@ -484,13 +424,13 @@ void Surface::surface_commit(Resource *) m_pending.newlyAttached = false; m_pending.damage = QRegion(); - if (m_backBuffer) - m_backBuffer->setCommitted(); + if (m_buffer) + m_buffer->setCommitted(); m_frameCallbacks << m_pendingFrameCallbacks; m_pendingFrameCallbacks.clear(); - emit m_waylandSurface->committed(); + emit m_waylandSurface->redraw(); } void Surface::frameStarted() diff --git a/src/compositor/wayland_wrapper/qwlsurface_p.h b/src/compositor/wayland_wrapper/qwlsurface_p.h index 6d911e915..12984a1f2 100644 --- a/src/compositor/wayland_wrapper/qwlsurface_p.h +++ b/src/compositor/wayland_wrapper/qwlsurface_p.h @@ -45,6 +45,7 @@ #include <private/qwlsurfacebuffer_p.h> #include <QtCompositor/qwaylandsurface.h> +#include <QtCompositor/qwaylandbufferref.h> #include <QtCore/QVector> #include <QtCore/QRect> @@ -54,10 +55,6 @@ #include <QtCore/QTextStream> #include <QtCore/QMetaType> -#ifdef QT_COMPOSITOR_WAYLAND_GL -#include <QtGui/qopengl.h> -#endif - #include <wayland-util.h> #include <QtCompositor/private/qwayland-server-wayland.h> @@ -79,7 +76,7 @@ class FrameCallback; class Q_COMPOSITOR_EXPORT Surface : public QtWaylandServer::wl_surface { public: - Surface(struct wl_client *client, uint32_t id, Compositor *compositor); + Surface(struct wl_client *client, uint32_t id, QWaylandCompositor *compositor, QWaylandSurface *surface); ~Surface(); static Surface *fromResource(struct ::wl_resource *resource); @@ -101,12 +98,6 @@ public: QRegion inputRegion() const; QRegion opaqueRegion() const; - QImage image() const; - -#ifdef QT_COMPOSITOR_WAYLAND_GL - GLuint textureId() const; -#endif - void sendFrameCallback(); void removeFrameCallback(FrameCallback *callback); @@ -140,20 +131,37 @@ public: bool isCursorSurface() const { return m_isCursorSurface; } void setCursorSurface(bool isCursor) { m_isCursorSurface = isCursor; } - void swapBuffers(); void releaseSurfaces(); void frameStarted(); -private: + inline bool isDestroyed() const { return m_destroyed; } + +protected: + void surface_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; + + void surface_destroy(Resource *resource) Q_DECL_OVERRIDE; + void surface_attach(Resource *resource, + struct wl_resource *buffer, int x, int y) Q_DECL_OVERRIDE; + void surface_damage(Resource *resource, + int32_t x, int32_t y, int32_t width, int32_t height) Q_DECL_OVERRIDE; + void surface_frame(Resource *resource, + uint32_t callback) Q_DECL_OVERRIDE; + void surface_set_opaque_region(Resource *resource, + struct wl_resource *region) Q_DECL_OVERRIDE; + void surface_set_input_region(Resource *resource, + struct wl_resource *region) Q_DECL_OVERRIDE; + void surface_commit(Resource *resource) Q_DECL_OVERRIDE; + Q_DISABLE_COPY(Surface) Compositor *m_compositor; QWaylandSurface *m_waylandSurface; - SurfaceBuffer *m_backBuffer; QRegion m_damage; - SurfaceBuffer *m_frontBuffer; + SurfaceBuffer *m_buffer; + QWaylandBufferRef m_bufferRef; bool m_surfaceMapped; + QWaylandBufferAttacher *m_attacher; struct { SurfaceBuffer *buffer; @@ -184,32 +192,12 @@ private: QString m_title; bool m_transientInactive; bool m_isCursorSurface; + bool m_destroyed; - inline SurfaceBuffer *currentSurfaceBuffer() const; void setBackBuffer(SurfaceBuffer *buffer); SurfaceBuffer *createSurfaceBuffer(struct ::wl_resource *buffer); - - void surface_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; - - void surface_destroy(Resource *resource) Q_DECL_OVERRIDE; - void surface_attach(Resource *resource, - struct wl_resource *buffer, int x, int y) Q_DECL_OVERRIDE; - void surface_damage(Resource *resource, - int32_t x, int32_t y, int32_t width, int32_t height) Q_DECL_OVERRIDE; - void surface_frame(Resource *resource, - uint32_t callback) Q_DECL_OVERRIDE; - void surface_set_opaque_region(Resource *resource, - struct wl_resource *region) Q_DECL_OVERRIDE; - void surface_set_input_region(Resource *resource, - struct wl_resource *region) Q_DECL_OVERRIDE; - void surface_commit(Resource *resource) Q_DECL_OVERRIDE; - }; -inline SurfaceBuffer *Surface::currentSurfaceBuffer() const { - return m_backBuffer? m_backBuffer : m_frontBuffer; -} - } QT_END_NAMESPACE diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp index b0e67e1fa..3ed469a6c 100644 --- a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp +++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp @@ -100,8 +100,6 @@ void SurfaceBuffer::initialize(struct ::wl_resource *buffer) void SurfaceBuffer::destructBufferState() { - destroyTexture(); - if (m_buffer) { sendRelease(); @@ -239,24 +237,23 @@ QImage SurfaceBuffer::image() return m_image; } -void SurfaceBuffer::bufferWasDestroyed() -{ - destroyTexture(); - m_destroyed = true; - m_buffer = 0; -} - void SurfaceBuffer::destroy_listener_callback(wl_listener *listener, void *data) { Q_UNUSED(data); struct surface_buffer_destroy_listener *destroy_listener = reinterpret_cast<struct surface_buffer_destroy_listener *>(listener); SurfaceBuffer *d = destroy_listener->surfaceBuffer; - d->m_compositor->bufferWasDestroyed(d); + + // Mark the buffer as destroyed and clear m_buffer right away to avoid + // touching it before it is properly cleaned up. + d->m_destroyed = true; + d->m_buffer = 0; } void SurfaceBuffer::createTexture() { + destroyTexture(); + ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration(); #ifdef QT_COMPOSITOR_WAYLAND_GL if (!m_texture) @@ -271,6 +268,22 @@ void SurfaceBuffer::createTexture() #endif } +bool SurfaceBuffer::isYInverted() const +{ + bool ret = false; + static bool negateReturn = qgetenv("QT_COMPOSITOR_NEGATE_INVERTED_Y").toInt(); + ClientBufferIntegration *clientBufferIntegration = m_compositor->clientBufferIntegration(); + +#ifdef QT_COMPOSITOR_WAYLAND_GL + if (clientBufferIntegration && waylandBufferHandle() && isShmBuffer()) { + ret = clientBufferIntegration->isYInverted(waylandBufferHandle()); + } else +#endif + ret = true; + + return ret != negateReturn; +} + } QT_END_NAMESPACE diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h b/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h index c2c39253a..26993b5d0 100644 --- a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h +++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h @@ -44,12 +44,14 @@ #include <QtCore/QRect> #include <QtGui/qopengl.h> #include <QImage> +#include <QAtomicInt> #include <wayland-server.h> QT_BEGIN_NAMESPACE class QWaylandClientBufferIntegration; +class QWaylandBufferRef; namespace QtWayland { @@ -75,6 +77,7 @@ public: QSize size() const; bool isShmBuffer() const; + bool isYInverted() const; inline bool isRegisteredWithBuffer() const { return m_is_registered_for_buffer; } @@ -131,10 +134,13 @@ private: mutable bool m_isSizeResolved; mutable QSize m_size; + QAtomicInt m_refCount; QImage m_image; static void destroy_listener_callback(wl_listener *listener, void *data); + + friend class ::QWaylandBufferRef; }; GLuint SurfaceBuffer::texture() const diff --git a/src/compositor/wayland_wrapper/qwltouch.cpp b/src/compositor/wayland_wrapper/qwltouch.cpp index 2a4070e5e..d160bc4bf 100644 --- a/src/compositor/wayland_wrapper/qwltouch.cpp +++ b/src/compositor/wayland_wrapper/qwltouch.cpp @@ -54,10 +54,15 @@ Touch::Touch(Compositor *compositor) , m_grab(this) { m_grab->setTouch(this); + connect(&m_focusDestroyListener, &WlListener::fired, this, &Touch::focusDestroyed); } void Touch::setFocus(Surface *surface) { + m_focusDestroyListener.reset(); + if (surface) + m_focusDestroyListener.listenForDestruction(surface->resource()->handle); + m_focus = surface; m_focusResource = surface ? resourceMap().value(surface->resource()->client()) : 0; } @@ -73,6 +78,15 @@ void Touch::endGrab() m_grab = this; } +void Touch::focusDestroyed(void *data) +{ + Q_UNUSED(data) + m_focusDestroyListener.reset(); + + m_focus = 0; + m_focusResource = 0; +} + void Touch::sendCancel() { if (m_focusResource) diff --git a/src/compositor/wayland_wrapper/qwltouch_p.h b/src/compositor/wayland_wrapper/qwltouch_p.h index 695609809..fc6b4d0e3 100644 --- a/src/compositor/wayland_wrapper/qwltouch_p.h +++ b/src/compositor/wayland_wrapper/qwltouch_p.h @@ -45,9 +45,12 @@ #include <QtCompositor/qwaylandexport.h> #include <QtCore/QPoint> +#include <QtCore/QObject> #include <QtCompositor/private/qwayland-server-wayland.h> +#include "qwllistener_p.h" + QT_BEGIN_NAMESPACE namespace QtWayland { @@ -73,7 +76,7 @@ private: Touch *m_touch; }; -class Q_COMPOSITOR_EXPORT Touch : public QtWaylandServer::wl_touch, public TouchGrabber +class Q_COMPOSITOR_EXPORT Touch : public QObject, public QtWaylandServer::wl_touch, public TouchGrabber { public: explicit Touch(Compositor *compositor); @@ -95,10 +98,13 @@ public: void motion(uint32_t time, int touch_id, const QPointF &position); private: + void focusDestroyed(void *data); + Compositor *m_compositor; Surface *m_focus; Resource *m_focusResource; + WlListener m_focusDestroyListener; TouchGrabber *m_grab; }; diff --git a/src/compositor/wayland_wrapper/wayland_wrapper.pri b/src/compositor/wayland_wrapper/wayland_wrapper.pri index 3b695532c..ac34ae283 100644 --- a/src/compositor/wayland_wrapper/wayland_wrapper.pri +++ b/src/compositor/wayland_wrapper/wayland_wrapper.pri @@ -37,6 +37,7 @@ HEADERS += \ wayland_wrapper/qwltextinput_p.h \ wayland_wrapper/qwltextinputmanager_p.h \ wayland_wrapper/qwltouch_p.h \ + wayland_wrapper/qwllistener_p.h \ SOURCES += \ wayland_wrapper/qwlcompositor.cpp \ @@ -65,6 +66,7 @@ SOURCES += \ wayland_wrapper/qwltextinput.cpp \ wayland_wrapper/qwltextinputmanager.cpp \ wayland_wrapper/qwltouch.cpp \ + wayland_wrapper/qwllistener.cpp \ INCLUDEPATH += wayland_wrapper diff --git a/tests/auto/compositor/tst_compositor.cpp b/tests/auto/compositor/tst_compositor.cpp index 44fb2ff96..99f08a4e5 100644 --- a/tests/auto/compositor/tst_compositor.cpp +++ b/tests/auto/compositor/tst_compositor.cpp @@ -42,6 +42,8 @@ #include "mockclient.h" #include "testcompositor.h" +#include "qwaylandbufferref.h" + #include <QtTest/QtTest> class tst_WaylandCompositor : public QObject @@ -186,6 +188,24 @@ static void registerFrameCallback(wl_surface *surface, int *counter) void tst_WaylandCompositor::frameCallback() { + class BufferAttacher : public QWaylandBufferAttacher + { + public: + void attach(const QWaylandBufferRef &ref) Q_DECL_OVERRIDE + { + bufferRef = ref; + } + + QImage image() const + { + if (!bufferRef || !bufferRef.isShm()) + return QImage(); + return bufferRef.image(); + } + + QWaylandBufferRef bufferRef; + }; + TestCompositor compositor; MockClient client; @@ -200,7 +220,9 @@ void tst_WaylandCompositor::frameCallback() QTRY_COMPARE(compositor.surfaces.size(), 1); QWaylandSurface *waylandSurface = compositor.surfaces.at(0); - QSignalSpy damagedSpy(waylandSurface, SIGNAL(damaged(const QRect &))); + BufferAttacher attacher; + waylandSurface->setBufferAttacher(&attacher); + QSignalSpy damagedSpy(waylandSurface, SIGNAL(damaged(const QRegion &))); for (int i = 0; i < 10; ++i) { registerFrameCallback(surface, &frameCounter); @@ -209,7 +231,7 @@ void tst_WaylandCompositor::frameCallback() QTRY_COMPARE(waylandSurface->type(), QWaylandSurface::Shm); QTRY_COMPARE(damagedSpy.count(), i + 1); - QCOMPARE(waylandSurface->image(), buffer.image); + QCOMPARE(static_cast<BufferAttacher *>(waylandSurface->bufferAttacher())->image(), buffer.image); compositor.sendFrameCallbacks(QList<QWaylandSurface *>() << waylandSurface); QTRY_COMPARE(frameCounter, i + 1); |