summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@theqtcompany.com>2015-12-09 14:38:30 +0100
committerPaul Olav Tvete <paul.tvete@theqtcompany.com>2016-02-04 12:08:58 +0000
commit933d69af3061e9fdfe9e9ca1ea61055aac2c0482 (patch)
tree0fccef825cf65421816d7a4104c01bd735b87495
parent93ca929fb9caf34715012dec608afd42e6ccf1e5 (diff)
Subsurface implementation, with C++ API
This adds support for subsurfaces to QWaylandCompositor and QWaylandSurface. Task-number: QTBUG-49809 Change-Id: I2fa9ee4dcd1f48a2a28dab536f9cd6edc716e42b Reviewed-by: Giulio Camuffo <giuliocamuffo@gmail.com>
-rw-r--r--examples/wayland/qwindow-compositor/compositorwindow.cpp3
-rw-r--r--examples/wayland/qwindow-compositor/windowcompositor.cpp65
-rw-r--r--examples/wayland/qwindow-compositor/windowcompositor.h10
-rw-r--r--examples/wayland/subsurface/main.qml18
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp14
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.h1
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor_p.h8
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp47
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.h4
-rw-r--r--src/compositor/compositor_api/qwaylandsurface_p.h27
10 files changed, 186 insertions, 11 deletions
diff --git a/examples/wayland/qwindow-compositor/compositorwindow.cpp b/examples/wayland/qwindow-compositor/compositorwindow.cpp
index a902a7d0d..4b69022f2 100644
--- a/examples/wayland/qwindow-compositor/compositorwindow.cpp
+++ b/examples/wayland/qwindow-compositor/compositorwindow.cpp
@@ -107,7 +107,8 @@ void CompositorWindow::paintGL()
if (surface && surface->isMapped()) {
QSize s = surface->size();
if (!s.isEmpty()) {
- QRectF surfaceGeometry(view->position(), s);
+ QPointF pos = view->position() + view->parentPosition();
+ QRectF surfaceGeometry(pos, s);
QOpenGLTextureBlitter::Origin surfaceOrigin =
view->currentBuffer().origin() == QWaylandSurface::OriginTopLeft
? QOpenGLTextureBlitter::OriginTopLeft
diff --git a/examples/wayland/qwindow-compositor/windowcompositor.cpp b/examples/wayland/qwindow-compositor/windowcompositor.cpp
index f271570de..57d6b382f 100644
--- a/examples/wayland/qwindow-compositor/windowcompositor.cpp
+++ b/examples/wayland/qwindow-compositor/windowcompositor.cpp
@@ -88,6 +88,8 @@ void WindowCompositor::create()
connect(this, &QWaylandCompositor::surfaceCreated, this, &WindowCompositor::onSurfaceCreated);
connect(defaultInputDevice(), &QWaylandInputDevice::cursorSurfaceRequest, this, &WindowCompositor::adjustCursorSurface);
connect(defaultInputDevice()->drag(), &QWaylandDrag::dragStarted, this, &WindowCompositor::startDrag);
+
+ connect(this, &QWaylandCompositor::subsurfaceChanged, this, &WindowCompositor::onSubsurfaceChanged);
}
void WindowCompositor::onSurfaceCreated(QWaylandSurface *surface)
@@ -96,6 +98,9 @@ void WindowCompositor::onSurfaceCreated(QWaylandSurface *surface)
connect(surface, &QWaylandSurface::mappedChanged, this, &WindowCompositor::surfaceMappedChanged);
connect(surface, &QWaylandSurface::redraw, this, &WindowCompositor::triggerRender);
connect(surface, &QWaylandSurface::offsetForNextFrame, this, &WindowCompositor::frameOffset);
+
+ connect(surface, &QWaylandSurface::subsurfacePositionChanged, this, &WindowCompositor::onSubsurfacePositionChanged);
+
WindowCompositorView *view = new WindowCompositorView;
view->setSurface(surface);
view->setOutput(outputFor(m_window));
@@ -167,9 +172,17 @@ void WindowCompositor::onStartResize(QWaylandInputDevice *, QWaylandShellSurface
emit startResize(int(edges));
}
-void WindowCompositor::onSetTransient(QWaylandSurface *parentSurface, const QPoint &relativeToParent, QWaylandShellSurface::FocusPolicy focusPolicy)
+void WindowCompositor::onSetTransient(QWaylandSurface *parent, const QPoint &relativeToParent, QWaylandShellSurface::FocusPolicy focusPolicy)
{
- qDebug() << "Transient window support not implemented" << parentSurface << relativeToParent << focusPolicy;
+ QWaylandShellSurface *surface = qobject_cast<QWaylandShellSurface*>(sender());
+ WindowCompositorView *view = findView(surface->surface());
+
+ if (view) {
+ raise(view);
+ WindowCompositorView *parentView = findView(parent);
+ if (parentView)
+ view->setPosition(parentView->position() + relativeToParent);
+ }
}
void WindowCompositor::onSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parent, const QPoint &relativeToParent)
@@ -186,6 +199,23 @@ void WindowCompositor::onSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurf
}
}
+void WindowCompositor::onSubsurfaceChanged(QWaylandSurface *child, QWaylandSurface *parent)
+{
+ WindowCompositorView *view = findView(child);
+ WindowCompositorView *parentView = findView(parent);
+ view->setParentView(parentView);
+}
+
+void WindowCompositor::onSubsurfacePositionChanged(const QPoint &position)
+{
+ QWaylandSurface *surface = qobject_cast<QWaylandSurface*>(sender());
+ if (!surface)
+ return;
+ WindowCompositorView *view = findView(surface);
+ view->setPosition(position);
+ triggerRender();
+}
+
void WindowCompositor::triggerRender()
{
m_window->requestUpdate();
@@ -288,8 +318,35 @@ void WindowCompositor::handleDrag(WindowCompositorView *target, QMouseEvent *me)
currentDrag->drop();
}
+// We only have a flat list of views, plus pointers from child to parent,
+// so maintaining a stacking order gets a bit complex. A better data
+// structure is left as an exercise for the reader.
+
+static int findEndOfChildTree(const QList<WindowCompositorView*> &list, int index)
+{
+ int n = list.count();
+ WindowCompositorView *parent = list.at(index);
+ while (index + 1 < n) {
+ if (list.at(index+1)->parentView() != parent)
+ break;
+ index = findEndOfChildTree(list, index + 1);
+ }
+ return index;
+}
+
void WindowCompositor::raise(WindowCompositorView *view)
{
- m_views.removeOne(view);
- m_views.append(view);
+ int startPos = m_views.indexOf(view);
+ int endPos = findEndOfChildTree(m_views, startPos);
+
+ int n = m_views.count();
+ int tail = n - endPos - 1;
+
+ //bubble sort: move the child tree to the end of the list
+ for (int i = 0; i < tail; i++) {
+ int source = endPos + 1 + i;
+ int dest = startPos + i;
+ for (int j = source; j > dest; j--)
+ m_views.swap(j, j-1);
+ }
}
diff --git a/examples/wayland/qwindow-compositor/windowcompositor.h b/examples/wayland/qwindow-compositor/windowcompositor.h
index 98cc88f6a..7a4f90aad 100644
--- a/examples/wayland/qwindow-compositor/windowcompositor.h
+++ b/examples/wayland/qwindow-compositor/windowcompositor.h
@@ -56,17 +56,22 @@ class WindowCompositorView : public QWaylandView
{
Q_OBJECT
public:
- WindowCompositorView() : m_texture(0), m_shellSurface(0) {}
+ WindowCompositorView() : m_texture(0), m_shellSurface(0), m_parentView(0) {}
GLuint getTexture();
QPointF position() const { return m_position; }
void setPosition(const QPointF &pos) { m_position = pos; }
bool isCursor() const;
bool hasShell() const { return m_shellSurface; }
+ void setParentView(WindowCompositorView *parent) { m_parentView = parent; }
+ WindowCompositorView *parentView() const { return m_parentView; }
+ QPointF parentPosition() const { return m_parentView ? (m_parentView->position() + m_parentView->parentPosition()) : QPointF(); }
+
private:
friend class WindowCompositor;
GLuint m_texture;
QPointF m_position;
QWaylandShellSurface *m_shellSurface;
+ WindowCompositorView *m_parentView;
};
class WindowCompositor : public QWaylandCompositor
@@ -114,6 +119,9 @@ private slots:
void onSetTransient(QWaylandSurface *parentSurface, const QPoint &relativeToParent, QWaylandShellSurface::FocusPolicy focusPolicy);
void onSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parent, const QPoint &relativeToParent);
+ void onSubsurfaceChanged(QWaylandSurface *child, QWaylandSurface *parent);
+ void onSubsurfacePositionChanged(const QPoint &position);
+
void updateCursor();
private:
WindowCompositorView *findView(const QWaylandSurface *s) const;
diff --git a/examples/wayland/subsurface/main.qml b/examples/wayland/subsurface/main.qml
index fa71d4b6b..8d221401b 100644
--- a/examples/wayland/subsurface/main.qml
+++ b/examples/wayland/subsurface/main.qml
@@ -69,4 +69,22 @@ Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
text: syncStatus.sync ? "sync mode" : "de-sync mode"
}
+
+ // If you can see these rectangles, something's not right
+ Rectangle {
+ //Child at (150, 70, 100, 100)
+ color: "yellow"
+ x: 150
+ y: 70
+ width:100
+ height:100
+ }
+ Rectangle {
+ //Shm at (30, 30, 50, 50)
+ color: "yellow"
+ x: 30
+ y: 30
+ width: 50
+ height: 50
+ }
}
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index 9aec337bd..5480b1cf1 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -158,6 +158,7 @@ void QWaylandCompositorPrivate::init()
socket_name = arguments.at(socketArg + 1).toLocal8Bit();
wl_compositor::init(display, 3);
+ wl_subcompositor::init(display, 1);
data_device_manager = new QtWayland::DataDeviceManager(q);
@@ -270,7 +271,7 @@ void QWaylandCompositorPrivate::addPolishObject(QObject *object)
*/
-void QWaylandCompositorPrivate::compositor_create_surface(Resource *resource, uint32_t id)
+void QWaylandCompositorPrivate::compositor_create_surface(wl_compositor::Resource *resource, uint32_t id)
{
Q_Q(QWaylandCompositor);
QWaylandClient *client = QWaylandClient::fromWlClient(q, resource->client());
@@ -292,11 +293,20 @@ void QWaylandCompositorPrivate::compositor_create_surface(Resource *resource, ui
emit q->surfaceCreated(surface);
}
-void QWaylandCompositorPrivate::compositor_create_region(Resource *resource, uint32_t id)
+void QWaylandCompositorPrivate::compositor_create_region(wl_compositor::Resource *resource, uint32_t id)
{
new QtWayland::Region(resource->client(), id);
}
+void QWaylandCompositorPrivate::subcompositor_get_subsurface(wl_subcompositor::Resource *resource, uint32_t id, wl_resource *surface, wl_resource *parent)
+{
+ Q_Q(QWaylandCompositor);
+ QWaylandSurface *childSurface = QWaylandSurface::fromResource(surface);
+ QWaylandSurface *parentSurface = QWaylandSurface::fromResource(parent);
+ QWaylandSurfacePrivate::get(childSurface)->initSubsurface(parentSurface, resource->client(), id, 1);
+ emit q->subsurfaceChanged(childSurface, parentSurface);
+}
+
/*!
\internal
Used to create a fallback QWaylandSurface when no surface was
diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h
index cae7b4582..789832762 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.h
+++ b/src/compositor/compositor_api/qwaylandcompositor.h
@@ -122,6 +122,7 @@ Q_SIGNALS:
void createSurface(QWaylandClient *client, uint id, int version);
void surfaceCreated(QWaylandSurface *surface);
void surfaceAboutToBeDestroyed(QWaylandSurface *surface);
+ void subsurfaceChanged(QWaylandSurface *child, QWaylandSurface *parent);
void defaultOutputChanged();
void defaultInputDeviceChanged();
diff --git a/src/compositor/compositor_api/qwaylandcompositor_p.h b/src/compositor/compositor_api/qwaylandcompositor_p.h
index fb0f803ed..942634af5 100644
--- a/src/compositor/compositor_api/qwaylandcompositor_p.h
+++ b/src/compositor/compositor_api/qwaylandcompositor_p.h
@@ -69,7 +69,7 @@ namespace QtWayland {
class QWindowSystemEventHandler;
class QWaylandSurface;
-class Q_COMPOSITOR_EXPORT QWaylandCompositorPrivate : public QObjectPrivate, public QtWaylandServer::wl_compositor
+class Q_COMPOSITOR_EXPORT QWaylandCompositorPrivate : public QObjectPrivate, public QtWaylandServer::wl_compositor, public QtWaylandServer::wl_subcompositor
{
public:
static QWaylandCompositorPrivate *get(QWaylandCompositor *compositor) { return compositor->d_func(); }
@@ -105,8 +105,10 @@ public:
inline void addOutput(QWaylandOutput *output);
inline void removeOutput(QWaylandOutput *output);
protected:
- void compositor_create_surface(Resource *resource, uint32_t id) Q_DECL_OVERRIDE;
- void compositor_create_region(Resource *resource, uint32_t id) Q_DECL_OVERRIDE;
+ void compositor_create_surface(wl_compositor::Resource *resource, uint32_t id) Q_DECL_OVERRIDE;
+ void compositor_create_region(wl_compositor::Resource *resource, uint32_t id) Q_DECL_OVERRIDE;
+
+ void subcompositor_get_subsurface(wl_subcompositor::Resource *resource, uint32_t id, struct ::wl_resource *surface, struct ::wl_resource *parent);
virtual QWaylandSurface *createDefaultSurface();
protected:
diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp
index 9391164cf..ed028824f 100644
--- a/src/compositor/compositor_api/qwaylandsurface.cpp
+++ b/src/compositor/compositor_api/qwaylandsurface.cpp
@@ -130,6 +130,7 @@ QWaylandSurfacePrivate::QWaylandSurfacePrivate()
, mapped(false)
, isInitialized(false)
, contentOrientation(Qt::PrimaryOrientation)
+ , subsurface(0)
{
pending.buffer = 0;
pending.newlyAttached = false;
@@ -777,4 +778,50 @@ void QWaylandSurfacePrivate::derefView(QWaylandView *view)
}
}
+void QWaylandSurfacePrivate::initSubsurface(QWaylandSurface *parent, wl_client *client, int id, int version)
+{
+ Q_Q(QWaylandSurface);
+ QWaylandSurface *oldParent = 0; // TODO: implement support for switching parents
+
+ subsurface = new Subsurface(this);
+ subsurface->init(client, id, version);
+ subsurface->parentSurface = parent->d_func();
+ emit q->parentChanged(parent, oldParent);
+ emit parent->childAdded(q);
+}
+
+void QWaylandSurfacePrivate::Subsurface::subsurface_set_position(wl_subsurface::Resource *resource, int32_t x, int32_t y)
+{
+ Q_UNUSED(resource);
+ position = QPoint(x,y);
+ emit surface->q_func()->subsurfacePositionChanged(position);
+
+}
+
+void QWaylandSurfacePrivate::Subsurface::subsurface_place_above(wl_subsurface::Resource *resource, struct wl_resource *sibling)
+{
+ Q_UNUSED(resource);
+ emit surface->q_func()->subsurfacePlaceAbove(QWaylandSurface::fromResource(sibling));
+}
+
+void QWaylandSurfacePrivate::Subsurface::subsurface_place_below(wl_subsurface::Resource *resource, struct wl_resource *sibling)
+{
+ Q_UNUSED(resource);
+ emit surface->q_func()->subsurfacePlaceBelow(QWaylandSurface::fromResource(sibling));
+}
+
+void QWaylandSurfacePrivate::Subsurface::subsurface_set_sync(wl_subsurface::Resource *resource)
+{
+ Q_UNUSED(resource);
+ // TODO: sync/desync implementation
+ qDebug() << Q_FUNC_INFO;
+}
+
+void QWaylandSurfacePrivate::Subsurface::subsurface_set_desync(wl_subsurface::Resource *resource)
+{
+ Q_UNUSED(resource);
+ // TODO: sync/desync implementation
+ qDebug() << Q_FUNC_INFO;
+}
+
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h
index d3fe4f15e..bb034080a 100644
--- a/src/compositor/compositor_api/qwaylandsurface.h
+++ b/src/compositor/compositor_api/qwaylandsurface.h
@@ -129,12 +129,16 @@ Q_SIGNALS:
void mappedChanged();
void damaged(const QRegion &rect);
void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent);
+ void childAdded(QWaylandSurface *child);
void sizeChanged();
void offsetForNextFrame(const QPoint &offset);
void contentOrientationChanged();
void pong();
void surfaceDestroyed();
void originChanged();
+ void subsurfacePositionChanged(const QPoint &position);
+ void subsurfacePlaceAbove(QWaylandSurface *sibling);
+ void subsurfacePlaceBelow(QWaylandSurface *sibling);
void configure(bool hasBuffer);
void redraw();
diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h
index 1f3676bd9..de71b7fe3 100644
--- a/src/compositor/compositor_api/qwaylandsurface_p.h
+++ b/src/compositor/compositor_api/qwaylandsurface_p.h
@@ -112,6 +112,11 @@ public:
static void removeUninitializedSurface(QWaylandSurfacePrivate *surface);
static bool hasUninitializedSurface();
#endif
+
+ void initSubsurface(QWaylandSurface *parent, struct ::wl_client *client, int id, int version);
+ bool isSubsurface() const { return subsurface; }
+ QWaylandSurfacePrivate *parentSurface() const { return subsurface ? subsurface->parentSurface : nullptr; }
+
protected:
void surface_destroy_resource(Resource *resource) Q_DECL_OVERRIDE;
@@ -170,6 +175,28 @@ protected: //member variables
Qt::ScreenOrientation contentOrientation;
QWindow::Visibility visibility;
+ class Subsurface : public QtWaylandServer::wl_subsurface
+ {
+ public:
+ Subsurface(QWaylandSurfacePrivate *s) : surface(s) {}
+ QWaylandSurfacePrivate *surfaceFromResource();
+
+ protected:
+ void subsurface_set_position(wl_subsurface::Resource *resource, int32_t x, int32_t y);
+ void subsurface_place_above(wl_subsurface::Resource *resource, struct wl_resource *sibling);
+ void subsurface_place_below(wl_subsurface::Resource *resource, struct wl_resource *sibling);
+ void subsurface_set_sync(wl_subsurface::Resource *resource);
+ void subsurface_set_desync(wl_subsurface::Resource *resource);
+
+ private:
+ friend class QWaylandSurfacePrivate;
+ QWaylandSurfacePrivate *surface;
+ QWaylandSurfacePrivate *parentSurface;
+ QPoint position;
+ };
+
+ Subsurface *subsurface;
+
#ifndef QT_NO_DEBUG
static QList<QWaylandSurfacePrivate *> uninitializedSurfaces;
#endif