// SPDX-FileCopyrightText: 2015 Marco Martin // SPDX-FileCopyrightText: 2022-2023 Devin Lin // SPDX-License-Identifier: GPL-2.0-or-later #include "homescreen.h" #include "windowlistener.h" #include #include #include #include #include #include #include #include #include #include #include #include K_PLUGIN_CLASS_WITH_JSON(HomeScreen, "metadata.json") namespace { const QString s_kwinService = QStringLiteral("org.kde.KWin"); const QString s_kwinEffectsPath = QStringLiteral("/Effects"); const QString s_kwinEffectsInterface = QStringLiteral("org.kde.kwin.Effects"); const QString s_dbusPropertiesInterface = QStringLiteral("org.freedesktop.DBus.Properties"); QStringList effectListFromVariant(const QVariant &value) { QVariant effectValue = value; if (effectValue.canConvert()) { effectValue = effectValue.value().variant(); } if (effectValue.canConvert()) { return effectValue.toStringList(); } QStringList effects; const QVariantList effectList = effectValue.toList(); effects.reserve(effectList.size()); for (const QVariant &effect : effectList) { effects.append(effect.toString()); } return effects; } } HomeScreen::HomeScreen(QObject *parent, const KPluginMetaData &data, const QVariantList &args) : Plasma::Containment{parent, data, args} , m_folioSettings{new FolioSettings{this}} , m_homeScreenState{new HomeScreenState{this}} , m_widgetsManager{new WidgetsManager{this}} , m_applicationListModel{new ApplicationListModel{this}} , m_applicationListSearchModel{new ApplicationListSearchModel{this, m_applicationListModel}} , m_applicationUsageStore{new ApplicationUsageStore{this}} , m_recentApplicationsModel{new ApplicationUsageModel{this, m_applicationUsageStore, ApplicationUsageModel::RecentUsage}} , m_mostUsedApplicationsModel{new ApplicationUsageModel{this, m_applicationUsageStore, ApplicationUsageModel::MostUsed}} , m_favouritesModel{new FavouritesModel{this}} , m_pageListModel{new PageListModel{this}} { // HomeScreenState init() has dependencies on other objects m_homeScreenState->init(); setHasConfigurationInterface(true); connect(KWindowSystem::self(), &KWindowSystem::showingDesktopChanged, this, &HomeScreen::showingDesktopChanged); updateOverviewActive(); QDBusConnection::sessionBus().connect(s_kwinService, s_kwinEffectsPath, s_dbusPropertiesInterface, QStringLiteral("PropertiesChanged"), this, SLOT(onOverviewEffectsChanged(QString, QVariantMap, QStringList))); auto overviewRefreshTimer = new QTimer(this); overviewRefreshTimer->setInterval(250); overviewRefreshTimer->setTimerType(Qt::CoarseTimer); connect(overviewRefreshTimer, &QTimer::timeout, this, &HomeScreen::updateOverviewActive); overviewRefreshTimer->start(); connect(this, &Plasma::Containment::appletAdded, this, &HomeScreen::onAppletAdded); connect(this, &Plasma::Containment::appletAboutToBeRemoved, this, &HomeScreen::onAppletAboutToBeRemoved); connect(WindowListener::instance(), &WindowListener::windowChanged, this, [this](QString storageId) { if (!WindowListener::instance()->windowsFromStorageId(storageId).empty()) { m_applicationUsageStore->recordUsage(storageId); } }); } HomeScreen::~HomeScreen() = default; void HomeScreen::configChanged() { Plasma::Containment::configChanged(); } void HomeScreen::onAppletAdded(Plasma::Applet *applet, const QRectF &geometryHint) { Q_UNUSED(geometryHint) widgetsManager()->addWidget(applet); } void HomeScreen::onAppletAboutToBeRemoved(Plasma::Applet *applet) { widgetsManager()->removeWidget(applet); } FolioSettings *HomeScreen::folioSettings() { return m_folioSettings; } HomeScreenState *HomeScreen::homeScreenState() { return m_homeScreenState; } WidgetsManager *HomeScreen::widgetsManager() { return m_widgetsManager; } ApplicationListModel *HomeScreen::applicationListModel() { return m_applicationListModel; } ApplicationListSearchModel *HomeScreen::applicationListSearchModel() { return m_applicationListSearchModel; } ApplicationUsageModel *HomeScreen::recentApplicationsModel() { return m_recentApplicationsModel; } ApplicationUsageModel *HomeScreen::mostUsedApplicationsModel() { return m_mostUsedApplicationsModel; } FavouritesModel *HomeScreen::favouritesModel() { return m_favouritesModel; } PageListModel *HomeScreen::pageListModel() { return m_pageListModel; } bool HomeScreen::overviewActive() const { return m_overviewActive; } void HomeScreen::setOverviewActive(bool overviewActive) { if (m_overviewActive == overviewActive) { return; } m_overviewActive = overviewActive; Q_EMIT overviewActiveChanged(); } void HomeScreen::updateOverviewActive() { QDBusInterface propIface(s_kwinService, s_kwinEffectsPath, s_dbusPropertiesInterface, QDBusConnection::sessionBus()); if (!propIface.isValid()) { setOverviewActive(false); return; } QDBusReply activeEffectsReply = propIface.call(QStringLiteral("Get"), s_kwinEffectsInterface, QStringLiteral("activeEffects")); if (!activeEffectsReply.isValid()) { setOverviewActive(false); return; } setOverviewActive(effectListFromVariant(activeEffectsReply.value().variant()).contains(QStringLiteral("overview"))); } void HomeScreen::onOverviewEffectsChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated) { if (interface != s_kwinEffectsInterface) { return; } if (changed.contains(QStringLiteral("activeEffects"))) { setOverviewActive(effectListFromVariant(changed.value(QStringLiteral("activeEffects"))).contains(QStringLiteral("overview"))); return; } if (invalidated.contains(QStringLiteral("activeEffects"))) { updateOverviewActive(); } } void HomeScreen::triggerOverview() { setOverviewActive(true); QDBusMessage message = QDBusMessage::createMethodCall("org.kde.kglobalaccel", "/component/kwin", "org.kde.kglobalaccel.Component", "invokeShortcut"); message.setArguments({QStringLiteral("Overview")}); QDBusConnection::sessionBus().send(message); } void HomeScreen::triggerMinimizeAll() const { QDBusMessage message = QDBusMessage::createMethodCall("org.kde.kglobalaccel", "/component/kwin", "org.kde.kglobalaccel.Component", "invokeShortcut"); message.setArguments({QStringLiteral("MinimizeAll")}); QDBusConnection::sessionBus().send(message); } void HomeScreen::activateVirtualDesktop(const QVariant &desktop) const { if (!desktop.isValid() || desktop.toString().isEmpty()) { return; } TaskManager::VirtualDesktopInfo virtualDesktopInfo; virtualDesktopInfo.requestActivate(desktop); } void HomeScreen::createVirtualDesktop() const { TaskManager::VirtualDesktopInfo virtualDesktopInfo; virtualDesktopInfo.requestCreateDesktop(virtualDesktopInfo.numberOfDesktops()); } void HomeScreen::removeLastVirtualDesktop() const { TaskManager::VirtualDesktopInfo virtualDesktopInfo; if (virtualDesktopInfo.numberOfDesktops() <= 1) { return; } virtualDesktopInfo.requestRemoveDesktop(virtualDesktopInfo.numberOfDesktops() - 1); } void HomeScreen::emptyTrash() const { QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kio.trash"), QStringLiteral("/trash"), QStringLiteral("org.kde.KIO.Trash"), QStringLiteral("emptyTrash")); QDBusConnection::sessionBus().send(message); } #include "homescreen.moc"