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<QRectF> and
WindowPrePaintData::opaque to device pixels.
This commit is contained in:
David Edmundson 2024-01-05 10:01:45 +00:00
parent b36894884e
commit c6a3d76b92

View file

@ -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()