File indexing completed on 2024-04-28 16:54:58

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Klapetek <mklapetek@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "osd.h"
0008 #include "debug.h"
0009 #include "shellcorona.h"
0010 
0011 #include <QDBusConnection>
0012 #include <QDebug>
0013 #include <QTimer>
0014 #include <QWindow>
0015 
0016 #include <KDeclarative/QmlObjectSharedEngine>
0017 #include <Plasma/Package>
0018 #include <klocalizedstring.h>
0019 
0020 Osd::Osd(const KSharedConfig::Ptr &config, ShellCorona *corona)
0021     : QObject(corona)
0022     , m_osdUrl(corona->lookAndFeelPackage().fileUrl("osdmainscript"))
0023     , m_osdConfigGroup(config, "OSD")
0024 {
0025     QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/kde/osdService"),
0026                                                  this,
0027                                                  QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals);
0028 }
0029 
0030 Osd::~Osd()
0031 {
0032 }
0033 
0034 void Osd::brightnessChanged(int percent)
0035 {
0036     showProgress(QStringLiteral("video-display-brightness"), percent, 100);
0037 }
0038 
0039 void Osd::keyboardBrightnessChanged(int percent)
0040 {
0041     showProgress(QStringLiteral("input-keyboard-brightness"), percent, 100);
0042 }
0043 
0044 void Osd::volumeChanged(int percent)
0045 {
0046     volumeChanged(percent, 100);
0047 }
0048 
0049 void Osd::volumeChanged(int percent, int maximumPercent)
0050 {
0051     QString icon;
0052     if (percent <= 0) {
0053         icon = QStringLiteral("audio-volume-muted");
0054         showText(icon, i18nc("OSD informing that the system is muted, keep short", "Audio Muted"));
0055         return;
0056     } else if (percent <= 25) {
0057         icon = QStringLiteral("audio-volume-low");
0058     } else if (percent <= 75) {
0059         icon = QStringLiteral("audio-volume-medium");
0060     } else {
0061         icon = QStringLiteral("audio-volume-high");
0062     }
0063 
0064     showProgress(icon, percent, maximumPercent);
0065 }
0066 
0067 void Osd::microphoneVolumeChanged(int percent)
0068 {
0069     QString icon;
0070     if (percent <= 0) {
0071         icon = QStringLiteral("microphone-sensitivity-muted");
0072         showText(icon, i18nc("OSD informing that the microphone is muted, keep short", "Microphone Muted"));
0073         return;
0074     } else if (percent <= 25) {
0075         icon = QStringLiteral("microphone-sensitivity-low");
0076     } else if (percent <= 75) {
0077         icon = QStringLiteral("microphone-sensitivity-medium");
0078     } else {
0079         icon = QStringLiteral("microphone-sensitivity-high");
0080     }
0081 
0082     showProgress(icon, percent, 100);
0083 }
0084 
0085 void Osd::mediaPlayerVolumeChanged(int percent, const QString &playerName, const QString &playerIconName)
0086 {
0087     if (percent == 0) {
0088         showText(playerIconName, i18nc("OSD informing that some media app is muted, eg. Amarok Muted", "%1 Muted", playerName));
0089     } else {
0090         showProgress(playerIconName, percent, 100, playerName);
0091     }
0092 }
0093 
0094 void Osd::kbdLayoutChanged(const QString &layoutName)
0095 {
0096     if (m_osdConfigGroup.readEntry("kbdLayoutChangedEnabled", true)) {
0097         showText(QStringLiteral("keyboard-layout"), layoutName);
0098     }
0099 }
0100 
0101 void Osd::virtualDesktopChanged(const QString &currentVirtualDesktopName)
0102 {
0103     // FIXME: need a VD icon
0104     showText(QString(), currentVirtualDesktopName);
0105 }
0106 
0107 void Osd::touchpadEnabledChanged(bool touchpadEnabled)
0108 {
0109     if (touchpadEnabled) {
0110         showText(QStringLiteral("input-touchpad-on"), i18nc("touchpad was enabled, keep short", "Touchpad On"));
0111     } else {
0112         showText(QStringLiteral("input-touchpad-off"), i18nc("touchpad was disabled, keep short", "Touchpad Off"));
0113     }
0114 }
0115 
0116 void Osd::wifiEnabledChanged(bool wifiEnabled)
0117 {
0118     if (wifiEnabled) {
0119         showText(QStringLiteral("network-wireless-on"), i18nc("wireless lan was enabled, keep short", "Wifi On"));
0120     } else {
0121         showText(QStringLiteral("network-wireless-off"), i18nc("wireless lan was disabled, keep short", "Wifi Off"));
0122     }
0123 }
0124 
0125 void Osd::bluetoothEnabledChanged(bool bluetoothEnabled)
0126 {
0127     if (bluetoothEnabled) {
0128         showText(QStringLiteral("preferences-system-bluetooth"), i18nc("Bluetooth was enabled, keep short", "Bluetooth On"));
0129     } else {
0130         showText(QStringLiteral("preferences-system-bluetooth-inactive"), i18nc("Bluetooth was disabled, keep short", "Bluetooth Off"));
0131     }
0132 }
0133 
0134 void Osd::wwanEnabledChanged(bool wwanEnabled)
0135 {
0136     if (wwanEnabled) {
0137         showText(QStringLiteral("network-mobile-on"), i18nc("mobile internet was enabled, keep short", "Mobile Internet On"));
0138     } else {
0139         showText(QStringLiteral("network-mobile-off"), i18nc("mobile internet was disabled, keep short", "Mobile Internet Off"));
0140     }
0141 }
0142 
0143 void Osd::virtualKeyboardEnabledChanged(bool virtualKeyboardEnabled)
0144 {
0145     if (virtualKeyboardEnabled) {
0146         showText(QStringLiteral("input-keyboard-virtual-on"),
0147                  i18nc("on screen keyboard was enabled because physical keyboard got unplugged, keep short", "On-Screen Keyboard Activated"));
0148     } else {
0149         showText(QStringLiteral("input-keyboard-virtual-off"),
0150                  i18nc("on screen keyboard was disabled because physical keyboard was plugged in, keep short", "On-Screen Keyboard Deactivated"));
0151     }
0152 }
0153 
0154 bool Osd::init()
0155 {
0156     if (!m_osdConfigGroup.readEntry("Enabled", true)) {
0157         return false;
0158     }
0159 
0160     if (m_osdObject && m_osdObject->rootObject()) {
0161         return true;
0162     }
0163 
0164     if (m_osdUrl.isEmpty()) {
0165         return false;
0166     }
0167 
0168     if (!m_osdObject) {
0169         m_osdObject = new KDeclarative::QmlObjectSharedEngine(this);
0170     }
0171 
0172     m_osdObject->setSource(m_osdUrl);
0173 
0174     if (m_osdObject->status() != QQmlComponent::Ready) {
0175         qCWarning(PLASMASHELL) << "Failed to load OSD QML file" << m_osdUrl;
0176         return false;
0177     }
0178 
0179     m_timeout = m_osdObject->rootObject()->property("timeout").toInt();
0180 
0181     if (!m_osdTimer) {
0182         m_osdTimer = new QTimer(this);
0183         m_osdTimer->setSingleShot(true);
0184         connect(m_osdTimer, &QTimer::timeout, this, &Osd::hideOsd);
0185     }
0186 
0187     return true;
0188 }
0189 
0190 void Osd::showProgress(const QString &icon, const int percent, const int maximumPercent, const QString &additionalText)
0191 {
0192     if (!init()) {
0193         return;
0194     }
0195 
0196     auto *rootObject = m_osdObject->rootObject();
0197     int value = qBound(0, percent, maximumPercent);
0198     rootObject->setProperty("osdValue", value);
0199     rootObject->setProperty("osdMaxValue", maximumPercent);
0200     rootObject->setProperty("osdAdditionalText", additionalText);
0201     rootObject->setProperty("showingProgress", true);
0202     rootObject->setProperty("icon", icon);
0203 
0204     Q_EMIT osdProgress(icon, value, additionalText);
0205     showOsd();
0206 }
0207 
0208 void Osd::showText(const QString &icon, const QString &text)
0209 {
0210     if (!init()) {
0211         return;
0212     }
0213 
0214     auto *rootObject = m_osdObject->rootObject();
0215 
0216     rootObject->setProperty("showingProgress", false);
0217     rootObject->setProperty("osdValue", text);
0218     rootObject->setProperty("icon", icon);
0219 
0220     Q_EMIT osdText(icon, text);
0221     showOsd();
0222 }
0223 
0224 void Osd::showOsd()
0225 {
0226     m_osdTimer->stop();
0227 
0228     auto *rootObject = m_osdObject->rootObject();
0229 
0230     // if our OSD understands animating the opacity, do it;
0231     // otherwise just show it to not break existing lnf packages
0232     if (rootObject->property("animateOpacity").isValid()) {
0233         rootObject->setProperty("animateOpacity", false);
0234         rootObject->setProperty("opacity", 1);
0235         rootObject->setProperty("visible", true);
0236         rootObject->setProperty("animateOpacity", true);
0237         rootObject->setProperty("opacity", 0);
0238     } else {
0239         rootObject->setProperty("visible", true);
0240     }
0241 
0242     m_osdTimer->start(m_timeout);
0243 }
0244 
0245 void Osd::hideOsd()
0246 {
0247     auto *rootObject = m_osdObject->rootObject();
0248     if (!rootObject) {
0249         return;
0250     }
0251 
0252     rootObject->setProperty("visible", false);
0253 
0254     // this is needed to prevent fading from "old" values when the OSD shows up
0255     rootObject->setProperty("osdValue", 0);
0256 }