From c6a3d76b927e59e01195c9fab50a2b5749fc66a6 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Fri, 5 Jan 2024 10:01:45 +0000 Subject: [PATCH] decorations: Avoid opaque areas of decorations being larger than the rendered contents Opaque is a QRegion in logical pixels, using .toRect will round to the nearest integer in either direction. This can mean an area is considered opaque outside the rendered area, leading to glitchy contents on shadows. This is most noticable on on X11 windows when fractional scaling is used. Long term I hope to move Item::opaque to QList and WindowPrePaintData::opaque to device pixels. --- src/scene/decorationitem.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/scene/decorationitem.cpp b/src/scene/decorationitem.cpp index 6d826a2cfe..133240fec1 100644 --- a/src/scene/decorationitem.cpp +++ b/src/scene/decorationitem.cpp @@ -124,7 +124,17 @@ QRegion DecorationItem::opaque() const } QRectF left, top, right, bottom; m_window->layoutDecorationRects(left, top, right, bottom); - return QRegion(left.toRect()).united(top.toRect()).united(right.toRect()).united(bottom.toRect()); + + // We have to map to integers which has rounding issues + // it's safer for a region to be considered transparent than opaque + // so always align inwards + const QMargins roundingPad = QMargins(1, 1, 1, 1); + QRegion roundedLeft = left.toAlignedRect().marginsRemoved(roundingPad); + QRegion roundedTop = top.toAlignedRect().marginsRemoved(roundingPad); + QRegion roundedRight = right.toAlignedRect().marginsRemoved(roundingPad); + QRegion roundedBottom = bottom.toAlignedRect().marginsRemoved(roundingPad); + + return roundedLeft | roundedTop | roundedRight | roundedBottom; } void DecorationItem::preprocess()