From 2b241d308147ec08701e88217d1b8fa8b682f8e6 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Tue, 8 Sep 2020 17:27:14 +0300 Subject: [PATCH] Properly handle opaque regions for CSD X11 windows Currently, we don't compute the clip region properly for some client- side decorated applications, for example gedit, due to mixing several separate coordinate spaces. This change ensures that the window pixmap shape and the opaque region are in the same coordinate space - the window pixmap coordinate. In order to simplify mapping regions from the window pixmap coordinates to the global screen coordinates, a new helper method was introduced in the WindowPixmap class - mapToGlobal(). --- scene.cpp | 24 ++++++++++++++++++++---- scene.h | 17 ++++++++++++++--- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/scene.cpp b/scene.cpp index 40a39e8fe9..80c687a2df 100644 --- a/scene.cpp +++ b/scene.cpp @@ -284,11 +284,17 @@ void Scene::paintSimpleScreen(int orig_mask, const QRegion ®ion) if (!(client && client->decorationHasAlpha())) { data.clip = window->decorationShape().translated(window->pos()); } - data.clip |= window->clientShape().translated(window->pos() + window->bufferOffset()); + const WindowPixmap *windowPixmap = window->windowPixmap(); + if (windowPixmap) { + data.clip |= windowPixmap->mapToGlobal(windowPixmap->shape()); + } } else if (toplevel->hasAlpha() && toplevel->opacity() == 1.0) { - const QRegion clientShape = window->clientShape().translated(window->pos() + window->bufferOffset()); - const QRegion opaqueShape = toplevel->opaqueRegion().translated(window->pos() + toplevel->clientPos()); - data.clip = clientShape & opaqueShape; + const WindowPixmap *windowPixmap = window->windowPixmap(); + if (windowPixmap) { + const QRegion shape = windowPixmap->mapToGlobal(windowPixmap->shape()); + const QRegion opaque = windowPixmap->mapToGlobal(windowPixmap->opaque()); + data.clip = shape & opaque; + } } else { data.clip = QRegion(); } @@ -1279,6 +1285,11 @@ QRegion WindowPixmap::shape() const return m_window->clientShape(); } +QRegion WindowPixmap::opaque() const +{ + return toplevel()->opaqueRegion().translated(toplevel()->clientPos()); +} + bool WindowPixmap::hasAlphaChannel() const { if (buffer()) @@ -1298,6 +1309,11 @@ QPointF WindowPixmap::mapToBuffer(const QPointF &point) const return point * scale(); } +QRegion WindowPixmap::mapToGlobal(const QRegion ®ion) const +{ + return region.translated(m_window->pos() + framePosition()); +} + //**************************************** // Scene::EffectFrame //**************************************** diff --git a/scene.h b/scene.h index af1bdbc67f..729212a7ae 100644 --- a/scene.h +++ b/scene.h @@ -357,9 +357,6 @@ public: return {}; } -protected: - WindowQuadList makeDecorationQuads(const QRect *rects, const QRegion ®ion, qreal textureScale = 1.0) const; - WindowQuadList makeContentsQuads() const; /** * @brief Returns the WindowPixmap for this Window. * @@ -377,6 +374,10 @@ protected: */ template T *windowPixmap() const; template T *previousWindowPixmap() const; + +protected: + WindowQuadList makeDecorationQuads(const QRect *rects, const QRegion ®ion, qreal textureScale = 1.0) const; + WindowQuadList makeContentsQuads() const; /** * @brief Factory method to create a WindowPixmap. * @@ -497,6 +498,12 @@ public: * The upper left corner of the attached buffer corresponds to (0, 0). */ QRegion shape() const; + /** + * Returns the region that specifies the opaque area inside the attached buffer. + * + * The upper left corner of the attached buffer corresponds to (0, 0). + */ + QRegion opaque() const; /** * The geometry of the Client's content inside the pixmap. In case of a decorated Client the * pixmap also contains the decoration which is not rendered into this pixmap, though. This @@ -520,6 +527,10 @@ public: * Maps the specified @a point from the window pixmap coordinates to the buffer pixel coordinates. */ QPointF mapToBuffer(const QPointF &point) const; + /** + * Maps the specified @a region from the window pixmap coordinates to the global screen coordinates. + */ + QRegion mapToGlobal(const QRegion ®ion) const; /** * @returns the parent WindowPixmap in the sub-surface tree