File indexing completed on 2024-05-12 05:38:24

0001 /*
0002     SPDX-FileCopyrightText: 2009 Aaron Seigo <aseigo@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "appinterface.h"
0008 #include <config-X11.h>
0009 
0010 #include <QEventLoop>
0011 #include <QTimer>
0012 
0013 #include <Solid/Battery>
0014 #include <Solid/Device>
0015 
0016 #include <Plasma/Containment>
0017 #include <Plasma/Corona>
0018 #include <Plasma/PluginLoader>
0019 #include <Plasma/Theme>
0020 
0021 #ifdef Q_OS_WIN
0022 #include <windows.h>
0023 #endif
0024 
0025 #if HAVE_X11
0026 #include <X11/Xlib.h>
0027 #include <fixx11h.h>
0028 #endif
0029 
0030 #include "debug.h"
0031 #include "scriptengine.h"
0032 
0033 namespace WorkspaceScripting
0034 {
0035 AppInterface::AppInterface(ScriptEngine *env)
0036     : QObject(env)
0037     , m_env(env)
0038 {
0039     m_theme = new Plasma::Theme(this);
0040 }
0041 
0042 int AppInterface::screenCount() const
0043 {
0044     return m_env->corona()->numScreens();
0045 }
0046 
0047 QJSValue AppInterface::screenGeometry(int screen) const
0048 {
0049     QRectF rect = m_env->corona()->screenGeometry(screen);
0050     QJSValueList args({QJSValue(rect.x()), QJSValue(rect.y()), QJSValue(rect.width()), QJSValue(rect.height())});
0051     return m_env->globalObject().property("QRectF").callAsConstructor(args);
0052 }
0053 
0054 QList<int> AppInterface::activityIds() const
0055 {
0056     // FIXME: the ints could overflow since Applet::id() returns a uint,
0057     //       however QScript deals with QList<uint> very, very poorly
0058     QList<int> containments;
0059 
0060     foreach (Plasma::Containment *c, m_env->corona()->containments()) {
0061         if (!ScriptEngine::isPanel(c)) {
0062             containments.append(c->id());
0063         }
0064     }
0065 
0066     return containments;
0067 }
0068 
0069 QList<int> AppInterface::panelIds() const
0070 {
0071     // FIXME: the ints could overflow since Applet::id() returns a uint,
0072     //       however QScript deals with QList<uint> very, very poorly
0073     QList<int> panels;
0074 
0075     foreach (Plasma::Containment *c, m_env->corona()->containments()) {
0076         // qDebug() << "checking" << (QObject*)c << isPanel(c);
0077         if (ScriptEngine::isPanel(c)) {
0078             panels.append(c->id());
0079         }
0080     }
0081 
0082     return panels;
0083 }
0084 
0085 QString AppInterface::applicationVersion() const
0086 {
0087     return qApp->applicationVersion();
0088 }
0089 
0090 QString AppInterface::platformVersion() const
0091 {
0092     return QString(); // KDE::versionString();
0093 }
0094 
0095 int AppInterface::scriptingVersion() const
0096 {
0097     return PLASMA_DESKTOP_SCRIPTING_VERSION;
0098 }
0099 
0100 QString AppInterface::theme() const
0101 {
0102     return m_theme->themeName();
0103 }
0104 
0105 void AppInterface::setTheme(const QString &name)
0106 {
0107     m_theme->setThemeName(name);
0108 }
0109 
0110 QString AppInterface::locale() const
0111 {
0112     return QLocale::system().name();
0113 }
0114 
0115 QString AppInterface::language() const
0116 {
0117     return QLocale::system().languageToString(QLocale::system().language());
0118 }
0119 
0120 QString AppInterface::languageId() const
0121 {
0122     return QLocale::system().bcp47Name().section(QLatin1Char('-'), 0, 0);
0123 }
0124 
0125 bool AppInterface::multihead() const
0126 {
0127     return false;
0128 }
0129 
0130 int AppInterface::multiheadScreen() const
0131 {
0132     return 0;
0133 }
0134 
0135 void AppInterface::lockCorona(bool locked)
0136 {
0137     m_env->corona()->setImmutability(locked ? Plasma::Types::UserImmutable : Plasma::Types::Mutable);
0138 }
0139 
0140 bool AppInterface::coronaLocked() const
0141 {
0142     return m_env->corona()->immutability() != Plasma::Types::Mutable;
0143 }
0144 
0145 void AppInterface::sleep(int ms)
0146 {
0147     Q_UNUSED(ms)
0148     // TODO KF6 remove
0149 
0150     // Sleep was implemented with a nested event loop which would cause nested
0151     // event processing from QML and offer a wide array of sources for
0152     // segfaulting. There isn't really a need to sleep from the scripting API,
0153     // so it was turned no-op.
0154     qCWarning(PLASMASHELL) << "Plasma scripting sleep() is deprecated and does nothing!";
0155 }
0156 
0157 bool AppInterface::hasBattery() const
0158 {
0159     QList<Solid::Device> batteryDevices = Solid::Device::listFromType(Solid::DeviceInterface::Battery);
0160 
0161     for (auto device : batteryDevices) {
0162         Solid::Battery *battery = device.as<Solid::Battery>();
0163         // check for _both_ primary and power supply status
0164         // apparently some devices misreport as "primary", and we don't
0165         // want to trigger on just having UPC connected to a desktop box
0166         if (battery && battery->type() == Solid::Battery::PrimaryBattery && battery->isPowerSupply()) {
0167             return true;
0168         }
0169     }
0170 
0171     return false;
0172 }
0173 
0174 QStringList AppInterface::knownWidgetTypes() const
0175 {
0176     if (m_knownWidgets.isEmpty()) {
0177         QStringList widgets;
0178         const QList<KPluginMetaData> plugins = Plasma::PluginLoader::self()->listAppletMetaData(QString());
0179 
0180         for (const auto &plugin : plugins) {
0181             widgets.append(plugin.pluginId());
0182         }
0183 
0184         const_cast<AppInterface *>(this)->m_knownWidgets = widgets;
0185     }
0186 
0187     return m_knownWidgets;
0188 }
0189 
0190 QStringList AppInterface::knownActivityTypes() const
0191 {
0192     return knownContainmentTypes(QStringLiteral("Desktop"));
0193 }
0194 
0195 QStringList AppInterface::knownPanelTypes() const
0196 {
0197     return knownContainmentTypes(QStringLiteral("Panel"));
0198 }
0199 
0200 QStringList AppInterface::knownContainmentTypes(const QString &type) const
0201 {
0202     QStringList containments;
0203     const QList<KPluginMetaData> plugins = Plasma::PluginLoader::listContainmentsMetaDataOfType(type);
0204 
0205     containments.reserve(plugins.count());
0206     for (const KPluginMetaData &plugin : plugins) {
0207         containments.append(plugin.pluginId());
0208     }
0209 
0210     return containments;
0211 }
0212 
0213 }