diff options
author | Paul Olav Tvete <paul.tvete@theqtcompany.com> | 2015-12-09 14:38:30 +0100 |
---|---|---|
committer | Paul Olav Tvete <paul.tvete@theqtcompany.com> | 2016-02-04 12:08:58 +0000 |
commit | 933d69af3061e9fdfe9e9ca1ea61055aac2c0482 (patch) | |
tree | 0fccef825cf65421816d7a4104c01bd735b87495 /examples | |
parent | 93ca929fb9caf34715012dec608afd42e6ccf1e5 (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>
Diffstat (limited to 'examples')
4 files changed, 90 insertions, 6 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 + } } |