summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJørgen Lind <jorgen.lind@nokia.com>2012-01-04 08:33:28 +0100
committerJørgen Lind <jorgen.lind@nokia.com>2012-01-04 10:34:40 +0100
commitd5ea033df8cf0a2dec49fce639d84e7dd0a2fced (patch)
tree15d92a4990b612e73450d110a6cc820df8cdee2e
parent62bba49c83849ca5904357de45c888f9fab3106a (diff)
Implement subsurfaces extension
This allows you to have subwindows in the compositor. We tried to experiment with composing subsurfaces client side, but the architecture did not feel very lean. This however, requires the compositor to compose each surface before drawing the surface. The example compositors render the subsurfaces into the wl_surfaces texture. This might not be a good idea. Change-Id: I6e186b62d7b490de7f4e6c6f22fcf6c1e0a70df3 Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
-rw-r--r--examples/qml-compositor/main.cpp43
-rw-r--r--examples/qml-compositor/qml-compositor.pro2
-rw-r--r--examples/qwidget-compositor/main.cpp190
-rw-r--r--examples/qwidget-compositor/qwidget-compositor.pro16
-rw-r--r--examples/qwidget-compositor/textureblitter.cpp118
-rw-r--r--examples/qwidget-compositor/textureblitter.h28
-rw-r--r--examples/qwindow-compositor/qwindow-compositor.pro16
-rw-r--r--examples/qwindow-compositor/qwindowcompositor.cpp98
-rw-r--r--examples/qwindow-compositor/qwindowcompositor.h14
-rw-r--r--examples/qwindow-compositor/surfacerenderer.cpp146
-rw-r--r--examples/qwindow-compositor/surfacerenderer.h29
-rw-r--r--examples/qwindow-compositor/textureblitter.cpp118
-rw-r--r--examples/qwindow-compositor/textureblitter.h26
-rw-r--r--extensions/sub-surface-extension.xml80
-rw-r--r--extensions/surface-extension.xml1
-rw-r--r--src/compositor/compositor_api/waylandcompositor.cpp5
-rw-r--r--src/compositor/compositor_api/waylandcompositor.h2
-rw-r--r--src/compositor/compositor_api/waylandsurface.cpp78
-rw-r--r--src/compositor/compositor_api/waylandsurface.h21
-rw-r--r--src/compositor/compositor_api/waylandsurfaceitem.cpp67
-rw-r--r--src/compositor/compositor_api/waylandsurfaceitem.h3
-rw-r--r--src/compositor/wayland_wrapper/wayland_wrapper.pri7
-rw-r--r--src/compositor/wayland_wrapper/wlcompositor.cpp9
-rw-r--r--src/compositor/wayland_wrapper/wlcompositor.h3
-rw-r--r--src/compositor/wayland_wrapper/wlextendedsurface.cpp6
-rw-r--r--src/compositor/wayland_wrapper/wlextendedsurface.h24
-rw-r--r--src/compositor/wayland_wrapper/wlsubsurface.cpp168
-rw-r--r--src/compositor/wayland_wrapper/wlsubsurface.h129
-rw-r--r--src/compositor/wayland_wrapper/wlsurface.cpp56
-rw-r--r--src/compositor/wayland_wrapper/wlsurface.h7
-rw-r--r--src/plugins/platforms/wayland/qwaylanddisplay.cpp3
-rw-r--r--src/plugins/platforms/wayland/qwaylanddisplay.h3
-rw-r--r--src/plugins/platforms/wayland/qwaylandextendedsurface.h1
-rw-r--r--src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp1
-rw-r--r--src/plugins/platforms/wayland/qwaylandsubsurface.cpp79
-rw-r--r--src/plugins/platforms/wayland/qwaylandsubsurface.h73
-rw-r--r--src/plugins/platforms/wayland/qwaylandwindow.cpp24
-rw-r--r--src/plugins/platforms/wayland/qwaylandwindow.h4
-rw-r--r--src/plugins/platforms/wayland/wayland.pro7
39 files changed, 1356 insertions, 349 deletions
diff --git a/examples/qml-compositor/main.cpp b/examples/qml-compositor/main.cpp
index fc6a4618e..466533b52 100644
--- a/examples/qml-compositor/main.cpp
+++ b/examples/qml-compositor/main.cpp
@@ -56,8 +56,10 @@ class QmlCompositor : public QQuickView, public WaylandCompositor
{
Q_OBJECT
public:
- QmlCompositor() : WaylandCompositor(this) {
- //setMouseTracking(true);
+ QmlCompositor()
+ : WaylandCompositor(this)
+ {
+ enableSubSurfaceExtension();
setSource(QUrl(QLatin1String("qrc:qml/QmlCompositor/main.qml")));
setResizeMode(QQuickView::SizeRootObjectToView);
winId();
@@ -78,27 +80,20 @@ public slots:
private slots:
void surfaceMapped() {
WaylandSurface *surface = qobject_cast<WaylandSurface *>(sender());
- surface->setGeometry(QRect(surface->geometry().topLeft(),size));
-
- if (m_windowMap.contains(surface)) {
- WaylandSurfaceItem *item = m_windowMap.value(surface);
- item->setWidth(size.width());
- item->setHeight(size.height());
- emit windowResized(QVariant::fromValue(static_cast<QQuickItem *>(item)));
- } else {
- WaylandSurfaceItem *item = new WaylandSurfaceItem(surface, rootObject());
- item->setTouchEventsEnabled(true);
- connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *)));
- emit windowAdded(QVariant::fromValue(static_cast<QQuickItem *>(item)));
- m_windowMap[surface] = item;
-
- item->takeFocus();
- }
+ WaylandSurfaceItem *item = surface->surfaceItem();
+ item->takeFocus();
+ emit windowAdded(QVariant::fromValue(static_cast<QQuickItem *>(item)));
+ }
+ void surfaceUnmapped() {
+ WaylandSurface *surface = qobject_cast<WaylandSurface *>(sender());
+ QQuickItem *item = surface->surfaceItem();
+ emit windowDestroyed(QVariant::fromValue(item));
}
void surfaceDestroyed(QObject *object) {
- WaylandSurfaceItem *item = m_windowMap.take(object);
- emit windowDestroyed(QVariant::fromValue(static_cast<QQuickItem *>(item)));
+ WaylandSurface *surface = static_cast<WaylandSurface *>(object);
+ QQuickItem *item = surface->surfaceItem();
+ emit windowDestroyed(QVariant::fromValue(item));
}
void frameSwappedSlot() {
@@ -107,11 +102,13 @@ private slots:
protected:
void surfaceCreated(WaylandSurface *surface) {
+ WaylandSurfaceItem *item = new WaylandSurfaceItem(surface, rootObject());
+ 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()));
}
-
-private:
- QMap<QObject *, WaylandSurfaceItem *> m_windowMap;
};
int main(int argc, char *argv[])
diff --git a/examples/qml-compositor/qml-compositor.pro b/examples/qml-compositor/qml-compositor.pro
index 88c4ca021..1414cef3d 100644
--- a/examples/qml-compositor/qml-compositor.pro
+++ b/examples/qml-compositor/qml-compositor.pro
@@ -3,6 +3,8 @@ TARGET = qml-compositor
DEPENDPATH += .
INCLUDEPATH += .
+DEFINES += QT_COMPOSITOR_QUICK
+
# comment out the following to not use pkg-config in the pri files
CONFIG += use_pkgconfig
diff --git a/examples/qwidget-compositor/main.cpp b/examples/qwidget-compositor/main.cpp
index b074735b0..a95eda67f 100644
--- a/examples/qwidget-compositor/main.cpp
+++ b/examples/qwidget-compositor/main.cpp
@@ -47,32 +47,17 @@
#include <QTimer>
#include <QPainter>
#include <QMouseEvent>
+#include <QtCore/QLinkedList>
#ifdef QT_COMPOSITOR_WAYLAND_GL
#include <QOpenGLContext>
#include <QGLWidget>
+#include <QtGui/private/qopengltexturecache_p.h>
+#include "textureblitter.h"
#endif
#include <QDebug>
-//#include "qtouchscreen.h"
-//
-//static int touch_x_min, touch_x_max, touch_y_min, touch_y_max;
-//
-//class QWidgetCompositor;
-//
-//class TouchObserver : public QTouchScreenObserver
-//{
-//public:
-// TouchObserver(QWidgetCompositor *compositor)
-// : m_compositor(compositor) { }
-// void touch_configure(int x_min, int x_max, int y_min, int y_max);
-// void touch_point(QEvent::Type state, const QList<QWindowSystemInterface::TouchPoint> &points);
-//
-//private:
-// QWidgetCompositor *m_compositor;
-//};
-
#ifdef QT_COMPOSITOR_WAYLAND_GL
class QWidgetCompositor : public QGLWidget, public WaylandCompositor
#else
@@ -85,18 +70,19 @@ public:
: WaylandCompositor(windowHandle())
, m_moveSurface(0)
, m_dragSourceSurface(0)
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ , m_surfaceCompositorFbo(0)
+ , m_textureBlitter(0)
+ , m_textureCache(0)
+#endif
{
+ enableSubSurfaceExtension();
setMouseTracking(true);
setRetainedSelectionEnabled(true);
m_background = QImage(QLatin1String("background.jpg"));
//make sure we get the window id and create the glcontext
//so that clients can successfully initialize egl
winId();
-#ifdef QT_COMPOSITOR_WAYLAND_GL
- if (windowHandle()) {
-// windowHandle()->surfaceHandle();
- }
-#endif
}
private slots:
@@ -115,9 +101,8 @@ private slots:
pos = QPoint(px, py);
surface->setGeometry(QRect(pos, surface->geometry().size()));
m_surfaces.append(surface);
- } else {
- surface->setGeometry(QRect(geometry().topLeft(),size));
}
+
setInputFocus(surface);
update();
}
@@ -140,29 +125,113 @@ protected:
}
void surfaceCreated(WaylandSurface *surface) {
- qDebug() << "surface created";
connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *)));
connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped()));
connect(surface, SIGNAL(damaged(const QRect &)), this, SLOT(surfaceDamaged(const QRect &)));
update();
}
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ GLuint composeSurface(WaylandSurface *surface) {
+ GLuint texture = 0;
+
+ if (!m_surfaceCompositorFbo) {
+ glGenFramebuffers(1,&m_surfaceCompositorFbo);
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, m_surfaceCompositorFbo);
+
+ if (surface->type() == WaylandSurface::Shm) {
+ texture = m_textureCache->bindTexture(context()->contextHandle(), surface->image());
+ } else {
+ texture = surface->texture(QOpenGLContext::currentContext());
+ }
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, texture, 0);
+ paintChildren(surface,surface);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, 0, 0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ return texture;
+ }
+
+ void paintChildren(WaylandSurface *surface, WaylandSurface *window) {
+
+ if (surface->subSurfaces().size() == 0)
+ return;
+
+ QLinkedListIterator<WaylandSurface *> i(surface->subSurfaces());
+ while (i.hasNext()) {
+ WaylandSurface *subSurface = i.next();
+ QPoint p = subSurface->mapTo(window,QPoint(0,0));
+ QRect geo = subSurface->geometry();
+ geo.moveTo(p);
+ if (geo.isValid()) {
+ GLuint texture = 0;
+ if (subSurface->type() == WaylandSurface::Texture) {
+ texture = subSurface->texture(QOpenGLContext::currentContext());
+ } else if (surface->type() == WaylandSurface::Shm ) {
+ texture = m_textureCache->bindTexture(context()->contextHandle(), surface->image());
+ }
+ m_textureBlitter->drawTexture(texture,geo,window->geometry().size(),0,window->isYInverted(),subSurface->isYInverted());
+ }
+ paintChildren(subSurface,window);
+ }
+ }
+#else //hmmm, this is actually untested :(
+ QImage composeSurface(WaylandSurface *surface)
+ {
+ Q_ASSER(surface->type() == WaylandSurface::Shm);
+ QImage img = surface->image();
+ QPainter p(&img);
+ paintChildren(surface,p,surface);
+
+ return img;
+ }
+
+ void paintChildren(WaylandSurface *surface, QPainter *painter, WaylandSurface *window) {
+ if (surface->subSurfaces().size() == 0)
+ return;
+
+ QLinkedListIterator<WaylandSurface *> i(surface->subSurfaces());
+ while (i.hasNext()) {
+ WaylandSurface *subSurface = i.next();
+ QPoint p = subSurface->mapTo(window,QPoint(0,0));
+ QRect geo = subSurface->geometry();
+ geo.moveTo(p);
+ if (geo.isValid()) {
+ painter->drawImage(p,subSurface->image());
+ }
+ paintChildren(subSurface,painter,window);
+ }
+ }
+#endif //QT_COMPOSITOR_WAYLAND_GL
+
+
+
void paintEvent(QPaintEvent *) {
QPainter p(this);
if (!m_background.isNull())
p.drawPixmap(rect(), m_backgroundScaled);
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ if (!m_textureCache) {
+ m_textureCache = new QOpenGLTextureCache(context()->contextHandle());
+ }
+ if (!m_textureBlitter) {
+ m_textureBlitter = new TextureBlitter();
+ }
+ m_textureBlitter->bind();
+#endif
for (int i = 0; i < m_surfaces.size(); ++i) {
- if (m_surfaces.at(i)->type() == WaylandSurface::Texture) {
#ifdef QT_COMPOSITOR_WAYLAND_GL
- drawTexture(m_surfaces.at(i)->geometry(), m_surfaces.at(i)->texture(QOpenGLContext::currentContext()));
- break;
+ GLuint texture = composeSurface(m_surfaces.at(i));
+ m_textureBlitter->drawTexture(texture,m_surfaces.at(i)->geometry(),size(),0,false,m_surfaces.at(i)->isYInverted());
+#else
+ QImage img = composeSurface(m_surfaces.at(i));
+ p.drawImage(m_surfaces.at(i)->geometry().topLeft(),img);
#endif //QT_COMPOSITOR_WAYLAND_GL
- } else if (m_surfaces.at(i)->type() == WaylandSurface::Shm) {
- QImage img = m_surfaces.at(i)->image();
- p.drawImage(m_surfaces.at(i)->geometry(), img);
- }
}
if (!m_cursor.isNull())
@@ -173,7 +242,7 @@ protected:
#ifdef QT_COMPOSITOR_WAYLAND_GL
//jl:FIX FIX FIX:)
// update();
- glFinish();
+ m_textureBlitter->release();
#endif
}
@@ -293,6 +362,12 @@ private:
QList<WaylandSurface *> m_surfaces;
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ GLuint m_surfaceCompositorFbo;
+ TextureBlitter *m_textureBlitter;
+ QOpenGLTextureCache *m_textureCache;
+#endif
+
WaylandSurface *m_moveSurface;
QPoint m_moveOffset;
WaylandSurface *m_dragSourceSurface;
@@ -305,53 +380,6 @@ private:
friend class TouchObserver;
};
-//void TouchObserver::touch_configure(int x_min, int x_max, int y_min, int y_max)
-//{
-// touch_x_min = x_min;
-// touch_x_max = x_max;
-// touch_y_min = y_min;
-// touch_y_max = y_max;
-//}
-
-//void TouchObserver::touch_point(QEvent::Type state, const QList<QWindowSystemInterface::TouchPoint> &points)
-//{
-// Q_UNUSED(state);
-// WaylandSurface *focusSurface = m_compositor->inputFocus();
-// if (focusSurface) {
-// if (points.isEmpty())
-// return;
-// for (int i = 0; i < points.count(); ++i) {
-// const QWindowSystemInterface::TouchPoint &point(points.at(i));
-
-// // These are hw coordinates.
-// int x = int(point.area.left());
-// int y = int(point.area.top());
-
-// // Wayland expects surface-relative coordinates.
-
-// // Translate so that (0, 0) is the top-left corner.
-// x = qBound(touch_x_min, x, touch_x_max) - touch_x_min;
-// y = qBound(touch_y_min, y, touch_y_max) - touch_y_min;
-
-// // Get a normalized position in range 0..1.
-// const int hw_w = touch_x_max - touch_x_min;
-// const int hw_h = touch_y_max - touch_y_min;
-// const qreal nx = x / qreal(hw_w);
-// const qreal ny = y / qreal(hw_h);
-
-// // Map to surface.
-// QRect winRect(focusSurface->geometry());
-// x = int(nx * winRect.width());
-// y = int(ny * winRect.height());
-
-// focusSurface->sendTouchPointEvent(point.id,
-// x, y,
-// point.state);
-// }
-// focusSurface->sendTouchFrameEvent();
-// }
-//}
-
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
diff --git a/examples/qwidget-compositor/qwidget-compositor.pro b/examples/qwidget-compositor/qwidget-compositor.pro
index 56379891e..b681fb88b 100644
--- a/examples/qwidget-compositor/qwidget-compositor.pro
+++ b/examples/qwidget-compositor/qwidget-compositor.pro
@@ -11,8 +11,6 @@ CONFIG += use_pkgconfig
# the following line
#include (../../src/qt-compositor/qt-compositor.pri)
-# Input
-SOURCES += main.cpp
CONFIG += qt warn_on debug create_prl link_prl
OBJECTS_DIR = .obj/release-shared
@@ -25,13 +23,15 @@ isEmpty(QT_SOURCE_TREE) {
QTBASE = $$QT_SOURCE_TREE
}
-#TOUCHSCREEN_BASE = $$QTBASE/src/plugins/generic/touchscreen
-#SOURCES += $$TOUCHSCREEN_BASE/qtouchscreen.cpp
-#HEADERS += $$TOUCHSCREEN_BASE/qtouchscreen.h
-#INCLUDEPATH += $$TOUCHSCREEN_BASE
-#LIBS += -ludev -lmtdev
+# Input
+HEADERS += \
+ textureblitter.h
+
+SOURCES += \
+ main.cpp \
+ textureblitter.cpp
-QT += gui-private widgets widgets-private opengl opengl-private compositor
+QT += core-private gui-private widgets widgets-private opengl opengl-private compositor
# install
target.path = $$[QT_INSTALL_EXAMPLES]/qtwayland/qwidget-compositor
diff --git a/examples/qwidget-compositor/textureblitter.cpp b/examples/qwidget-compositor/textureblitter.cpp
new file mode 100644
index 000000000..8fefe48f6
--- /dev/null
+++ b/examples/qwidget-compositor/textureblitter.cpp
@@ -0,0 +1,118 @@
+#include "textureblitter.h"
+
+#include <QtGui/QOpenGLShaderProgram>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFunctions>
+
+TextureBlitter::TextureBlitter()
+ : m_shaderProgram(new QOpenGLShaderProgram())
+{
+ static const char *textureVertexProgram =
+ "uniform highp mat4 matrix;\n"
+ "attribute highp vec3 vertexCoordEntry;\n"
+ "attribute highp vec2 textureCoordEntry;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main() {\n"
+ " textureCoord = textureCoordEntry;\n"
+ " gl_Position = matrix * vec4(vertexCoordEntry, 1);\n"
+ "}\n";
+
+ static const char *textureFragmentProgram =
+ "uniform sampler2D texture;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(texture, textureCoord);\n"
+ "}\n";
+
+ //Enable transparent windows
+ glEnable(GL_BLEND);
+ glBlendFunc (GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
+
+ m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
+ m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
+ m_shaderProgram->link();
+}
+
+
+void TextureBlitter::bind()
+{
+
+ m_shaderProgram->bind();
+
+ m_vertexCoordEntry = m_shaderProgram->attributeLocation("vertexCoordEntry");
+ m_textureCoordEntry = m_shaderProgram->attributeLocation("textureCoordEntry");
+ m_matrixLocation = m_shaderProgram->uniformLocation("matrix");
+}
+
+void TextureBlitter::release()
+{
+ m_shaderProgram->release();
+}
+
+void TextureBlitter::drawTexture(int textureId, const QRectF &targetRect, const QSize &targetSize, int depth, bool targethasInvertedY, bool sourceHasInvertedY)
+{
+
+ glViewport(0,0,targetSize.width(),targetSize.height());
+ GLfloat zValue = depth / 1000.0f;
+ //Set Texture and Vertex coordinates
+ const GLfloat textureCoordinates[] = {
+ 0, 0,
+ 1, 0,
+ 1, 1,
+ 0, 1
+ };
+
+ int x1 = targetRect.left();
+ int x2 = targetRect.right();
+ int y1, y2;
+ if (targethasInvertedY) {
+ if (sourceHasInvertedY) {
+ y1 = targetRect.top();
+ y2 = targetRect.bottom();
+ } else {
+ y1 = targetRect.bottom();
+ y2 = targetRect.top();
+ }
+ } else {
+ if (sourceHasInvertedY) {
+ y1 = targetSize.height() - targetRect.top();
+ y2 = targetSize.height() - targetRect.bottom();
+ } else {
+ y1 = targetSize.height() - targetRect.bottom();
+ y2 = targetSize.height() - targetRect.top();
+ }
+ }
+
+ const GLfloat vertexCoordinates[] = {
+ x1, y1, zValue,
+ x2, y1, zValue,
+ x2, y2, zValue,
+ x1, y2, zValue
+ };
+
+ //Set matrix to transfrom geometry values into gl coordinate space.
+ m_transformMatrix.setToIdentity();
+ m_transformMatrix.scale( 2.0f / targetSize.width(), 2.0f / targetSize.height() );
+ m_transformMatrix.translate(-targetSize.width() / 2.0f, -targetSize.height() / 2.0f);
+
+ //attach the data!
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext();
+ currentContext->functions()->glEnableVertexAttribArray(m_vertexCoordEntry);
+ currentContext->functions()->glEnableVertexAttribArray(m_textureCoordEntry);
+
+ currentContext->functions()->glVertexAttribPointer(m_vertexCoordEntry, 3, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
+ currentContext->functions()->glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
+ m_shaderProgram->setUniformValue(m_matrixLocation, m_transformMatrix);
+
+ glBindTexture(GL_TEXTURE_2D, textureId);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ currentContext->functions()->glDisableVertexAttribArray(m_vertexCoordEntry);
+ currentContext->functions()->glDisableVertexAttribArray(m_textureCoordEntry);
+}
diff --git a/examples/qwidget-compositor/textureblitter.h b/examples/qwidget-compositor/textureblitter.h
new file mode 100644
index 000000000..35d5cffc0
--- /dev/null
+++ b/examples/qwidget-compositor/textureblitter.h
@@ -0,0 +1,28 @@
+#ifndef TEXTUREBLITTER_H
+#define TEXTUREBLITTER_H
+
+#include <QtGui/QMatrix4x4>
+
+#include <QtGui/qopengl.h>
+
+class QOpenGLShaderProgram;
+class TextureBlitter
+{
+public:
+ TextureBlitter();
+ void bind();
+ void release();
+ void drawTexture(int textureId, const QRectF &sourceGeometry,
+ const QSize &targetRect, int depth,
+ bool targethasInvertedY, bool sourceHasInvertedY);
+
+private:
+ QOpenGLShaderProgram *m_shaderProgram;
+ QMatrix4x4 m_transformMatrix;
+
+ int m_matrixLocation;
+ int m_vertexCoordEntry;
+ int m_textureCoordEntry;
+};
+
+#endif // TEXTUREBLITTER_H
diff --git a/examples/qwindow-compositor/qwindow-compositor.pro b/examples/qwindow-compositor/qwindow-compositor.pro
index b3e7ffbc2..3bae92dd6 100644
--- a/examples/qwindow-compositor/qwindow-compositor.pro
+++ b/examples/qwindow-compositor/qwindow-compositor.pro
@@ -9,17 +9,22 @@ CONFIG += use_pkgconfig
LIBS += -L ../../lib
#include (../../src/qt-compositor/qt-compositor.pri)
+HEADERS += \
+ qopenglwindow.h \
+ qwindowcompositor.h \
+ textureblitter.h
+
# Input
SOURCES += main.cpp \
qopenglwindow.cpp \
- surfacerenderer.cpp \
- qwindowcompositor.cpp
+ qwindowcompositor.cpp \
+ textureblitter.cpp
CONFIG += qt warn_on debug create_prl link_prl
OBJECTS_DIR = .obj/release-shared
MOC_DIR = .moc/release-shared
-QT += gui
+QT += gui gui-private core-private
QT += compositor
@@ -28,11 +33,6 @@ QT += compositor
# the following line
#include(../../src/compositor/compositor.pri)
-HEADERS += \
- qopenglwindow.h \
- surfacerenderer.h \
- qwindowcompositor.h
-
RESOURCES += qwindow-compositor.qrc
# install
diff --git a/examples/qwindow-compositor/qwindowcompositor.cpp b/examples/qwindow-compositor/qwindowcompositor.cpp
index 59e181a21..d194a4832 100644
--- a/examples/qwindow-compositor/qwindowcompositor.cpp
+++ b/examples/qwindow-compositor/qwindowcompositor.cpp
@@ -6,16 +6,27 @@
QWindowCompositor::QWindowCompositor(QOpenGLWindow *window)
: WaylandCompositor(window)
, m_window(window)
+ , m_textureBlitter(0)
+ , m_renderScheduler(this)
{
+ enableSubSurfaceExtension();
+ m_window->makeCurrent();
+
+ m_textureCache = new QOpenGLTextureCache(m_window->context());
+ m_textureBlitter = new TextureBlitter();
m_backgroundImage = QImage(QLatin1String(":/background.jpg"));
- m_renderer = new SurfaceRenderer(m_window->context(), m_window);
- m_backgroundTexture = m_renderer->textureFromImage(m_backgroundImage);
+ m_renderScheduler.setSingleShot(true);
+ connect(&m_renderScheduler,SIGNAL(timeout()),this,SLOT(render()));
+
+
+
+ glGenFramebuffers(1,&m_surface_fbo);
window->installEventFilter(this);
setRetainedSelectionEnabled(true);
- render();
+ m_renderScheduler.start(0);
}
void QWindowCompositor::surfaceDestroyed(QObject *object)
@@ -24,7 +35,7 @@ void QWindowCompositor::surfaceDestroyed(QObject *object)
m_surfaces.removeOne(surface);
if (inputFocus() == surface || !inputFocus()) // typically reset to 0 already in Compositor::surfaceDestroyed()
setInputFocus(m_surfaces.isEmpty() ? 0 : m_surfaces.last());
- render();
+ m_renderScheduler.start(0);
}
void QWindowCompositor::surfaceMapped()
@@ -42,7 +53,7 @@ void QWindowCompositor::surfaceMapped()
}
m_surfaces.append(surface);
setInputFocus(surface);
- render();
+ m_renderScheduler.start(0);
}
void QWindowCompositor::surfaceDamaged(const QRect &rect)
@@ -55,7 +66,7 @@ void QWindowCompositor::surfaceDamaged(WaylandSurface *surface, const QRect &rec
{
Q_UNUSED(surface)
Q_UNUSED(rect)
- render();
+ m_renderScheduler.start(0);
}
void QWindowCompositor::surfaceCreated(WaylandSurface *surface)
@@ -63,7 +74,7 @@ void QWindowCompositor::surfaceCreated(WaylandSurface *surface)
connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *)));
connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped()));
connect(surface, SIGNAL(damaged(const QRect &)), this, SLOT(surfaceDamaged(const QRect &)));
- render();
+ m_renderScheduler.start(0);
}
QPointF QWindowCompositor::toSurface(WaylandSurface *surface, const QPointF &pos) const
@@ -83,33 +94,78 @@ WaylandSurface *QWindowCompositor::surfaceAt(const QPoint &point, QPoint *local)
return 0;
}
+GLuint QWindowCompositor::composeSurface(WaylandSurface *surface) {
+ GLuint texture = 0;
+
+ glBindFramebuffer(GL_FRAMEBUFFER, m_surface_fbo);
+
+ if (surface->type() == WaylandSurface::Shm) {
+ texture = m_textureCache->bindTexture(QOpenGLContext::currentContext(),surface->image());
+ } else {
+ texture = surface->texture(QOpenGLContext::currentContext());
+ }
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, texture, 0);
+ paintChildren(surface,surface);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D,0, 0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER,0);
+ return texture;
+}
+
+void QWindowCompositor::paintChildren(WaylandSurface *surface, WaylandSurface *window) {
+
+ if (surface->subSurfaces().size() == 0)
+ return;
+
+ QLinkedListIterator<WaylandSurface *> i(surface->subSurfaces());
+ while (i.hasNext()) {
+ WaylandSurface *subSurface = i.next();
+ QPoint p = subSurface->mapTo(window,QPoint(0,0));
+ QRect geo = subSurface->geometry();
+ geo.moveTo(p);
+ if (geo.isValid()) {
+ GLuint texture = 0;
+ if (subSurface->type() == WaylandSurface::Texture) {
+ texture = subSurface->texture(QOpenGLContext::currentContext());
+ } else if (surface->type() == WaylandSurface::Shm ) {
+ texture = m_textureCache->bindTexture(QOpenGLContext::currentContext(),surface->image());
+ }
+ qDebug() << "window geo is" << window->geometry().size();
+ m_textureBlitter->drawTexture(texture,geo,window->geometry().size(),0,window->isYInverted(),subSurface->isYInverted());
+ }
+ paintChildren(subSurface,window);
+ }
+}
+
+
void QWindowCompositor::render()
{
m_window->makeCurrent();
+ m_backgroundTexture = m_textureCache->bindTexture(QOpenGLContext::currentContext(),m_backgroundImage);
+ m_textureBlitter->bind();
//Draw the background Image texture
int w = m_window->width();
int h = m_window->height();
- int iw = m_backgroundImage.width();
- int ih = m_backgroundImage.height();
- for (int y = 0; y < h; y += ih) {
- for (int x = 0; x < w; x += iw) {
- m_renderer->drawTexture(m_backgroundTexture, QRect(QPoint(x, y), QSize(iw, ih)), 0);
+ QSize imageSize = m_backgroundImage.size();
+ for (int y = 0; y < h; y += imageSize.height()) {
+ for (int x = 0; x < w; x += imageSize.width()) {
+ m_textureBlitter->drawTexture(m_backgroundTexture,QRect(QPoint(x, y),imageSize),window()->size(), 0,true,true);
}
}
- //Iterate all surfaces in m_surfaces
- //If type == WaylandSurface::Texture draw textureId at geometry
foreach (WaylandSurface *surface, m_surfaces) {
- if (surface->type() == WaylandSurface::Texture)
- m_renderer->drawTexture(surface->texture(QOpenGLContext::currentContext()), surface->geometry(), 1); //depth argument should be dynamic (focused should be top).
- else if (surface->type() == WaylandSurface::Shm)
- m_renderer->drawImage(surface->image(), surface->geometry());
+ GLuint texture = composeSurface(surface);
+ m_textureBlitter->drawTexture(texture,surface->geometry(),m_window->size(),0,false,surface->isYInverted());
}
+
+ m_textureBlitter->release();
frameFinished();
glFinish();
+
m_window->swapBuffers();
- m_window->context()->doneCurrent();
}
bool QWindowCompositor::eventFilter(QObject *obj, QEvent *event)
@@ -119,7 +175,7 @@ bool QWindowCompositor::eventFilter(QObject *obj, QEvent *event)
switch (event->type()) {
case QEvent::Expose:
- render();
+ m_renderScheduler.start(0);
break;
case QEvent::MouseButtonPress: {
QPoint local;
@@ -130,7 +186,7 @@ bool QWindowCompositor::eventFilter(QObject *obj, QEvent *event)
setInputFocus(targetSurface);
m_surfaces.removeOne(targetSurface);
m_surfaces.append(targetSurface);
- render();
+ m_renderScheduler.start(0);
}
targetSurface->sendMousePressEvent(local, me->button());
}
diff --git a/examples/qwindow-compositor/qwindowcompositor.h b/examples/qwindow-compositor/qwindowcompositor.h
index 247260406..558451eb9 100644
--- a/examples/qwindow-compositor/qwindowcompositor.h
+++ b/examples/qwindow-compositor/qwindowcompositor.h
@@ -3,9 +3,11 @@
#include "waylandcompositor.h"
#include "waylandsurface.h"
-#include "surfacerenderer.h"
+#include "textureblitter.h"
#include "qopenglwindow.h"
+#include <QtGui/private/qopengltexturecache_p.h>
+
#include <QObject>
class QWindowCompositor : public QObject, public WaylandCompositor
@@ -18,13 +20,16 @@ private slots:
void surfaceMapped();
void surfaceDamaged(const QRect &rect);
+ void render();
protected:
void surfaceDamaged(WaylandSurface *surface, const QRect &rect);
void surfaceCreated(WaylandSurface *surface);
WaylandSurface* surfaceAt(const QPoint &point, QPoint *local = 0);
- void render();
+ GLuint composeSurface(WaylandSurface *surface);
+ void paintChildren(WaylandSurface *surface, WaylandSurface *window);
+
bool eventFilter(QObject *obj, QEvent *event);
QPointF toSurface(WaylandSurface *surface, const QPointF &pos) const;
@@ -34,7 +39,10 @@ private:
QImage m_backgroundImage;
GLuint m_backgroundTexture;
QList<WaylandSurface *> m_surfaces;
- SurfaceRenderer *m_renderer;
+ TextureBlitter *m_textureBlitter;
+ QOpenGLTextureCache *m_textureCache;
+ GLuint m_surface_fbo;
+ QTimer m_renderScheduler;
};
#endif // QWINDOWCOMPOSITOR_H
diff --git a/examples/qwindow-compositor/surfacerenderer.cpp b/examples/qwindow-compositor/surfacerenderer.cpp
deleted file mode 100644
index 31f31419d..000000000
--- a/examples/qwindow-compositor/surfacerenderer.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-#include "surfacerenderer.h"
-
-#include <QOpenGLFunctions>
-#include <QImage>
-
-SurfaceRenderer::SurfaceRenderer(QOpenGLContext *context, QWindow *surface)
- : m_context(context)
- , m_surface(surface)
-{
- const char *textureVertexProgram =
- "uniform highp mat4 matrix;\n"
- "attribute highp vec3 vertexCoordEntry;\n"
- "attribute highp vec2 textureCoordEntry;\n"
- "varying highp vec2 textureCoord;\n"
- "void main() {\n"
- " textureCoord = textureCoordEntry;\n"
- " gl_Position = matrix * vec4(vertexCoordEntry, 1);\n"
- "}\n";
-
- const char *textureFragmentProgram =
- "uniform sampler2D texture;\n"
- "varying highp vec2 textureCoord;\n"
- "void main() {\n"
- " gl_FragColor = texture2D(texture, textureCoord);\n"
- "}\n";
-
- m_context->makeCurrent(m_surface);
-
- //Enable transparent windows
- glEnable(GL_BLEND);
- glBlendFunc (GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
-
- //May need to manually set context here
- m_shaderProgram = new QOpenGLShaderProgram();
-
- m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
- m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
- m_shaderProgram->link();
- m_shaderProgram->bind();
-
- m_vertexCoordEntry = m_shaderProgram->attributeLocation("vertexCoordEntry");
- m_textureCoordEntry = m_shaderProgram->attributeLocation("textureCoordEntry");
- m_matrixLocation = m_shaderProgram->uniformLocation("matrix");
-
-}
-
-void SurfaceRenderer::drawImage(const QImage &image, const QRectF &geometry)
-{
- if (image.isNull())
- return;
- GLuint textureId = textureFromImage(image);
- drawTexture(textureId, geometry);
- glDeleteTextures(1, &textureId);
-}
-
-void SurfaceRenderer::drawTexture(int textureId, const QRectF &geometry, int depth)
-{
- GLfloat zValue = depth / 1000.0f;
- //Set Texture and Vertex coordinates
- GLfloat textureCoordinates[] = { 0, 1,
- 1, 1,
- 1, 0,
- 0, 0
- };
-
- GLfloat vertexCoordinates[] = { geometry.left(), geometry.top(), zValue,
- geometry.right(), geometry.top(), zValue,
- geometry.right(), geometry.bottom(), zValue,
- geometry.left(), geometry.bottom(), zValue
- };
-
- //Set matrix to transfrom geometry values into gl coordinate space.
- m_transformMatrix.setToIdentity();
- m_transformMatrix.scale( 2.0f / m_surface->geometry().width(), -2.0f / m_surface->geometry().height());
- m_transformMatrix.translate(-m_surface->geometry().width() / 2.0f, -m_surface->geometry().height() / 2.0f);
-
- m_shaderProgram->bind();
-
- //attach the data!
- m_context->functions()->glEnableVertexAttribArray(m_vertexCoordEntry);
- m_context->functions()->glEnableVertexAttribArray(m_textureCoordEntry);
-
- m_context->functions()->glVertexAttribPointer(m_vertexCoordEntry, 3, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
- m_context->functions()->glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
- m_shaderProgram->setUniformValue(m_matrixLocation, m_transformMatrix);
-
- glBindTexture(GL_TEXTURE_2D, textureId);
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- glBindTexture(GL_TEXTURE_2D, 0);
-
- m_context->functions()->glDisableVertexAttribArray(m_vertexCoordEntry);
- m_context->functions()->glDisableVertexAttribArray(m_textureCoordEntry);
- m_shaderProgram->release();
-}
-
-static inline QImage convertToGLFormat(const QImage &img)
-{
- QImage dst(img.width(), img.height(), QImage::Format_ARGB32);
- const int width = img.width();
- const int height = img.height();
- const uint *p = (const uint*) img.scanLine(img.height() - 1);
- uint *q = (uint*) dst.scanLine(0);
-
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- for (int i=0; i < height; ++i) {
- const uint *end = p + width;
- while (p < end) {
- *q = (*p << 8) | ((*p >> 24) & 0xff);
- p++;
- q++;
- }
- p -= 2 * width;
- }
- } else {
- for (int i=0; i < height; ++i) {
- const uint *end = p + width;
- while (p < end) {
- *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
- p++;
- q++;
- }
- p -= 2 * width;
- }
- }
-
- return dst;
-}
-
-GLuint SurfaceRenderer::textureFromImage(const QImage &image)
-{
- QImage convertedImage = convertToGLFormat(image);
- GLuint textureId;
- //Copy QImage data to Texture
- glGenTextures(1, &textureId);
- glBindTexture(GL_TEXTURE_2D, textureId);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, convertedImage.width(), convertedImage.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, convertedImage.constBits());
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- return textureId;
-}
diff --git a/examples/qwindow-compositor/surfacerenderer.h b/examples/qwindow-compositor/surfacerenderer.h
deleted file mode 100644
index abfb554b0..000000000
--- a/examples/qwindow-compositor/surfacerenderer.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef SURFACERENDERER_H
-#define SURFACERENDERER_H
-
-#include <QOpenGLContext>
-#include <QOpenGLShaderProgram>
-#include <QWindow>
-
-class SurfaceRenderer
-{
-public:
- SurfaceRenderer(QOpenGLContext *context, QWindow *surface);
-
- void drawImage(const QImage &image, const QRectF &geometry);
- void drawTexture(int textureId, const QRectF &geometry, int depth = 0);
- GLuint textureFromImage(const QImage &image);
-
-private:
-
- QOpenGLContext *m_context;
- QWindow *m_surface;
- QOpenGLShaderProgram *m_shaderProgram;
- QMatrix4x4 m_transformMatrix;
-
- int m_matrixLocation;
- int m_vertexCoordEntry;
- int m_textureCoordEntry;
-};
-
-#endif // SURFACERENDERER_H
diff --git a/examples/qwindow-compositor/textureblitter.cpp b/examples/qwindow-compositor/textureblitter.cpp
new file mode 100644
index 000000000..8fefe48f6
--- /dev/null
+++ b/examples/qwindow-compositor/textureblitter.cpp
@@ -0,0 +1,118 @@
+#include "textureblitter.h"
+
+#include <QtGui/QOpenGLShaderProgram>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFunctions>
+
+TextureBlitter::TextureBlitter()
+ : m_shaderProgram(new QOpenGLShaderProgram())
+{
+ static const char *textureVertexProgram =
+ "uniform highp mat4 matrix;\n"
+ "attribute highp vec3 vertexCoordEntry;\n"
+ "attribute highp vec2 textureCoordEntry;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main() {\n"
+ " textureCoord = textureCoordEntry;\n"
+ " gl_Position = matrix * vec4(vertexCoordEntry, 1);\n"
+ "}\n";
+
+ static const char *textureFragmentProgram =
+ "uniform sampler2D texture;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(texture, textureCoord);\n"
+ "}\n";
+
+ //Enable transparent windows
+ glEnable(GL_BLEND);
+ glBlendFunc (GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
+
+ m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
+ m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
+ m_shaderProgram->link();
+}
+
+
+void TextureBlitter::bind()
+{
+
+ m_shaderProgram->bind();
+
+ m_vertexCoordEntry = m_shaderProgram->attributeLocation("vertexCoordEntry");
+ m_textureCoordEntry = m_shaderProgram->attributeLocation("textureCoordEntry");
+ m_matrixLocation = m_shaderProgram->uniformLocation("matrix");
+}
+
+void TextureBlitter::release()
+{
+ m_shaderProgram->release();
+}
+
+void TextureBlitter::drawTexture(int textureId, const QRectF &targetRect, const QSize &targetSize, int depth, bool targethasInvertedY, bool sourceHasInvertedY)
+{
+
+ glViewport(0,0,targetSize.width(),targetSize.height());
+ GLfloat zValue = depth / 1000.0f;
+ //Set Texture and Vertex coordinates
+ const GLfloat textureCoordinates[] = {
+ 0, 0,
+ 1, 0,
+ 1, 1,
+ 0, 1
+ };
+
+ int x1 = targetRect.left();
+ int x2 = targetRect.right();
+ int y1, y2;
+ if (targethasInvertedY) {
+ if (sourceHasInvertedY) {
+ y1 = targetRect.top();
+ y2 = targetRect.bottom();
+ } else {
+ y1 = targetRect.bottom();
+ y2 = targetRect.top();
+ }
+ } else {
+ if (sourceHasInvertedY) {
+ y1 = targetSize.height() - targetRect.top();
+ y2 = targetSize.height() - targetRect.bottom();
+ } else {
+ y1 = targetSize.height() - targetRect.bottom();
+ y2 = targetSize.height() - targetRect.top();
+ }
+ }
+
+ const GLfloat vertexCoordinates[] = {
+ x1, y1, zValue,
+ x2, y1, zValue,
+ x2, y2, zValue,
+ x1, y2, zValue
+ };
+
+ //Set matrix to transfrom geometry values into gl coordinate space.
+ m_transformMatrix.setToIdentity();
+ m_transformMatrix.scale( 2.0f / targetSize.width(), 2.0f / targetSize.height() );
+ m_transformMatrix.translate(-targetSize.width() / 2.0f, -targetSize.height() / 2.0f);
+
+ //attach the data!
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext();
+ currentContext->functions()->glEnableVertexAttribArray(m_vertexCoordEntry);
+ currentContext->functions()->glEnableVertexAttribArray(m_textureCoordEntry);
+
+ currentContext->functions()->glVertexAttribPointer(m_vertexCoordEntry, 3, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
+ currentContext->functions()->glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
+ m_shaderProgram->setUniformValue(m_matrixLocation, m_transformMatrix);
+
+ glBindTexture(GL_TEXTURE_2D, textureId);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ currentContext->functions()->glDisableVertexAttribArray(m_vertexCoordEntry);
+ currentContext->functions()->glDisableVertexAttribArray(m_textureCoordEntry);
+}
diff --git a/examples/qwindow-compositor/textureblitter.h b/examples/qwindow-compositor/textureblitter.h
new file mode 100644
index 000000000..13b2c6af8
--- /dev/null
+++ b/examples/qwindow-compositor/textureblitter.h
@@ -0,0 +1,26 @@
+#ifndef TEXTUREBLITTER_H
+#define TEXTUREBLITTER_H
+
+#include <QtGui/QMatrix4x4>
+
+class QOpenGLShaderProgram;
+class TextureBlitter
+{
+public:
+ TextureBlitter();
+ void bind();
+ void release();
+ void drawTexture(int textureId, const QRectF &sourceGeometry,
+ const QSize &targetRect, int depth,
+ bool targethasInvertedY, bool sourceHasInvertedY);
+
+private:
+ QOpenGLShaderProgram *m_shaderProgram;
+ QMatrix4x4 m_transformMatrix;
+
+ int m_matrixLocation;
+ int m_vertexCoordEntry;
+ int m_textureCoordEntry;
+};
+
+#endif // TEXTUREBLITTER_H
diff --git a/extensions/sub-surface-extension.xml b/extensions/sub-surface-extension.xml
new file mode 100644
index 000000000..6f9ca07d9
--- /dev/null
+++ b/extensions/sub-surface-extension.xml
@@ -0,0 +1,80 @@
+<!--
+# /****************************************************************************
+# **
+# ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+# ** Contact: Nokia Corporation (qt-info@nokia.com)
+# **
+# ** This file is part of qt-compositor.
+# **
+# ****************************************************************************/
+-->
+<protocol name="sub_surface_extension">
+
+ <copyright>
+ Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ All rights reserved.
+ Contact: Nokia Corporation (qt-info@nokia.com)
+
+ This file is part of the plugins of the Qt Toolkit.
+
+ $QT_BEGIN_LICENSE:LGPL$
+ GNU Lesser General Public License Usage
+ 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, Nokia gives you certain additional
+ rights. These rights are described in the Nokia 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.
+
+ Other Usage
+ Alternatively, this file may be used in accordance with the terms and
+ conditions contained in a signed written agreement between you and Nokia.
+
+
+
+
+
+ $QT_END_LICENSE$
+ </copyright>
+
+ <interface name="wl_sub_surface_extension" version="1">
+ <request name="get_sub_surface_aware_surface">
+ <arg name="id" type="new_id" interface="wl_sub_surface"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ </request>
+ </interface>
+
+ <interface name="wl_sub_surface" version="1">
+ <request name="attach_sub_surface">
+ <arg name="sub_surface" type="object" interface="wl_sub_surface"/>
+ <arg name="x" type="int"/>
+ <arg name="y" type="int"/>
+ </request>
+
+ <request name="move_sub_surface">
+ <arg name="sub_surface" type="object" interface="wl_sub_surface"/>
+ <arg name="x" type="int"/>
+ <arg name="y" type="int"/>
+ </request>
+
+ <request name="raise">
+ <arg name="sub_surface" type="object" interface="wl_sub_surface"/>
+ </request>
+
+ <request name="lower">
+ <arg name="sub_surface" type="object" interface="wl_sub_surface"/>
+ </request>
+ </interface>
+</protocol>
diff --git a/extensions/surface-extension.xml b/extensions/surface-extension.xml
index db150aee4..51850f8bf 100644
--- a/extensions/surface-extension.xml
+++ b/extensions/surface-extension.xml
@@ -66,7 +66,6 @@
<arg name="value" type="array"/>
</event>
- <!-- update generic property from client to server -->
<request name="update_generic_property">
<arg name="name" type="string"/>
<arg name="value" type="array"/>
diff --git a/src/compositor/compositor_api/waylandcompositor.cpp b/src/compositor/compositor_api/waylandcompositor.cpp
index 3f84f7c84..73ddf236f 100644
--- a/src/compositor/compositor_api/waylandcompositor.cpp
+++ b/src/compositor/compositor_api/waylandcompositor.cpp
@@ -186,3 +186,8 @@ void WaylandCompositor::changeCursor(const QImage &image, int hotspotX, int hots
Q_UNUSED(hotspotY);
qDebug() << "changeCursor" << image.size() << hotspotX << hotspotY;
}
+
+void WaylandCompositor::enableSubSurfaceExtension()
+{
+ m_compositor->enableSubSurfaceExtension();
+}
diff --git a/src/compositor/compositor_api/waylandcompositor.h b/src/compositor/compositor_api/waylandcompositor.h
index a38c3df47..b38458577 100644
--- a/src/compositor/compositor_api/waylandcompositor.h
+++ b/src/compositor/compositor_api/waylandcompositor.h
@@ -91,6 +91,8 @@ public:
virtual void changeCursor(const QImage &image, int hotspotX, int hotspotY);
+ void enableSubSurfaceExtension();
+
private:
static void retainedSelectionChanged(QMimeData *mimeData, void *param);
diff --git a/src/compositor/compositor_api/waylandsurface.cpp b/src/compositor/compositor_api/waylandsurface.cpp
index 003a6d451..60d2684ea 100644
--- a/src/compositor/compositor_api/waylandsurface.cpp
+++ b/src/compositor/compositor_api/waylandsurface.cpp
@@ -3,16 +3,35 @@
#include <private/qobject_p.h>
#include "wayland_wrapper/wlsurface.h"
+#include "wayland_wrapper/wlextendedsurface.h"
+#include "wayland_wrapper/wlsubsurface.h"
+
+#ifdef QT_COMPOSITOR_QUICK
+#include "waylandsurfaceitem.h"
+#endif
class WaylandSurfacePrivate : public QObjectPrivate
{
public:
WaylandSurfacePrivate(Wayland::Surface *srfc)
: surface(srfc)
+#ifdef QT_COMPOSITOR_QUICK
+ , surface_item(0)
+#endif
{}
+ ~WaylandSurfacePrivate()
+ {
+#ifdef QT_COMPOSITOR_QUICK
+ if (surface_item)
+ surface_item->setSurface(0);
+#endif
+ }
+
Wayland::Surface *surface;
- QRect geometry;
+#ifdef QT_COMPOSITOR_QUICK
+ WaylandSurfaceItem *surface_item;
+#endif
};
WaylandSurface::WaylandSurface(Wayland::Surface *surface)
@@ -21,6 +40,24 @@ WaylandSurface::WaylandSurface(Wayland::Surface *surface)
}
+WaylandSurface *WaylandSurface::parentSurface() const
+{
+ Q_D(const WaylandSurface);
+ if (d->surface->subSurface()) {
+ return d->surface->subSurface()->parent()->waylandSurface();
+ }
+ return 0;
+}
+
+QLinkedList<WaylandSurface *> WaylandSurface::subSurfaces() const
+{
+ Q_D(const WaylandSurface);
+ if (d->surface->subSurface()) {
+ return d->surface->subSurface()->subSurfaces();
+ }
+ return QLinkedList<WaylandSurface *>();
+}
+
WaylandSurface::Type WaylandSurface::type() const
{
Q_D(const WaylandSurface);
@@ -42,13 +79,13 @@ bool WaylandSurface::visible() const
QRect WaylandSurface::geometry() const
{
Q_D(const WaylandSurface);
- return d->geometry;
+ return d->surface->geometry();
}
void WaylandSurface::setGeometry(const QRect &geometry)
{
Q_D(WaylandSurface);
- d->geometry = geometry;
+ d->surface->setGeometry(geometry);
}
QImage WaylandSurface::image() const
@@ -76,6 +113,20 @@ Wayland::Surface * WaylandSurface::handle() const
return d->surface;
}
+#ifdef QT_COMPOSITOR_QUICK
+WaylandSurfaceItem *WaylandSurface::surfaceItem() const
+{
+ Q_D(const WaylandSurface);
+ return d->surface_item;
+}
+
+void WaylandSurface::setSurfaceItem(WaylandSurfaceItem *surfaceItem)
+{
+ Q_D(WaylandSurface);
+ d->surface_item = surfaceItem;
+}
+#endif //QT_COMPOSITOR_QUICK
+
qint64 WaylandSurface::processId() const
{
Q_D(const WaylandSurface);
@@ -100,6 +151,27 @@ void WaylandSurface::setWindowProperty(const QString &name, const QVariant &valu
d->surface->setWindowProperty(name, value);
}
+QPoint WaylandSurface::mapToParent(const QPoint &pos) const
+{
+ return pos + geometry().topLeft();
+}
+
+QPoint WaylandSurface::mapTo(WaylandSurface *parent, const QPoint &pos) const
+{
+ QPoint p = pos;
+ if (parent) {
+ const WaylandSurface * surface = this;
+ while (surface != parent) {
+ Q_ASSERT_X(surface, "WaylandSurface::mapTo(WaylandSurface *parent, const QPoint &pos)",
+ "parent must be in parent hierarchy");
+ p = surface->mapToParent(p);
+ surface = surface->parentSurface();
+ }
+ }
+ return p;
+
+}
+
void WaylandSurface::sendMousePressEvent(const QPoint &pos, Qt::MouseButton button)
{
Q_D(WaylandSurface);
diff --git a/src/compositor/compositor_api/waylandsurface.h b/src/compositor/compositor_api/waylandsurface.h
index 45c308a6b..89befeafc 100644
--- a/src/compositor/compositor_api/waylandsurface.h
+++ b/src/compositor/compositor_api/waylandsurface.h
@@ -54,15 +54,21 @@
class WaylandSurfacePrivate;
+#ifdef QT_COMPOSITOR_QUICK
+class WaylandSurfaceItem;
+#endif
+
namespace Wayland {
class Surface;
class SurfacePrivate;
+class ExtendedSurface;
}
class Q_COMPOSITOR_EXPORT WaylandSurface : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(WaylandSurface)
+ Q_PROPERTY(QRect geometry READ geometry WRITE setGeometry NOTIFY geometryChanged)
public:
enum Type {
Invalid,
@@ -73,6 +79,9 @@ public:
WaylandSurface(Wayland::Surface *surface);
+ WaylandSurface *parentSurface() const;
+ QLinkedList<WaylandSurface *> subSurfaces() const;
+
Type type() const;
bool isYInverted() const;
@@ -105,19 +114,31 @@ public:
void setInputFocus();
Wayland::Surface *handle() const;
+
+#ifdef QT_COMPOSITOR_QUICK
+ WaylandSurfaceItem *surfaceItem() const;
+ void setSurfaceItem(WaylandSurfaceItem *surfaceItem);
+#endif
+
qint64 processId() const;
QByteArray authenticationToken() const;
QVariantMap windowProperties() const;
void setWindowProperty(const QString &name, const QVariant &value);
+ QPoint mapToParent(const QPoint &) const;
+ QPoint mapTo(WaylandSurface *, const QPoint &) const;
+
signals:
void mapped();
void unmapped();
void damaged(const QRect &rect);
+ void parentChanged(WaylandSurface *newParent, WaylandSurface *oldParent);
+ void geometryChanged();
void windowPropertyChanged(const QString &name, const QVariant &value);
friend class Wayland::Surface;
friend class Wayland::SurfacePrivate;
+ friend class Wayland::ExtendedSurface;
};
#endif // WAYLANDSURFACE_H
diff --git a/src/compositor/compositor_api/waylandsurfaceitem.cpp b/src/compositor/compositor_api/waylandsurfaceitem.cpp
index 67d478432..4d3687ceb 100644
--- a/src/compositor/compositor_api/waylandsurfaceitem.cpp
+++ b/src/compositor/compositor_api/waylandsurfaceitem.cpp
@@ -41,6 +41,9 @@
#include "waylandsurfaceitem.h"
#include "waylandsurface.h"
+#include "wlsurface.h"
+#include "wlextendedsurface.h"
+
#include <QtGui/QKeyEvent>
#include <QtQuick/QSGSimpleTextureNode>
@@ -62,13 +65,6 @@ public:
bool smooth;
};
-void WaylandSurfaceItem::surfaceDamaged(const QRect &)
-{
- m_damaged = true;
- emit textureChanged();
- update();
-}
-
WaylandSurfaceItem::WaylandSurfaceItem(QQuickItem *parent)
: QQuickItem(parent)
, m_surface(0)
@@ -95,7 +91,12 @@ void WaylandSurfaceItem::init(WaylandSurface *surface)
if (!surface)
return;
+ if (m_surface) {
+ m_surface->setSurfaceItem(0);
+ }
+
m_surface = surface;
+ m_surface->setSurfaceItem(this);
setWidth(surface->geometry().width());
setHeight(surface->geometry().height());
@@ -104,8 +105,12 @@ void WaylandSurfaceItem::init(WaylandSurface *surface)
setFlag(ItemHasContents);
setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
connect(surface, SIGNAL(mapped(const QSize &)), this, SLOT(surfaceMapped(const QSize &)));
+ connect(surface, SIGNAL(unmapped()), this, SLOT(surfaceUnmapped()));
connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *)));
connect(surface, SIGNAL(damaged(const QRect &)), this, SLOT(surfaceDamaged(const QRect &)));
+ connect(surface, SIGNAL(parentChanged(WaylandSurface*,WaylandSurface*)),
+ this, SLOT(parentChanged(WaylandSurface*,WaylandSurface*)));
+ connect(surface, SIGNAL(geometryChanged()), this, SLOT(updateGeometry()));
m_damaged = false;
@@ -113,6 +118,9 @@ void WaylandSurfaceItem::init(WaylandSurface *surface)
WaylandSurfaceItem::~WaylandSurfaceItem()
{
+ if (m_surface) {
+ m_surface->setSurfaceItem(0);
+ }
m_texture->deleteLater();
}
@@ -194,10 +202,14 @@ QPoint WaylandSurfaceItem::toSurface(const QPointF &pos) const
return pos.toPoint();
}
-void WaylandSurfaceItem::surfaceMapped(const QSize &size)
+void WaylandSurfaceItem::surfaceMapped(const QSize &)
+{
+ setPaintEnabled(true);
+}
+
+void WaylandSurfaceItem::surfaceUnmapped()
{
- setWidth(size.width());
- setHeight(size.height());
+ setPaintEnabled(false);
}
void WaylandSurfaceItem::surfaceDestroyed(QObject *)
@@ -205,6 +217,34 @@ void WaylandSurfaceItem::surfaceDestroyed(QObject *)
m_surface = 0;
}
+void WaylandSurfaceItem::surfaceDamaged(const QRect &)
+{
+ m_damaged = true;
+ emit textureChanged();
+ update();
+}
+
+void WaylandSurfaceItem::parentChanged(WaylandSurface *newParent, WaylandSurface *oldParent)
+{
+ Q_UNUSED(oldParent);
+
+ WaylandSurfaceItem *item = newParent? newParent->surfaceItem():0;
+ setParentItem(item);
+
+ if (newParent) {
+ setPaintEnabled(true);
+ setVisible(true);
+ setOpacity(1);
+ setEnabled(true);
+ }
+}
+
+void WaylandSurfaceItem::updateGeometry()
+{
+ setPos(m_surface->geometry().topLeft());
+ setSize(m_surface->geometry().size());
+}
+
bool WaylandSurfaceItem::paintEnabled() const
{
return m_paintEnabled;
@@ -218,9 +258,10 @@ void WaylandSurfaceItem::setPaintEnabled(bool enabled)
QSGNode *WaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
- if (!m_surface)
+ if (!m_surface) {
+ delete oldNode;
return 0;
- QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode);
+ }
if (m_damaged) {
QSGTexture *oldTexture = m_texture;
@@ -234,6 +275,7 @@ QSGNode *WaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
} else {
m_texture = canvas()->createTextureFromImage(m_surface->image());
}
+
delete oldTexture;
m_damaged = false;
}
@@ -243,6 +285,7 @@ QSGNode *WaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
m_provider->smooth = smooth();
}
+ QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode);
if (!m_texture || !m_paintEnabled) {
delete oldNode;
return 0;
diff --git a/src/compositor/compositor_api/waylandsurfaceitem.h b/src/compositor/compositor_api/waylandsurfaceitem.h
index a66a2cead..e08cda3ba 100644
--- a/src/compositor/compositor_api/waylandsurfaceitem.h
+++ b/src/compositor/compositor_api/waylandsurfaceitem.h
@@ -100,8 +100,11 @@ public slots:
private slots:
void surfaceMapped(const QSize &size);
+ void surfaceUnmapped();
void surfaceDestroyed(QObject *object);
void surfaceDamaged(const QRect &);
+ void parentChanged(WaylandSurface *newParent, WaylandSurface *oldParent);
+ void updateGeometry();
signals:
void textureChanged();
diff --git a/src/compositor/wayland_wrapper/wayland_wrapper.pri b/src/compositor/wayland_wrapper/wayland_wrapper.pri
index cf841f914..6340f5c3f 100644
--- a/src/compositor/wayland_wrapper/wayland_wrapper.pri
+++ b/src/compositor/wayland_wrapper/wayland_wrapper.pri
@@ -1,5 +1,6 @@
WAYLANDSOURCES += \
$$PWD/../../../extensions/surface-extension.xml \
+ $$PWD/../../../extensions/sub-surface-extension.xml \
$$PWD/../../../extensions/output-extension.xml
@@ -16,7 +17,8 @@ HEADERS += \
$$PWD/wldataoffer.h \
$$PWD/wldatasource.h \
$$PWD/wlextendedsurface.h \
- $$PWD/wlextendedoutput.h
+ $$PWD/wlextendedoutput.h \
+ $$PWD/wlsubsurface.h
SOURCES += \
$$PWD/wlcompositor.cpp \
@@ -31,5 +33,6 @@ SOURCES += \
$$PWD/wldataoffer.cpp \
$$PWD/wldatasource.cpp \
$$PWD/wlextendedsurface.cpp \
- $$PWD/wlextendedoutput.cpp
+ $$PWD/wlextendedoutput.cpp \
+ $$PWD/wlsubsurface.cpp
diff --git a/src/compositor/wayland_wrapper/wlcompositor.cpp b/src/compositor/wayland_wrapper/wlcompositor.cpp
index abfcac63f..b998c9120 100644
--- a/src/compositor/wayland_wrapper/wlcompositor.cpp
+++ b/src/compositor/wayland_wrapper/wlcompositor.cpp
@@ -49,6 +49,7 @@
#include "wldatadevice.h"
#include "wlextendedoutput.h"
#include "wlextendedsurface.h"
+#include "wlsubsurface.h"
#include <QWindow>
#include <QSocketNotifier>
@@ -120,6 +121,7 @@ Compositor::Compositor(WaylandCompositor *qt_compositor)
, m_retainNotify(0)
, m_outputExtension(0)
, m_surfaceExtension(0)
+ , m_subSurfaceExtension(0)
{
compositor = this;
qDebug() << "Compositor instance is" << this;
@@ -339,6 +341,13 @@ void Compositor::initializeWindowManagerProtocol()
m_windowManagerIntegration->initialize(m_display);
}
+void Compositor::enableSubSurfaceExtension()
+{
+ if (!m_subSurfaceExtension) {
+ m_subSurfaceExtension = new SubSurfaceExtensionGlobal(this);
+ }
+}
+
bool Compositor::setDirectRenderSurface(Surface *surface)
{
#ifdef QT_COMPOSITOR_WAYLAND_GL
diff --git a/src/compositor/wayland_wrapper/wlcompositor.h b/src/compositor/wayland_wrapper/wlcompositor.h
index 4404ff81e..a26e23aab 100644
--- a/src/compositor/wayland_wrapper/wlcompositor.h
+++ b/src/compositor/wayland_wrapper/wlcompositor.h
@@ -64,6 +64,7 @@ class InputDevice;
class DataDeviceManager;
class OutputExtensionGlobal;
class SurfaceExtensionGlobal;
+class SubSurfaceExtensionGlobal;
class Q_COMPOSITOR_EXPORT Compositor : public QObject
{
@@ -100,6 +101,7 @@ public:
GraphicsHardwareIntegration *graphicsHWIntegration() const;
void initializeHardwareIntegration();
void initializeWindowManagerProtocol();
+ void enableSubSurfaceExtension();
bool setDirectRenderSurface(Surface *surface);
Surface *directRenderSurface() const {return m_directRenderSurface;}
@@ -181,6 +183,7 @@ private:
OutputExtensionGlobal *m_outputExtension;
SurfaceExtensionGlobal *m_surfaceExtension;
+ SubSurfaceExtensionGlobal *m_subSurfaceExtension;
static void bind_func(struct wl_client *client, void *data,
uint32_t version, uint32_t id);
diff --git a/src/compositor/wayland_wrapper/wlextendedsurface.cpp b/src/compositor/wayland_wrapper/wlextendedsurface.cpp
index 85bdd8e33..68f6d0573 100644
--- a/src/compositor/wayland_wrapper/wlextendedsurface.cpp
+++ b/src/compositor/wayland_wrapper/wlextendedsurface.cpp
@@ -87,6 +87,11 @@ ExtendedSurface::ExtendedSurface(struct wl_client *client, uint32_t id, Surface
this);
}
+ExtendedSurface::~ExtendedSurface()
+{
+
+}
+
void ExtendedSurface::sendGenericProperty(const char *name, const QVariant &variant)
{
QByteArray byteValue;
@@ -106,6 +111,7 @@ void ExtendedSurface::sendOnScreenVisibllity(bool visible)
wl_resource_post_event(m_extended_surface_resource,WL_EXTENDED_SURFACE_ONSCREEN_VISIBILITY,visibleInt);
}
+
void ExtendedSurface::update_generic_property(wl_client *client, wl_resource *extended_surface_resource, const char *name, wl_array *value)
{
Q_UNUSED(client);
diff --git a/src/compositor/wayland_wrapper/wlextendedsurface.h b/src/compositor/wayland_wrapper/wlextendedsurface.h
index d32289615..46dc03c18 100644
--- a/src/compositor/wayland_wrapper/wlextendedsurface.h
+++ b/src/compositor/wayland_wrapper/wlextendedsurface.h
@@ -43,12 +43,16 @@
#include "wayland-surface-extension-server-protocol.h"
+#include "wlsurface.h"
+
#include <QtCore/QVariant>
+#include <QtCore/QLinkedList>
+
+class WaylandSurface;
namespace Wayland {
class Compositor;
-class Surface;
class SurfaceExtensionGlobal
{
@@ -72,10 +76,17 @@ class ExtendedSurface
{
public:
ExtendedSurface(struct wl_client *client, uint32_t id, Surface *surface);
+ ~ExtendedSurface();
void sendGenericProperty(const char *name, const QVariant &variant);
void sendOnScreenVisibllity(bool visible);
+ void setSubSurface(ExtendedSurface *subSurface,int x, int y);
+ void removeSubSurface(ExtendedSurface *subSurfaces);
+ ExtendedSurface *parent() const;
+ void setParent(ExtendedSurface *parent);
+ QLinkedList<WaylandSurface *> subSurfaces() const;
+
private:
struct wl_resource *m_extended_surface_resource;
Surface *m_surface;
@@ -84,6 +95,17 @@ private:
struct wl_resource *resource,
const char *name,
struct wl_array *value);
+ static void map_sub_surface(struct wl_client *client,
+ struct wl_resource *extended_surface_resource,
+ struct wl_resource *sub_surface_resource,
+ int32_t x,
+ int32_t y);
+ static void move_sub_surface(struct wl_client *client,
+ struct wl_resource *extended_surface_resource,
+ struct wl_resource *sub_surface_resource,
+ int32_t x,
+ int32_t y);
+
static const struct wl_extended_surface_interface extended_surface_interface;
};
diff --git a/src/compositor/wayland_wrapper/wlsubsurface.cpp b/src/compositor/wayland_wrapper/wlsubsurface.cpp
new file mode 100644
index 000000000..e8b8ab6e3
--- /dev/null
+++ b/src/compositor/wayland_wrapper/wlsubsurface.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** This file is part of QtCompositor**
+**
+** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+**
+** Contact: Nokia Corporation qt-info@nokia.com
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**
+** Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+#include "wlsubsurface.h"
+
+#include "wlcompositor.h"
+
+namespace Wayland {
+
+SubSurfaceExtensionGlobal::SubSurfaceExtensionGlobal(Compositor *compositor)
+ : m_compositor(compositor)
+{
+ wl_display_add_global(m_compositor->wl_display(),
+ &wl_sub_surface_extension_interface,
+ this,
+ SubSurfaceExtensionGlobal::bind_func);
+}
+
+void SubSurfaceExtensionGlobal::bind_func(wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+ Q_UNUSED(version);
+ wl_client_add_object(client, &wl_sub_surface_extension_interface,&sub_surface_extension_interface,id,data);
+}
+
+void SubSurfaceExtensionGlobal::get_sub_surface_aware_surface(wl_client *client, wl_resource *sub_surface_extension_resource, uint32_t id, wl_resource *surface_resource)
+{
+ Q_UNUSED(sub_surface_extension_resource);
+ Surface *surface = reinterpret_cast<Surface *>(surface_resource);
+ new SubSurface(client,id,surface);
+}
+
+const struct wl_sub_surface_extension_interface SubSurfaceExtensionGlobal::sub_surface_extension_interface = {
+ SubSurfaceExtensionGlobal::get_sub_surface_aware_surface
+};
+
+SubSurface::SubSurface(wl_client *client, uint32_t id, Surface *surface)
+ : m_surface(surface)
+ , m_parent(0)
+{
+ surface->setSubSurface(this);
+ m_sub_surface_resource = wl_client_add_object(client,
+ &wl_sub_surface_interface,
+ &sub_surface_interface,
+ id,
+ this);
+}
+
+SubSurface::~SubSurface()
+{
+ if (m_parent) {
+ m_parent->removeSubSurface(this);
+ }
+}
+
+void SubSurface::setSubSurface(SubSurface *subSurface, int x, int y)
+{
+// Q_ASSERT(!m_sub_surfaces.contains(subSurface->m_surface->handle()));
+ m_sub_surfaces.append(subSurface->m_surface->handle());
+ subSurface->setParent(this);
+ QRect rect = m_surface->geometry();
+ rect.moveTo(x,y);
+ subSurface->m_surface->setGeometry(rect);
+}
+
+void SubSurface::removeSubSurface(SubSurface *subSurfaces)
+{
+ Q_ASSERT(m_sub_surfaces.contains(subSurfaces->m_surface->handle()));
+ m_sub_surfaces.removeOne(subSurfaces->m_surface->handle());
+}
+
+SubSurface *SubSurface::parent() const
+{
+ return m_parent;
+}
+
+void SubSurface::setParent(SubSurface *parent)
+{
+ if (m_parent == parent)
+ return;
+
+ WaylandSurface *oldParent = 0;
+ WaylandSurface *newParent = 0;
+
+ if (m_parent) {
+ oldParent = m_parent->m_surface->handle();
+ m_parent->removeSubSurface(this);
+ }
+ if (parent) {
+ newParent = parent->m_surface->handle();
+ }
+ m_parent = parent;
+
+ m_surface->handle()->parentChanged(newParent,oldParent);
+}
+
+QLinkedList<WaylandSurface *> SubSurface::subSurfaces() const
+{
+ return m_sub_surfaces;
+}
+
+void SubSurface::attach_sub_surface(wl_client *client, wl_resource *sub_surface_parent_resource, wl_resource *sub_surface_child_resource, int32_t x, int32_t y)
+{
+ Q_UNUSED(client);
+ SubSurface *parent_sub_surface = static_cast<SubSurface *>(sub_surface_parent_resource->data);
+ SubSurface *child_sub_surface = static_cast<SubSurface *>(sub_surface_child_resource->data);
+ parent_sub_surface->setSubSurface(child_sub_surface,x,y);
+}
+
+void SubSurface::move_sub_surface(wl_client *client, wl_resource *sub_surface_parent_resource, wl_resource *sub_surface_child_resource, int32_t x, int32_t y)
+{
+ Q_UNUSED(client);
+ SubSurface *parent_sub_surface = static_cast<SubSurface *>(sub_surface_parent_resource->data);
+ SubSurface *child_sub_surface = static_cast<SubSurface *>(sub_surface_child_resource->data);
+}
+
+void SubSurface::raise(wl_client *client, wl_resource *sub_surface_parent_resource, wl_resource *sub_surface_child_resource)
+{
+}
+
+void SubSurface::lower(wl_client *client, wl_resource *sub_surface_parent_resource, wl_resource *sub_surface_child_resource)
+{
+}
+
+const struct wl_sub_surface_interface SubSurface::sub_surface_interface = {
+ SubSurface::attach_sub_surface,
+ SubSurface::move_sub_surface,
+ SubSurface::raise,
+ SubSurface::lower
+};
+
+}
diff --git a/src/compositor/wayland_wrapper/wlsubsurface.h b/src/compositor/wayland_wrapper/wlsubsurface.h
new file mode 100644
index 000000000..947cd02ca
--- /dev/null
+++ b/src/compositor/wayland_wrapper/wlsubsurface.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** This file is part of QtCompositor**
+**
+** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+**
+** Contact: Nokia Corporation qt-info@nokia.com
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**
+** Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+#ifndef WLSUBSURFACE_H
+#define WLSUBSURFACE_H
+
+#include "wlsurface.h"
+
+#include "wayland-sub-surface-extension-server-protocol.h"
+
+#include <QtCore/QLinkedList>
+
+class Compositor;
+class WaylandSurface;
+
+namespace Wayland {
+
+class SubSurfaceExtensionGlobal
+{
+public:
+ SubSurfaceExtensionGlobal(Compositor *compositor);
+
+private:
+ Compositor *m_compositor;
+
+ static void bind_func(struct wl_client *client, void *data,
+ uint32_t version, uint32_t id);
+ static void get_sub_surface_aware_surface(struct wl_client *client,
+ struct wl_resource *sub_surface_extension_resource,
+ uint32_t id,
+ struct wl_resource *surface_resource);
+
+ static const struct wl_sub_surface_extension_interface sub_surface_extension_interface;
+};
+
+class SubSurface
+{
+public:
+ SubSurface(struct wl_client *client, uint32_t id, Surface *surface);
+ ~SubSurface();
+
+ void setSubSurface(SubSurface *subSurface, int x, int y);
+ void removeSubSurface(SubSurface *subSurfaces);
+
+ SubSurface *parent() const;
+ void setParent(SubSurface *parent);
+
+ QLinkedList<WaylandSurface *> subSurfaces() const;
+
+ Surface *surface() const;
+ WaylandSurface *waylandSurface() const;
+
+private:
+ struct wl_resource *m_sub_surface_resource;
+ Surface *m_surface;
+
+ SubSurface *m_parent;
+ QLinkedList<WaylandSurface *> m_sub_surfaces;
+
+ static void attach_sub_surface(struct wl_client *client,
+ struct wl_resource *sub_surface_parent_resource,
+ struct wl_resource *sub_surface_child_resource,
+ int32_t x,
+ int32_t y);
+ static void move_sub_surface(struct wl_client *client,
+ struct wl_resource *sub_surface_parent_resource,
+ struct wl_resource *sub_surface_child_resource,
+ int32_t x,
+ int32_t y);
+ static void raise(struct wl_client *client,
+ struct wl_resource *sub_surface_parent_resource,
+ struct wl_resource *sub_surface_child_resource);
+ static void lower(struct wl_client *client,
+ struct wl_resource *sub_surface_parent_resource,
+ struct wl_resource *sub_surface_child_resource);
+ static const struct wl_sub_surface_interface sub_surface_interface;
+};
+
+inline Surface *SubSurface::surface() const
+{
+ return m_surface;
+}
+
+inline WaylandSurface *SubSurface::waylandSurface() const
+{
+ return m_surface->handle();
+}
+
+
+}
+
+#endif // WLSUBSURFACE_H
diff --git a/src/compositor/wayland_wrapper/wlsurface.cpp b/src/compositor/wayland_wrapper/wlsurface.cpp
index 21f2d3167..30b0bd09c 100644
--- a/src/compositor/wayland_wrapper/wlsurface.cpp
+++ b/src/compositor/wayland_wrapper/wlsurface.cpp
@@ -46,6 +46,7 @@
#include "wlshmbuffer.h"
#include "wlinputdevice.h"
#include "wlextendedsurface.h"
+#include "wlsubsurface.h"
#include <QtCore/QDebug>
@@ -203,11 +204,13 @@ public:
: q_ptr(surface)
, client(client)
, compositor(compositor)
+ , qtSurface(new WaylandSurface(surface))
, directRenderBuffer(0)
, processId(0)
, textureBuffer(0)
, surfaceBuffer(0)
, extendedSurface(0)
+ , subSurface(0)
{
@@ -236,8 +239,11 @@ public:
struct wl_list frame_callback_list;
ExtendedSurface *extendedSurface;
+ SubSurface *subSurface;
SurfaceBuffer bufferPool[buffer_pool_size];
+
+ QRect geometry;
private:
Surface *q_ptr;
};
@@ -278,7 +284,7 @@ Surface::Surface(struct wl_client *client, Compositor *compositor)
: d_ptr(new SurfacePrivate(this,client,compositor))
{
base()->resource.client = client;
- d_ptr->qtSurface = new WaylandSurface(this);
+
}
Surface::~Surface()
@@ -309,6 +315,9 @@ bool Surface::isYInverted() const
#ifdef QT_COMPOSITOR_WAYLAND_GL
Q_D(const Surface);
+ if (!d->surfaceBuffer)
+ return false;
+
if (d->compositor->graphicsHWIntegration() && !d->surfaceBuffer->bufferIsDestroyed()) {
if (type() == WaylandSurface::Texture) {
return d->compositor->graphicsHWIntegration()->isYInverted(d->surfaceBuffer->handle());
@@ -368,11 +377,31 @@ QImage Surface::image() const
return QImage();
}
+QRect Surface::geometry() const
+{
+ Q_D(const Surface);
+ return d->geometry;
+}
+
+void Surface::setGeometry(const QRect &rect)
+{
+ Q_D(Surface);
+ bool emitChange = false;
+ if (rect != d->geometry)
+ emitChange = true;
+ d->geometry = rect;
+ if (emitChange)
+ d->qtSurface->geometryChanged();
+}
+
#ifdef QT_COMPOSITOR_WAYLAND_GL
GLuint Surface::textureId(QOpenGLContext *context) const
{
Q_D(const Surface);
+ if (!d->surfaceBuffer) {
+ return 0;
+ }
if (d->compositor->graphicsHWIntegration() && type() == WaylandSurface::Texture
&& !d->surfaceBuffer->textureCreated()) {
Surface *that = const_cast<Surface *>(this);
@@ -408,7 +437,7 @@ void Surface::attach(struct wl_buffer *buffer)
Q_ASSERT(newBuffer);
}
- bool emitMap = !d->surfaceBuffer && buffer;
+ bool emitMap = !d->surfaceBuffer && buffer && (!d->subSurface || !d->subSurface->parent());
bool emitUnmap = d->surfaceBuffer && !buffer;
if (d->surfaceBuffer && d->surfaceBuffer != d->directRenderBuffer) {
@@ -418,6 +447,17 @@ void Surface::attach(struct wl_buffer *buffer)
d->surfaceBuffer = 0;
}
d->surfaceBuffer = newBuffer;
+ int width = 0;
+ int height = 0;
+ if (d->surfaceBuffer) {
+ width = d->surfaceBuffer->width();
+ height = d->surfaceBuffer->height();
+ }
+ QRect geo = geometry();
+ geo.setWidth(width);
+ geo.setHeight(height);
+ setGeometry(geo);
+
if (emitMap) {
d->qtSurface->mapped();
} else if (emitUnmap) {
@@ -515,6 +555,18 @@ ExtendedSurface *Surface::extendedSurface() const
return d->extendedSurface;
}
+void Surface::setSubSurface(SubSurface *subSurface)
+{
+ Q_D(Surface);
+ d->subSurface = subSurface;
+}
+
+SubSurface *Surface::subSurface() const
+{
+ Q_D(const Surface);
+ return d->subSurface;
+}
+
void Surface::sendMousePressEvent(int x, int y, Qt::MouseButton button)
{
Q_D(Surface);
diff --git a/src/compositor/wayland_wrapper/wlsurface.h b/src/compositor/wayland_wrapper/wlsurface.h
index 425e3ce88..905ee535e 100644
--- a/src/compositor/wayland_wrapper/wlsurface.h
+++ b/src/compositor/wayland_wrapper/wlsurface.h
@@ -64,6 +64,7 @@ namespace Wayland {
class Compositor;
class Buffer;
class ExtendedSurface;
+class SubSurface;
class SurfacePrivate;
@@ -83,6 +84,9 @@ public:
QImage image() const;
+ QRect geometry() const;
+ void setGeometry(const QRect &rect);
+
#ifdef QT_COMPOSITOR_WAYLAND_GL
GLuint textureId(QOpenGLContext *context) const;
#endif
@@ -121,6 +125,9 @@ public:
void setExtendedSurface(ExtendedSurface *extendedSurface);
ExtendedSurface *extendedSurface() const;
+ void setSubSurface(SubSurface *subSurface);
+ SubSurface *subSurface() const;
+
static const struct wl_surface_interface surface_interface;
protected:
QScopedPointer<SurfacePrivate> d_ptr;
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
index 0d6287722..3f160b794 100644
--- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp
+++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
@@ -59,6 +59,7 @@
#include "qwaylandextendedoutput.h"
#include "qwaylandextendedsurface.h"
+#include "qwaylandsubsurface.h"
#include <QtCore/QAbstractEventDispatcher>
#include <QtGui/private/qguiapplication_p.h>
@@ -306,6 +307,8 @@ void QWaylandDisplay::displayHandleGlobal(uint32_t id,
mOutputExtension = new QWaylandOutputExtension(this,id);
} else if (interface == "wl_surface_extension") {
mWindowExtension = new QWaylandSurfaceExtension(this,id);
+ } else if (interface == "wl_sub_surface_extension") {
+ mSubSurfaceExtension = new QWaylandSubSurfaceExtension(this,id);
}
}
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.h b/src/plugins/platforms/wayland/qwaylanddisplay.h
index cce0486c9..416379921 100644
--- a/src/plugins/platforms/wayland/qwaylanddisplay.h
+++ b/src/plugins/platforms/wayland/qwaylanddisplay.h
@@ -60,6 +60,7 @@ class QWaylandWindowManagerIntegration;
class QWaylandDataDeviceManager;
class QWaylandShell;
class QWaylandSurfaceExtension;
+class QWaylandSubSurfaceExtension;
class QWaylandOutputExtension;
class QWaylandDisplay : public QObject {
@@ -97,6 +98,7 @@ public:
QWaylandDataDeviceManager *dndSelectionHandler() const { return mDndSelectionHandler; }
QWaylandSurfaceExtension *windowExtension() const { return mWindowExtension; }
+ QWaylandSubSurfaceExtension *subSurfaceExtension() const { return mSubSurfaceExtension; }
QWaylandOutputExtension *outputExtension() const { return mOutputExtension; }
struct wl_shm *shm() const { return mShm; }
@@ -125,6 +127,7 @@ private:
QWaylandInputDevice *mLastKeyboardFocusInputDevice;
QWaylandDataDeviceManager *mDndSelectionHandler;
QWaylandSurfaceExtension *mWindowExtension;
+ QWaylandSubSurfaceExtension *mSubSurfaceExtension;
QWaylandOutputExtension *mOutputExtension;
QSocketNotifier *mReadNotifier;
diff --git a/src/plugins/platforms/wayland/qwaylandextendedsurface.h b/src/plugins/platforms/wayland/qwaylandextendedsurface.h
index 10d17b9bf..c17df8492 100644
--- a/src/plugins/platforms/wayland/qwaylandextendedsurface.h
+++ b/src/plugins/platforms/wayland/qwaylandextendedsurface.h
@@ -70,6 +70,7 @@ public:
QVariantMap properties() const;
QVariant property(const QString &name);
QVariant property(const QString &name, const QVariant &defaultValue);
+
private:
QWaylandWindow *m_window;
struct wl_extended_surface *m_extended_surface;
diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
index 42e0416e0..da9031b5d 100644
--- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
+++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp
@@ -130,7 +130,6 @@ void QWaylandShmBackingStore::flush(QWindow *window, const QRegion &region, cons
void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &)
{
QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->handle());
- Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm);
QImage::Format format = QPlatformScreen::platformScreenForWindow(window())->format();
diff --git a/src/plugins/platforms/wayland/qwaylandsubsurface.cpp b/src/plugins/platforms/wayland/qwaylandsubsurface.cpp
new file mode 100644
index 000000000..13d8c99b6
--- /dev/null
+++ b/src/plugins/platforms/wayland/qwaylandsubsurface.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandsubsurface.h"
+
+#include "qwaylandwindow.h"
+
+#include "wayland-sub-surface-extension-client-protocol.h"
+
+QWaylandSubSurfaceExtension::QWaylandSubSurfaceExtension(QWaylandDisplay *display, uint32_t id)
+{
+ m_sub_surface_extension = static_cast<struct wl_sub_surface_extension *>(
+ wl_display_bind(display->wl_display(),id, &wl_sub_surface_extension_interface));
+}
+
+QWaylandSubSurface *QWaylandSubSurfaceExtension::getSubSurfaceAwareWindow(QWaylandWindow *window)
+{
+ struct wl_surface *surface = window->wl_surface();
+ Q_ASSERT(surface);
+ struct wl_sub_surface *sub_surface =
+ wl_sub_surface_extension_get_sub_surface_aware_surface(m_sub_surface_extension,surface);
+
+ return new QWaylandSubSurface(window,sub_surface);
+
+}
+
+QWaylandSubSurface::QWaylandSubSurface(QWaylandWindow *window, struct wl_sub_surface *sub_surface)
+ : m_window(window)
+ , m_sub_surface(sub_surface)
+{
+}
+
+void QWaylandSubSurface::setParent(const QWaylandWindow *parent)
+{
+ QWaylandSubSurface *parentSurface = parent? parent->subSurfaceWindow():0;
+ if (parentSurface) {
+ int x = m_window->geometry().x();
+ int y = m_window->geometry().y();
+ wl_sub_surface_attach_sub_surface(parentSurface->m_sub_surface,m_sub_surface,x,y);
+ }
+}
diff --git a/src/plugins/platforms/wayland/qwaylandsubsurface.h b/src/plugins/platforms/wayland/qwaylandsubsurface.h
new file mode 100644
index 000000000..5c8b2b254
--- /dev/null
+++ b/src/plugins/platforms/wayland/qwaylandsubsurface.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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, Nokia gives you certain additional
+** rights. These rights are described in the Nokia 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDSUBSURFACE_H
+#define QWAYLANDSUBSURFACE_H
+
+class QWaylandDisplay;
+class QWaylandWindow;
+class QWaylandSubSurface;
+
+#include <wayland-client.h>
+
+class QWaylandSubSurfaceExtension
+{
+public:
+ QWaylandSubSurfaceExtension(QWaylandDisplay *display, uint32_t id);
+
+ QWaylandSubSurface *getSubSurfaceAwareWindow(QWaylandWindow *window);
+private:
+ struct wl_sub_surface_extension *m_sub_surface_extension;
+};
+
+class QWaylandSubSurface
+{
+public:
+ QWaylandSubSurface(QWaylandWindow *window, struct wl_sub_surface *sub_surface);
+
+ void setParent(const QWaylandWindow *parent);
+
+private:
+ QWaylandWindow *m_window;
+ struct wl_sub_surface *m_sub_surface;
+};
+
+#endif // QWAYLANDSUBSURFACE_H
diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp
index 73ed85096..9e45831b2 100644
--- a/src/plugins/platforms/wayland/qwaylandwindow.cpp
+++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp
@@ -55,18 +55,18 @@
#endif
#include "qwaylandextendedsurface.h"
+#include "qwaylandsubsurface.h"
#include <QCoreApplication>
#include <QtGui/QWindowSystemInterface>
-#include <QDebug>
-
QWaylandWindow::QWaylandWindow(QWindow *window)
: QPlatformWindow(window)
, mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display())
, mSurface(mDisplay->createSurface(this))
, mShellSurface(mDisplay->shell()->createShellSurface(this))
, mExtendedWindow(0)
+ , mSubSurfaceWindow(0)
, mBuffer(0)
, mWaitingForFrameSync(false)
, mFrameCallback(0)
@@ -76,14 +76,19 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
if (mDisplay->windowExtension())
mExtendedWindow = mDisplay->windowExtension()->getExtendedWindow(this);
+ if (mDisplay->subSurfaceExtension())
+ mSubSurfaceWindow = mDisplay->subSurfaceExtension()->getSubSurfaceAwareWindow(this);
#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
mDisplay->windowManagerIntegration()->mapClientToProcess(qApp->applicationPid());
mDisplay->windowManagerIntegration()->authenticateWithToken();
#endif
- //all surfaces are toplevel surfaces for now
- wl_shell_surface_set_toplevel(mShellSurface->handle());
+ if (parent() && mSubSurfaceWindow) {
+ mSubSurfaceWindow->setParent(static_cast<const QWaylandWindow *>(parent()));
+ } else {
+ wl_shell_surface_set_toplevel(mShellSurface->handle());
+ }
}
QWaylandWindow::~QWaylandWindow()
@@ -106,8 +111,10 @@ WId QWaylandWindow::winId() const
void QWaylandWindow::setParent(const QPlatformWindow *parent)
{
- Q_UNUSED(parent);
- qWarning("Sub window is not supported");
+ const QWaylandWindow *parentWaylandWindow = static_cast<const QWaylandWindow *>(parent);
+ if (subSurfaceWindow()) {
+ subSurfaceWindow()->setParent(parentWaylandWindow);
+ }
}
void QWaylandWindow::setVisible(bool visible)
@@ -192,3 +199,8 @@ QWaylandExtendedSurface *QWaylandWindow::extendedWindow() const
{
return mExtendedWindow;
}
+
+QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
+{
+ return mSubSurfaceWindow;
+}
diff --git a/src/plugins/platforms/wayland/qwaylandwindow.h b/src/plugins/platforms/wayland/qwaylandwindow.h
index fb4ac7484..282454baf 100644
--- a/src/plugins/platforms/wayland/qwaylandwindow.h
+++ b/src/plugins/platforms/wayland/qwaylandwindow.h
@@ -51,6 +51,8 @@ class QWaylandDisplay;
class QWaylandBuffer;
class QWaylandShellSurface;
class QWaylandExtendedSurface;
+class QWaylandSubSurface;
+
struct wl_egl_window;
class QWaylandWindow : public QPlatformWindow
@@ -81,12 +83,14 @@ public:
QWaylandShellSurface *shellSurface() const;
QWaylandExtendedSurface *extendedWindow() const;
+ QWaylandSubSurface *subSurfaceWindow() const;
protected:
QWaylandDisplay *mDisplay;
struct wl_surface *mSurface;
QWaylandShellSurface *mShellSurface;
QWaylandExtendedSurface *mExtendedWindow;
+ QWaylandSubSurface *mSubSurfaceWindow;
QWaylandBuffer *mBuffer;
WId mWindowId;
diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro
index aeef60839..51ad95a9f 100644
--- a/src/plugins/platforms/wayland/wayland.pro
+++ b/src/plugins/platforms/wayland/wayland.pro
@@ -17,6 +17,7 @@ QT += core-private gui-private platformsupport-private
WAYLANDSOURCES += \
$$PWD/../../../../extensions/surface-extension.xml \
+ $$PWD/../../../../extensions/sub-surface-extension.xml \
$$PWD/../../../../extensions/output-extension.xml
SOURCES = main.cpp \
@@ -37,7 +38,8 @@ SOURCES = main.cpp \
qwaylandshell.cpp \
qwaylandshellsurface.cpp \
qwaylandextendedoutput.cpp \
- qwaylandextendedsurface.cpp
+ qwaylandextendedsurface.cpp \
+ qwaylandsubsurface.cpp
HEADERS = qwaylandintegration.h \
qwaylandnativeinterface.h \
@@ -56,7 +58,8 @@ HEADERS = qwaylandintegration.h \
qwaylandshell.h \
qwaylandshellsurface.h \
qwaylandextendedoutput.h \
- qwaylandextendedsurface.h
+ qwaylandextendedsurface.h \
+ qwaylandsubsurface.h
INCLUDEPATH += $$QMAKE_INCDIR_WAYLAND
LIBS += $$QMAKE_LIBS_WAYLAND