File indexing completed on 2024-09-08 10:54:08
0001 /* 0002 SPDX-FileCopyrightText: 2016 Smith AR <audoban@openmaibox.org> 0003 SPDX-FileCopyrightText: 2016 Michail Vourlakos <mvourlakos@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "lattecorona.h" 0009 0010 // local 0011 #include <coretypes.h> 0012 #include "alternativeshelper.h" 0013 #include "apptypes.h" 0014 #include "lattedockadaptor.h" 0015 #include "screenpool.h" 0016 #include "data/generictable.h" 0017 #include "data/layouticondata.h" 0018 #include "declarativeimports/interfaces.h" 0019 #include "declarativeimports/contextmenulayerquickitem.h" 0020 #include "indicator/factory.h" 0021 #include "layout/abstractlayout.h" 0022 #include "layout/centrallayout.h" 0023 #include "layout/genericlayout.h" 0024 #include "layouts/importer.h" 0025 #include "layouts/manager.h" 0026 #include "layouts/synchronizer.h" 0027 #include "shortcuts/globalshortcuts.h" 0028 #include "package/lattepackage.h" 0029 #include "plasma/extended/backgroundcache.h" 0030 #include "plasma/extended/backgroundtracker.h" 0031 #include "plasma/extended/screengeometries.h" 0032 #include "plasma/extended/screenpool.h" 0033 #include "plasma/extended/theme.h" 0034 #include "settings/universalsettings.h" 0035 #include "templates/templatesmanager.h" 0036 #include "view/originalview.h" 0037 #include "view/view.h" 0038 #include "view/settings/viewsettingsfactory.h" 0039 #include "view/windowstracker/windowstracker.h" 0040 #include "view/windowstracker/allscreenstracker.h" 0041 #include "view/windowstracker/currentscreentracker.h" 0042 #include "wm/abstractwindowinterface.h" 0043 #include "wm/schemecolors.h" 0044 #include "wm/waylandinterface.h" 0045 #include "wm/xwindowinterface.h" 0046 #include "wm/tracker/lastactivewindow.h" 0047 #include "wm/tracker/schemes.h" 0048 #include "wm/tracker/windowstracker.h" 0049 0050 // Qt 0051 #include <QAction> 0052 #include <QApplication> 0053 #include <QScreen> 0054 #include <QDBusConnection> 0055 #include <QDebug> 0056 #include <QDesktopWidget> 0057 #include <QFile> 0058 #include <QFontDatabase> 0059 #include <QQmlContext> 0060 #include <QProcess> 0061 0062 // Plasma 0063 #include <Plasma> 0064 #include <Plasma/Corona> 0065 #include <Plasma/Containment> 0066 #include <PlasmaQuick/ConfigView> 0067 0068 // KDE 0069 #include <KActionCollection> 0070 #include <KPluginMetaData> 0071 #include <KGlobalAccel> 0072 #include <KLocalizedString> 0073 #include <KPackage/Package> 0074 #include <KPackage/PackageLoader> 0075 #include <KAboutData> 0076 #include <KActivities/Consumer> 0077 #include <KDeclarative/QmlObjectSharedEngine> 0078 #include <KWindowSystem> 0079 #include <KWayland/Client/connection_thread.h> 0080 #include <KWayland/Client/registry.h> 0081 #include <KWayland/Client/plasmashell.h> 0082 #include <KWayland/Client/plasmawindowmanagement.h> 0083 0084 namespace Latte { 0085 0086 Corona::Corona(bool defaultLayoutOnStartup, QString layoutNameOnStartUp, QString addViewTemplateName, int userSetMemoryUsage, QObject *parent) 0087 : Plasma::Corona(parent), 0088 m_defaultLayoutOnStartup(defaultLayoutOnStartup), 0089 m_startupAddViewTemplateName(addViewTemplateName), 0090 m_userSetMemoryUsage(userSetMemoryUsage), 0091 m_layoutNameOnStartUp(layoutNameOnStartUp), 0092 m_activitiesConsumer(new KActivities::Consumer(this)), 0093 m_screenPool(new ScreenPool(KSharedConfig::openConfig(), this)), 0094 m_indicatorFactory(new Indicator::Factory(this)), 0095 m_universalSettings(new UniversalSettings(KSharedConfig::openConfig(), this)), 0096 m_globalShortcuts(new GlobalShortcuts(this)), 0097 m_plasmaScreenPool(new PlasmaExtended::ScreenPool(this)), 0098 m_themeExtended(new PlasmaExtended::Theme(KSharedConfig::openConfig(), this)), 0099 m_viewSettingsFactory(new ViewSettingsFactory(this)), 0100 m_templatesManager(new Templates::Manager(this)), 0101 m_layoutsManager(new Layouts::Manager(this)), 0102 m_plasmaGeometries(new PlasmaExtended::ScreenGeometries(this)), 0103 m_dialogShadows(new PanelShadows(this, QStringLiteral("dialogs/background"))) 0104 { 0105 connect(qApp, &QApplication::aboutToQuit, this, &Corona::onAboutToQuit); 0106 0107 //! create the window manager 0108 if (KWindowSystem::isPlatformWayland()) { 0109 m_wm = new WindowSystem::WaylandInterface(this); 0110 } else { 0111 m_wm = new WindowSystem::XWindowInterface(this); 0112 } 0113 0114 setupWaylandIntegration(); 0115 0116 KPackage::Package package(new Latte::Package(this)); 0117 0118 m_screenPool->load(); 0119 0120 if (!package.isValid()) { 0121 qWarning() << staticMetaObject.className() 0122 << "the package" << package.metadata().rawData() << "is invalid!"; 0123 return; 0124 } else { 0125 qDebug() << staticMetaObject.className() 0126 << "the package" << package.metadata().rawData() << "is valid!"; 0127 } 0128 0129 setKPackage(package); 0130 //! universal settings / extendedtheme must be loaded after the package has been set 0131 m_universalSettings->load(); 0132 m_themeExtended->load(); 0133 0134 qmlRegisterTypes(); 0135 0136 if (m_activitiesConsumer && (m_activitiesConsumer->serviceStatus() == KActivities::Consumer::Running)) { 0137 load(); 0138 } 0139 0140 connect(m_activitiesConsumer, &KActivities::Consumer::serviceStatusChanged, this, &Corona::load); 0141 0142 m_viewsScreenSyncTimer.setSingleShot(true); 0143 m_viewsScreenSyncTimer.setInterval(m_universalSettings->screenTrackerInterval()); 0144 connect(&m_viewsScreenSyncTimer, &QTimer::timeout, this, &Corona::syncLatteViewsToScreens); 0145 connect(m_universalSettings, &UniversalSettings::screenTrackerIntervalChanged, this, [this]() { 0146 m_viewsScreenSyncTimer.setInterval(m_universalSettings->screenTrackerInterval()); 0147 }); 0148 0149 //! Dbus adaptor initialization 0150 new LatteDockAdaptor(this); 0151 QDBusConnection dbus = QDBusConnection::sessionBus(); 0152 dbus.registerObject(QStringLiteral("/Latte"), this); 0153 } 0154 0155 Corona::~Corona() 0156 { 0157 /*m_inQuit = true; 0158 0159 //! BEGIN: Give the time to slide-out views when closing 0160 m_layoutsManager->synchronizer()->hideAllViews(); 0161 m_viewSettingsFactory->deleteLater(); 0162 0163 m_viewsScreenSyncTimer.stop(); 0164 0165 if (m_layoutsManager->memoryUsage() == MemoryUsage::SingleLayout) { 0166 cleanConfig(); 0167 } 0168 0169 qDebug() << "Latte Corona - unload: containments ..."; 0170 m_layoutsManager->unload();*/ 0171 0172 m_plasmaGeometries->deleteLater(); 0173 m_wm->deleteLater(); 0174 m_dialogShadows->deleteLater(); 0175 m_globalShortcuts->deleteLater(); 0176 m_layoutsManager->deleteLater(); 0177 m_screenPool->deleteLater(); 0178 m_universalSettings->deleteLater(); 0179 m_plasmaScreenPool->deleteLater(); 0180 m_themeExtended->deleteLater(); 0181 m_indicatorFactory->deleteLater(); 0182 0183 disconnect(m_activitiesConsumer, &KActivities::Consumer::serviceStatusChanged, this, &Corona::load); 0184 delete m_activitiesConsumer; 0185 0186 qDebug() << "Latte Corona - deleted..."; 0187 0188 if (!m_importFullConfigurationFile.isEmpty()) { 0189 //!NOTE: Restart latte to import the new configuration 0190 QString importCommand = "latte-dock --import-full \"" + m_importFullConfigurationFile + "\""; 0191 qDebug() << "Executing Import Full Configuration command : " << importCommand; 0192 0193 QProcess::startDetached(importCommand); 0194 } 0195 } 0196 0197 void Corona::onAboutToQuit() 0198 { 0199 m_inQuit = true; 0200 0201 //! BEGIN: Give the time to slide-out views when closing 0202 m_layoutsManager->synchronizer()->hideAllViews(); 0203 m_viewSettingsFactory->deleteLater(); 0204 0205 m_viewsScreenSyncTimer.stop(); 0206 0207 if (m_layoutsManager->memoryUsage() == MemoryUsage::SingleLayout) { 0208 cleanConfig(); 0209 } 0210 0211 if (m_layoutsManager->memoryUsage() == Latte::MemoryUsage::MultipleLayouts) { 0212 m_layoutsManager->importer()->setMultipleLayoutsStatus(Latte::MultipleLayouts::Paused); 0213 } 0214 0215 qDebug() << "Latte Corona - unload: containments ..."; 0216 m_layoutsManager->unload(); 0217 } 0218 0219 void Corona::load() 0220 { 0221 if (m_activitiesConsumer && (m_activitiesConsumer->serviceStatus() == KActivities::Consumer::Running) && m_activitiesStarting) { 0222 m_activitiesStarting = false; 0223 0224 disconnect(m_activitiesConsumer, &KActivities::Consumer::serviceStatusChanged, this, &Corona::load); 0225 0226 m_templatesManager->init(); 0227 m_layoutsManager->init(); 0228 0229 connect(this, &Corona::availableScreenRectChangedFrom, this, &Plasma::Corona::availableScreenRectChanged, Qt::UniqueConnection); 0230 connect(this, &Corona::availableScreenRegionChangedFrom, this, &Plasma::Corona::availableScreenRegionChanged, Qt::UniqueConnection); 0231 connect(m_screenPool, &ScreenPool::primaryScreenChanged, this, &Corona::onScreenCountChanged, Qt::UniqueConnection); 0232 0233 QString loadLayoutName = ""; 0234 0235 if (m_userSetMemoryUsage != -1) { 0236 MemoryUsage::LayoutsMemory usage = static_cast<MemoryUsage::LayoutsMemory>(m_userSetMemoryUsage); 0237 m_universalSettings->setLayoutsMemoryUsage(usage); 0238 } 0239 0240 if (!m_defaultLayoutOnStartup && m_layoutNameOnStartUp.isEmpty()) { 0241 if (m_universalSettings->layoutsMemoryUsage() == MemoryUsage::MultipleLayouts) { 0242 loadLayoutName = ""; 0243 } else { 0244 loadLayoutName = m_universalSettings->singleModeLayoutName(); 0245 0246 if (!m_layoutsManager->synchronizer()->layoutExists(loadLayoutName)) { 0247 //! If chosen layout does not exist, force Default layout loading 0248 QString defaultLayoutTemplateName = i18n(Templates::DEFAULTLAYOUTTEMPLATENAME); 0249 loadLayoutName = defaultLayoutTemplateName; 0250 0251 if (!m_layoutsManager->synchronizer()->layoutExists(defaultLayoutTemplateName)) { 0252 //! If Default layout does not exist at all, create it 0253 QString path = m_templatesManager->newLayout("", defaultLayoutTemplateName); 0254 m_layoutsManager->setOnAllActivities(Layout::AbstractLayout::layoutName(path)); 0255 } 0256 } 0257 } 0258 } else if (m_defaultLayoutOnStartup) { 0259 //! force loading a NEW default layout even though a default layout may already exists 0260 QString newDefaultLayoutPath = m_templatesManager->newLayout("", i18n(Templates::DEFAULTLAYOUTTEMPLATENAME)); 0261 loadLayoutName = Layout::AbstractLayout::layoutName(newDefaultLayoutPath); 0262 m_universalSettings->setLayoutsMemoryUsage(MemoryUsage::SingleLayout); 0263 } else { 0264 loadLayoutName = m_layoutNameOnStartUp; 0265 m_universalSettings->setLayoutsMemoryUsage(MemoryUsage::SingleLayout); 0266 } 0267 0268 m_layoutsManager->loadLayoutOnStartup(loadLayoutName); 0269 0270 //! load screens signals such screenGeometryChanged in order to support 0271 //! plasmoid.screenGeometry properly 0272 for (QScreen *screen : qGuiApp->screens()) { 0273 onScreenAdded(screen); 0274 } 0275 0276 connect(m_layoutsManager->synchronizer(), &Layouts::Synchronizer::initializationFinished, [this]() { 0277 if (!m_startupAddViewTemplateName.isEmpty()) { 0278 //! user requested through cmd startup to add view from specific view template and we can add it after the startup 0279 //! sequence has loaded all required layouts properly 0280 addView(0, m_startupAddViewTemplateName); 0281 m_startupAddViewTemplateName = ""; 0282 } 0283 }); 0284 0285 m_inStartup = false; 0286 0287 connect(qGuiApp, &QGuiApplication::screenAdded, this, &Corona::onScreenAdded, Qt::UniqueConnection); 0288 connect(qGuiApp, &QGuiApplication::screenRemoved, this, &Corona::onScreenRemoved, Qt::UniqueConnection); 0289 } 0290 } 0291 0292 void Corona::unload() 0293 { 0294 qDebug() << "unload: removing containments..."; 0295 0296 while (!containments().isEmpty()) { 0297 //deleting a containment will remove it from the list due to QObject::destroyed connect in Corona 0298 //this form doesn't crash, while qDeleteAll(containments()) does 0299 delete containments().first(); 0300 } 0301 } 0302 0303 void Corona::setupWaylandIntegration() 0304 { 0305 if (!KWindowSystem::isPlatformWayland()) { 0306 return; 0307 } 0308 0309 using namespace KWayland::Client; 0310 0311 auto connection = ConnectionThread::fromApplication(this); 0312 0313 if (!connection) { 0314 return; 0315 } 0316 0317 Registry *registry{new Registry(this)}; 0318 registry->create(connection); 0319 0320 connect(registry, &Registry::plasmaShellAnnounced, this 0321 , [this, registry](quint32 name, quint32 version) { 0322 m_waylandCorona = registry->createPlasmaShell(name, version, this); 0323 }); 0324 0325 QObject::connect(registry, &KWayland::Client::Registry::plasmaWindowManagementAnnounced, 0326 [this, registry](quint32 name, quint32 version) { 0327 KWayland::Client::PlasmaWindowManagement *pwm = registry->createPlasmaWindowManagement(name, version, this); 0328 0329 WindowSystem::WaylandInterface *wI = qobject_cast<WindowSystem::WaylandInterface *>(m_wm); 0330 0331 if (wI) { 0332 wI->initWindowManagement(pwm); 0333 } 0334 }); 0335 0336 0337 QObject::connect(registry, &KWayland::Client::Registry::plasmaVirtualDesktopManagementAnnounced, 0338 [this, registry] (quint32 name, quint32 version) { 0339 KWayland::Client::PlasmaVirtualDesktopManagement *vdm = registry->createPlasmaVirtualDesktopManagement(name, version, this); 0340 0341 WindowSystem::WaylandInterface *wI = qobject_cast<WindowSystem::WaylandInterface *>(m_wm); 0342 0343 if (wI) { 0344 wI->initVirtualDesktopManagement(vdm); 0345 } 0346 }); 0347 0348 0349 registry->setup(); 0350 connection->roundtrip(); 0351 } 0352 0353 KWayland::Client::PlasmaShell *Corona::waylandCoronaInterface() const 0354 { 0355 return m_waylandCorona; 0356 } 0357 0358 void Corona::cleanConfig() 0359 { 0360 auto containmentsEntries = config()->group("Containments"); 0361 bool changed = false; 0362 0363 for(const auto &cId : containmentsEntries.groupList()) { 0364 if (!containmentExists(cId.toUInt())) { 0365 //cleanup obsolete containments 0366 containmentsEntries.group(cId).deleteGroup(); 0367 changed = true; 0368 qDebug() << "obsolete containment configuration deleted:" << cId; 0369 } else { 0370 //cleanup obsolete applets of running containments 0371 auto appletsEntries = containmentsEntries.group(cId).group("Applets"); 0372 0373 for(const auto &appletId : appletsEntries.groupList()) { 0374 if (!appletExists(cId.toUInt(), appletId.toUInt())) { 0375 appletsEntries.group(appletId).deleteGroup(); 0376 changed = true; 0377 qDebug() << "obsolete applet configuration deleted:" << appletId; 0378 } 0379 } 0380 } 0381 } 0382 0383 if (changed) { 0384 config()->sync(); 0385 qDebug() << "configuration file cleaned..."; 0386 } 0387 } 0388 0389 bool Corona::containmentExists(uint id) const 0390 { 0391 for(const auto containment : containments()) { 0392 if (id == containment->id()) { 0393 return true; 0394 } 0395 } 0396 0397 return false; 0398 } 0399 0400 bool Corona::appletExists(uint containmentId, uint appletId) const 0401 { 0402 Plasma::Containment *containment = nullptr; 0403 0404 for(const auto cont : containments()) { 0405 if (containmentId == cont->id()) { 0406 containment = cont; 0407 break; 0408 } 0409 } 0410 0411 if (!containment) { 0412 return false; 0413 } 0414 0415 for(const auto applet : containment->applets()) { 0416 if (applet->id() == appletId) { 0417 return true; 0418 } 0419 } 0420 0421 return false; 0422 } 0423 0424 bool Corona::inQuit() const 0425 { 0426 return m_inQuit; 0427 } 0428 0429 KActivities::Consumer *Corona::activitiesConsumer() const 0430 { 0431 return m_activitiesConsumer; 0432 } 0433 0434 PanelShadows *Corona::dialogShadows() const 0435 { 0436 return m_dialogShadows; 0437 } 0438 0439 GlobalShortcuts *Corona::globalShortcuts() const 0440 { 0441 return m_globalShortcuts; 0442 } 0443 0444 ScreenPool *Corona::screenPool() const 0445 { 0446 return m_screenPool; 0447 } 0448 0449 UniversalSettings *Corona::universalSettings() const 0450 { 0451 return m_universalSettings; 0452 } 0453 0454 ViewSettingsFactory *Corona::viewSettingsFactory() const 0455 { 0456 return m_viewSettingsFactory; 0457 } 0458 0459 WindowSystem::AbstractWindowInterface *Corona::wm() const 0460 { 0461 return m_wm; 0462 } 0463 0464 Indicator::Factory *Corona::indicatorFactory() const 0465 { 0466 return m_indicatorFactory; 0467 } 0468 0469 Layouts::Manager *Corona::layoutsManager() const 0470 { 0471 return m_layoutsManager; 0472 } 0473 0474 Templates::Manager *Corona::templatesManager() const 0475 { 0476 return m_templatesManager; 0477 } 0478 0479 PlasmaExtended::ScreenPool *Corona::plasmaScreenPool() const 0480 { 0481 return m_plasmaScreenPool; 0482 } 0483 0484 PlasmaExtended::Theme *Corona::themeExtended() const 0485 { 0486 return m_themeExtended; 0487 } 0488 0489 int Corona::numScreens() const 0490 { 0491 return qGuiApp->screens().count(); 0492 } 0493 0494 QRect Corona::screenGeometry(int id) const 0495 { 0496 const auto screens = qGuiApp->screens(); 0497 const QScreen *screen{m_screenPool->primaryScreen()}; 0498 0499 QString screenName; 0500 0501 if (m_screenPool->hasScreenId(id)) { 0502 screenName = m_screenPool->connector(id); 0503 } 0504 0505 for(const auto scr : screens) { 0506 if (scr->name() == screenName) { 0507 screen = scr; 0508 break; 0509 } 0510 } 0511 0512 return screen->geometry(); 0513 } 0514 0515 CentralLayout *Corona::centralLayout(QString name) const 0516 { 0517 CentralLayout *result{nullptr}; 0518 0519 if (!name.isEmpty()) { 0520 result = m_layoutsManager->synchronizer()->centralLayout(name); 0521 } 0522 0523 return result; 0524 } 0525 0526 Layout::GenericLayout *Corona::layout(QString name) const 0527 { 0528 Layout::GenericLayout *result{nullptr}; 0529 0530 if (!name.isEmpty()) { 0531 result = m_layoutsManager->synchronizer()->layout(name); 0532 } 0533 0534 return result; 0535 } 0536 0537 QRegion Corona::availableScreenRegion(int id) const 0538 { 0539 //! ignore modes are added in order for notifications to be placed 0540 //! in better positioning and not overlap with sidebars or usually hidden views 0541 QList<Types::Visibility> ignoremodes({Latte::Types::AutoHide, 0542 Latte::Types::SidebarOnDemand, 0543 Latte::Types::SidebarAutoHide}); 0544 0545 0546 return availableScreenRegionWithCriteria(id, 0547 QString(), 0548 ignoremodes); 0549 } 0550 0551 QRegion Corona::availableScreenRegionWithCriteria(int id, 0552 QString activityid, 0553 QList<Types::Visibility> ignoreModes, 0554 QList<Plasma::Types::Location> ignoreEdges, 0555 bool ignoreExternalPanels, 0556 bool desktopUse) const 0557 { 0558 const QScreen *screen = m_screenPool->screenForId(id); 0559 bool inCurrentActivity{activityid.isEmpty()}; 0560 0561 if (!screen) { 0562 return {}; 0563 } 0564 0565 QRegion available = ignoreExternalPanels ? screen->geometry() : screen->availableGeometry(); 0566 0567 QList<Latte::View *> views; 0568 0569 if (inCurrentActivity) { 0570 views = m_layoutsManager->synchronizer()->viewsBasedOnActivityId(m_activitiesConsumer->currentActivity()); 0571 } else { 0572 views = m_layoutsManager->synchronizer()->viewsBasedOnActivityId(activityid); 0573 } 0574 0575 if (views.isEmpty()) { 0576 return available; 0577 } 0578 0579 //! blacklist irrelevant visibility modes 0580 if (!ignoreModes.contains(Latte::Types::None)) { 0581 ignoreModes << Latte::Types::None; 0582 } 0583 0584 if (!ignoreModes.contains(Latte::Types::NormalWindow)) { 0585 ignoreModes << Latte::Types::NormalWindow; 0586 } 0587 0588 bool allEdges = ignoreEdges.isEmpty(); 0589 0590 for (const auto *view : views) { 0591 bool inDesktopOffScreenStartup = desktopUse && view && view->positioner() && view->positioner()->isOffScreen(); 0592 0593 if (view && view->containment() && view->screen() == screen && !inDesktopOffScreenStartup 0594 && ((allEdges || !ignoreEdges.contains(view->location())) 0595 && (view->visibility() && !ignoreModes.contains(view->visibility()->mode())))) { 0596 int realThickness = view->normalThickness(); 0597 0598 int x = 0; int y = 0; int w = 0; int h = 0; 0599 0600 switch (view->formFactor()) { 0601 case Plasma::Types::Horizontal: 0602 if (view->behaveAsPlasmaPanel()) { 0603 w = view->width(); 0604 x = view->x(); 0605 } else { 0606 w = view->maxLength() * view->width(); 0607 int offsetW = view->offset() * view->width(); 0608 0609 switch (view->alignment()) { 0610 case Latte::Types::Left: 0611 x = view->x() + offsetW; 0612 break; 0613 0614 case Latte::Types::Center: 0615 case Latte::Types::Justify: 0616 x = (view->geometry().center().x() - w/2) + 1 + offsetW; 0617 break; 0618 0619 case Latte::Types::Right: 0620 x = view->geometry().right() + 1 - w - offsetW; 0621 break; 0622 } 0623 } 0624 break; 0625 case Plasma::Types::Vertical: 0626 if (view->behaveAsPlasmaPanel()) { 0627 h = view->height(); 0628 y = view->y(); 0629 } else { 0630 h = view->maxLength() * view->height(); 0631 int offsetH = view->offset() * view->height(); 0632 0633 switch (view->alignment()) { 0634 case Latte::Types::Top: 0635 y = view->y() + offsetH; 0636 break; 0637 0638 case Latte::Types::Center: 0639 case Latte::Types::Justify: 0640 y = (view->geometry().center().y() - h/2) + 1 + offsetH; 0641 break; 0642 0643 case Latte::Types::Bottom: 0644 y = view->geometry().bottom() - h - offsetH; 0645 break; 0646 } 0647 } 0648 break; 0649 } 0650 0651 // Usually availableScreenRect is used by the desktop, 0652 // but Latte don't have desktop, then here just 0653 // need calculate available space for top and bottom location, 0654 // because the left and right are those who dodge others views 0655 switch (view->location()) { 0656 case Plasma::Types::TopEdge: 0657 if (view->behaveAsPlasmaPanel()) { 0658 QRect viewGeometry = view->geometry(); 0659 0660 if (desktopUse) { 0661 //! ignore any real window slide outs in all cases 0662 viewGeometry.moveTop(view->screen()->geometry().top() + view->screenEdgeMargin()); 0663 } 0664 0665 available -= viewGeometry; 0666 } else { 0667 y = view->y(); 0668 available -= QRect(x, y, w, realThickness); 0669 } 0670 0671 break; 0672 0673 case Plasma::Types::BottomEdge: 0674 if (view->behaveAsPlasmaPanel()) { 0675 QRect viewGeometry = view->geometry(); 0676 0677 if (desktopUse) { 0678 //! ignore any real window slide outs in all cases 0679 viewGeometry.moveTop(view->screen()->geometry().bottom() - view->screenEdgeMargin() - viewGeometry.height()); 0680 } 0681 0682 available -= viewGeometry; 0683 } else { 0684 y = view->geometry().bottom() - realThickness + 1; 0685 available -= QRect(x, y, w, realThickness); 0686 } 0687 0688 break; 0689 0690 case Plasma::Types::LeftEdge: 0691 if (view->behaveAsPlasmaPanel()) { 0692 QRect viewGeometry = view->geometry(); 0693 0694 if (desktopUse) { 0695 //! ignore any real window slide outs in all cases 0696 viewGeometry.moveLeft(view->screen()->geometry().left() + view->screenEdgeMargin()); 0697 } 0698 0699 available -= viewGeometry; 0700 } else { 0701 x = view->x(); 0702 available -= QRect(x, y, realThickness, h); 0703 } 0704 0705 break; 0706 0707 case Plasma::Types::RightEdge: 0708 if (view->behaveAsPlasmaPanel()) { 0709 QRect viewGeometry = view->geometry(); 0710 0711 if (desktopUse) { 0712 //! ignore any real window slide outs in all cases 0713 viewGeometry.moveLeft(view->screen()->geometry().right() - view->screenEdgeMargin() - viewGeometry.width()); 0714 } 0715 0716 available -= viewGeometry; 0717 } else { 0718 x = view->geometry().right() - realThickness + 1; 0719 available -= QRect(x, y, realThickness, h); 0720 } 0721 0722 break; 0723 0724 default: 0725 //! bypass clang warnings 0726 break; 0727 } 0728 } 0729 } 0730 0731 /*qDebug() << "::::: FREE AREAS :::::"; 0732 0733 for (int i = 0; i < available.rectCount(); ++i) { 0734 qDebug() << available.rects().at(i); 0735 } 0736 0737 qDebug() << "::::: END OF FREE AREAS :::::";*/ 0738 0739 return available; 0740 } 0741 0742 QRect Corona::availableScreenRect(int id) const 0743 { 0744 //! ignore modes are added in order for notifications to be placed 0745 //! in better positioning and not overlap with sidebars or usually hidden views 0746 QList<Types::Visibility> ignoremodes({Latte::Types::AutoHide, 0747 Latte::Types::SidebarOnDemand, 0748 Latte::Types::SidebarAutoHide}); 0749 0750 return availableScreenRectWithCriteria(id, 0751 QString(), 0752 ignoremodes); 0753 } 0754 0755 QRect Corona::availableScreenRectWithCriteria(int id, 0756 QString activityid, 0757 QList<Types::Visibility> ignoreModes, 0758 QList<Plasma::Types::Location> ignoreEdges, 0759 bool ignoreExternalPanels, 0760 bool desktopUse) const 0761 { 0762 const QScreen *screen = m_screenPool->screenForId(id); 0763 bool inCurrentActivity{activityid.isEmpty()}; 0764 0765 if (!screen) { 0766 return {}; 0767 } 0768 0769 QRect available = ignoreExternalPanels ? screen->geometry() : screen->availableGeometry(); 0770 0771 QList<Latte::View *> views; 0772 0773 if (inCurrentActivity) { 0774 views = m_layoutsManager->synchronizer()->viewsBasedOnActivityId(m_activitiesConsumer->currentActivity()); 0775 } else { 0776 views = m_layoutsManager->synchronizer()->viewsBasedOnActivityId(activityid); 0777 } 0778 0779 if (views.isEmpty()) { 0780 return available; 0781 } 0782 0783 //! blacklist irrelevant visibility modes 0784 if (!ignoreModes.contains(Latte::Types::None)) { 0785 ignoreModes << Latte::Types::None; 0786 } 0787 0788 if (!ignoreModes.contains(Latte::Types::NormalWindow)) { 0789 ignoreModes << Latte::Types::NormalWindow; 0790 } 0791 0792 bool allEdges = ignoreEdges.isEmpty(); 0793 0794 for (const auto *view : views) { 0795 bool inDesktopOffScreenStartup = desktopUse && view && view->positioner() && view->positioner()->isOffScreen(); 0796 0797 if (view && view->containment() && view->screen() == screen && !inDesktopOffScreenStartup 0798 && ((allEdges || !ignoreEdges.contains(view->location())) 0799 && (view->visibility() && !ignoreModes.contains(view->visibility()->mode())))) { 0800 0801 int appliedThickness = view->behaveAsPlasmaPanel() ? view->screenEdgeMargin() + view->normalThickness() : view->normalThickness(); 0802 0803 // Usually availableScreenRect is used by the desktop, 0804 // but Latte don't have desktop, then here just 0805 // need calculate available space for top and bottom location, 0806 // because the left and right are those who dodge others docks 0807 switch (view->location()) { 0808 case Plasma::Types::TopEdge: 0809 if (view->behaveAsPlasmaPanel() && desktopUse) { 0810 //! ignore any real window slide outs in all cases 0811 available.setTop(qMax(available.top(), view->screen()->geometry().top() + appliedThickness)); 0812 } else { 0813 available.setTop(qMax(available.top(), view->y() + appliedThickness)); 0814 } 0815 break; 0816 0817 case Plasma::Types::BottomEdge: 0818 if (view->behaveAsPlasmaPanel() && desktopUse) { 0819 //! ignore any real window slide outs in all cases 0820 available.setBottom(qMin(available.bottom(), view->screen()->geometry().bottom() - appliedThickness)); 0821 } else { 0822 available.setBottom(qMin(available.bottom(), view->y() + view->height() - appliedThickness)); 0823 } 0824 break; 0825 0826 case Plasma::Types::LeftEdge: 0827 if (view->behaveAsPlasmaPanel() && desktopUse) { 0828 //! ignore any real window slide outs in all cases 0829 available.setLeft(qMax(available.left(), view->screen()->geometry().left() + appliedThickness)); 0830 } else { 0831 available.setLeft(qMax(available.left(), view->x() + appliedThickness)); 0832 } 0833 break; 0834 0835 case Plasma::Types::RightEdge: 0836 if (view->behaveAsPlasmaPanel() && desktopUse) { 0837 //! ignore any real window slide outs in all cases 0838 available.setRight(qMin(available.right(), view->screen()->geometry().right() - appliedThickness)); 0839 } else { 0840 available.setRight(qMin(available.right(), view->x() + view->width() - appliedThickness)); 0841 } 0842 break; 0843 0844 default: 0845 //! bypass clang warnings 0846 break; 0847 } 0848 } 0849 } 0850 0851 return available; 0852 } 0853 0854 void Corona::onScreenAdded(QScreen *screen) 0855 { 0856 Q_ASSERT(screen); 0857 0858 int id = m_screenPool->id(screen->name()); 0859 0860 if (id == -1) { 0861 m_screenPool->insertScreenMapping(screen->name()); 0862 } 0863 0864 connect(screen, &QScreen::geometryChanged, this, &Corona::onScreenGeometryChanged); 0865 0866 emit availableScreenRectChanged(); 0867 emit screenAdded(m_screenPool->id(screen->name())); 0868 0869 onScreenCountChanged(); 0870 } 0871 0872 void Corona::onScreenRemoved(QScreen *screen) 0873 { 0874 disconnect(screen, &QScreen::geometryChanged, this, &Corona::onScreenGeometryChanged); 0875 onScreenCountChanged(); 0876 } 0877 0878 void Corona::onScreenCountChanged() 0879 { 0880 m_viewsScreenSyncTimer.start(); 0881 } 0882 0883 void Corona::onScreenGeometryChanged(const QRect &geometry) 0884 { 0885 Q_UNUSED(geometry); 0886 0887 QScreen *screen = qobject_cast<QScreen *>(sender()); 0888 0889 if (!screen) { 0890 return; 0891 } 0892 0893 const int id = m_screenPool->id(screen->name()); 0894 0895 if (id >= 0) { 0896 emit screenGeometryChanged(id); 0897 emit availableScreenRegionChanged(); 0898 emit availableScreenRectChanged(); 0899 } 0900 } 0901 0902 //! the central functions that updates loading/unloading latteviews 0903 //! concerning screen changed (for multi-screen setups mainly) 0904 void Corona::syncLatteViewsToScreens() 0905 { 0906 m_layoutsManager->synchronizer()->syncLatteViewsToScreens(); 0907 } 0908 0909 int Corona::primaryScreenId() const 0910 { 0911 return m_screenPool->primaryScreenId(); 0912 } 0913 0914 void Corona::quitApplication() 0915 { 0916 m_inQuit = true; 0917 0918 //! this code must be called asynchronously because it is called 0919 //! also from qml (Settings window). 0920 QTimer::singleShot(300, [this]() { 0921 m_layoutsManager->hideLatteSettingsDialog(); 0922 m_layoutsManager->synchronizer()->hideAllViews(); 0923 }); 0924 0925 //! give the time for the views to hide themselves 0926 QTimer::singleShot(800, [this]() { 0927 qGuiApp->quit(); 0928 }); 0929 } 0930 0931 void Corona::aboutApplication() 0932 { 0933 if (aboutDialog) { 0934 aboutDialog->hide(); 0935 aboutDialog->deleteLater(); 0936 } 0937 0938 aboutDialog = new KAboutApplicationDialog(KAboutData::applicationData()); 0939 connect(aboutDialog.data(), &QDialog::finished, aboutDialog.data(), &QObject::deleteLater); 0940 m_wm->skipTaskBar(*aboutDialog); 0941 m_wm->setKeepAbove(aboutDialog->winId(), true); 0942 0943 aboutDialog->show(); 0944 } 0945 0946 void Corona::loadDefaultLayout() 0947 { 0948 //disabled 0949 } 0950 0951 int Corona::screenForContainment(const Plasma::Containment *containment) const 0952 { 0953 //FIXME: indexOf is not a proper way to support multi-screen 0954 // as for environment to environment the indexes change 0955 // also there is the following issue triggered 0956 // from latteView adaptToScreen() 0957 // 0958 // in a multi-screen environment that 0959 // primary screen is not set to 0 it was 0960 // created an endless showing loop at 0961 // startup (catch-up race) between 0962 // screen:0 and primaryScreen 0963 0964 //case in which this containment is child of an applet, hello systray :) 0965 if (Plasma::Applet *parentApplet = qobject_cast<Plasma::Applet *>(containment->parent())) { 0966 if (Plasma::Containment *cont = parentApplet->containment()) { 0967 return screenForContainment(cont); 0968 } else { 0969 return -1; 0970 } 0971 } 0972 0973 Plasma::Containment *c = const_cast<Plasma::Containment *>(containment); 0974 int scrId = m_layoutsManager->synchronizer()->screenForContainment(c); 0975 0976 if (scrId >= 0) { 0977 return scrId; 0978 } 0979 0980 return containment->lastScreen(); 0981 } 0982 0983 void Corona::showAlternativesForApplet(Plasma::Applet *applet) 0984 { 0985 const QString alternativesQML = kPackage().filePath("appletalternativesui"); 0986 0987 if (alternativesQML.isEmpty()) { 0988 return; 0989 } 0990 0991 Latte::View *latteView = m_layoutsManager->synchronizer()->viewForContainment(applet->containment()); 0992 0993 KDeclarative::QmlObjectSharedEngine *qmlObj{nullptr}; 0994 0995 if (latteView) { 0996 latteView->setAlternativesIsShown(true); 0997 qmlObj = new KDeclarative::QmlObjectSharedEngine(latteView); 0998 } else { 0999 qmlObj = new KDeclarative::QmlObjectSharedEngine(this); 1000 } 1001 1002 qmlObj->setInitializationDelayed(true); 1003 qmlObj->setSource(QUrl::fromLocalFile(alternativesQML)); 1004 1005 AlternativesHelper *helper = new AlternativesHelper(applet, qmlObj); 1006 qmlObj->rootContext()->setContextProperty(QStringLiteral("alternativesHelper"), helper); 1007 1008 m_alternativesObjects << qmlObj; 1009 qmlObj->completeInitialization(); 1010 1011 //! Alternative dialog signals 1012 connect(helper, &QObject::destroyed, this, [latteView]() { 1013 latteView->setAlternativesIsShown(false); 1014 }); 1015 1016 connect(qmlObj->rootObject(), SIGNAL(visibleChanged(bool)), 1017 this, SLOT(alternativesVisibilityChanged(bool))); 1018 1019 connect(applet, &Plasma::Applet::destroyedChanged, this, [this, qmlObj](bool destroyed) { 1020 if (!destroyed) { 1021 return; 1022 } 1023 1024 QMutableListIterator<KDeclarative::QmlObjectSharedEngine *> it(m_alternativesObjects); 1025 1026 while (it.hasNext()) { 1027 KDeclarative::QmlObjectSharedEngine *obj = it.next(); 1028 1029 if (obj == qmlObj) { 1030 it.remove(); 1031 obj->deleteLater(); 1032 } 1033 } 1034 }); 1035 } 1036 1037 void Corona::alternativesVisibilityChanged(bool visible) 1038 { 1039 if (visible) { 1040 return; 1041 } 1042 1043 QObject *root = sender(); 1044 1045 QMutableListIterator<KDeclarative::QmlObjectSharedEngine *> it(m_alternativesObjects); 1046 1047 while (it.hasNext()) { 1048 KDeclarative::QmlObjectSharedEngine *obj = it.next(); 1049 1050 if (obj->rootObject() == root) { 1051 it.remove(); 1052 obj->deleteLater(); 1053 } 1054 } 1055 } 1056 1057 QStringList Corona::containmentsIds() 1058 { 1059 QStringList ids; 1060 1061 for(const auto containment : containments()) { 1062 ids << QString::number(containment->id()); 1063 } 1064 1065 return ids; 1066 } 1067 1068 QStringList Corona::appletsIds() 1069 { 1070 QStringList ids; 1071 1072 for(const auto containment : containments()) { 1073 auto applets = containment->config().group("Applets"); 1074 ids << applets.groupList(); 1075 } 1076 1077 return ids; 1078 } 1079 1080 //! Activate launcher menu through dbus interface 1081 void Corona::activateLauncherMenu() 1082 { 1083 m_globalShortcuts->activateLauncherMenu(); 1084 } 1085 1086 void Corona::windowColorScheme(QString windowIdAndScheme) 1087 { 1088 int firstSlash = windowIdAndScheme.indexOf("-"); 1089 QString windowIdStr = windowIdAndScheme.mid(0, firstSlash); 1090 QString schemeStr = windowIdAndScheme.mid(firstSlash + 1); 1091 1092 if (KWindowSystem::isPlatformWayland()) { 1093 QTimer::singleShot(200, [this, schemeStr]() { 1094 //! [Wayland Case] - give the time to be informed correctly for the active window id 1095 //! otherwise the active window id may not be the same with the one trigerred 1096 //! the color scheme dbus signal 1097 QString windowIdStr = m_wm->activeWindow().toString(); 1098 m_wm->schemesTracker()->setColorSchemeForWindow(windowIdStr.toUInt(), schemeStr); 1099 }); 1100 } else { 1101 m_wm->schemesTracker()->setColorSchemeForWindow(windowIdStr.toUInt(), schemeStr); 1102 } 1103 } 1104 1105 //! update badge for specific view item 1106 void Corona::updateDockItemBadge(QString identifier, QString value) 1107 { 1108 m_globalShortcuts->updateViewItemBadge(identifier, value); 1109 } 1110 1111 void Corona::setAutostart(const bool &enabled) 1112 { 1113 m_universalSettings->setAutostart(enabled); 1114 } 1115 1116 void Corona::switchToLayout(QString layout) 1117 { 1118 if ((layout.startsWith("file:/") || layout.startsWith("/")) && layout.endsWith(".layout.latte")) { 1119 importLayoutFile(layout); 1120 } else { 1121 m_layoutsManager->switchToLayout(layout); 1122 } 1123 } 1124 1125 void Corona::importLayoutFile(const QString &filepath, const QString &suggestedLayoutName) 1126 { 1127 bool isFilepathValid = (filepath.startsWith("file:/") || filepath.startsWith("/")) && filepath.endsWith(".layout.latte"); 1128 1129 if (!isFilepathValid) { 1130 qDebug() << i18n("The layout cannot be imported from file :: ") << filepath; 1131 return; 1132 } 1133 1134 //! Import and load runtime a layout through dbus interface 1135 //! It can be used from external programs that want to update runtime 1136 //! the Latte shown layout 1137 QString layoutPath = filepath; 1138 1139 //! cleanup layout path 1140 if (layoutPath.startsWith("file:///")) { 1141 layoutPath = layoutPath.remove("file://"); 1142 } else if (layoutPath.startsWith("file://")) { 1143 layoutPath = layoutPath.remove("file:/"); 1144 } 1145 1146 //! check out layoutpath existence 1147 if (QFileInfo(layoutPath).exists()) { 1148 qDebug() << " Layout is going to be imported and loaded from file :: " << layoutPath << " with suggested name :: " << suggestedLayoutName; 1149 1150 QString importedLayout = m_layoutsManager->importer()->importLayout(layoutPath, suggestedLayoutName); 1151 1152 if (importedLayout.isEmpty()) { 1153 qDebug() << i18n("The layout cannot be imported from file :: ") << layoutPath; 1154 } else { 1155 m_layoutsManager->switchToLayout(importedLayout, MemoryUsage::SingleLayout); 1156 } 1157 } else { 1158 qDebug() << " Layout from missing file can not be imported and loaded :: " << layoutPath; 1159 } 1160 } 1161 1162 void Corona::showSettingsWindow(int page) 1163 { 1164 if (m_inStartup) { 1165 return; 1166 } 1167 1168 Settings::Dialog::ConfigurationPage p = Settings::Dialog::LayoutPage; 1169 1170 if (page >= Settings::Dialog::LayoutPage && page <= Settings::Dialog::PreferencesPage) { 1171 p = static_cast<Settings::Dialog::ConfigurationPage>(page); 1172 } 1173 1174 m_layoutsManager->showLatteSettingsDialog(p); 1175 } 1176 1177 QStringList Corona::contextMenuData(const uint &containmentId) 1178 { 1179 QStringList data; 1180 Types::ViewType viewType{Types::DockView}; 1181 auto view = m_layoutsManager->synchronizer()->viewForContainment(containmentId); 1182 1183 if (view) { 1184 viewType = view->type(); 1185 } 1186 1187 data << QString::number((int)m_layoutsManager->memoryUsage()); // Memory Usage 1188 data << m_layoutsManager->centralLayoutsNames().join(";;"); // All Active layouts 1189 data << m_layoutsManager->synchronizer()->currentLayoutsNames().join(";;"); // All Current layouts 1190 data << m_universalSettings->contextMenuActionsAlwaysShown().join(";;"); 1191 1192 QStringList layoutsmenu; 1193 1194 for(const auto &layoutName : m_layoutsManager->synchronizer()->menuLayouts()) { 1195 if (m_layoutsManager->synchronizer()->centralLayout(layoutName) 1196 || m_layoutsManager->memoryUsage() == Latte::MemoryUsage::SingleLayout) { 1197 QStringList layoutdata; 1198 Data::LayoutIcon layouticon = m_layoutsManager->iconForLayout(layoutName); 1199 layoutdata << layoutName; 1200 layoutdata << QString::number(layouticon.isBackgroundFile); 1201 layoutdata << layouticon.name; 1202 layoutsmenu << layoutdata.join("**"); 1203 } 1204 } 1205 1206 data << layoutsmenu.join(";;"); 1207 data << (view ? view->layout()->name() : QString()); //Selected View layout*/ 1208 1209 QStringList viewtype; 1210 viewtype << QString::number((int)viewType); //Selected View type 1211 1212 if (view && view->isOriginal()) { /*View*/ 1213 auto originalview = qobject_cast<Latte::OriginalView *>(view); 1214 viewtype << "0"; //original view 1215 viewtype << QString::number(originalview->clonesCount()); 1216 } else if (view && view->isCloned()) { 1217 viewtype << "1"; //cloned view 1218 viewtype << "0"; //has no clones 1219 } else { 1220 viewtype << "0"; //original view 1221 viewtype << "0"; //has no clones 1222 } 1223 1224 data << viewtype.join(";;"); 1225 1226 return data; 1227 } 1228 1229 QStringList Corona::viewTemplatesData() 1230 { 1231 QStringList data; 1232 1233 Latte::Data::GenericTable<Data::Generic> viewtemplates = m_templatesManager->viewTemplates(); 1234 1235 for(int i=0; i<viewtemplates.rowCount(); ++i) { 1236 data << viewtemplates[i].name; 1237 data << viewtemplates[i].id; 1238 } 1239 1240 return data; 1241 } 1242 1243 void Corona::addView(const uint &containmentId, const QString &templateId) 1244 { 1245 if (containmentId <= 0) { 1246 auto currentlayouts = m_layoutsManager->currentLayouts(); 1247 if (currentlayouts.count() > 0) { 1248 currentlayouts[0]->newView(templateId); 1249 } 1250 } else { 1251 auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId); 1252 if (view) { 1253 view->newView(templateId); 1254 } 1255 } 1256 } 1257 1258 void Corona::duplicateView(const uint &containmentId) 1259 { 1260 auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId); 1261 if (view) { 1262 view->duplicateView(); 1263 } 1264 } 1265 1266 void Corona::exportViewTemplate(const uint &containmentId) 1267 { 1268 auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId); 1269 if (view) { 1270 view->exportTemplate(); 1271 } 1272 } 1273 1274 void Corona::moveViewToLayout(const uint &containmentId, const QString &layoutName) 1275 { 1276 auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId); 1277 if (view && !layoutName.isEmpty() && view->layout()->name() != layoutName) { 1278 Latte::Types::ScreensGroup screensgroup{Latte::Types::SingleScreenGroup}; 1279 1280 if (view->isOriginal()) { 1281 auto originalview = qobject_cast<Latte::OriginalView *>(view); 1282 screensgroup = originalview->screensGroup(); 1283 } 1284 1285 view->positioner()->setNextLocation(layoutName, screensgroup, "", Plasma::Types::Floating, Latte::Types::NoneAlignment); 1286 } 1287 } 1288 1289 void Corona::removeView(const uint &containmentId) 1290 { 1291 auto view = m_layoutsManager->synchronizer()->viewForContainment((int)containmentId); 1292 if (view) { 1293 view->removeView(); 1294 } 1295 } 1296 1297 void Corona::setBackgroundFromBroadcast(QString activity, QString screenName, QString filename) 1298 { 1299 if (filename.startsWith("file://")) { 1300 filename = filename.remove(0,7); 1301 } 1302 1303 PlasmaExtended::BackgroundCache::self()->setBackgroundFromBroadcast(activity, screenName, filename); 1304 } 1305 1306 void Corona::setBroadcastedBackgroundsEnabled(QString activity, QString screenName, bool enabled) 1307 { 1308 PlasmaExtended::BackgroundCache::self()->setBroadcastedBackgroundsEnabled(activity, screenName, enabled); 1309 } 1310 1311 void Corona::toggleHiddenState(QString layoutName, QString viewName, QString screenName, int screenEdge) 1312 { 1313 if (layoutName.isEmpty()) { 1314 for(auto layout : m_layoutsManager->currentLayouts()) { 1315 layout->toggleHiddenState(viewName, screenName, (Plasma::Types::Location)screenEdge); 1316 } 1317 } else { 1318 Layout::GenericLayout *gLayout = layout(layoutName); 1319 1320 if (gLayout) { 1321 gLayout->toggleHiddenState(viewName, screenName, (Plasma::Types::Location)screenEdge); 1322 } 1323 } 1324 } 1325 1326 void Corona::importFullConfiguration(const QString &file) 1327 { 1328 m_importFullConfigurationFile = file; 1329 quitApplication(); 1330 } 1331 1332 inline void Corona::qmlRegisterTypes() const 1333 { 1334 qmlRegisterUncreatableMetaObject(Latte::Settings::staticMetaObject, 1335 "org.kde.latte.private.app", // import statement 1336 0, 1, // major and minor version of the import 1337 "Settings", // name in QML 1338 "Error: only enums of latte app settings"); 1339 1340 qmlRegisterType<Latte::BackgroundTracker>("org.kde.latte.private.app", 0, 1, "BackgroundTracker"); 1341 qmlRegisterType<Latte::Interfaces>("org.kde.latte.private.app", 0, 1, "Interfaces"); 1342 qmlRegisterType<Latte::ContextMenuLayerQuickItem>("org.kde.latte.private.app", 0, 1, "ContextMenuLayer"); 1343 qmlRegisterAnonymousType<QScreen>("latte-dock", 1); 1344 qmlRegisterAnonymousType<Latte::View>("latte-dock", 1); 1345 qmlRegisterAnonymousType<Latte::ViewPart::WindowsTracker>("latte-dock", 1); 1346 qmlRegisterAnonymousType<Latte::ViewPart::TrackerPart::CurrentScreenTracker>("latte-dock", 1); 1347 qmlRegisterAnonymousType<Latte::ViewPart::TrackerPart::AllScreensTracker>("latte-dock", 1); 1348 qmlRegisterAnonymousType<Latte::WindowSystem::SchemeColors>("latte-dock", 1); 1349 qmlRegisterAnonymousType<Latte::WindowSystem::Tracker::LastActiveWindow>("latte-dock", 1); 1350 qmlRegisterAnonymousType<Latte::Types>("latte-dock", 1); 1351 1352 } 1353 1354 }