summaryrefslogtreecommitdiffstats
path: root/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp')
-rw-r--r--src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp55
1 files changed, 40 insertions, 15 deletions
diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
index 28806f622..7eb1479f5 100644
--- a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
+++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
@@ -18,9 +18,8 @@ QWaylandQuickShellSurfaceItem *QWaylandQuickShellSurfaceItemPrivate::maybeCreate
auto *popupItem = new QWaylandQuickShellSurfaceItem(q);
popupItem->setShellSurface(shellSurface);
popupItem->setAutoCreatePopupItems(true);
- QObject::connect(popupItem, &QWaylandQuickShellSurfaceItem::surfaceDestroyed, [popupItem](){
- popupItem->deleteLater();
- });
+ QObject::connect(popupItem, &QWaylandQuickShellSurfaceItem::surfaceDestroyed,
+ popupItem, &QObject::deleteLater);
return popupItem;
}
@@ -77,7 +76,7 @@ QWaylandQuickShellSurfaceItem::QWaylandQuickShellSurfaceItem(QWaylandQuickShellS
}
/*!
- * \qmlproperty ShellSurface QtWaylandCompositor::ShellSurfaceItem::shellSurface
+ * \qmlproperty ShellSurface QtWayland.Compositor::ShellSurfaceItem::shellSurface
*
* This property holds the ShellSurface rendered by this ShellSurfaceItem.
* It may either be an XdgSurfaceV5, WlShellSurface or IviSurface depending on which shell protocol
@@ -103,6 +102,9 @@ void QWaylandQuickShellSurfaceItem::setShellSurface(QWaylandShellSurface *shellS
if (d->m_shellSurface == shellSurface)
return;
+ if (Q_UNLIKELY(d->m_shellSurface))
+ disconnect(d->m_shellSurface, &QWaylandShellSurface::modalChanged, this, nullptr);
+
d->m_shellSurface = shellSurface;
if (d->m_shellIntegration) {
@@ -116,11 +118,14 @@ void QWaylandQuickShellSurfaceItem::setShellSurface(QWaylandShellSurface *shellS
installEventFilter(d->m_shellIntegration);
}
+ connect(shellSurface, &QWaylandShellSurface::modalChanged, this,
+ [d](){ if (d->m_shellSurface->modal()) d->raise(); });
+
emit shellSurfaceChanged();
}
/*!
- * \qmlproperty Item QtWaylandCompositor::ShellSurfaceItem::moveItem
+ * \qmlproperty Item QtWayland.Compositor::ShellSurfaceItem::moveItem
*
* This property holds the move item for this ShellSurfaceItem. This is the item that will be moved
* when the clients request the ShellSurface to be moved, maximized, resized etc. This property is
@@ -151,7 +156,7 @@ void QWaylandQuickShellSurfaceItem::setMoveItem(QQuickItem *moveItem)
}
/*!
- * \qmlproperty bool QtWaylandCompositor::ShellSurfaceItem::autoCreatePopupItems
+ * \qmlproperty bool QtWayland.Compositor::ShellSurfaceItem::autoCreatePopupItems
*
* This property holds whether ShellSurfaceItems for popups parented to the shell
* surface managed by this item should automatically be created.
@@ -300,11 +305,22 @@ static QWaylandQuickShellSurfaceItem *findSurfaceItemFromMoveItem(QQuickItem *mo
return nullptr;
}
+static inline bool onTop(QWaylandQuickShellSurfaceItem *surf)
+{
+ return surf->staysOnTop() || surf->shellSurface()->modal();
+}
+
+static inline bool onBottom(QWaylandQuickShellSurfaceItem *surf)
+{
+ return surf->staysOnBottom() && !surf->shellSurface()->modal();
+}
+
/*
To raise a surface, find the topmost suitable surface and place above that.
We start from the top and:
If we don't have staysOnTop, skip all surfaces with staysOnTop
If we have staysOnBottom, skip all surfaces that don't have staysOnBottom
+ A modal dialog is handled as if it had staysOnTop
*/
void QWaylandQuickShellSurfaceItemPrivate::raise()
{
@@ -313,17 +329,23 @@ void QWaylandQuickShellSurfaceItemPrivate::raise()
QQuickItem *parent = moveItem->parentItem();
if (!parent)
return;
+ const bool putOnTop = staysOnTop || m_shellSurface->modal();
+ const bool putOnBottom = staysOnBottom && !m_shellSurface->modal();
+
auto it = parent->childItems().crbegin();
- auto skip = [this](QQuickItem *item) {
+ auto skip = [=](QQuickItem *item) {
if (auto *surf = findSurfaceItemFromMoveItem(item))
- return (!staysOnTop && surf->staysOnTop()) || (staysOnBottom && !surf->staysOnBottom());
+ return (!putOnTop && onTop(surf)) || (putOnBottom && !onBottom(surf));
return true; // ignore any other Quick items that may be there
};
- while (skip(*it))
+ auto end = parent->childItems().crend();
+ while (it != end && skip(*it))
++it;
- QQuickItem *top = *it;
- if (moveItem != top)
- moveItem->stackAfter(top);
+ if (it != end) {
+ QQuickItem *top = *it;
+ if (moveItem != top)
+ moveItem->stackAfter(top);
+ }
}
/*
@@ -331,6 +353,7 @@ void QWaylandQuickShellSurfaceItemPrivate::raise()
We start from the bottom and:
If we don't have staysOnBottom, skip all surfaces with staysOnBottom
If we have staysOnTop, skip all surfaces that don't have staysOnTop
+ A modal dialog is handled as if it had staysOnTop
*/
void QWaylandQuickShellSurfaceItemPrivate::lower()
{
@@ -339,11 +362,13 @@ void QWaylandQuickShellSurfaceItemPrivate::lower()
QQuickItem *parent = moveItem->parentItem();
if (!parent)
return;
- auto it = parent->childItems().cbegin();
+ const bool putOnTop = staysOnTop || m_shellSurface->modal();
+ const bool putOnBottom = staysOnBottom && !m_shellSurface->modal();
- auto skip = [this](QQuickItem *item) {
+ auto it = parent->childItems().cbegin();
+ auto skip = [=](QQuickItem *item) {
if (auto *surf = findSurfaceItemFromMoveItem(item))
- return (!staysOnBottom && surf->staysOnBottom()) || (staysOnTop && !surf->staysOnTop());
+ return (!putOnBottom && onBottom(surf)) || (putOnTop && !onTop(surf));
return true; // ignore any other Quick items that may be there
};
while (skip(*it))