File indexing completed on 2024-04-21 05:36:02

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