From 4f66cd4c7813625a43d3efc9f287ea7c86bacd48 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Thu, 5 Aug 2021 14:58:46 +0300 Subject: [PATCH] effects/overview: Make expo layout spacing configurable This allows setting "hidpi-aware" spacing on X11. --- src/effects/overview/expolayout.cpp | 52 ++++++++++++++++--------- src/effects/overview/expolayout.h | 6 +++ src/effects/overview/qml/WindowHeap.qml | 1 + 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/effects/overview/expolayout.cpp b/src/effects/overview/expolayout.cpp index 44045066a4..0cb5839451 100644 --- a/src/effects/overview/expolayout.cpp +++ b/src/effects/overview/expolayout.cpp @@ -231,6 +231,20 @@ void ExpoLayout::setFillGaps(bool fill) } } +int ExpoLayout::spacing() const +{ + return m_spacing; +} + +void ExpoLayout::setSpacing(int spacing) +{ + if (m_spacing != spacing) { + m_spacing = spacing; + scheduleUpdate(); + Q_EMIT spacingChanged(); + } +} + void ExpoLayout::update() { if (m_cells.isEmpty()) { @@ -340,7 +354,7 @@ void ExpoLayout::calculateWindowTransformationsClosest() QRect target(area.x() + (slot % columns) * slotWidth, area.y() + (slot / columns) * slotHeight, slotWidth, slotHeight); - target.adjust(10, 10, -10, -10); // Borders + target.adjust(m_spacing, m_spacing, -m_spacing, -m_spacing); // Borders qreal scale; if (target.width() / qreal(cell->naturalWidth()) < target.height() / qreal(cell->naturalHeight())) { @@ -393,7 +407,6 @@ void ExpoLayout::calculateWindowTransformationsKompose() }); // The location of the windows should not depend on the stacking order // Following code is taken from Kompose 0.5.4, src/komposelayout.cpp - int spacing = 10; int rows, columns; qreal parentRatio = availRect.width() / qreal(availRect.height()); // Use more columns than rows when parent's width > parent's height @@ -407,8 +420,8 @@ void ExpoLayout::calculateWindowTransformationsKompose() //qCDebug(KWINEFFECTS) << "Using " << rows << " rows & " << columns << " columns for " << windowlist.count() << " clients"; // Calculate width & height - int w = (availRect.width() - (columns + 1) * spacing) / columns; - int h = (availRect.height() - (rows + 1) * spacing) / rows; + int w = (availRect.width() - (columns + 1) * m_spacing) / columns; + int h = (availRect.height() - (rows + 1) * m_spacing) / rows; QList::iterator it(m_cells.begin()); QList geometryRects; @@ -480,8 +493,8 @@ void ExpoLayout::calculateWindowTransformationsKompose() if (j == 0 && w > widgetWidth) { alignmentXoffset = w - widgetWidth; } - QRect geom(availRect.x() + j *(w + spacing) + spacing + alignmentXoffset + xOffsetFromLastCol, - availRect.y() + i *(h + spacing) + spacing + alignmentYoffset, + QRect geom(availRect.x() + j *(w + m_spacing) + m_spacing + alignmentXoffset + xOffsetFromLastCol, + availRect.y() + i *(h + m_spacing) + m_spacing + alignmentYoffset, widgetWidth, widgetHeight); geometryRects.append(geom); @@ -523,7 +536,7 @@ void ExpoLayout::calculateWindowTransformationsKompose() } } -static bool isOverlappingAny(ExpoCell *w, const QHash &targets, const QRegion &border) +static bool isOverlappingAny(ExpoCell *w, const QHash &targets, const QRegion &border, int spacing) { QHash::const_iterator winTarget = targets.find(w); if (winTarget == targets.constEnd()) { @@ -532,6 +545,7 @@ static bool isOverlappingAny(ExpoCell *w, const QHash &target if (border.intersects(*winTarget)) { return true; } + const QMargins halfSpacing(spacing / 2, spacing / 2, spacing / 2, spacing / 2); // Is there a better way to do this? QHash::const_iterator target; @@ -539,7 +553,7 @@ static bool isOverlappingAny(ExpoCell *w, const QHash &target if (target == winTarget) { continue; } - if (winTarget->adjusted(-5, -5, 5, 5).intersects(target->adjusted(-5, -5, 5, 5))) { + if (winTarget->marginsAdded(halfSpacing).intersects(target->marginsAdded(halfSpacing))) { return true; } } @@ -587,6 +601,7 @@ void ExpoLayout::calculateWindowTransformationsNatural() // Iterate over all windows, if two overlap push them apart _slightly_ as we try to // brute-force the most optimal positions over many iterations. + const int halfSpacing = m_spacing / 2; bool overlap; do { overlap = false; @@ -598,7 +613,8 @@ void ExpoLayout::calculateWindowTransformationsNatural() } QRect *target_e = &targets[e]; - if (target_w->adjusted(-5, -5, 5, 5).intersects(target_e->adjusted(-5, -5, 5, 5))) { + if (target_w->adjusted(-halfSpacing, -halfSpacing, halfSpacing, halfSpacing) + .intersects(target_e->adjusted(-halfSpacing, -halfSpacing, halfSpacing, halfSpacing))) { overlap = true; // Determine pushing direction @@ -670,13 +686,13 @@ void ExpoLayout::calculateWindowTransformationsNatural() if (bounds == area) { scale = 1.0; // Don't add borders to the screen } else if (area.width() / qreal(bounds.width()) < area.height() / qreal(bounds.height())) { - scale = (area.width() - 20) / qreal(bounds.width()); + scale = (area.width() - 2 * m_spacing) / qreal(bounds.width()); } else { - scale = (area.height() - 20) / qreal(bounds.height()); + scale = (area.height() - 2 * m_spacing) / qreal(bounds.height()); } // Make bounding rect fill the screen size for later steps - bounds = QRect((bounds.x() * scale - (area.width() - 20 - bounds.width() * scale) / 2 - 10) / scale, - (bounds.y() * scale - (area.height() - 20 - bounds.height() * scale) / 2 - 10) / scale, + bounds = QRect((bounds.x() * scale - (area.width() - 2 * m_spacing - bounds.width() * scale) / 2 - m_spacing) / scale, + (bounds.y() * scale - (area.height() - 2 * m_spacing - bounds.height() * scale) / 2 - m_spacing) / scale, area.width() / scale, area.height() / scale); @@ -694,7 +710,7 @@ void ExpoLayout::calculateWindowTransformationsNatural() if (m_fillGaps) { // Don't expand onto or over the border QRegion borderRegion(area.adjusted(-200, -200, 200, 200)); - borderRegion ^= area.adjusted(10 / scale, 10 / scale, -10 / scale, -10 / scale); + borderRegion ^= area.adjusted(m_spacing / scale, m_spacing / scale, -m_spacing / scale, -m_spacing / scale); bool moved; do { @@ -717,7 +733,7 @@ void ExpoLayout::calculateWindowTransformationsNatural() target->y() - yDiff - heightDiff, target->width() + widthDiff, target->height() + heightDiff); - if (isOverlappingAny(cell, targets, borderRegion)) + if (isOverlappingAny(cell, targets, borderRegion, m_spacing)) *target = oldRect; else { moved = true; @@ -731,7 +747,7 @@ void ExpoLayout::calculateWindowTransformationsNatural() target->y() + yDiff, target->width() + widthDiff, target->height() + heightDiff); - if (isOverlappingAny(cell, targets, borderRegion)) + if (isOverlappingAny(cell, targets, borderRegion, m_spacing)) *target = oldRect; else { moved = true; @@ -745,7 +761,7 @@ void ExpoLayout::calculateWindowTransformationsNatural() target->y() + yDiff, target->width() + widthDiff, target->height() + heightDiff); - if (isOverlappingAny(cell, targets, borderRegion)) + if (isOverlappingAny(cell, targets, borderRegion, m_spacing)) *target = oldRect; else { moved = true; @@ -759,7 +775,7 @@ void ExpoLayout::calculateWindowTransformationsNatural() target->y() - yDiff - heightDiff, target->width() + widthDiff, target->height() + heightDiff); - if (isOverlappingAny(cell, targets, borderRegion)) { + if (isOverlappingAny(cell, targets, borderRegion, m_spacing)) { *target = oldRect; } else { moved = true; diff --git a/src/effects/overview/expolayout.h b/src/effects/overview/expolayout.h index 9fe3b42887..e6e52cedd5 100644 --- a/src/effects/overview/expolayout.h +++ b/src/effects/overview/expolayout.h @@ -20,6 +20,7 @@ class ExpoLayout : public QQuickItem Q_OBJECT Q_PROPERTY(LayoutMode mode READ mode WRITE setMode NOTIFY modeChanged) Q_PROPERTY(bool fillGaps READ fillGaps WRITE setFillGaps NOTIFY fillGapsChanged) + Q_PROPERTY(int spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) public: enum LayoutMode : uint { @@ -37,6 +38,9 @@ public: bool fillGaps() const; void setFillGaps(bool fill); + int spacing() const; + void setSpacing(int spacing); + void addCell(ExpoCell *cell); void removeCell(ExpoCell *cell); @@ -50,6 +54,7 @@ public Q_SLOTS: Q_SIGNALS: void modeChanged(); void fillGapsChanged(); + void spacingChanged(); private: void calculateWindowTransformationsClosest(); @@ -60,6 +65,7 @@ private: LayoutMode m_mode = LayoutNatural; QTimer m_updateTimer; int m_accuracy = 20; + int m_spacing = 10; bool m_fillGaps = false; }; diff --git a/src/effects/overview/qml/WindowHeap.qml b/src/effects/overview/qml/WindowHeap.qml index edf8844d57..835210ad43 100644 --- a/src/effects/overview/qml/WindowHeap.qml +++ b/src/effects/overview/qml/WindowHeap.qml @@ -29,6 +29,7 @@ FocusScope { anchors.fill: parent mode: effect.layout focus: true + spacing: PlasmaCore.Units.largeSpacing // This assumes that the position of the WindowHeap is static. readonly property point scenePosition: mapToItem(null, 0, 0)