summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/qml-compositor/WindowContainer.qml27
-rw-r--r--examples/qml-compositor/main.cpp48
-rw-r--r--examples/qml-compositor/main.qml30
-rw-r--r--examples/qwindow-compositor/qwindowcompositor.cpp108
-rw-r--r--examples/qwindow-compositor/qwindowcompositor.h4
-rw-r--r--examples/server-buffer/compositor/main.cpp34
-rw-r--r--examples/server-buffer/compositor/qml/main.qml17
-rw-r--r--src/compositor/compositor_api/compositor_api.pri15
-rw-r--r--src/compositor/compositor_api/qwaylandbufferref.cpp131
-rw-r--r--src/compositor/compositor_api/qwaylandbufferref.h87
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp37
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.h5
-rw-r--r--src/compositor/compositor_api/qwaylandquickcompositor.cpp102
-rw-r--r--src/compositor/compositor_api/qwaylandquickcompositor.h64
-rw-r--r--src/compositor/compositor_api/qwaylandquicksurface.cpp241
-rw-r--r--src/compositor/compositor_api/qwaylandquicksurface.h91
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp220
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.h57
-rw-r--r--src/compositor/compositor_api/qwaylandsurface_p.h68
-rw-r--r--src/compositor/compositor_api/qwaylandsurfaceitem.cpp173
-rw-r--r--src/compositor/compositor_api/qwaylandsurfaceitem.h41
-rw-r--r--src/compositor/wayland_wrapper/qwlcompositor.cpp55
-rw-r--r--src/compositor/wayland_wrapper/qwlcompositor_p.h12
-rw-r--r--src/compositor/wayland_wrapper/qwlinputdevice.cpp5
-rw-r--r--src/compositor/wayland_wrapper/qwlkeyboard.cpp12
-rw-r--r--src/compositor/wayland_wrapper/qwlkeyboard_p.h4
-rw-r--r--src/compositor/wayland_wrapper/qwllistener.cpp70
-rw-r--r--src/compositor/wayland_wrapper/qwllistener_p.h75
-rw-r--r--src/compositor/wayland_wrapper/qwlpointer.cpp14
-rw-r--r--src/compositor/wayland_wrapper/qwlpointer_p.h9
-rw-r--r--src/compositor/wayland_wrapper/qwlsurface.cpp124
-rw-r--r--src/compositor/wayland_wrapper/qwlsurface_p.h60
-rw-r--r--src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp33
-rw-r--r--src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h6
-rw-r--r--src/compositor/wayland_wrapper/qwltouch.cpp14
-rw-r--r--src/compositor/wayland_wrapper/qwltouch_p.h8
-rw-r--r--src/compositor/wayland_wrapper/wayland_wrapper.pri2
-rw-r--r--tests/auto/compositor/tst_compositor.cpp26
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);