Clamp XdgShellClient::clientSize to surface size, not m_windowGeometry

Summary:
It's perfectly legitimate to call setWindowSize before a buffer is
attached. This seems to have happen with plasma surfaces that commit
when attaching a shadow, but technically could happen anywhere.

By clamping to the applied surface here, we get the wrong window size
cached and not re-evaluated when a surface is eventually applied. This
leaves us thinking the windowsize is empty but with a massive margin
which actually holds the content.

We want all internal usages of xdgshellclient to use the window geometry
set. Only the wider kwin part needs to care about clamping it to the
surface.

This fixes popup placement in the plasma panel
BUG: 415317

As well as ghost notification popups with no background contrast that
you can't interact with.

Test Plan: Ran kwin

Reviewers: #kwin, zzag

Reviewed By: #kwin, zzag

Subscribers: romangg, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D26233
This commit is contained in:
David Edmundson 2020-01-06 15:10:50 +00:00
parent ab85638946
commit 89024e2bcc

View file

@ -311,9 +311,29 @@ QPoint XdgShellClient::clientContentPos() const
return -1 * clientPos(); return -1 * clientPos();
} }
static QRect subSurfaceTreeRect(const SurfaceInterface *surface, const QPoint &position = QPoint())
{
QRect rect(position, surface->size());
const QList<QPointer<SubSurfaceInterface>> subSurfaces = surface->childSubSurfaces();
for (const QPointer<SubSurfaceInterface> &subSurface : subSurfaces) {
if (Q_UNLIKELY(!subSurface)) {
continue;
}
const SurfaceInterface *child = subSurface->surface();
if (Q_UNLIKELY(!child)) {
continue;
}
rect |= subSurfaceTreeRect(child, position + subSurface->position());
}
return rect;
}
QSize XdgShellClient::clientSize() const QSize XdgShellClient::clientSize() const
{ {
return m_windowGeometry.size(); const QRect boundingRect = subSurfaceTreeRect(surface());
return m_windowGeometry.size().boundedTo(boundingRect.size());
} }
void XdgShellClient::debug(QDebug &stream) const void XdgShellClient::debug(QDebug &stream) const
@ -1163,29 +1183,9 @@ void XdgShellClient::handleWindowClassChanged(const QByteArray &windowClass)
setDesktopFileName(windowClass); setDesktopFileName(windowClass);
} }
static QRect subSurfaceTreeRect(const SurfaceInterface *surface, const QPoint &position = QPoint())
{
QRect rect(position, surface->size());
const QList<QPointer<SubSurfaceInterface>> subSurfaces = surface->childSubSurfaces();
for (const QPointer<SubSurfaceInterface> &subSurface : subSurfaces) {
if (Q_UNLIKELY(!subSurface)) {
continue;
}
const SurfaceInterface *child = subSurface->surface();
if (Q_UNLIKELY(!child)) {
continue;
}
rect |= subSurfaceTreeRect(child, position + subSurface->position());
}
return rect;
}
void XdgShellClient::handleWindowGeometryChanged(const QRect &windowGeometry) void XdgShellClient::handleWindowGeometryChanged(const QRect &windowGeometry)
{ {
const QRect boundingRect = subSurfaceTreeRect(surface()); m_windowGeometry = windowGeometry;
m_windowGeometry = windowGeometry & boundingRect;
m_hasWindowGeometry = true; m_hasWindowGeometry = true;
} }