[plasma/kwin] src/plugins/private: Port ExpoLayout to RectF

Vlad Zahorodnii <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 46109da23e938214c7fbb86cb9434863fb42e55a by Vlad Zahorodnii.
Committed on 23/07/2026 at 06:04.
Pushed by vladz into branch 'master'.

Port ExpoLayout to RectF

M  +27   -27   src/plugins/private/expolayout.cpp
M  +9    -10   src/plugins/private/expolayout.h

https://invent.kde.org/plasma/kwin/-/commit/46109da23e938214c7fbb86cb9434863fb42e55a

diff --git a/src/plugins/private/expolayout.cpp b/src/plugins/private/expolayout.cpp
index 76f1373c754..c07db4cda3b 100644
--- a/src/plugins/private/expolayout.cpp
+++ b/src/plugins/private/expolayout.cpp
@@ -231,9 +231,9 @@ void ExpoCell::setNaturalHeight(qreal height)
     }
 }
 
-QRectF ExpoCell::naturalRect() const
+KWin::RectF ExpoCell::naturalRect() const
 {
-    return QRectF(m_naturalX, m_naturalY, m_naturalWidth, m_naturalHeight);
+    return KWin::RectF(m_naturalX, m_naturalY, m_naturalWidth, m_naturalHeight);
 }
 
 QMarginsF ExpoCell::margins() const
@@ -281,7 +281,7 @@ void ExpoCell::updateContentItemGeometry()
         return;
     }
 
-    QRectF rect = mapRectToItem(m_contentItem->parentItem(), boundingRect());
+    KWin::RectF rect = mapRectToItem(m_contentItem->parentItem(), boundingRect());
 
     rect = {
         rect.x() * m_partialActivationFactor + (m_naturalX + m_offsetX) * (1.0 - m_partialActivationFactor),
@@ -360,7 +360,7 @@ void ExpoLayout::geometryChange(const QRectF &newGeometry, const QRectF &oldGeom
 }
 
 // Move and scale rect to fit inside area
-static void moveToFit(QRectF &rect, const QRectF &area)
+static void moveToFit(KWin::RectF &rect, const KWin::RectF &area)
 {
     qreal scale = std::min(area.width() / rect.width(), area.height() / rect.height());
     rect.setWidth(rect.width() * scale);
@@ -375,7 +375,7 @@ void ExpoLayout::updatePolish()
         return;
     }
 
-    QRectF area = QRectF(0, 0, width(), height());
+    KWin::RectF area = KWin::RectF(0, 0, width(), height());
 
     std::sort(m_cells.begin(), m_cells.end(), [](const ExpoCell *a, const ExpoCell *b) {
         return a->persistentKey() < b->persistentKey();
@@ -390,7 +390,7 @@ void ExpoLayout::updatePolish()
     qreal scale = std::sqrt(availableArea / totalArea) * 0.7; // conservative estimate
     scale = std::clamp(scale, 0.1, 10.0); // don't go crazy
 
-    QList<QRectF> windowSizes;
+    QList<KWin::RectF> windowSizes;
     for (ExpoCell *cell : std::as_const(m_cells)) {
         const QMarginsF &margins = cell->margins();
         const QMarginsF scaledMargins(margins.left() / scale, margins.top() / scale, margins.right() / scale, margins.bottom() / scale);
@@ -399,14 +399,14 @@ void ExpoLayout::updatePolish()
     auto windowLayouts = ExpoLayout::layout(area, windowSizes);
     for (int i = 0; i < windowLayouts.size(); ++i) {
         ExpoCell *cell = m_cells[i];
-        QRectF target = windowLayouts[i];
+        KWin::RectF target = windowLayouts[i];
 
-        QRectF adjustedTarget = target.marginsRemoved(cell->margins());
+        KWin::RectF adjustedTarget = target.marginsRemoved(cell->margins());
         if (adjustedTarget.isValid()) {
             target = adjustedTarget; // Borders
         }
 
-        QRectF rect = cell->naturalRect();
+        KWin::RectF rect = cell->naturalRect();
         moveToFit(rect, target);
         if (m_ready) {
             // Use setProperty so the QML side can animate with Behavior
@@ -424,7 +424,7 @@ void ExpoLayout::updatePolish()
     setReady();
 }
 
-Layer::Layer(qreal maxWidth, const QList<QRectF> &windowSizes, const QList<size_t> &windowIds, size_t startPos, size_t endPos)
+Layer::Layer(qreal maxWidth, const QList<KWin::RectF> &windowSizes, const QList<size_t> &windowIds, size_t startPos, size_t endPos)
     : maxWidth(maxWidth)
     , maxHeight(windowSizes[windowIds[endPos - 1]].height())
     , ids(windowIds.begin() + startPos, windowIds.begin() + endPos)
@@ -440,7 +440,7 @@ qreal Layer::width() const
     return maxWidth - remainingWidth;
 }
 
-LayeredPacking::LayeredPacking(qreal maxWidth, const QList<QRectF> &windowSizes, const QList<size_t> &ids, const QList<size_t> &layerStartPos)
+LayeredPacking::LayeredPacking(qreal maxWidth, const QList<KWin::RectF> &windowSizes, const QList<size_t> &ids, const QList<size_t> &layerStartPos)
     : maxWidth(maxWidth)
     , width(0)
     , height(0)
@@ -650,9 +650,9 @@ static QMarginsF reflect(const QMarginsF &margins)
 {
     return QMarginsF(margins.top(), margins.right(), margins.bottom(), margins.left());
 }
-static QRectF reflect(const QRectF &rect)
+static KWin::RectF reflect(const KWin::RectF &rect)
 {
-    return QRectF(rect.y(), rect.x(), rect.height(), rect.width());
+    return KWin::RectF(rect.y(), rect.x(), rect.height(), rect.width());
 }
 static QPointF reflect(const QPointF &point)
 {
@@ -669,7 +669,7 @@ static QList<T> reflect(const QList<T> &v)
     return result;
 }
 
-QList<QRectF> ExpoLayout::layout(const QRectF &area, const QList<QRectF> &windowSizes)
+QList<KWin::RectF> ExpoLayout::layout(const KWin::RectF &area, const QList<KWin::RectF> &windowSizes)
 {
     const qreal shortSide = std::min(area.width(), area.height());
     const QMarginsF margins(shortSide * m_relativeMarginLeft,
@@ -677,21 +677,21 @@ QList<QRectF> ExpoLayout::layout(const QRectF &area, const QList<QRectF> &window
                             shortSide * m_relativeMarginRight,
                             shortSide * m_relativeMarginBottom);
     const qreal minLength = m_relativeMinLength * shortSide;
-    const QRectF minSize = QRectF(0, 0, minLength, minLength);
+    const KWin::RectF minSize = KWin::RectF(0, 0, minLength, minLength);
 
     QList<QPointF> centers;
-    for (const QRectF &windowSize : windowSizes) {
+    for (const KWin::RectF &windowSize : windowSizes) {
         centers.push_back(windowSize.center());
     }
 
     // windows bigger than 4x the area are considered ill-behaved and their sizes are clipped
-    const auto adjustedSizes = adjustSizes(minSize, QRectF(0, 0, 4 * area.width(), 4 * area.height()), margins, windowSizes);
+    const auto adjustedSizes = adjustSizes(minSize, KWin::RectF(0, 0, 4 * area.width(), 4 * area.height()), margins, windowSizes);
 
     if (placementMode() == PlacementMode::Rows) {
         LayeredPacking bestPacking = findGoodPacking(area, adjustedSizes, centers, m_idealWidthRatio, m_searchTolerance);
         return refineAndApplyPacking(area, margins, bestPacking, adjustedSizes, centers);
     } else {
-        QList<QRectF> adjustedSizesReflected(reflect(adjustedSizes));
+        QList<KWin::RectF> adjustedSizesReflected(reflect(adjustedSizes));
         QList<QPointF> centersReflected(reflect(centers));
 
         LayeredPacking bestPacking = findGoodPacking(area.transposed(), adjustedSizesReflected, centersReflected, m_idealWidthRatio, m_searchTolerance);
@@ -699,10 +699,10 @@ QList<QRectF> ExpoLayout::layout(const QRectF &area, const QList<QRectF> &window
     }
 }
 
-QList<QRectF> ExpoLayout::adjustSizes(const QRectF &minSize, const QRectF &maxSize, const QMarginsF &margins, const QList<QRectF> &windowSizes)
+QList<KWin::RectF> ExpoLayout::adjustSizes(const KWin::RectF &minSize, const KWin::RectF &maxSize, const QMarginsF &margins, const QList<KWin::RectF> &windowSizes)
 {
-    QList<QRectF> adjustedSizes;
-    for (QRectF windowSize : windowSizes) {
+    QList<KWin::RectF> adjustedSizes;
+    for (KWin::RectF windowSize : windowSizes) {
         windowSize.setWidth(std::clamp(windowSize.width(), minSize.width(), maxSize.width()));
         windowSize.setHeight(std::clamp(windowSize.height(), minSize.height(), maxSize.height()));
         windowSize += margins;
@@ -712,9 +712,9 @@ QList<QRectF> ExpoLayout::adjustSizes(const QRectF &minSize, const QRectF &maxSi
 }
 
 LayeredPacking
-ExpoLayout::findGoodPacking(const QRectF &area, const QList<QRectF> &windowSizes, const QList<QPointF> &centers, qreal idealWidthRatio, qreal tol)
+ExpoLayout::findGoodPacking(const KWin::RectF &area, const QList<KWin::RectF> &windowSizes, const QList<QPointF> &centers, qreal idealWidthRatio, qreal tol)
 {
-    QList<std::tuple<size_t, QRectF, QPointF>> windowSizesWithIds;
+    QList<std::tuple<size_t, KWin::RectF, QPointF>> windowSizesWithIds;
 
     for (int i = 0; i < windowSizes.size(); ++i) {
         windowSizesWithIds.emplace_back(i, windowSizes[i], centers[i]);
@@ -803,7 +803,7 @@ ExpoLayout::findGoodPacking(const QRectF &area, const QList<QRectF> &windowSizes
     }
 }
 
-QList<QRectF> ExpoLayout::refineAndApplyPacking(const QRectF &area, const QMarginsF &margins, const LayeredPacking &packing, const QList<QRectF> &windowSizes, const QList<QPointF> &centers)
+QList<KWin::RectF> ExpoLayout::refineAndApplyPacking(const KWin::RectF &area, const QMarginsF &margins, const LayeredPacking &packing, const QList<KWin::RectF> &windowSizes, const QList<QPointF> &centers)
 {
     // Scale packing to fit area
     qreal scale = std::min(area.width() / packing.width, area.height() / packing.height);
@@ -821,7 +821,7 @@ QList<QRectF> ExpoLayout::refineAndApplyPacking(const QRectF &area, const QMargi
     qreal gapY = std::min(maxGapY, extraY / (packing.layers.size() + 1));
     qreal y = area.y() + (extraY - gapY * (packing.layers.size() - 1)) / 2;
 
-    QList<QRectF> finalWindowLayouts(windowSizes);
+    QList<KWin::RectF> finalWindowLayouts(windowSizes);
     // smaller windows "float" to the top
     for (const auto &layer : packing.layers) {
         qreal extraX = area.width() - layer.width() * scale;
@@ -833,9 +833,9 @@ QList<QRectF> ExpoLayout::refineAndApplyPacking(const QRectF &area, const QMargi
             return centers[a].x() < centers[b].x(); // minimize horizontal movement
         });
         for (auto id : std::as_const(ids)) {
-            QRectF &windowLayout = finalWindowLayouts[id];
+            KWin::RectF &windowLayout = finalWindowLayouts[id];
             qreal newY = y + (layer.maxHeight - windowLayout.height()) * scale / 2; // center align y
-            windowLayout = QRectF(x, newY, windowLayout.width() * scale, windowLayout.height() * scale);
+            windowLayout = KWin::RectF(x, newY, windowLayout.width() * scale, windowLayout.height() * scale);
             x += windowLayout.width() + gapX;
             windowLayout -= scaledMargins;
         }
diff --git a/src/plugins/private/expolayout.h b/src/plugins/private/expolayout.h
index 99f6957b728..69db73ae8ab 100644
--- a/src/plugins/private/expolayout.h
+++ b/src/plugins/private/expolayout.h
@@ -7,12 +7,11 @@
 
 #pragma once
 
+#include "core/rect.h"
+
 #include <QList>
 #include <QObject>
 #include <QQuickItem>
-#include <QRect>
-
-#include <optional>
 
 class ExpoCell;
 struct Layer;
@@ -116,14 +115,14 @@ protected:
      *
      * This is the main entry point for the layout algorithm.
      */
-    QList<QRectF> layout(const QRectF &area, const QList<QRectF> &windowSizes);
+    QList<KWin::RectF> layout(const KWin::RectF &area, const QList<KWin::RectF> &windowSizes);
 
     /**
      * @brief First clip @param windowSizes to be between @param minSize and
      * @param maxSize. Then add @param margins to each window size, and @return
      * the adjusted window sizes.
      */
-    QList<QRectF> adjustSizes(const QRectF &minSize, const QRectF &maxSize, const QMarginsF &margins, const QList<QRectF> &windowSizes);
+    QList<KWin::RectF> adjustSizes(const KWin::RectF &minSize, const KWin::RectF &maxSize, const QMarginsF &margins, const QList<KWin::RectF> &windowSizes);
 
     /**
      * @brief Use binary search to find a good packing of the @param windowSizes
@@ -145,7 +144,7 @@ protected:
      * Since we clip the window size, this is just O(n log n log log n)
      */
     LayeredPacking
-    findGoodPacking(const QRectF &area, const QList<QRectF> &windowSizes, const QList<QPointF> &centers, qreal idealWidthRatio, qreal tol);
+    findGoodPacking(const KWin::RectF &area, const QList<KWin::RectF> &windowSizes, const QList<QPointF> &centers, qreal idealWidthRatio, qreal tol);
 
     /**
      * @brief LogicalOutput the final window layouts from the packing.
@@ -155,7 +154,7 @@ protected:
      * and @return the final layout.
      * In each layer, sort the windows by x coordinates of the @param centers.
      */
-    QList<QRectF> refineAndApplyPacking(const QRectF &area, const QMarginsF &margins, const LayeredPacking &packing, const QList<QRectF> &windowSizes, const QList<QPointF> &centers);
+    QList<KWin::RectF> refineAndApplyPacking(const KWin::RectF &area, const QMarginsF &margins, const LayeredPacking &packing, const QList<KWin::RectF> &windowSizes, const QList<QPointF> &centers);
 
 Q_SIGNALS:
     void placementModeChanged();
@@ -238,7 +237,7 @@ public:
     qreal naturalHeight() const;
     void setNaturalHeight(qreal height);
 
-    QRectF naturalRect() const;
+    KWin::RectF naturalRect() const;
     QMarginsF margins() const;
 
     QString persistentKey() const;
@@ -314,7 +313,7 @@ struct Layer
      * @param startPos windowIds[startPos] is the first window in this layer.
      * @param endPos windowIds[endPos-1] is the last window in this layer.
      */
-    Layer(qreal maxWidth, const QList<QRectF> &windowSizes, const QList<size_t> &windowIds, size_t startPos, size_t endPos);
+    Layer(qreal maxWidth, const QList<KWin::RectF> &windowSizes, const QList<size_t> &windowIds, size_t startPos, size_t endPos);
 
     /**
      * @brief The total width of all the windows in this layer.
@@ -344,5 +343,5 @@ struct LayeredPacking
      * @param layerStartPos Array of indices into ids that indicate the start
      * of a new layer. Must start with 0 and end with ids.size().
      */
-    LayeredPacking(qreal maxWidth, const QList<QRectF> &windowSizes, const QList<size_t> &ids, const QList<size_t> &layerStartPos);
+    LayeredPacking(qreal maxWidth, const QList<KWin::RectF> &windowSizes, const QList<size_t> &ids, const QList<size_t> &layerStartPos);
 };
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.