x11window: round border size to integral XNative units

Both frameSize and clientSize are rounded to integral XNative units.
So their difference must also be rounded to integral XNative units.
Otherwise we get cycles of rounding that can cause growing window sizes.

BUG: 481460
This commit is contained in:
Yifan Zhu 2024-03-20 07:55:13 -07:00
parent 5c16cdd4ed
commit 111657ad04
3 changed files with 26 additions and 8 deletions

View file

@ -644,6 +644,11 @@ QSizeF fromXNative(const QSize &s)
return QSizeF(fromXNative(s.width()), fromXNative(s.height()));
}
qreal nativeRound(qreal value)
{
return fromXNative(toXNative(value));
}
static qreal nativeFloor(qreal value)
{
return std::floor(value * kwinApp()->xwaylandScale()) / kwinApp()->xwaylandScale();

View file

@ -46,6 +46,13 @@ qreal KWIN_EXPORT fromXNative(int value);
QRectF KWIN_EXPORT fromXNative(const QRect &value);
QSizeF KWIN_EXPORT fromXNative(const QSize &value);
/**
* Rounds a given value using the scale as a base
*
* Equivalent to fromXNative(toXNative(value))
*/
qreal KWIN_EXPORT nativeRound(qreal value);
/** Floors a given value to using the scale as a base
* Use when flooring to ints from Xwayland
* i.e floor(a/scale) * scale

View file

@ -2807,8 +2807,8 @@ QPointF X11Window::framePosToClientPos(const QPointF &point) const
qreal y = point.y();
if (isDecorated()) {
x += borderLeft();
y += borderTop();
x += Xcb::nativeRound(borderLeft());
y += Xcb::nativeRound(borderTop());
} else {
x -= m_clientFrameExtents.left();
y -= m_clientFrameExtents.top();
@ -2823,8 +2823,8 @@ QPointF X11Window::clientPosToFramePos(const QPointF &point) const
qreal y = point.y();
if (isDecorated()) {
x -= borderLeft();
y -= borderTop();
x -= Xcb::nativeRound(borderLeft());
y -= Xcb::nativeRound(borderTop());
} else {
x += m_clientFrameExtents.left();
y += m_clientFrameExtents.top();
@ -2839,8 +2839,11 @@ QSizeF X11Window::frameSizeToClientSize(const QSizeF &size) const
qreal height = size.height();
if (isDecorated()) {
width -= borderLeft() + borderRight();
height -= borderTop() + borderBottom();
// Both frameSize and clientSize are rounded to integral XNative units
// So their difference must also be rounded to integral XNative units
// Otherwise we get cycles of rounding that can cause growing window sizes
width -= Xcb::nativeRound(borderLeft()) + Xcb::nativeRound(borderRight());
height -= Xcb::nativeRound(borderTop()) + Xcb::nativeRound(borderBottom());
} else {
width += m_clientFrameExtents.left() + m_clientFrameExtents.right();
height += m_clientFrameExtents.top() + m_clientFrameExtents.bottom();
@ -2855,8 +2858,11 @@ QSizeF X11Window::clientSizeToFrameSize(const QSizeF &size) const
qreal height = size.height();
if (isDecorated()) {
width += borderLeft() + borderRight();
height += borderTop() + borderBottom();
// Both frameSize and clientSize are rounded to integral XNative units
// So their difference must also be rounded to integral XNative units
// Otherwise we get cycles of rounding that can cause growing window sizes
width += Xcb::nativeRound(borderLeft()) + Xcb::nativeRound(borderRight());
height += Xcb::nativeRound(borderTop()) + Xcb::nativeRound(borderBottom());
} else {
width -= m_clientFrameExtents.left() + m_clientFrameExtents.right();
height -= m_clientFrameExtents.top() + m_clientFrameExtents.bottom();