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>
{
Q_OBJECT
public:
- QmlCompositor() : WaylandCompositor(this) {
- //setMouseTracking(true);
+ QmlCompositor()
+ : WaylandCompositor(this)
+ {
+ enableSubSurfaceExtension();
setSource(QUrl(QLatin1String("qrc:qml/QmlCompositor/main.qml")));
setResizeMode(QQuickView::SizeRootObjectToView);
winId();
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() {
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[])
DEPENDPATH += .
INCLUDEPATH += .
+DEFINES += QT_COMPOSITOR_QUICK
+
# comment out the following to not use pkg-config in the pri files
CONFIG += use_pkgconfig
#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
: 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:
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();
}
}
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())
#ifdef QT_COMPOSITOR_WAYLAND_GL
//jl:FIX FIX FIX:)
// update();
- glFinish();
+ m_textureBlitter->release();
#endif
}
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;
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);
# 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
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
--- /dev/null
+#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);
+}
--- /dev/null
+#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
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
# the following line
#include(../../src/compositor/compositor.pri)
-HEADERS += \
- qopenglwindow.h \
- surfacerenderer.h \
- qwindowcompositor.h
-
RESOURCES += qwindow-compositor.qrc
# install
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)
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()
}
m_surfaces.append(surface);
setInputFocus(surface);
- render();
+ m_renderScheduler.start(0);
}
void QWindowCompositor::surfaceDamaged(const QRect &rect)
{
Q_UNUSED(surface)
Q_UNUSED(rect)
- render();
+ m_renderScheduler.start(0);
}
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
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)
switch (event->type()) {
case QEvent::Expose:
- render();
+ m_renderScheduler.start(0);
break;
case QEvent::MouseButtonPress: {
QPoint local;
setInputFocus(targetSurface);
m_surfaces.removeOne(targetSurface);
m_surfaces.append(targetSurface);
- render();
+ m_renderScheduler.start(0);
}
targetSurface->sendMousePressEvent(local, me->button());
}
#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
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;
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
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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
--- /dev/null
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+<!--
+# /****************************************************************************
+# **
+# ** 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>
<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"/>
Q_UNUSED(hotspotY);
qDebug() << "changeCursor" << image.size() << hotspotX << hotspotY;
}
+
+void WaylandCompositor::enableSubSurfaceExtension()
+{
+ m_compositor->enableSubSurfaceExtension();
+}
virtual void changeCursor(const QImage &image, int hotspotX, int hotspotY);
+ void enableSubSurfaceExtension();
+
private:
static void retainedSelectionChanged(QMimeData *mimeData, void *param);
#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)
}
+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);
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
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);
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);
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,
WaylandSurface(Wayland::Surface *surface);
+ WaylandSurface *parentSurface() const;
+ QLinkedList<WaylandSurface *> subSurfaces() const;
+
Type type() const;
bool isYInverted() const;
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
#include "waylandsurfaceitem.h"
#include "waylandsurface.h"
+#include "wlsurface.h"
+#include "wlextendedsurface.h"
+
#include <QtGui/QKeyEvent>
#include <QtQuick/QSGSimpleTextureNode>
bool smooth;
};
-void WaylandSurfaceItem::surfaceDamaged(const QRect &)
-{
- m_damaged = true;
- emit textureChanged();
- update();
-}
-
WaylandSurfaceItem::WaylandSurfaceItem(QQuickItem *parent)
: QQuickItem(parent)
, m_surface(0)
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());
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;
WaylandSurfaceItem::~WaylandSurfaceItem()
{
+ if (m_surface) {
+ m_surface->setSurfaceItem(0);
+ }
m_texture->deleteLater();
}
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 *)
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;
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;
} else {
m_texture = canvas()->createTextureFromImage(m_surface->image());
}
+
delete oldTexture;
m_damaged = false;
}
m_provider->smooth = smooth();
}
+ QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode);
if (!m_texture || !m_paintEnabled) {
delete oldNode;
return 0;
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();
WAYLANDSOURCES += \
$$PWD/../../../extensions/surface-extension.xml \
+ $$PWD/../../../extensions/sub-surface-extension.xml \
$$PWD/../../../extensions/output-extension.xml
$$PWD/wldataoffer.h \
$$PWD/wldatasource.h \
$$PWD/wlextendedsurface.h \
- $$PWD/wlextendedoutput.h
+ $$PWD/wlextendedoutput.h \
+ $$PWD/wlsubsurface.h
SOURCES += \
$$PWD/wlcompositor.cpp \
$$PWD/wldataoffer.cpp \
$$PWD/wldatasource.cpp \
$$PWD/wlextendedsurface.cpp \
- $$PWD/wlextendedoutput.cpp
+ $$PWD/wlextendedoutput.cpp \
+ $$PWD/wlsubsurface.cpp
#include "wldatadevice.h"
#include "wlextendedoutput.h"
#include "wlextendedsurface.h"
+#include "wlsubsurface.h"
#include <QWindow>
#include <QSocketNotifier>
, m_retainNotify(0)
, m_outputExtension(0)
, m_surfaceExtension(0)
+ , m_subSurfaceExtension(0)
{
compositor = this;
qDebug() << "Compositor instance is" << this;
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
class DataDeviceManager;
class OutputExtensionGlobal;
class SurfaceExtensionGlobal;
+class SubSurfaceExtensionGlobal;
class Q_COMPOSITOR_EXPORT Compositor : public QObject
{
GraphicsHardwareIntegration *graphicsHWIntegration() const;
void initializeHardwareIntegration();
void initializeWindowManagerProtocol();
+ void enableSubSurfaceExtension();
bool setDirectRenderSurface(Surface *surface);
Surface *directRenderSurface() const {return m_directRenderSurface;}
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);
this);
}
+ExtendedSurface::~ExtendedSurface()
+{
+
+}
+
void ExtendedSurface::sendGenericProperty(const char *name, const QVariant &variant)
{
QByteArray byteValue;
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);
#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
{
{
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;
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;
};
--- /dev/null
+/****************************************************************************
+**
+** 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
+};
+
+}
--- /dev/null
+/****************************************************************************
+**
+** 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
#include "wlshmbuffer.h"
#include "wlinputdevice.h"
#include "wlextendedsurface.h"
+#include "wlsubsurface.h"
#include <QtCore/QDebug>
: q_ptr(surface)
, client(client)
, compositor(compositor)
+ , qtSurface(new WaylandSurface(surface))
, directRenderBuffer(0)
, processId(0)
, textureBuffer(0)
, surfaceBuffer(0)
, extendedSurface(0)
+ , subSurface(0)
{
struct wl_list frame_callback_list;
ExtendedSurface *extendedSurface;
+ SubSurface *subSurface;
SurfaceBuffer bufferPool[buffer_pool_size];
+
+ QRect geometry;
private:
Surface *q_ptr;
};
: d_ptr(new SurfacePrivate(this,client,compositor))
{
base()->resource.client = client;
- d_ptr->qtSurface = new WaylandSurface(this);
+
}
Surface::~Surface()
#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());
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);
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) {
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) {
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);
class Compositor;
class Buffer;
class ExtendedSurface;
+class SubSurface;
class SurfacePrivate;
QImage image() const;
+ QRect geometry() const;
+ void setGeometry(const QRect &rect);
+
#ifdef QT_COMPOSITOR_WAYLAND_GL
GLuint textureId(QOpenGLContext *context) const;
#endif
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;
#include "qwaylandextendedoutput.h"
#include "qwaylandextendedsurface.h"
+#include "qwaylandsubsurface.h"
#include <QtCore/QAbstractEventDispatcher>
#include <QtGui/private/qguiapplication_p.h>
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);
}
}
class QWaylandDataDeviceManager;
class QWaylandShell;
class QWaylandSurfaceExtension;
+class QWaylandSubSurfaceExtension;
class QWaylandOutputExtension;
class QWaylandDisplay : public QObject {
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; }
QWaylandInputDevice *mLastKeyboardFocusInputDevice;
QWaylandDataDeviceManager *mDndSelectionHandler;
QWaylandSurfaceExtension *mWindowExtension;
+ QWaylandSubSurfaceExtension *mSubSurfaceExtension;
QWaylandOutputExtension *mOutputExtension;
QSocketNotifier *mReadNotifier;
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;
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();
--- /dev/null
+/****************************************************************************
+**
+** 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);
+ }
+}
--- /dev/null
+/****************************************************************************
+**
+** 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
#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)
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()
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)
{
return mExtendedWindow;
}
+
+QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
+{
+ return mSubSurfaceWindow;
+}
class QWaylandBuffer;
class QWaylandShellSurface;
class QWaylandExtendedSurface;
+class QWaylandSubSurface;
+
struct wl_egl_window;
class QWaylandWindow : public QPlatformWindow
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;
WAYLANDSOURCES += \
$$PWD/../../../../extensions/surface-extension.xml \
+ $$PWD/../../../../extensions/sub-surface-extension.xml \
$$PWD/../../../../extensions/output-extension.xml
SOURCES = main.cpp \
qwaylandshell.cpp \
qwaylandshellsurface.cpp \
qwaylandextendedoutput.cpp \
- qwaylandextendedsurface.cpp
+ qwaylandextendedsurface.cpp \
+ qwaylandsubsurface.cpp
HEADERS = qwaylandintegration.h \
qwaylandnativeinterface.h \
qwaylandshell.h \
qwaylandshellsurface.h \
qwaylandextendedoutput.h \
- qwaylandextendedsurface.h
+ qwaylandextendedsurface.h \
+ qwaylandsubsurface.h
INCLUDEPATH += $$QMAKE_INCDIR_WAYLAND
LIBS += $$QMAKE_LIBS_WAYLAND