summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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