diff options
author | Paul Olav Tvete <paul.tvete@qt.io> | 2018-08-14 13:54:53 +0200 |
---|---|---|
committer | Paul Olav Tvete <paul.tvete@qt.io> | 2018-08-17 14:37:54 +0000 |
commit | 0e2e88f1c0f24d058b26032dc8133529a71b53bf (patch) | |
tree | 5ae85e131482883089cff07817947169c350bde0 | |
parent | bc9fc09caf4f638005977281dc57e7d9c99cfddf (diff) |
Compositor: Subsurface placeAbove/Below implementation
[ChangeLog][Compositor] Added support for wl_subsurface.place_above and
place_below in WaylandQuickItem.
Task-number: QTBUG-49809
Change-Id: Ie30c342f329c26feaa954f8909b61b139e5588dc
Reviewed-by: Johan Helsing <johan.helsing@qt.io>
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
-rw-r--r-- | src/compositor/compositor_api/qwaylandquickitem.cpp | 118 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandquickitem.h | 2 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandquickitem_p.h | 7 |
3 files changed, 127 insertions, 0 deletions
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp index f0dc08cc2..8480db6f4 100644 --- a/src/compositor/compositor_api/qwaylandquickitem.cpp +++ b/src/compositor/compositor_api/qwaylandquickitem.cpp @@ -731,7 +731,39 @@ void QWaylandQuickItem::handleSubsurfaceAdded(QWaylandSurface *childSurface) } } +void QWaylandQuickItem::handlePlaceAbove(QWaylandSurface *referenceSurface) +{ + Q_D(QWaylandQuickItem); + auto *parent = qobject_cast<QWaylandQuickItem*>(parentItem()); + if (!parent) + return; + if (parent->surface() == referenceSurface) { + d->placeAboveParent(); + } else if (auto *sibling = d->findSibling(referenceSurface)) { + d->placeAboveSibling(sibling); + } else { + qWarning() << "Couldn't find QWaylandQuickItem for surface" << referenceSurface + << "when handling wl_subsurface.place_above"; + } +} + +void QWaylandQuickItem::handlePlaceBelow(QWaylandSurface *referenceSurface) +{ + Q_D(QWaylandQuickItem); + QWaylandQuickItem *parent = qobject_cast<QWaylandQuickItem*>(parentItem()); + if (!parent) + return; + + if (parent->surface() == referenceSurface) { + d->placeBelowParent(); + } else if (auto *sibling = d->findSibling(referenceSurface)) { + d->placeBelowSibling(sibling); + } else { + qWarning() << "Couldn't find QWaylandQuickItem for surface" << referenceSurface + << "when handling wl_subsurface.place_below"; + } +} /*! \qmlproperty object QtWaylandCompositor::WaylandQuickItem::subsurfaceHandler @@ -859,6 +891,8 @@ void QWaylandQuickItem::handleSurfaceChanged() disconnect(d->oldSurface, &QWaylandSurface::configure, this, &QWaylandQuickItem::updateBuffer); disconnect(d->oldSurface, &QWaylandSurface::redraw, this, &QQuickItem::update); disconnect(d->oldSurface, &QWaylandSurface::childAdded, this, &QWaylandQuickItem::handleSubsurfaceAdded); + disconnect(d->oldSurface, &QWaylandSurface::subsurfacePlaceAbove, this, &QWaylandQuickItem::handlePlaceAbove); + disconnect(d->oldSurface, &QWaylandSurface::subsurfacePlaceBelow, this, &QWaylandQuickItem::handlePlaceBelow); #if QT_CONFIG(draganddrop) disconnect(d->oldSurface, &QWaylandSurface::dragStarted, this, &QWaylandQuickItem::handleDragStarted); #endif @@ -874,6 +908,8 @@ void QWaylandQuickItem::handleSurfaceChanged() connect(newSurface, &QWaylandSurface::configure, this, &QWaylandQuickItem::updateBuffer); connect(newSurface, &QWaylandSurface::redraw, this, &QQuickItem::update); connect(newSurface, &QWaylandSurface::childAdded, this, &QWaylandQuickItem::handleSubsurfaceAdded); + connect(newSurface, &QWaylandSurface::subsurfacePlaceAbove, this, &QWaylandQuickItem::handlePlaceAbove); + connect(newSurface, &QWaylandSurface::subsurfacePlaceBelow, this, &QWaylandQuickItem::handlePlaceBelow); #if QT_CONFIG(draganddrop) connect(newSurface, &QWaylandSurface::dragStarted, this, &QWaylandQuickItem::handleDragStarted); #endif @@ -1364,4 +1400,86 @@ qreal QWaylandQuickItemPrivate::scaleFactor() const return f; } +QWaylandQuickItem *QWaylandQuickItemPrivate::findSibling(QWaylandSurface *surface) const +{ + Q_Q(const QWaylandQuickItem); + auto *parent = q->parentItem(); + if (!parent) + return nullptr; + + const auto siblings = q->parentItem()->childItems(); + for (auto *sibling : siblings) { + auto *waylandItem = qobject_cast<QWaylandQuickItem *>(sibling); + if (waylandItem && waylandItem->surface() == surface) + return waylandItem; + } + return nullptr; +} + +void QWaylandQuickItemPrivate::placeAboveSibling(QWaylandQuickItem *sibling) +{ + Q_Q(QWaylandQuickItem); + q->stackAfter(sibling); + q->setZ(sibling->z()); + belowParent = sibling->d_func()->belowParent; +} + +void QWaylandQuickItemPrivate::placeBelowSibling(QWaylandQuickItem *sibling) +{ + Q_Q(QWaylandQuickItem); + q->stackBefore(sibling); + q->setZ(sibling->z()); + belowParent = sibling->d_func()->belowParent; +} + +//### does not handle changes in z value if parent is a subsurface +void QWaylandQuickItemPrivate::placeAboveParent() +{ + Q_Q(QWaylandQuickItem); + const auto siblings = q->parentItem()->childItems(); + + // Stack below first (bottom) sibling above parent + bool foundSibling = false; + for (auto it = siblings.cbegin(); it != siblings.cend(); ++it) { + QWaylandQuickItem *sibling = qobject_cast<QWaylandQuickItem*>(*it); + if (sibling && !sibling->d_func()->belowParent) { + q->stackBefore(sibling); + foundSibling = true; + break; + } + } + + // No other subsurfaces above parent + if (!foundSibling && siblings.last() != q) + q->stackAfter(siblings.last()); + + q->setZ(q->parentItem()->z()); + belowParent = false; +} + +//### does not handle changes in z value if parent is a subsurface +void QWaylandQuickItemPrivate::placeBelowParent() +{ + Q_Q(QWaylandQuickItem); + const auto siblings = q->parentItem()->childItems(); + + // Stack above last (top) sibling below parent + bool foundSibling = false; + for (auto it = siblings.crbegin(); it != siblings.crend(); ++it) { + QWaylandQuickItem *sibling = qobject_cast<QWaylandQuickItem*>(*it); + if (sibling && sibling->d_func()->belowParent) { + q->stackAfter(sibling); + foundSibling = true; + break; + } + } + + // No other subsurfaces below parent + if (!foundSibling && siblings.first() != q) + q->stackBefore(siblings.first()); + + q->setZ(q->parentItem()->z() - 1.0); + belowParent = true; +} + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquickitem.h b/src/compositor/compositor_api/qwaylandquickitem.h index 0aa863f5f..aac88236c 100644 --- a/src/compositor/compositor_api/qwaylandquickitem.h +++ b/src/compositor/compositor_api/qwaylandquickitem.h @@ -163,6 +163,8 @@ private Q_SLOTS: void beforeSync(); void handleSubsurfaceAdded(QWaylandSurface *childSurface); void handleSubsurfacePosition(const QPoint &pos); + void handlePlaceAbove(QWaylandSurface *referenceSurface); + void handlePlaceBelow(QWaylandSurface *referenceSurface); #if QT_CONFIG(draganddrop) void handleDragStarted(QWaylandDrag *drag); #endif diff --git a/src/compositor/compositor_api/qwaylandquickitem_p.h b/src/compositor/compositor_api/qwaylandquickitem_p.h index f926d55e8..ee8ea5442 100644 --- a/src/compositor/compositor_api/qwaylandquickitem_p.h +++ b/src/compositor/compositor_api/qwaylandquickitem_p.h @@ -151,6 +151,12 @@ public: bool shouldSendInputEvents() const { return view->surface() && inputEventsEnabled; } qreal scaleFactor() const; + QWaylandQuickItem *findSibling(QWaylandSurface *surface) const; + void placeAboveSibling(QWaylandQuickItem *sibling); + void placeBelowSibling(QWaylandQuickItem *sibling); + void placeAboveParent(); + void placeBelowParent(); + static QMutex *mutex; QScopedPointer<QWaylandView> view; @@ -163,6 +169,7 @@ public: bool newTexture = false; bool focusOnClick = true; bool sizeFollowsSurface = true; + bool belowParent = false; QPoint hoverPos; QMatrix4x4 lastMatrix; |