diff --git a/src/tiles/tile.cpp b/src/tiles/tile.cpp index 328c7043d4..e11cf4450c 100644 --- a/src/tiles/tile.cpp +++ b/src/tiles/tile.cpp @@ -372,6 +372,14 @@ Tile *Tile::parentTile() const return m_parentTile; } +void Tile::visitDescendants(std::function callback) const +{ + callback(this); + for (const Tile *child : m_children) { + child->visitDescendants(callback); + } +} + TileManager *Tile::manager() const { return m_tiling; diff --git a/src/tiles/tile.h b/src/tiles/tile.h index 8eefff400b..22e309a7c9 100644 --- a/src/tiles/tile.h +++ b/src/tiles/tile.h @@ -98,6 +98,11 @@ public: */ QList descendants() const; + /** + * Visit all tiles descendant of this tile, recursive + */ + void visitDescendants(std::function callback) const; + void resizeFromGravity(Gravity gravity, int x_root, int y_root); Q_INVOKABLE void resizeByPixels(qreal delta, Qt::Edge edge); diff --git a/src/workspace.cpp b/src/workspace.cpp index 74f4e94467..5f71da7135 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -1595,12 +1595,51 @@ void Workspace::updateOutputs(const QVector &outputOrder) Q_EMIT outputAdded(output); } - desktopResized(); - const auto removed = oldOutputsSet - outputsSet; for (Output *output : removed) { - m_tileManagers.erase(output); Q_EMIT outputRemoved(output); + auto tileManager = std::move(m_tileManagers[output]); + m_tileManagers.erase(output); + + // Evacuate windows from the defunct custom tile tree. + tileManager->rootTile()->visitDescendants([](const Tile *child) { + const QList windows = child->windows(); + for (Window *window : windows) { + window->setTile(nullptr); + } + }); + + // Migrate windows from the defunct quick tile to a quick tile tree on another output. + static constexpr QuickTileMode quickTileModes[] = { + QuickTileFlag::Left, + QuickTileFlag::Right, + QuickTileFlag::Top, + QuickTileFlag::Bottom, + QuickTileFlag::Top | QuickTileFlag::Left, + QuickTileFlag::Top | QuickTileFlag::Right, + QuickTileFlag::Bottom | QuickTileFlag::Left, + QuickTileFlag::Bottom | QuickTileFlag::Right, + }; + + for (const QuickTileMode &quickTileMode : quickTileModes) { + Tile *quickTile = tileManager->quickTile(quickTileMode); + const QList windows = quickTile->windows(); + if (windows.isEmpty()) { + continue; + } + + Output *bestOutput = outputAt(output->geometry().center()); + Tile *bestTile = m_tileManagers[bestOutput]->quickTile(quickTileMode); + + for (Window *window : windows) { + window->setTile(bestTile); + } + } + } + + desktopResized(); + + for (Output *output : removed) { output->unref(); }