summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@qt.io>2018-08-14 13:54:53 +0200
committerPaul Olav Tvete <paul.tvete@qt.io>2018-08-17 14:37:54 +0000
commit0e2e88f1c0f24d058b26032dc8133529a71b53bf (patch)
tree5ae85e131482883089cff07817947169c350bde0
parentbc9fc09caf4f638005977281dc57e7d9c99cfddf (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.cpp118
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.h2
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem_p.h7
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;