From 111657ad04e7627d6e3c7b345a48670459cdeacc Mon Sep 17 00:00:00 2001 From: Yifan Zhu Date: Wed, 20 Mar 2024 07:55:13 -0700 Subject: [PATCH] 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 --- src/utils/xcbutils.cpp | 5 +++++ src/utils/xcbutils.h | 7 +++++++ src/x11window.cpp | 22 ++++++++++++++-------- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/utils/xcbutils.cpp b/src/utils/xcbutils.cpp index 9a6f27fd22..6dacd83f91 100644 --- a/src/utils/xcbutils.cpp +++ b/src/utils/xcbutils.cpp @@ -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(); diff --git a/src/utils/xcbutils.h b/src/utils/xcbutils.h index 3f7e137ad3..112522e196 100644 --- a/src/utils/xcbutils.h +++ b/src/utils/xcbutils.h @@ -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 diff --git a/src/x11window.cpp b/src/x11window.cpp index 717888f5ce..6b3776d7ce 100644 --- a/src/x11window.cpp +++ b/src/x11window.cpp @@ -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();