From e3271ec2e10eab3447f6861e405e71115fafc251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sun, 9 Mar 2014 09:12:09 +0100 Subject: [PATCH] [kwin] Add isEffectSupported method to Effects DBus interface EffectsHandlerImpl::isEffectsSupported performs the check whether the effect with the given name is supported by the current compositor. The check is the following: * if effect is already loaded, it is supported * if the effect cannot be found, it is not supported * if it's a scripted effect, it's always supported * if it's a built-in effect, we ask BuiltInEffects::supported * for all other effects we resolve the library and the supported method The idea behind providing this functionality in the DBus interface is to allow filtering in the effects KCM for the effects which are supported by the current compositor. In addition a areEffectsSupported method is added which takes a list of names and returns a list of bools. REVIEW: 116665 --- effects.cpp | 86 +++++++++++++++++++++++++++++++++++++--- effects.h | 5 +++ org.kde.kwin.Effects.xml | 9 +++++ 3 files changed, 95 insertions(+), 5 deletions(-) diff --git a/effects.cpp b/effects.cpp index 8266d2417e..bc62975c61 100644 --- a/effects.cpp +++ b/effects.cpp @@ -1395,6 +1395,21 @@ QStringList EffectsHandlerImpl::listOfEffects() const return listOfModules; } +KService::Ptr EffectsHandlerImpl::findEffectService(const QString &internalName) const +{ + QString constraint = QStringLiteral("[X-KDE-PluginInfo-Name] == '%1'").arg(internalName); + KService::List offers = KServiceTypeTrader::self()->query(QStringLiteral("KWin/Effect"), constraint); + if (offers.isEmpty()) { + return KService::Ptr(); + } + return offers.first(); +} + +bool EffectsHandlerImpl::isScriptedEffect(KService::Ptr service) const +{ + return service->property(QStringLiteral("X-Plasma-API")).toString() == QStringLiteral("javascript"); +} + bool EffectsHandlerImpl::loadEffect(const QString& name, bool checkDefault) { makeOpenGLContextCurrent(); @@ -1415,15 +1430,13 @@ bool EffectsHandlerImpl::loadEffect(const QString& name, bool checkDefault) qDebug() << "Trying to load " << name; QString internalname = name.toLower(); - QString constraint = QStringLiteral("[X-KDE-PluginInfo-Name] == '%1'").arg(internalname); - KService::List offers = KServiceTypeTrader::self()->query(QStringLiteral("KWin/Effect"), constraint); - if (offers.isEmpty()) { + KService::Ptr service = findEffectService(internalname); + if (!service) { qCritical() << "Couldn't find effect " << name << endl; return false; } - KService::Ptr service = offers.first(); - if (service->property(QStringLiteral("X-Plasma-API")).toString() == QStringLiteral("javascript")) { + if (isScriptedEffect(service)) { // this is a scripted effect - use different loader return loadScriptedEffect(name, service.data()); } @@ -1606,6 +1619,69 @@ bool EffectsHandlerImpl::isEffectLoaded(const QString& name) const return false; } +bool EffectsHandlerImpl::isEffectSupported(const QString &name) +{ + // if the effect is loaded, it is obviously supported + auto it = std::find_if(loaded_effects.constBegin(), loaded_effects.constEnd(), [name](const EffectPair &pair) { + return pair.first == name; + }); + if (it != loaded_effects.constEnd()) { + return true; + } + + const QString internalName = name.toLower(); + KService::Ptr service = findEffectService(name.toLower()); + if (!service) { + // effect not found + return false; + } + + if (isScriptedEffect(service)) { + // scripted effects are generally supported + return true; + } + + // next checks might require a context + makeOpenGLContextCurrent(); + m_compositor->addRepaintFull(); + + // try builtin effects + const QByteArray builtInName = internalName.mid(13).toUtf8(); // drop kwin4_effect_ + if (BuiltInEffects::available(builtInName)) { + return BuiltInEffects::supported(builtInName); + } + + // try remaining effects + KLibrary* library = findEffectLibrary(service.data()); + if (!library) { + return false; + } + + const QString supported_symbol = QStringLiteral("effect_supported_") + name; + KLibrary::void_function_ptr supported_func = library->resolveFunction(supported_symbol.toAscii().data()); + + bool supported = true; + + if (supported_func) { + typedef bool (*t_supportedfunc)(); + t_supportedfunc supportedFunction = reinterpret_cast(supported_func); + supported = supportedFunction(); + } + + library->unload(); + + return supported; +} + +QList< bool > EffectsHandlerImpl::areEffectsSupported(const QStringList &names) +{ + QList< bool > retList; + for (const QString &name : names) { + retList << isEffectSupported(name); + } + return retList; +} + void EffectsHandlerImpl::reloadEffect(Effect *effect) { QString effectName; diff --git a/effects.h b/effects.h index 89849f5a1b..70a5f4120c 100644 --- a/effects.h +++ b/effects.h @@ -31,6 +31,7 @@ along with this program. If not, see . #include #include #include +#include namespace Plasma { class Theme; @@ -220,6 +221,8 @@ public Q_SLOTS: Q_SCRIPTABLE void toggleEffect(const QString& name); Q_SCRIPTABLE void unloadEffect(const QString& name); Q_SCRIPTABLE bool isEffectLoaded(const QString& name) const; + Q_SCRIPTABLE bool isEffectSupported(const QString& name); + Q_SCRIPTABLE QList areEffectsSupported(const QStringList &names); Q_SCRIPTABLE QString supportInformation(const QString& name) const; Q_SCRIPTABLE QString debug(const QString& name, const QString& parameter = QString()) const; @@ -265,6 +268,8 @@ private Q_SLOTS: void slotEffectsQueried(); private: + KService::Ptr findEffectService(const QString &internalName) const; + bool isScriptedEffect(KService::Ptr service) const; typedef QVector< Effect*> EffectsList; typedef EffectsList::const_iterator EffectsIterator; Effect *loadBuiltInEffect(const QByteArray &name, bool checkDefault); diff --git a/org.kde.kwin.Effects.xml b/org.kde.kwin.Effects.xml index 4456743973..c96aa84b58 100644 --- a/org.kde.kwin.Effects.xml +++ b/org.kde.kwin.Effects.xml @@ -26,6 +26,15 @@ + + + + + + + + +