File indexing completed on 2024-05-12 05:30:04
0001 /* 0002 SPDX-FileCopyrightText: 2016 Sebastian Kügler <sebas@kde.org> 0003 SPDX-FileCopyrightText: 2022 David Redondo <kde@david-redondo.de> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "osdmanager.h" 0009 #include "osd.h" 0010 #include "osdserviceadaptor.h" 0011 0012 #include <KScreen/Config> 0013 #include <KScreen/EDID> 0014 #include <KScreen/GetConfigOperation> 0015 #include <KScreen/Output> 0016 0017 #include <QDBusConnection> 0018 #include <QDBusMessage> 0019 0020 #include <QQmlEngine> 0021 0022 namespace KScreen 0023 { 0024 OsdManager::OsdManager(QObject *parent) 0025 : QObject(parent) 0026 , m_cleanupTimer(new QTimer(this)) 0027 { 0028 qmlRegisterUncreatableMetaObject(OsdAction::staticMetaObject, "org.kde.KScreen", 1, 0, "OsdAction", QStringLiteral("Can't create OsdAction")); 0029 new OsdServiceAdaptor(this); 0030 0031 // free up memory when the osd hasn't been used for more than 1 minute 0032 m_cleanupTimer->setInterval(60000); 0033 m_cleanupTimer->setSingleShot(true); 0034 connect(m_cleanupTimer, &QTimer::timeout, this, [this]() { 0035 quit(); 0036 }); 0037 QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/kde/kscreen/osdService"), this, QDBusConnection::ExportAdaptors); 0038 QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.kscreen.osdService")); 0039 } 0040 0041 void OsdManager::hideOsd() 0042 { 0043 // Let QML engine finish execution of signal handlers, if any. 0044 QTimer::singleShot(0, this, &OsdManager::quit); 0045 } 0046 0047 void OsdManager::quit() 0048 { 0049 qDeleteAll(m_osds); 0050 m_osds.clear(); 0051 qApp->quit(); 0052 } 0053 0054 OsdManager::~OsdManager() 0055 { 0056 } 0057 0058 void OsdManager::showActionSelector() 0059 { 0060 connect(new KScreen::GetConfigOperation(), &KScreen::GetConfigOperation::finished, this, [this](const KScreen::ConfigOperation *op) { 0061 if (op->hasError()) { 0062 qWarning() << op->errorString(); 0063 return; 0064 } 0065 0066 // Show selector on at most one of the enabled screens 0067 const auto outputs = op->config()->outputs(); 0068 KScreen::OutputPtr osdOutput; 0069 for (const auto &output : outputs) { 0070 if (!output->isConnected() || !output->isEnabled() || !output->currentMode()) { 0071 continue; 0072 } 0073 0074 // Prefer laptop screen 0075 if (output->type() == KScreen::Output::Panel) { 0076 osdOutput = output; 0077 break; 0078 } 0079 0080 // Fallback to primary 0081 if (output->isPrimary()) { 0082 osdOutput = output; 0083 break; 0084 } 0085 } 0086 // no laptop or primary screen, just take the first usable one 0087 if (!osdOutput) { 0088 for (const auto &output : outputs) { 0089 if (output->isConnected() && output->isEnabled() && output->currentMode()) { 0090 osdOutput = output; 0091 break; 0092 } 0093 } 0094 } 0095 0096 if (!osdOutput) { 0097 return; 0098 } 0099 0100 KScreen::Osd *osd = nullptr; 0101 if (m_osds.contains(osdOutput->name())) { 0102 osd = m_osds.value(osdOutput->name()); 0103 } else { 0104 osd = new KScreen::Osd(osdOutput, this); 0105 m_osds.insert(osdOutput->name(), osd); 0106 connect(osd, &Osd::osdActionSelected, this, [this, cfg = op->config()](OsdAction::Action action) { 0107 OsdAction::applyAction(cfg, action); 0108 hideOsd(); 0109 }); 0110 } 0111 0112 osd->showActionSelector(); 0113 m_cleanupTimer->start(); 0114 }); 0115 } 0116 } 0117 0118 #include "moc_osdmanager.cpp"