File indexing completed on 2024-04-21 16:17:06
0001 /* 0002 * Copyright 2017 Smith AR <audoban@openmailbox.org> 0003 * Michail Vourlakos <mvourlakos@gmail.com> 0004 * 0005 * This file is part of Latte-Dock 0006 * 0007 * Latte-Dock is free software; you can redistribute it and/or 0008 * modify it under the terms of the GNU General Public License as 0009 * published by the Free Software Foundation; either version 2 of 0010 * the License, or (at your option) any later version. 0011 * 0012 * Latte-Dock is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 * GNU General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU General Public License 0018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0019 */ 0020 0021 #include "centrallayout.h" 0022 0023 // local 0024 #include "sharedlayout.h" 0025 #include "../lattecorona.h" 0026 #include "../screenpool.h" 0027 #include "../layouts/importer.h" 0028 #include "../layouts/manager.h" 0029 #include "../layouts/synchronizer.h" 0030 #include "../settings/universalsettings.h" 0031 #include "../view/view.h" 0032 #include "../../liblatte2/types.h" 0033 0034 // KDE 0035 #include <KConfigGroup> 0036 #include <KActivities/Consumer> 0037 0038 namespace Latte { 0039 0040 CentralLayout::CentralLayout(QObject *parent, QString layoutFile, QString assignedName) 0041 : Layout::GenericLayout(parent, layoutFile, assignedName) 0042 { 0043 if (m_loadedCorrectly) { 0044 loadConfig(); 0045 init(); 0046 } 0047 } 0048 0049 CentralLayout::~CentralLayout() 0050 { 0051 if (!m_layoutFile.isEmpty()) { 0052 m_layoutGroup.sync(); 0053 } 0054 } 0055 0056 void CentralLayout::unloadContainments() 0057 { 0058 Layout::GenericLayout::unloadContainments(); 0059 0060 if (m_sharedLayout) { 0061 disconnectSharedConnections(); 0062 m_sharedLayout->removeCentralLayout(this); 0063 } 0064 } 0065 0066 void CentralLayout::init() 0067 { 0068 connect(this, &CentralLayout::activitiesChanged, this, &CentralLayout::saveConfig); 0069 connect(this, &CentralLayout::disableBordersForMaximizedWindowsChanged, this, &CentralLayout::saveConfig); 0070 connect(this, &CentralLayout::sharedLayoutNameChanged, this, &CentralLayout::saveConfig); 0071 connect(this, &CentralLayout::showInMenuChanged, this, &CentralLayout::saveConfig); 0072 } 0073 0074 void CentralLayout::initToCorona(Latte::Corona *corona) 0075 { 0076 if (GenericLayout::initToCorona(corona)) { 0077 connect(m_corona->universalSettings(), &UniversalSettings::canDisableBordersChanged, this, [&]() { 0078 if (m_corona->universalSettings()->canDisableBorders()) { 0079 kwin_setDisabledMaximizedBorders(disableBordersForMaximizedWindows()); 0080 } else { 0081 kwin_setDisabledMaximizedBorders(false); 0082 } 0083 }); 0084 0085 0086 if (m_corona->layoutsManager()->memoryUsage() == Types::SingleLayout && m_corona->universalSettings()->canDisableBorders()) { 0087 kwin_setDisabledMaximizedBorders(disableBordersForMaximizedWindows()); 0088 } else if (m_corona->layoutsManager()->memoryUsage() == Types::MultipleLayouts) { 0089 connect(m_corona->layoutsManager(), &Layouts::Manager::currentLayoutNameChanged, this, [&]() { 0090 if (m_corona->universalSettings()->canDisableBorders() 0091 && m_corona->layoutsManager()->currentLayoutName() == name()) { 0092 kwin_setDisabledMaximizedBorders(disableBordersForMaximizedWindows()); 0093 } 0094 }); 0095 } 0096 0097 //! Request the SharedLayout in case there is one and Latte is functioning in MultipleLayouts mode 0098 if (m_corona->layoutsManager()->memoryUsage() == Types::MultipleLayouts && !m_sharedLayoutName.isEmpty()) { 0099 if (m_corona->layoutsManager()->synchronizer()->registerAtSharedLayout(this, m_sharedLayoutName)) { 0100 setSharedLayout(m_corona->layoutsManager()->synchronizer()->sharedLayout(m_sharedLayoutName)); 0101 } 0102 } 0103 } 0104 } 0105 0106 bool CentralLayout::disableBordersForMaximizedWindows() const 0107 { 0108 return m_disableBordersForMaximizedWindows; 0109 } 0110 0111 void CentralLayout::setDisableBordersForMaximizedWindows(bool disable) 0112 { 0113 if (m_disableBordersForMaximizedWindows == disable) { 0114 return; 0115 } 0116 0117 m_disableBordersForMaximizedWindows = disable; 0118 kwin_setDisabledMaximizedBorders(disable); 0119 0120 emit disableBordersForMaximizedWindowsChanged(); 0121 } 0122 0123 bool CentralLayout::kwin_disabledMaximizedBorders() const 0124 { 0125 if (!m_corona) { 0126 return false; 0127 } 0128 0129 return m_corona->universalSettings()->kwin_borderlessMaximizedWindowsEnabled(); 0130 } 0131 0132 void CentralLayout::kwin_setDisabledMaximizedBorders(bool disable) 0133 { 0134 if (!m_corona) { 0135 return; 0136 } 0137 0138 m_corona->universalSettings()->kwin_setDisabledMaximizedBorders(disable); 0139 } 0140 0141 bool CentralLayout::showInMenu() const 0142 { 0143 return m_showInMenu; 0144 } 0145 0146 void CentralLayout::setShowInMenu(bool show) 0147 { 0148 if (m_showInMenu == show) { 0149 return; 0150 } 0151 0152 m_showInMenu = show; 0153 emit showInMenuChanged(); 0154 } 0155 0156 Layout::Type CentralLayout::type() const 0157 { 0158 return Layout::Type::Central; 0159 } 0160 0161 QStringList CentralLayout::activities() const 0162 { 0163 return m_activities; 0164 } 0165 0166 void CentralLayout::setActivities(QStringList activities) 0167 { 0168 if (m_activities == activities) { 0169 return; 0170 } 0171 0172 m_activities = activities; 0173 0174 emit activitiesChanged(); 0175 } 0176 0177 QString CentralLayout::sharedLayoutName() const 0178 { 0179 return m_sharedLayoutName; 0180 } 0181 0182 void CentralLayout::setSharedLayoutName(QString name) 0183 { 0184 if (m_sharedLayoutName == name || (!Layouts::Importer::layoutExists(name) && !name.isEmpty())) { 0185 return; 0186 } 0187 0188 m_sharedLayoutName = name; 0189 emit sharedLayoutNameChanged(); 0190 } 0191 0192 SharedLayout *CentralLayout::sharedLayout() const 0193 { 0194 return m_sharedLayout; 0195 } 0196 0197 void CentralLayout::setSharedLayout(SharedLayout *layout) 0198 { 0199 if (m_sharedLayout == layout) { 0200 return; 0201 } 0202 0203 disconnectSharedConnections(); 0204 0205 m_sharedLayout = layout; 0206 0207 if (layout) { 0208 setSharedLayoutName(m_sharedLayout->name()); 0209 0210 //! attach new signals 0211 m_sharedConnections << connect(m_sharedLayout, &Layout::GenericLayout::viewsCountChanged, this, &Layout::GenericLayout::viewsCountChanged); 0212 m_sharedConnections << connect(m_sharedLayout, &Layout::AbstractLayout::nameChanged, this, [this]() { 0213 setSharedLayoutName(m_sharedLayout->name()); 0214 }); 0215 m_sharedConnections << connect(m_sharedLayout, &Layout::GenericLayout::viewEdgeChanged, this, [this]() { 0216 syncLatteViewsToScreens(); 0217 }); 0218 } else { 0219 setSharedLayoutName(QString()); 0220 } 0221 0222 syncLatteViewsToScreens(); 0223 emit viewsCountChanged(); 0224 } 0225 0226 void CentralLayout::disconnectSharedConnections() 0227 { 0228 //! drop old signals 0229 for (const auto &sc : m_sharedConnections) { 0230 QObject::disconnect(sc); 0231 } 0232 0233 m_sharedConnections.clear(); 0234 } 0235 0236 void CentralLayout::loadConfig() 0237 { 0238 m_disableBordersForMaximizedWindows = m_layoutGroup.readEntry("disableBordersForMaximizedWindows", false); 0239 m_showInMenu = m_layoutGroup.readEntry("showInMenu", false); 0240 m_activities = m_layoutGroup.readEntry("activities", QStringList()); 0241 0242 QString sharedLayoutName = m_layoutGroup.readEntry("sharedLayout", QString()); 0243 0244 if (Layouts::Importer::layoutExists(sharedLayoutName)) { 0245 m_sharedLayoutName = sharedLayoutName; 0246 } 0247 0248 emit activitiesChanged(); 0249 } 0250 0251 void CentralLayout::saveConfig() 0252 { 0253 qDebug() << "CENTRAL layout is saving... for layout:" << m_layoutName; 0254 m_layoutGroup.writeEntry("showInMenu", m_showInMenu); 0255 m_layoutGroup.writeEntry("disableBordersForMaximizedWindows", m_disableBordersForMaximizedWindows); 0256 m_layoutGroup.writeEntry("sharedLayout", m_sharedLayoutName); 0257 m_layoutGroup.writeEntry("activities", m_activities); 0258 0259 m_layoutGroup.sync(); 0260 } 0261 0262 //! OVERRIDES 0263 0264 void CentralLayout::addView(Plasma::Containment *containment, bool forceOnPrimary, int explicitScreen, Layout::ViewsMap *occupied) 0265 { 0266 if (m_sharedLayout) { 0267 //! consider already occupied edges from SharedLayout 0268 Layout::ViewsMap ocMap = m_sharedLayout->validViewsMap(); 0269 qDebug() << " HIGH PRIORITY ALREADY OCCUPIED EDGES :: " << ocMap; 0270 Layout::GenericLayout::addView(containment, forceOnPrimary, explicitScreen, &ocMap); 0271 } else { 0272 Layout::GenericLayout::addView(containment, forceOnPrimary, explicitScreen, occupied); 0273 } 0274 } 0275 0276 bool CentralLayout::configViewIsShown() const 0277 { 0278 bool genericShown = GenericLayout::configViewIsShown(); 0279 if (m_sharedLayout) { 0280 return (m_sharedLayout->configViewIsShown() || genericShown); 0281 } 0282 0283 return genericShown; 0284 } 0285 0286 const QStringList CentralLayout::appliedActivities() 0287 { 0288 if (!m_corona) { 0289 return {}; 0290 } 0291 0292 if (m_corona->layoutsManager()->memoryUsage() == Types::SingleLayout) { 0293 return {"0"}; 0294 } else if (m_corona->layoutsManager()->memoryUsage() == Types::MultipleLayouts) { 0295 if (m_activities.isEmpty()) { 0296 return m_corona->layoutsManager()->synchronizer()->orphanedActivities(); 0297 } else { 0298 return m_activities; 0299 } 0300 } else { 0301 return {"0"}; 0302 } 0303 } 0304 0305 QList<Latte::View *> CentralLayout::latteViews() 0306 { 0307 if (m_sharedLayout) { 0308 QList<Latte::View *> views = Layout::GenericLayout::latteViews(); 0309 views << m_sharedLayout->latteViews(); 0310 0311 return views; 0312 } 0313 0314 return Layout::GenericLayout::latteViews(); 0315 } 0316 0317 int CentralLayout::viewsCount(int screen) const 0318 { 0319 if (!m_corona) { 0320 return 0; 0321 } 0322 0323 int views = Layout::GenericLayout::viewsCount(screen); 0324 0325 if (m_sharedLayout) { 0326 QScreen *scr = m_corona->screenPool()->screenForId(screen); 0327 0328 for (const auto view : m_sharedLayout->latteViews()) { 0329 if (view && view->screen() == scr && !view->containment()->destroyed()) { 0330 ++views; 0331 } 0332 } 0333 } 0334 0335 return views; 0336 } 0337 0338 int CentralLayout::viewsCount(QScreen *screen) const 0339 { 0340 if (!m_corona) { 0341 return 0; 0342 } 0343 0344 int views = Layout::GenericLayout::viewsCount(screen); 0345 0346 if (m_sharedLayout) { 0347 for (const auto view : m_sharedLayout->latteViews()) { 0348 if (view && view->screen() == screen && !view->containment()->destroyed()) { 0349 ++views; 0350 } 0351 } 0352 } 0353 0354 return views; 0355 } 0356 0357 int CentralLayout::viewsCount() const 0358 { 0359 if (!m_corona) { 0360 return 0; 0361 } 0362 0363 int views = Layout::GenericLayout::viewsCount(); 0364 0365 if (m_sharedLayout) { 0366 for (const auto view : m_sharedLayout->latteViews()) { 0367 if (view && view->containment() && !view->containment()->destroyed()) { 0368 ++views; 0369 } 0370 } 0371 } 0372 0373 return views; 0374 } 0375 0376 QList<Plasma::Types::Location> CentralLayout::availableEdgesForView(QScreen *scr, Latte::View *forView) const 0377 { 0378 using Plasma::Types; 0379 QList<Types::Location> edges{Types::BottomEdge, Types::LeftEdge, 0380 Types::TopEdge, Types::RightEdge}; 0381 0382 if (!m_corona) { 0383 return edges; 0384 } 0385 0386 edges = Layout::GenericLayout::availableEdgesForView(scr, forView); 0387 0388 if (m_sharedLayout) { 0389 for (const auto view : m_sharedLayout->latteViews()) { 0390 //! make sure that availabe edges takes into account only views that should be excluded, 0391 //! this is why the forView should not be excluded 0392 if (view && view != forView && view->positioner()->currentScreenName() == scr->name()) { 0393 edges.removeOne(view->location()); 0394 } 0395 } 0396 } 0397 0398 return edges; 0399 } 0400 0401 QList<Plasma::Types::Location> CentralLayout::freeEdges(QScreen *scr) const 0402 { 0403 using Plasma::Types; 0404 QList<Types::Location> edges{Types::BottomEdge, Types::LeftEdge, 0405 Types::TopEdge, Types::RightEdge}; 0406 0407 if (!m_corona) { 0408 return edges; 0409 } 0410 0411 edges = Layout::GenericLayout::freeEdges(scr); 0412 0413 if (m_sharedLayout) { 0414 for (const auto view : m_sharedLayout->latteViews()) { 0415 if (view && view->positioner()->currentScreenName() == scr->name()) { 0416 edges.removeOne(view->location()); 0417 } 0418 } 0419 } 0420 0421 return edges; 0422 } 0423 0424 QList<Plasma::Types::Location> CentralLayout::freeEdges(int screen) const 0425 { 0426 using Plasma::Types; 0427 QList<Types::Location> edges{Types::BottomEdge, Types::LeftEdge, 0428 Types::TopEdge, Types::RightEdge}; 0429 0430 if (!m_corona) { 0431 return edges; 0432 } 0433 0434 edges = Layout::GenericLayout::freeEdges(screen); 0435 QScreen *scr = m_corona->screenPool()->screenForId(screen); 0436 0437 if (m_sharedLayout) { 0438 for (const auto view : m_sharedLayout->latteViews()) { 0439 if (view && scr && view->positioner()->currentScreenName() == scr->name()) { 0440 edges.removeOne(view->location()); 0441 } 0442 } 0443 } 0444 0445 return edges; 0446 } 0447 0448 Types::ViewType CentralLayout::latteViewType(int containmentId) const 0449 { 0450 for (const auto view : m_latteViews) { 0451 if (view->containment() && view->containment()->id() == containmentId) { 0452 return view->type(); 0453 } 0454 } 0455 0456 if (m_sharedLayout) { 0457 return m_sharedLayout->latteViewType(containmentId); 0458 } 0459 0460 return Types::DockView; 0461 } 0462 0463 QList<Latte::View *> CentralLayout::sortedLatteViews(QList<Latte::View *> views) 0464 { 0465 QList<Latte::View *> vws = latteViews(); 0466 0467 return Layout::GenericLayout::sortedLatteViews(vws); 0468 } 0469 0470 QList<Latte::View *> CentralLayout::viewsWithPlasmaShortcuts() 0471 { 0472 QList<Latte::View *> combined = Layout::GenericLayout::viewsWithPlasmaShortcuts(); 0473 0474 if (m_sharedLayout) { 0475 combined << m_sharedLayout->viewsWithPlasmaShortcuts(); 0476 } 0477 0478 return combined; 0479 } 0480 0481 void CentralLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap) 0482 { 0483 if (m_sharedLayout) { 0484 Layout::ViewsMap map = m_sharedLayout->validViewsMap(); 0485 Layout::GenericLayout::syncLatteViewsToScreens(&map); 0486 } else { 0487 Layout::GenericLayout::syncLatteViewsToScreens(); 0488 } 0489 } 0490 0491 }