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().
This commit is contained in:
Vlad Zahorodnii 2020-09-08 17:27:14 +03:00
parent c0da7faa6f
commit 2b241d3081
2 changed files with 34 additions and 7 deletions

View file

@ -284,11 +284,17 @@ void Scene::paintSimpleScreen(int orig_mask, const QRegion &region)
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<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<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 &region) const
{
return region.translated(m_window->pos() + framePosition());
}
//****************************************
// Scene::EffectFrame
//****************************************

17
scene.h
View file

@ -357,9 +357,6 @@ public:
return {};
}
protected:
WindowQuadList makeDecorationQuads(const QRect *rects, const QRegion &region, qreal textureScale = 1.0) const;
WindowQuadList makeContentsQuads() const;
/**
* @brief Returns the WindowPixmap for this Window.
*
@ -377,6 +374,10 @@ protected:
*/
template<typename T> T *windowPixmap() const;
template<typename T> T *previousWindowPixmap() const;
protected:
WindowQuadList makeDecorationQuads(const QRect *rects, const QRegion &region, 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 &region) const;
/**
* @returns the parent WindowPixmap in the sub-surface tree