summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@qt.io>2024-04-11 15:03:42 +0200
committerPaul Olav Tvete <paul.tvete@qt.io>2024-04-12 13:19:47 +0000
commitf6c4b2f0691ea0240566c068cf36ed95003153e1 (patch)
treebeee29015a726f10f61bd973ca2ff590b3794a10
parent0417a5f34a327be44a50b5164266b9f607776461 (diff)
ShellSurfaceItem: Make sure modal dialogs stay on top
Use the new modal property from ShellSurface, and treat modal dialogs as StaysOnTop. [ChangeLog][QtWaylandCompositor] ShellSurfaceItem will keep modal dialogs on top of other surfaces when using XdgShell. Fixes: QTBUG-118813 Change-Id: Iaa0ca411dc4fec740e0fbe1db523b16b028c4c29 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
-rw-r--r--src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp33
1 files changed, 28 insertions, 5 deletions
diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
index cd0ac84f8..7eb1479f5 100644
--- a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
+++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
@@ -102,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) {
@@ -115,6 +118,9 @@ void QWaylandQuickShellSurfaceItem::setShellSurface(QWaylandShellSurface *shellS
installEventFilter(d->m_shellIntegration);
}
+ connect(shellSurface, &QWaylandShellSurface::modalChanged, this,
+ [d](){ if (d->m_shellSurface->modal()) d->raise(); });
+
emit shellSurfaceChanged();
}
@@ -299,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()
{
@@ -312,10 +329,13 @@ 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
};
auto end = parent->childItems().crend();
@@ -333,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()
{
@@ -341,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))