13#include "virtualdesktops.h" 
   16#include <KConfigGroup> 
   17#include <KLocalizedString> 
   18#include <KSharedConfig> 
   21#include <QJsonDocument> 
   31        QList<Tile *> tiles({tileManager->
rootTile()});
 
   32        QList<Tile *> tilePath;
 
   33        QString indent(QStringLiteral(
"|-"));
 
   34        debug << tileManager->metaObject()->className() << 
'(' << 
static_cast<const void *
>(tileManager) << 
')' << 
'\n';
 
   35        while (!tiles.isEmpty()) {
 
   36            auto *tile = tiles.last();
 
   38            debug << indent << qobject_cast<CustomTile *>(tile) << 
'\n';
 
   39            if (tile->childCount() > 0) {
 
   40                tiles.append(tile->childTiles());
 
   41                tilePath.append(tile->childTiles().first());
 
   42                indent.prepend(QStringLiteral(
"| "));
 
   44            if (!tilePath.isEmpty() && tile == tilePath.last()) {
 
 
   61    m_saveTimer = std::make_unique<QTimer>(
this);
 
   62    m_saveTimer->setSingleShot(
true);
 
   63    m_saveTimer->setInterval(2000);
 
   64    connect(m_saveTimer.get(), &QTimer::timeout, 
this, &TileManager::saveSettings);
 
   66    m_rootTile = std::make_unique<RootTile>(
this);
 
   67    m_rootTile->setRelativeGeometry(QRectF(0, 0, 1, 1));
 
   71    m_quickRootTile = std::make_unique<QuickRootTile>(
this);
 
 
   87    const auto tiles = m_rootTile->descendants();
 
   88    qreal minimumDistance = std::numeric_limits<qreal>::max();
 
   91    for (
auto *t : tiles) {
 
   95            qreal distance = (r.center() - pos).manhattanLength();
 
   96            if (!exclusiveContains(r, pos)) {
 
   99                distance += m_output->
geometryF().width();
 
  101            if (distance < minimumDistance) {
 
  102                minimumDistance = distance;
 
 
  117    return m_rootTile.get();
 
 
  122    return m_quickRootTile->tileForMode(mode);
 
 
  127    return m_tileModel.get();
 
 
  132    if (dir == QStringLiteral(
"horizontal")) {
 
  134    } 
else if (dir == QStringLiteral(
"vertical")) {
 
 
  141CustomTile *TileManager::parseTilingJSon(
const QJsonValue &val, 
const QRectF &availableArea, CustomTile *parentTile)
 
  143    if (availableArea.isEmpty()) {
 
  147    if (val.isObject()) {
 
  148        const auto &obj = val.toObject();
 
  152            QRectF rect = availableArea;
 
  153            const auto width = obj.value(QStringLiteral(
"width"));
 
  154            if (width.isDouble()) {
 
  155                rect.setWidth(std::min(width.toDouble(), availableArea.width()));
 
  157            if (!rect.isEmpty()) {
 
  158                createdTile = parentTile->createChildAt(rect, parentTile->layoutDirection(), parentTile->childCount());
 
  162            QRectF rect = availableArea;
 
  163            const auto height = obj.value(QStringLiteral(
"height"));
 
  164            if (height.isDouble()) {
 
  165                rect.setHeight(std::min(height.toDouble(), availableArea.height()));
 
  167            if (!rect.isEmpty()) {
 
  168                createdTile = parentTile->createChildAt(rect, parentTile->layoutDirection(), parentTile->childCount());
 
  172            QRectF rect(0, 0, 1, 1);
 
  173            rect = QRectF(obj.value(QStringLiteral(
"x")).toDouble(),
 
  174                          obj.value(QStringLiteral(
"y")).toDouble(),
 
  175                          obj.value(QStringLiteral(
"width")).toDouble(),
 
  176                          obj.value(QStringLiteral(
"height")).toDouble());
 
  178            if (!rect.isEmpty()) {
 
  179                createdTile = parentTile->createChildAt(rect, parentTile->layoutDirection(), parentTile->childCount());
 
  183        if (createdTile && obj.contains(QStringLiteral(
"tiles"))) {
 
  185            const auto arr = obj.value(QStringLiteral(
"tiles"));
 
  186            const auto direction = obj.value(QStringLiteral(
"layoutDirection"));
 
  188            if (arr.isArray() && arr.toArray().count() > 0) {
 
  190                createdTile->setLayoutDirection(dir);
 
  191                parseTilingJSon(arr, createdTile->relativeGeometry(), createdTile);
 
  195    } 
else if (val.isArray()) {
 
  196        const auto arr = val.toArray();
 
  197        auto avail = availableArea;
 
  198        for (
auto it = arr.cbegin(); it != arr.cend(); it++) {
 
  199            if ((*it).isObject()) {
 
  200                auto *tile = parseTilingJSon(*it, avail, parentTile);
 
  202                    avail.setLeft(tile->relativeGeometry().right());
 
  204                    avail.setTop(tile->relativeGeometry().bottom());
 
  210            && parentTile->childCount() > 0) {
 
  211            auto *last = parentTile->childTile(parentTile->childCount() - 1);
 
  212            auto geom = last->relativeGeometry();
 
  213            geom.setRight(parentTile->relativeGeometry().right());
 
  214            last->setRelativeGeometry(geom);
 
  221void TileManager::readSettings()
 
  223    KConfigGroup cg = kwinApp()->config()->group(QStringLiteral(
"Tiling"));
 
  224    qreal padding = cg.readEntry(
"padding", 4);
 
  225    cg = KConfigGroup(&cg, m_output->
uuid().toString(QUuid::WithoutBraces));
 
  227    auto createDefaultSetup = [
this]() {
 
  228        Q_ASSERT(m_rootTile->childCount() == 0);
 
  233        Q_ASSERT(m_rootTile->childCount() == 3);
 
  235        m_rootTile->childTile(1)->setRelativeGeometry({0.25, 0.0, 0.5, 1.0});
 
  238    QJsonParseError error;
 
  239    const auto tiles = cg.readEntry(
"tiles", QByteArray());
 
  240    if (tiles.isEmpty()) {
 
  241        qCDebug(KWIN_CORE) << 
"Empty tiles configuration for monitor" << m_output->
uuid().toString(QUuid::WithoutBraces) << 
":" 
  242                           << 
"Creating default setup";
 
  243        createDefaultSetup();
 
  246    QJsonDocument doc = QJsonDocument::fromJson(tiles, &error);
 
  248    if (error.error != QJsonParseError::NoError) {
 
  249        qCWarning(KWIN_CORE) << 
"Parse error in tiles configuration for monitor" << m_output->
uuid().toString(QUuid::WithoutBraces) << 
":" << error.errorString() << 
"Creating default setup";
 
  250        createDefaultSetup();
 
  254    if (doc.object().contains(QStringLiteral(
"tiles"))) {
 
  255        const auto arr = doc.object().value(QStringLiteral(
"tiles"));
 
  256        if (arr.isArray() && arr.toArray().count() > 0) {
 
  257            m_rootTile->setLayoutDirection(
strToLayoutDirection(doc.object().value(QStringLiteral(
"layoutDirection")).toString()));
 
  258            parseTilingJSon(arr, QRectF(0, 0, 1, 1), m_rootTile.get());
 
  262    m_rootTile->setPadding(padding);
 
  265QJsonObject TileManager::tileToJSon(CustomTile *tile)
 
  269    auto *parentTile = 
static_cast<CustomTile *
>(tile->parentTile());
 
  273        switch (parentTile->layoutDirection()) {
 
  275            obj[QStringLiteral(
"width")] = tile->relativeGeometry().width();
 
  278            obj[QStringLiteral(
"height")] = tile->relativeGeometry().height();
 
  282            obj[QStringLiteral(
"x")] = tile->relativeGeometry().x();
 
  283            obj[QStringLiteral(
"y")] = tile->relativeGeometry().y();
 
  284            obj[QStringLiteral(
"width")] = tile->relativeGeometry().width();
 
  285            obj[QStringLiteral(
"height")] = tile->relativeGeometry().height();
 
  289    if (tile->isLayout()) {
 
  290        switch (tile->layoutDirection()) {
 
  292            obj[QStringLiteral(
"layoutDirection")] = QStringLiteral(
"horizontal");
 
  295            obj[QStringLiteral(
"layoutDirection")] = QStringLiteral(
"vertical");
 
  299            obj[QStringLiteral(
"layoutDirection")] = QStringLiteral(
"floating");
 
  303        const int nChildren = tile->childCount();
 
  304        for (
int i = 0; i < nChildren; ++i) {
 
  305            tiles.append(tileToJSon(
static_cast<CustomTile *
>(tile->childTile(i))));
 
  307        obj[QStringLiteral(
"tiles")] = tiles;
 
  313void TileManager::saveSettings()
 
  315    auto obj = tileToJSon(m_rootTile.get());
 
  316    QJsonDocument doc(obj);
 
  317    KConfigGroup cg = kwinApp()->config()->group(QStringLiteral(
"Tiling"));
 
  318    cg.writeEntry(
"padding", m_rootTile->padding());
 
  319    cg = KConfigGroup(&cg, m_output->
uuid().toString(QUuid::WithoutBraces));
 
  320    cg.writeEntry(
"tiles", doc.toJson(QJsonDocument::Compact));
 
  326#include "moc_tilemanager.cpp" 
void paddingChanged(qreal padding)
TileManager(Output *parent=nullptr)
KWin::Tile * quickTile(QuickTileMode mode) const
KWin::Tile * bestTileForPosition(const QPointF &pos)
Tile::LayoutDirection strToLayoutDirection(const QString &dir)
QDebug & operator<<(QDebug &s, const KWin::DrmConnector *obj)