[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
This commit is contained in:
Martin Gräßlin 2014-03-09 09:12:09 +01:00
parent 098620832a
commit e3271ec2e1
3 changed files with 95 additions and 5 deletions

View file

@ -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<t_supportedfunc>(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;

View file

@ -31,6 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QHash>
#include <QQueue>
#include <Plasma/FrameSvg>
#include <KService>
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<bool> 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);

View file

@ -26,6 +26,15 @@
<arg type="b" direction="out"/>
<arg name="name" type="s" direction="in"/>
</method>
<method name="isEffectSupported">
<arg type="b" direction="out"/>
<arg name="name" type="s" direction="in"/>
</method>
<method name="areEffectsSupported">
<arg type="ab" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;bool&gt;"/>
<arg name="names" type="as" direction="in"/>
</method>
<method name="supportInformation">
<arg type="s" direction="out"/>
<arg name="name" type="s" direction="in"/>