/* * Copyright 2019 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "synchronizer.h" //! local #include "importer.h" #include "manager.h" #include "../apptypes.h" #include "../data/layoutdata.h" #include "../lattecorona.h" #include "../layout/centrallayout.h" #include "../layout/genericlayout.h" #include "../settings/universalsettings.h" #include "../templates/templatesmanager.h" #include "../view/view.h" // Qt #include #include // Plasma #include // KDE #include #include #include #define LAYOUTSINITINTERVAL 350 namespace Latte { namespace Layouts { Synchronizer::Synchronizer(QObject *parent) : QObject(parent), m_activitiesController(new KActivities::Controller) { m_manager = qobject_cast(parent); connect(this, &Synchronizer::layoutsChanged, this, &Synchronizer::reloadAssignedLayouts); //! KWin update Disabled Borders connect(this, &Synchronizer::centralLayoutsChanged, this, &Synchronizer::updateKWinDisabledBorders); connect(m_manager->corona()->universalSettings(), &UniversalSettings::canDisableBordersChanged, this, &Synchronizer::updateKWinDisabledBorders); //! KActivities tracking connect(m_manager->corona()->activitiesConsumer(), &KActivities::Consumer::activityRemoved, this, &Synchronizer::onActivityRemoved); connect(m_manager->corona()->activitiesConsumer(), &KActivities::Consumer::currentActivityChanged, this, &Synchronizer::onCurrentActivityChanged); connect(m_manager->corona()->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged, this, [&]() { if (m_manager->memoryUsage() == MemoryUsage::MultipleLayouts) { syncMultipleLayoutsToActivities(); } }); } Synchronizer::~Synchronizer() { m_activitiesController->deleteLater(); } KActivities::Controller *Synchronizer::activitiesController() const { return m_activitiesController; } bool Synchronizer::latteViewExists(Latte::View *view) const { for (const auto layout : m_centralLayouts) { for (const auto &v : layout->latteViews()) { if (v == view) { return true; } } } return false; } bool Synchronizer::layoutExists(QString layoutName) const { return m_layouts.containsName(layoutName); } bool Synchronizer::isAssigned(QString layoutName) const { for(auto activityid : m_assignedLayouts.keys()) { if (m_assignedLayouts[activityid].contains(layoutName)) { return true; } } return false; } int Synchronizer::centralLayoutPos(QString id) const { for (int i = 0; i < m_centralLayouts.size(); ++i) { CentralLayout *layout = m_centralLayouts.at(i); if (layout->name() == id) { return i; } } return -1; } QString Synchronizer::layoutPath(QString layoutName) { QString path = Layouts::Importer::layoutUserFilePath(layoutName); if (!QFile(path).exists()) { path = ""; } return path; } QStringList Synchronizer::activities() { return m_manager->corona()->activitiesConsumer()->activities(); } QStringList Synchronizer::freeActivities() { QStringList frees = activities(); for(auto assigned : m_assignedLayouts.keys()) { frees.removeAll(assigned); } return frees; } QStringList Synchronizer::runningActivities() { return m_manager->corona()->activitiesConsumer()->runningActivities(); } QStringList Synchronizer::freeRunningActivities() { QStringList fActivities; for (const auto &activity : runningActivities()) { if (!m_assignedLayouts.contains(activity)) { fActivities.append(activity); } } return fActivities; } QStringList Synchronizer::validActivities(const QStringList &layoutActivities) { QStringList valids; QStringList allactivities = activities(); for(auto activity : layoutActivities) { if (allactivities.contains(activity)) { valids << activity; } } return valids; } QStringList Synchronizer::centralLayoutsNames() { QStringList names; if (m_manager->memoryUsage() == MemoryUsage::SingleLayout) { names << m_centralLayouts.at(0)->name(); } else { for (int i = 0; i < m_centralLayouts.size(); ++i) { CentralLayout *layout = m_centralLayouts.at(i); names << layout->name(); } } return names; } QStringList Synchronizer::currentLayoutsNames() const { QList currents = currentLayouts(); QStringList currentNames; for (int i = 0; i < currents.size(); ++i) { CentralLayout *layout = currents.at(i); currentNames << layout->name(); } return currentNames; } QStringList Synchronizer::layouts() const { return m_layouts.names(); } QStringList Synchronizer::menuLayouts() const { QStringList menulayouts; for (int i=0; iname())) { menulayouts.prepend(layout->name()); } } return menulayouts; } void Synchronizer::setIsSingleLayoutInDeprecatedRenaming(const bool &enabled) { m_isSingleLayoutInDeprecatedRenaming = enabled; } Data::LayoutsTable Synchronizer::layoutsTable() const { return m_layouts; } void Synchronizer::setLayoutsTable(const Data::LayoutsTable &table) { if (m_layouts == table) { return; } m_layouts = table; emit layoutsChanged(); } void Synchronizer::updateLayoutsTable() { for (int i = 0; i < m_centralLayouts.size(); ++i) { CentralLayout *layout = m_centralLayouts.at(i); if (m_layouts.containsId(layout->file())) { m_layouts[layout->file()] = layout->data(); } } for (int i = 0; i < m_layouts.rowCount(); ++i) { if (m_layouts[i].isBroken && !m_layouts[i].isActive) { CentralLayout central(this, m_layouts[i].id); m_layouts[i].isBroken = central.isBroken(); } } } CentralLayout *Synchronizer::centralLayout(QString layoutname) const { for (int i = 0; i < m_centralLayouts.size(); ++i) { CentralLayout *layout = m_centralLayouts.at(i); if (layout->name() == layoutname) { return layout; } } return nullptr; } QList Synchronizer::currentLayouts() const { QList layouts; if (m_manager->memoryUsage() == MemoryUsage::SingleLayout) { layouts << m_centralLayouts.at(0); } else { for (auto layout : m_centralLayouts) { if (layout->isOnAllActivities() || layout->appliedActivities().contains(m_manager->corona()->activitiesConsumer()->currentActivity())) { layouts << layout; } } } return layouts; } QList Synchronizer::centralLayoutsForActivity(const QString activityid) const { QList layouts; if (m_manager->memoryUsage() == MemoryUsage::SingleLayout && m_centralLayouts.count() >= 1) { layouts << m_centralLayouts.at(0); } else { for (auto layout : m_centralLayouts) { if (layout->isOnAllActivities() || layout->appliedActivities().contains(activityid)) { layouts << layout; } } } return layouts; } QList Synchronizer::currentViews() const { QList views; for(auto layout : currentLayouts()) { views << layout->latteViews(); } return views; } QList Synchronizer::currentViewsWithPlasmaShortcuts() const { QList views; for(auto layout : currentLayouts()) { views << layout->viewsWithPlasmaShortcuts(); } return views; } QList Synchronizer::sortedCurrentViews() const { QList views = currentViews(); return Layout::GenericLayout::sortedLatteViews(views); } QList Synchronizer::viewsBasedOnActivityId(const QString &id) const { QList views; for(auto layout : centralLayoutsForActivity(id)) { if (m_centralLayouts.contains(layout)) { views << layout->latteViews(); } } return views; } Layout::GenericLayout *Synchronizer::layout(QString layoutname) const { Layout::GenericLayout *l = centralLayout(layoutname); return l; } Latte::View *Synchronizer::viewForContainment(uint id) { for (auto layout : m_centralLayouts) { Latte::View *view = layout->viewForContainment(id); if (view) { return view; } } return nullptr; } Latte::View *Synchronizer::viewForContainment(Plasma::Containment *containment) { for (auto layout : m_centralLayouts) { Latte::View *view = layout->viewForContainment(containment); if (view) { return view; } } return nullptr; } void Synchronizer::addLayout(CentralLayout *layout) { if (!m_centralLayouts.contains(layout)) { m_centralLayouts.append(layout); layout->initToCorona(m_manager->corona()); } } void Synchronizer::onActivityRemoved(const QString &activityid) { if (!m_assignedLayouts.contains(activityid)) { return; } //! remove any other explicit set layouts for the current activity QStringList explicits = m_assignedLayouts[activityid]; for(auto explicitlayoutname : explicits) { QString explicitlayoutid = m_layouts.idForName(explicitlayoutname); m_layouts[explicitlayoutid].activities.removeAll(activityid); m_manager->setOnActivities(explicitlayoutname, m_layouts[explicitlayoutid].activities); emit layoutActivitiesChanged(m_layouts[explicitlayoutid]); } QStringList freelayoutnames; if (m_assignedLayouts.contains(Data::Layout::FREEACTIVITIESID)) { freelayoutnames = m_assignedLayouts[Data::Layout::FREEACTIVITIESID]; } reloadAssignedLayouts(); for(auto freelayoutname : freelayoutnames) { //! inform free activities layouts that their activities probably changed CentralLayout *central = centralLayout(freelayoutname); if (central) { emit central->activitiesChanged(); } } } void Synchronizer::onCurrentActivityChanged(const QString &activityid) { if (m_manager->memoryUsage() == MemoryUsage::MultipleLayouts) { updateKWinDisabledBorders(); } } void Synchronizer::hideAllViews() { for (const auto layout : m_centralLayouts) { emit currentLayoutIsSwitching(layout->name()); } } void Synchronizer::pauseLayout(QString layoutName) { if (m_manager->memoryUsage() == MemoryUsage::MultipleLayouts) { CentralLayout *layout = centralLayout(layoutName); if (layout->isOnAllActivities()) { return; } QStringList appliedactivities = layout->appliedActivities(); if (layout && !appliedactivities.isEmpty()) { int i = 0; for (const auto &activityid : appliedactivities) { //! Stopping the activities must be done asynchronous because otherwise //! the activity manager cant close multiple activities QTimer::singleShot(i * 1000, [this, activityid]() { m_activitiesController->stopActivity(activityid); }); i = i + 1; } } } } void Synchronizer::syncActiveLayoutsToOriginalFiles() { if (m_manager->memoryUsage() == MemoryUsage::MultipleLayouts) { for (const auto layout : m_centralLayouts) { layout->syncToLayoutFile(); } } } void Synchronizer::syncLatteViewsToScreens() { for (const auto layout : m_centralLayouts) { layout->syncLatteViewsToScreens(); } } void Synchronizer::unloadCentralLayout(CentralLayout *layout) { int pos = m_centralLayouts.indexOf(layout); if (pos>=0) { CentralLayout *central = m_centralLayouts.takeAt(pos); if (m_multipleModeInitialized) { central->syncToLayoutFile(true); } central->unloadLatteViews(); central->unloadContainments(); if (m_multipleModeInitialized) { m_manager->clearUnloadedContainmentsFromLinkedFile(central->unloadedContainmentsIds(), true); } delete central; } } void Synchronizer::initLayouts() { m_layouts.clear(); QDir layoutDir(Layouts::Importer::layoutUserDir()); QStringList filter; filter.append(QString("*.layout.latte")); QStringList files = layoutDir.entryList(filter, QDir::Files | QDir::NoSymLinks); for (const auto &layout : files) { if (layout.contains(Layout::MULTIPLELAYOUTSHIDDENNAME)) { //! IMPORTANT: DON'T ADD MultipleLayouts hidden file in layouts list continue; } QString layoutpath = layoutDir.absolutePath() + "/" + layout; onLayoutAdded(layoutpath); } emit layoutsChanged(); if (!m_isLoaded) { m_isLoaded = true; connect(m_manager->corona()->templatesManager(), &Latte::Templates::Manager::newLayoutAdded, this, &Synchronizer::onLayoutAdded); connect(m_manager->importer(), &Latte::Layouts::Importer::newLayoutAdded, this, &Synchronizer::onLayoutAdded); } } void Synchronizer::onLayoutAdded(const QString &layout) { CentralLayout centrallayout(this, layout); m_layouts.insertBasedOnName(centrallayout.data()); if (m_isLoaded) { emit layoutsChanged(); } } void Synchronizer::reloadAssignedLayouts() { m_assignedLayouts.clear(); for (int i=0; i< m_layouts.rowCount(); ++i) { for (const auto &activity : m_layouts[i].activities) { if (m_assignedLayouts.contains(activity)) { m_assignedLayouts[activity] << m_layouts[i].name; } else { m_assignedLayouts[activity] = QStringList(m_layouts[i].name); } } } } void Synchronizer::unloadLayouts() { //! Unload all CentralLayouts while (!m_centralLayouts.isEmpty()) { CentralLayout *layout = m_centralLayouts.at(0); unloadCentralLayout(layout); } m_multipleModeInitialized = false; } bool Synchronizer::memoryInitialized() const { return ((m_manager->memoryUsage() == MemoryUsage::SingleLayout && m_centralLayouts.size()>0) || (m_manager->memoryUsage() == MemoryUsage::MultipleLayouts && m_multipleModeInitialized)); } bool Synchronizer::initSingleMode(QString layoutName) { QString layoutpath = layoutName.isEmpty() ? layoutPath(m_manager->corona()->universalSettings()->singleModeLayoutName()) : layoutPath(layoutName); if (layoutpath.isEmpty()) { qDebug() << "Layout : " << layoutName << " was not found..."; return false; } if (m_centralLayouts.size() > 0) { emit currentLayoutIsSwitching(m_centralLayouts[0]->name()); } //! this code must be called asynchronously because it can create crashes otherwise. //! Tasks plasmoid case that triggers layouts switching through its context menu QTimer::singleShot(LAYOUTSINITINTERVAL, [this, layoutName, layoutpath]() { qDebug() << " ... initializing layout in single mode : " << layoutName << " - " << layoutpath; unloadLayouts(); //! load the main layout/corona file CentralLayout *newLayout = new CentralLayout(this, layoutpath, layoutName); addLayout(newLayout); m_manager->loadLatteLayout(layoutpath); emit centralLayoutsChanged(); if (m_isSingleLayoutInDeprecatedRenaming) { QString deprecatedlayoutpath = layoutPath(m_manager->corona()->universalSettings()->singleModeLayoutName()); if (!deprecatedlayoutpath.isEmpty()) { qDebug() << "Removing Deprecated single layout after renaming:: " << m_manager->corona()->universalSettings()->singleModeLayoutName(); QFile(deprecatedlayoutpath).remove(); } m_isSingleLayoutInDeprecatedRenaming = false; } m_manager->corona()->universalSettings()->setSingleModeLayoutName(layoutName); }); return true; } bool Synchronizer::initMultipleMode(QString layoutName) { if (m_multipleModeInitialized) { return false; } for (const auto layout : m_centralLayouts) { emit currentLayoutIsSwitching(layout->name()); } //! this code must be called asynchronously because it can create crashes otherwise. //! Tasks plasmoid case that triggers layouts switching through its context menu QTimer::singleShot(LAYOUTSINITINTERVAL, [this, layoutName]() { qDebug() << " ... initializing layout in multiple mode : " << layoutName ; unloadLayouts(); m_manager->loadLatteLayout(layoutPath(QString(Layout::MULTIPLELAYOUTSHIDDENNAME))); m_multipleModeInitialized = true; emit centralLayoutsChanged(); if (!layoutName.isEmpty()) { switchToLayoutInMultipleModeBasedOnActivities(layoutName); } syncMultipleLayoutsToActivities(); }); return true; } bool Synchronizer::switchToLayoutInSingleMode(QString layoutName) { if (!memoryInitialized() || m_manager->memoryUsage() != MemoryUsage::SingleLayout) { return false; } if (m_centralLayouts.size()>0 && m_centralLayouts[0]->name() == layoutName) { return true; } return initSingleMode(layoutName); } bool Synchronizer::switchToLayoutInMultipleModeBasedOnActivities(const QString &layoutName) { Data::Layout layoutdata; CentralLayout *central = centralLayout(layoutName); if (central) { layoutdata = central->data(); } else if (m_layouts.containsName(layoutName)) { QString layoutid = m_layouts.idForName(layoutName); CentralLayout storagedlayout(this, layoutid); layoutdata = storagedlayout.data(); m_layouts[layoutid] = layoutdata; } if (layoutdata.isEmpty()) { return false; } QString switchToActivity; //! try to not remove activityids that belong to different machines that are not currently present QStringList validlayoutactivities = validActivities(layoutdata.activities); if (layoutdata.isOnAllActivities()) { //! no reason to switch in any activity; } else if (layoutdata.isForFreeActivities()) { //! free-activities case QStringList freerunningactivities = freeRunningActivities(); if (freerunningactivities.count() > 0) { if (freerunningactivities.contains(layoutdata.lastUsedActivity)) { switchToActivity = layoutdata.lastUsedActivity; } else { switchToActivity = freerunningactivities[0]; } } else { QStringList freepausedactivities = freeActivities(); if (freepausedactivities.count() > 0) { switchToActivity = freepausedactivities[0]; } } } else if (!validlayoutactivities.isEmpty()) { //! set on-explicit activities QStringList allactivities = activities(); if (validlayoutactivities.contains(layoutdata.lastUsedActivity)) { switchToActivity = layoutdata.lastUsedActivity; } else { switchToActivity = validlayoutactivities[0]; } } else if (validlayoutactivities.isEmpty() && m_layouts.containsName(layoutName)) { //! no-activities are set //! has not been set in any activities but nonetheless it is requested probably by the user //! requested layout is assigned explicitly in current activity and any remaining explicit layouts //! are removing current activity from their activities list QString layoutid = m_layouts.idForName(layoutName); QString currentactivityid = m_activitiesController->currentActivity(); QStringList layoutIdsChanged; m_layouts[layoutid].activities.append(currentactivityid); m_manager->setOnActivities(layoutName, m_layouts[layoutid].activities); emit layoutActivitiesChanged(m_layouts[layoutid]); layoutIdsChanged << layoutid; if (m_assignedLayouts.contains(currentactivityid)) { //! remove any other explicit set layouts for the current activity QStringList explicits = m_assignedLayouts[currentactivityid]; for(auto explicitlayoutname : explicits) { QString explicitlayoutid = m_layouts.idForName(explicitlayoutname); m_layouts[explicitlayoutid].activities.removeAll(currentactivityid); m_manager->setOnActivities(explicitlayoutname, m_layouts[explicitlayoutid].activities); emit layoutActivitiesChanged(m_layouts[explicitlayoutid]); } } QStringList freelayoutnames; if (m_assignedLayouts.contains(Data::Layout::FREEACTIVITIESID)) { freelayoutnames = m_assignedLayouts[Data::Layout::FREEACTIVITIESID]; } reloadAssignedLayouts(); for(auto freelayoutname : freelayoutnames) { //! inform free activities layouts that their activities probably changed CentralLayout *central = centralLayout(freelayoutname); if (central) { emit central->activitiesChanged(); } } } if (!switchToActivity.isEmpty()) { if (!m_manager->corona()->activitiesConsumer()->runningActivities().contains(switchToActivity)) { m_activitiesController->startActivity(switchToActivity); } m_activitiesController->setCurrentActivity(switchToActivity); } return true; } bool Synchronizer::switchToLayoutInMultipleMode(QString layoutName) { if (!memoryInitialized() || m_manager->memoryUsage() != MemoryUsage::MultipleLayouts) { return false; } CentralLayout *layout = centralLayout(layoutName); if (layout) { QStringList appliedActivities = layout->appliedActivities(); QString nextActivity = !layout->lastUsedActivity().isEmpty() ? layout->lastUsedActivity() : appliedActivities[0]; if (!appliedActivities.contains(m_manager->corona()->activitiesConsumer()->currentActivity())) { //! it means we are at a foreign activity and we can switch to correct one m_activitiesController->setCurrentActivity(nextActivity); return true; } } else { if (!layoutName.isEmpty()) { switchToLayoutInMultipleModeBasedOnActivities(layoutName); } syncMultipleLayoutsToActivities(); } return true; } bool Synchronizer::switchToLayout(QString layoutName, MemoryUsage::LayoutsMemory newMemoryUsage) { qDebug() << " >>>>> SWITCHING >> " << layoutName << " __ from memory: " << m_manager->memoryUsage() << " to memory: " << newMemoryUsage; if (newMemoryUsage == MemoryUsage::Current) { newMemoryUsage = m_manager->memoryUsage(); } if (!memoryInitialized() || newMemoryUsage != m_manager->memoryUsage()) { //! Initiate Layouts memory properly m_manager->setMemoryUsage(newMemoryUsage); return (newMemoryUsage == MemoryUsage::SingleLayout ? initSingleMode(layoutName) : initMultipleMode(layoutName)); } if (m_manager->memoryUsage() == MemoryUsage::SingleLayout) { return switchToLayoutInSingleMode(layoutName); } else { return switchToLayoutInMultipleMode(layoutName); } } void Synchronizer::syncMultipleLayoutsToActivities() { qDebug() << " ---- --------- ------ syncMultipleLayoutsToActivities ------- "; qDebug() << " ---- --------- ------ ------------------------------- ------- "; QStringList layoutNamesToUnload; QStringList layoutNamesToLoad; QStringList currentNames = centralLayoutsNames(); //! discover OnAllActivities layouts if (m_assignedLayouts.contains(Data::Layout::ALLACTIVITIESID)) { layoutNamesToLoad << m_assignedLayouts[Data::Layout::ALLACTIVITIESID]; } //! discover ForFreeActivities layouts if (m_assignedLayouts.contains(Data::Layout::FREEACTIVITIESID) && freeRunningActivities().count()>0) { layoutNamesToLoad << m_assignedLayouts[Data::Layout::FREEACTIVITIESID]; } //! discover layouts assigned to explicit activities based on running activities for (const auto &activity : runningActivities()) { if (KWindowSystem::isPlatformWayland() && (m_activitiesController->currentActivity() != activity)){ //! Wayland Protection: Plasma wayland does not support yet Activities for windows //! but we can load the layouts that belong OnAllActivities + (ForFreeActivities OR SpecificActivity) continue; } if (m_assignedLayouts.contains(activity)) { layoutNamesToLoad << m_assignedLayouts[activity]; } } //! discover layouts that must be unloaded because of running activities changes for (const auto layout : m_centralLayouts) { if (!layoutNamesToLoad.contains(layout->name())) { layoutNamesToUnload << layout->name(); } } QString defaultForcedLayout; //! Safety if (layoutNamesToLoad.isEmpty()) { //! If no layout is found then force loading Default Layout QString layoutPath = m_manager->corona()->templatesManager()->newLayout("", i18n(Templates::DEFAULTLAYOUTTEMPLATENAME)); layoutNamesToLoad << Layout::AbstractLayout::layoutName(layoutPath); m_manager->setOnAllActivities(layoutNamesToLoad[0]); defaultForcedLayout = layoutNamesToLoad[0]; } QStringList newlyActivatedLayouts; //! Add needed Layouts based on Activities settings for (const auto &layoutname : layoutNamesToLoad) { if (!centralLayout(layoutname)) { CentralLayout *newLayout = new CentralLayout(this, QString(layoutPath(layoutname)), layoutname); if (newLayout) { qDebug() << "ACTIVATING LAYOUT ::::: " << layoutname; addLayout(newLayout); newLayout->importToCorona(); if (!defaultForcedLayout.isEmpty() && defaultForcedLayout == layoutname) { emit newLayoutAdded(newLayout->data()); } newlyActivatedLayouts << newLayout->name(); } } } if (m_manager->corona()->universalSettings()->showInfoWindow()) { if (newlyActivatedLayouts.count() == 1) { m_manager->showInfoWindow(i18n("Activating layout: %0 ...").arg(newlyActivatedLayouts[0]), 4000, QStringList(Data::Layout::ALLACTIVITIESID)); } else if (newlyActivatedLayouts.count() > 1) { m_manager->showInfoWindow(i18n("Activating layouts: %0 ...").arg(newlyActivatedLayouts.join(", ")), 4000, QStringList(Data::Layout::ALLACTIVITIESID)); } } //! Unload no needed Layouts //! hide layouts that will be removed in the end if (!layoutNamesToUnload.isEmpty()) { for (const auto layoutname : layoutNamesToUnload) { emit currentLayoutIsSwitching(layoutname); } QTimer::singleShot(LAYOUTSINITINTERVAL, [this, layoutNamesToUnload]() { unloadLayouts(layoutNamesToUnload); }); } qSort(currentNames); qSort(layoutNamesToLoad); if (currentNames != layoutNamesToLoad) { emit centralLayoutsChanged(); } } void Synchronizer::unloadLayouts(const QStringList &layoutNames) { if (layoutNames.isEmpty()) { return; } //! Unload no needed Layouts for (const auto &layoutname : layoutNames) { CentralLayout *layout = centralLayout(layoutname); int posLayout = centralLayoutPos(layoutname); if (posLayout >= 0) { qDebug() << "REMOVING LAYOUT ::::: " << layoutname; m_centralLayouts.removeAt(posLayout); layout->syncToLayoutFile(true); layout->unloadContainments(); layout->unloadLatteViews(); m_manager->clearUnloadedContainmentsFromLinkedFile(layout->unloadedContainmentsIds()); delete layout; } } emit centralLayoutsChanged(); } void Synchronizer::updateKWinDisabledBorders() { if (!m_manager->corona()->universalSettings()->canDisableBorders()) { m_manager->corona()->universalSettings()->kwin_setDisabledMaximizedBorders(false); } else { if (m_manager->corona()->layoutsManager()->memoryUsage() == MemoryUsage::SingleLayout) { m_manager->corona()->universalSettings()->kwin_setDisabledMaximizedBorders(m_centralLayouts.at(0)->disableBordersForMaximizedWindows()); } else if (m_manager->corona()->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) { QList centrals = centralLayoutsForActivity(m_manager->corona()->activitiesConsumer()->currentActivity()); for (int i = 0; i < centrals.size(); ++i) { CentralLayout *layout = centrals.at(i); if (layout->disableBordersForMaximizedWindows()) { m_manager->corona()->universalSettings()->kwin_setDisabledMaximizedBorders(true); return; } } m_manager->corona()->universalSettings()->kwin_setDisabledMaximizedBorders(false); } } } } } // end of namespace