File indexing completed on 2024-05-12 05:30:04

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Klapetek <mklapetek@kde.org>
0003     SPDX-FileCopyrightText: 2016 Sebastian Kügler <sebas@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "osd.h"
0009 
0010 #include <KScreen/Mode>
0011 
0012 #include <LayerShellQt/Window>
0013 
0014 #include <KWindowSystem>
0015 #include <KX11Extras>
0016 
0017 #include <QCursor>
0018 #include <QGuiApplication>
0019 #include <QQuickItem>
0020 #include <QScreen>
0021 #include <QStandardPaths>
0022 #include <QTimer>
0023 
0024 #include <QQuickView>
0025 
0026 using namespace KScreen;
0027 
0028 Osd::Osd(const KScreen::OutputPtr &output, QObject *parent)
0029     : QObject(parent)
0030     , m_output(output)
0031 {
0032     connect(output.data(), &KScreen::Output::isConnectedChanged, this, &Osd::onOutputAvailabilityChanged);
0033     connect(output.data(), &KScreen::Output::isEnabledChanged, this, &Osd::onOutputAvailabilityChanged);
0034     m_engine.setProperty("_kirigamiTheme", QStringLiteral("KirigamiPlasmaStyle"));
0035 }
0036 
0037 Osd::~Osd()
0038 {
0039 }
0040 
0041 void Osd::showActionSelector()
0042 {
0043     if (!m_osdActionSelector) {
0044         m_osdActionSelector = std::make_unique<QQuickView>(&m_engine, nullptr);
0045         m_osdActionSelector->setInitialProperties({{QLatin1String("actions"), QVariant::fromValue(OsdAction::availableActions())}});
0046         m_osdActionSelector->setSource(QUrl(QStringLiteral("qrc:/qml/OsdSelector.qml")));
0047         m_osdActionSelector->setColor(Qt::transparent);
0048         m_osdActionSelector->setFlag(Qt::FramelessWindowHint);
0049 
0050         if (m_osdActionSelector->status() != QQuickView::Ready) {
0051             qWarning() << "Failed to load OSD QML file";
0052             m_osdActionSelector.reset();
0053             return;
0054         }
0055 
0056         auto rootObject = m_osdActionSelector->rootObject();
0057         connect(rootObject, SIGNAL(clicked(int)), this, SLOT(onOsdActionSelected(int)));
0058     }
0059 
0060     auto screen = qGuiApp->screenAt(m_output->pos());
0061     if (!screen) {
0062         screen = qGuiApp->primaryScreen();
0063     }
0064 
0065     if (KWindowSystem::isPlatformWayland()) {
0066         auto layerWindow = LayerShellQt::Window::get(m_osdActionSelector.get());
0067         layerWindow->setScope(QStringLiteral("on-screen-display"));
0068         layerWindow->setLayer(LayerShellQt::Window::LayerOverlay);
0069         layerWindow->setAnchors({});
0070         layerWindow->setKeyboardInteractivity(LayerShellQt::Window::KeyboardInteractivityOnDemand);
0071         m_osdActionSelector->setScreen(screen);
0072     } else {
0073         auto newGeometry = m_osdActionSelector->geometry();
0074         newGeometry.moveCenter(screen->geometry().center());
0075         m_osdActionSelector->setGeometry(newGeometry);
0076         KX11Extras::setState(m_osdActionSelector->winId(), NET::SkipPager | NET::SkipSwitcher | NET::SkipTaskbar);
0077         KX11Extras::setType(m_osdActionSelector->winId(), NET::OnScreenDisplay);
0078         m_osdActionSelector->requestActivate();
0079     }
0080     m_osdActionSelector->setVisible(true);
0081 }
0082 
0083 void Osd::onOsdActionSelected(int action)
0084 {
0085     Q_EMIT osdActionSelected(static_cast<OsdAction::Action>(action));
0086     hideOsd();
0087 }
0088 
0089 void Osd::onOutputAvailabilityChanged()
0090 {
0091     if (!m_output || !m_output->isConnected() || !m_output->isEnabled() || !m_output->currentMode()) {
0092         hideOsd();
0093     }
0094 }
0095 
0096 void Osd::hideOsd()
0097 {
0098     if (m_osdActionSelector) {
0099         m_osdActionSelector->setVisible(false);
0100     }
0101 }
0102 
0103 #include "moc_osd.cpp"