File indexing completed on 2024-05-19 05:32:27

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2022 Marco Martin <mart@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "quicktile.h"
0011 
0012 namespace KWin
0013 {
0014 
0015 QuickRootTile::QuickRootTile(TileManager *tiling, Tile *parentItem)
0016     : Tile(tiling, parentItem)
0017 {
0018     setPadding(0.0);
0019     setRelativeGeometry(QRectF(0, 0, 1, 1));
0020     setQuickTileMode(QuickTileFlag::Maximize);
0021 
0022     auto createTile = [this, &tiling](const QRectF &geometry, QuickTileMode tileMode) {
0023         Tile *tile = new Tile(tiling, this);
0024         tile->setPadding(0.0);
0025         tile->setQuickTileMode(tileMode);
0026         tile->setRelativeGeometry(geometry);
0027 
0028         connect(tile, &Tile::relativeGeometryChanged, this, [this, tile]() {
0029             relayoutToFit(tile);
0030         });
0031 
0032         return std::unique_ptr<Tile>(tile);
0033     };
0034 
0035     m_leftVerticalTile = createTile(QRectF(0, 0, 0.5, 1), QuickTileFlag::Left);
0036     m_rightVerticalTile = createTile(QRectF(0.5, 0, 0.5, 1), QuickTileFlag::Right);
0037     m_topHorizontalTile = createTile(QRectF(0, 0, 1, 0.5), QuickTileFlag::Top);
0038     m_bottomHorizontalTile = createTile(QRectF(0, 0.5, 1, 0.5), QuickTileFlag::Bottom);
0039 
0040     m_topLeftTile = createTile(QRectF(0, 0, 0.5, 0.5), QuickTileFlag::Top | QuickTileFlag::Left);
0041     m_topRightTile = createTile(QRectF(0.5, 0, 0.5, 0.5), QuickTileFlag::Top | QuickTileFlag::Right);
0042     m_bottomLeftTile = createTile(QRectF(0, 0.5, 0.5, 0.5), QuickTileFlag::Bottom | QuickTileFlag::Left);
0043     m_bottomRightTile = createTile(QRectF(0.5, 0.5, 0.5, 0.5), QuickTileFlag::Bottom | QuickTileFlag::Right);
0044 }
0045 
0046 QuickRootTile::~QuickRootTile()
0047 {
0048 }
0049 
0050 void QuickRootTile::relayoutToFit(Tile *tile)
0051 {
0052     if (m_resizedTile) {
0053         return;
0054     }
0055 
0056     m_resizedTile = tile;
0057 
0058     const QRectF geometry = tile->relativeGeometry();
0059 
0060     if (m_topHorizontalTile.get() == tile) {
0061         setVerticalSplit(geometry.bottom());
0062     } else if (m_bottomHorizontalTile.get() == tile) {
0063         setVerticalSplit(geometry.top());
0064     } else if (m_leftVerticalTile.get() == tile) {
0065         setHorizontalSplit(geometry.right());
0066     } else if (m_rightVerticalTile.get() == tile) {
0067         setHorizontalSplit(geometry.left());
0068     } else if (m_topLeftTile.get() == tile) {
0069         setHorizontalSplit(geometry.right());
0070         setVerticalSplit(geometry.bottom());
0071     } else if (m_topRightTile.get() == tile) {
0072         setHorizontalSplit(geometry.left());
0073         setVerticalSplit(geometry.bottom());
0074     } else if (m_bottomRightTile.get() == tile) {
0075         setHorizontalSplit(geometry.left());
0076         setVerticalSplit(geometry.top());
0077     } else if (m_bottomLeftTile.get() == tile) {
0078         setHorizontalSplit(geometry.right());
0079         setVerticalSplit(geometry.top());
0080     }
0081 
0082     m_resizedTile = nullptr;
0083 }
0084 
0085 Tile *QuickRootTile::tileForMode(QuickTileMode mode)
0086 {
0087     switch (mode) {
0088     case QuickTileMode(QuickTileFlag::Left):
0089         return m_leftVerticalTile.get();
0090     case QuickTileMode(QuickTileFlag::Right):
0091         return m_rightVerticalTile.get();
0092     case QuickTileMode(QuickTileFlag::Top):
0093         return m_topHorizontalTile.get();
0094     case QuickTileMode(QuickTileFlag::Bottom):
0095         return m_bottomHorizontalTile.get();
0096     case QuickTileMode(QuickTileFlag::Left | QuickTileFlag::Top):
0097         return m_topLeftTile.get();
0098     case QuickTileMode(QuickTileFlag::Right | QuickTileFlag::Top):
0099         return m_topRightTile.get();
0100     case QuickTileMode(QuickTileFlag::Left | QuickTileFlag::Bottom):
0101         return m_bottomLeftTile.get();
0102     case QuickTileMode(QuickTileFlag::Right | QuickTileFlag::Bottom):
0103         return m_bottomRightTile.get();
0104     case QuickTileMode(QuickTileFlag::Maximize):
0105     case QuickTileMode(QuickTileFlag::Horizontal):
0106     case QuickTileMode(QuickTileFlag::Vertical):
0107         return this;
0108     default:
0109         return nullptr;
0110     }
0111 }
0112 
0113 Tile *QuickRootTile::tileForBorder(ElectricBorder border)
0114 {
0115     switch (border) {
0116     case ElectricTop:
0117         return m_topHorizontalTile.get();
0118     case ElectricTopRight:
0119         return m_topRightTile.get();
0120     case ElectricRight:
0121         return m_rightVerticalTile.get();
0122     case ElectricBottomRight:
0123         return m_bottomRightTile.get();
0124     case ElectricBottom:
0125         return m_bottomHorizontalTile.get();
0126     case ElectricBottomLeft:
0127         return m_bottomLeftTile.get();
0128     case ElectricLeft:
0129         return m_leftVerticalTile.get();
0130     case ElectricTopLeft:
0131         return m_topLeftTile.get();
0132     case ElectricNone:
0133     default:
0134         return nullptr;
0135     }
0136 }
0137 
0138 qreal QuickRootTile::horizontalSplit() const
0139 {
0140     return m_leftVerticalTile->relativeGeometry().right();
0141 }
0142 
0143 void QuickRootTile::setHorizontalSplit(qreal split)
0144 {
0145     const QSizeF minSize = minimumSize(); // minimum size is the same for all tiles
0146     const qreal effectiveSplit = std::clamp(split, minSize.width(), 1.0 - minSize.width());
0147 
0148     auto geom = m_leftVerticalTile->relativeGeometry();
0149     geom.setRight(effectiveSplit);
0150     m_leftVerticalTile->setRelativeGeometry(geom);
0151 
0152     geom = m_rightVerticalTile->relativeGeometry();
0153     geom.setLeft(effectiveSplit);
0154     m_rightVerticalTile->setRelativeGeometry(geom);
0155 
0156     geom = m_topLeftTile->relativeGeometry();
0157     geom.setRight(effectiveSplit);
0158     m_topLeftTile->setRelativeGeometry(geom);
0159 
0160     geom = m_topRightTile->relativeGeometry();
0161     geom.setLeft(effectiveSplit);
0162     m_topRightTile->setRelativeGeometry(geom);
0163 
0164     geom = m_bottomLeftTile->relativeGeometry();
0165     geom.setRight(effectiveSplit);
0166     m_bottomLeftTile->setRelativeGeometry(geom);
0167 
0168     geom = m_bottomRightTile->relativeGeometry();
0169     geom.setLeft(effectiveSplit);
0170     m_bottomRightTile->setRelativeGeometry(geom);
0171 }
0172 
0173 qreal QuickRootTile::verticalSplit() const
0174 {
0175     return m_topHorizontalTile->relativeGeometry().bottom();
0176 }
0177 
0178 void QuickRootTile::setVerticalSplit(qreal split)
0179 {
0180     const QSizeF minSize = minimumSize(); // minimum size is the same for all tiles
0181     const qreal effectiveSplit = std::clamp(split, minSize.height(), 1.0 - minSize.height());
0182 
0183     auto geom = m_topHorizontalTile->relativeGeometry();
0184     geom.setBottom(effectiveSplit);
0185     m_topHorizontalTile->setRelativeGeometry(geom);
0186 
0187     geom = m_bottomHorizontalTile->relativeGeometry();
0188     geom.setTop(effectiveSplit);
0189     m_bottomHorizontalTile->setRelativeGeometry(geom);
0190 
0191     geom = m_topLeftTile->relativeGeometry();
0192     geom.setBottom(effectiveSplit);
0193     m_topLeftTile->setRelativeGeometry(geom);
0194 
0195     geom = m_topRightTile->relativeGeometry();
0196     geom.setBottom(effectiveSplit);
0197     m_topRightTile->setRelativeGeometry(geom);
0198 
0199     geom = m_bottomLeftTile->relativeGeometry();
0200     geom.setTop(effectiveSplit);
0201     m_bottomLeftTile->setRelativeGeometry(geom);
0202 
0203     geom = m_bottomRightTile->relativeGeometry();
0204     geom.setTop(effectiveSplit);
0205     m_bottomRightTile->setRelativeGeometry(geom);
0206 }
0207 
0208 } // namespace KWin
0209 
0210 #include "moc_quicktile.cpp"