remove kwin scripting support

This commit is contained in:
Ivailo Monev 2014-12-08 20:07:54 +00:00
parent 26551d36f0
commit cfb6741c02
30 changed files with 0 additions and 5878 deletions

View file

@ -6,7 +6,6 @@ OPTION(KWIN_BUILD_OXYGEN "Enable building of default decoration Oxygen" ON)
OPTION(KWIN_BUILD_KCMS "Enable building of KWin configuration modules." ON)
OPTION(KWIN_BUILD_TABBOX "Enable building of KWin Tabbox functionality" ON)
OPTION(KWIN_BUILD_SCREENEDGES "Enable building of KWin with screen edge support" ON)
OPTION(KWIN_BUILD_SCRIPTING "Enable building of KWin with scripting support" ON)
OPTION(KWIN_BUILD_KAPPMENU "Enable building of KWin with application menu support" ON)
OPTION(KWIN_BUILD_XRENDER_COMPOSITING "Enable building of KWin with XRender Compositing support" ON)
OPTION(KWIN_BUILD_OPENGL_1_COMPOSITING "Enable support for OpenGL 1.x, automatically disabled when building for OpenGL ES 2.0" ON)
@ -23,7 +22,6 @@ if(KWIN_PLASMA_ACTIVE)
set(KWIN_BUILD_DECORATIONS OFF)
set(KWIN_BUILD_KCMS OFF)
set(KWIN_BUILD_SCREENEDGES OFF)
set(KWIN_BUILD_SCRIPTING ON)
set(KWIN_BUILD_XRENDER_COMPOSITING OFF)
set(KWIN_MOBILE_EFFECTS ON)
set(KWIN_BUILD_WITH_OPENGLES ON)
@ -86,12 +84,8 @@ endif()
add_subdirectory( data )
add_subdirectory( effects )
add_subdirectory( scripts )
add_subdirectory( tabbox )
if(KWIN_BUILD_SCRIPTING)
add_subdirectory(scripting)
endif()
########### next target ###############
@ -143,19 +137,6 @@ set(kwin_KDEINIT_SRCS
xcbutils.cpp
)
if(KWIN_BUILD_SCRIPTING)
set(
kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS}
scripting/scripting.cpp
scripting/workspace_wrapper.cpp
scripting/meta.cpp
scripting/scriptedeffect.cpp
scripting/scriptingutils.cpp
scripting/timer.cpp
scripting/scripting_model.cpp
)
endif()
if(KWIN_BUILD_TABBOX)
set(
kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS}
@ -262,10 +243,6 @@ else()
add_definitions(-DKWIN_NO_XF86VM)
endif()
if(KWIN_BUILD_SCRIPTING)
set(kwin_QT_LIBS ${kwin_QT_LIBS} ${QT_QTSCRIPT_LIBRARY})
endif()
if(OPENGL_EGL_FOUND)
set(kwin_OPENGL_LIBS ${kwin_OPENGL_LIBS} ${OPENGLES_EGL_LIBRARY})
endif()
@ -324,11 +301,6 @@ install( FILES kwin.kcfg DESTINATION ${KCFG_INSTALL_DIR} RENAME ${KWIN_NAME}.k
install( FILES kwin.notifyrc DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME} RENAME ${KWIN_NAME}.notifyrc)
install( FILES org.kde.KWin.xml DESTINATION ${DBUS_INTERFACES_INSTALL_DIR} )
if( KWIN_BUILD_SCRIPTING )
# Install the KWin/WindowSwitcher service type
install( FILES scripting/kwinscript.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR} )
endif()
kde4_install_icons( ${ICON_INSTALL_DIR} )
add_subdirectory(tests)

View file

@ -1,4 +0,0 @@
set(kcm_kwin4_genericscripted_SRCS genericscriptedconfig.cpp)
kde4_add_plugin( kcm_kwin4_genericscripted ${kcm_kwin4_genericscripted_SRCS} )
target_link_libraries( kcm_kwin4_genericscripted ${KDE4_KIO_LIBS} ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${QT_QTUITOOLS_LIBRARY} )
install( TARGETS kcm_kwin4_genericscripted DESTINATION ${PLUGIN_INSTALL_DIR} )

View file

@ -1,4 +0,0 @@
#!/bin/bash
$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp
$XGETTEXT `find . -name \*.h -o -name \*.cpp` -o $podir/kwin_scripting.pot
rm -f rc.cpp

View file

@ -1,179 +0,0 @@
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.7.6.1">
<!-- Documentation for global KWin effect methods. In doxygen XML format as this can be converted to MediaWiki -->
<!-- Use script and XSLT from kde:scratch/graesslin/kwin-scripting-api-generator to generate the documentation -->
<!-- This xml is not meant to be doxygen complient -->
<compounddef>
<compoundname>Global</compoundname>
<briefdescription>Methods and properties added to the global JavaScript object.</briefdescription>
<sectiondef kind="property">
<memberdef kind="property" writable="no">
<type>KWin::EffectsHandler</type>
<definition></definition>
<argsstring></argsstring>
<name>effects</name>
<read></read>
<detaileddescription>Global property to the core wrapper of KWin Effects</detaileddescription>
</memberdef>
<memberdef kind="property" writable="no">
<type>KWin::ScriptedEffect</type>
<definition></definition>
<argsstring></argsstring>
<name>effect</name>
<read></read>
<detaileddescription>Global property to the actual Effect</detaileddescription>
</memberdef>
<memberdef kind="property" writable="no">
<type>object</type>
<definition></definition>
<argsstring></argsstring>
<name>Effect</name>
<read></read>
<detaileddescription>Provides access to enums defined in KWin::AnimationEffect and KWin::ScriptedEffect</detaileddescription>
</memberdef>
<memberdef kind="property" writable="no">
<type>object</type>
<definition></definition>
<argsstring></argsstring>
<name>KWin</name>
<read></read>
<detaileddescription>Provides access to enums defined in KWin::WorkspaceWrapper</detaileddescription>
</memberdef>
<memberdef kind="property" writable="no">
<type>object</type>
<definition></definition>
<argsstring></argsstring>
<name>QEasingCurve</name>
<read></read>
<detaileddescription>Provides access to enums defined in QEasingCurve</detaileddescription>
</memberdef>
</sectiondef>
<sectiondef kind="public-func">
<memberdef kind="function">
<type>Q_SCRIPTABLE QList&lt;quint64&gt;</type>
<definition>QList&lt;quint64&gt; KWin::ScriptedEffect::animate</definition>
<argsstring>(settings)</argsstring>
<name>animate</name>
<read></read>
<detaileddescription>
Schedules one or many animations for one window. The animations are defined through the settings object providing
a more declarative way to specify the animations than the animate call on the effect object. The settings object
supports the following attributes:
&lt;syntaxhighlight lang="javascript"&gt;
{
window: EffectWindow, /* the window to animate, required */
duration: int, /* duration in msec, required */
curve: QEasingCurve.Type, /* global easing curve, optional */
type: Effect.Attribute, /* for first animation, optional */
from: FPx2, /* for first animation, optional */
to: FPx2, /* for first animation, optional */
delay: int, /* for first animation, optional */
animations: [ /* additional animations, optional */
{
curve: QEasingCurve.Type, /* overrides global */
type: Effect.Attribute,
from: FPx2,
to: FPx2,
delay: int
}
]
}
&lt;/syntaxhighlight&gt;
At least one animation or attribute setter (see below) needs to be specified either with the top-level properties or in the animations list.
</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE QList&lt;quint64&gt;</type>
<definition>QList&lt;quint64&gt; KWin::ScriptedEffect::set</definition>
<argsstring>(settings)</argsstring>
<name>set</name>
<read></read>
<detaileddescription>
Like animate, just that the manipulation does not implicitly end with the animation. You have to explicitly cancel it.
Until then, the manipulated attribute will remain at animation target value.
</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE bool</type>
<definition>bool KWin::ScriptedEffect::cancel</definition>
<argsstring>(QList&lt;quint64&gt;)</argsstring>
<name>cancel</name>
<read></read>
<detaileddescription>
Cancel one or more present animations caused and returned by KWin::ScriptedEffect::animate or KWin::ScriptedEffect::set.
For convenience you can pass a single quint64 as well.
</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE void</type>
<definition>void KWin::ScriptedEffect::print</definition>
<argsstring>(QVariant ... values)</argsstring>
<name>print</name>
<read></read>
<detaileddescription>Prints all provided values to kDebug and as a D-Bus signal</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE int</type>
<definition>int KWin::ScriptedEffect::animationTime</definition>
<argsstring>(int duration)</argsstring>
<name>animationTime</name>
<read></read>
<detaileddescription>Adjusts the passed in duration to the global animation time facator.</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE int</type>
<definition>int KWin::ScriptedEffect::displayWidth</definition>
<argsstring>()</argsstring>
<name>displayWidth</name>
<read></read>
<detaileddescription>Width of the complete display (all screens).</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE int</type>
<definition>int KWin::ScriptedEffect::displayHeight</definition>
<argsstring>()</argsstring>
<name>displayHeight</name>
<read></read>
<detaileddescription>Height of the complete display (all screens).</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE bool</type>
<definition>bool KWin::ScriptedEffect::registerScreenEdge</definition>
<argsstring>(ElectricBorder border, QScriptValue callback)</argsstring>
<name>registerScreenEdge</name>
<read></read>
<detaileddescription>Registers the callback for the screen edge. When the mouse gets pushed against the given edge the callback will be invoked.</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE bool</type>
<definition>bool KWin::ScriptedEffect::registerShortcut</definition>
<argsstring>(QString title, QString text, QString keySequence, QScriptValue callback)</argsstring>
<name>registerShortcut</name>
<read></read>
<detaileddescription>Registers keySequence as a global shortcut. When the shortcut is invoked the callback will be called. Title and text are used to name the shortcut and make it available to the global shortcut configuration module.</detaileddescription>
</memberdef>
</sectiondef>
</compounddef>
<compounddef>
<compoundname>KWin::FPx2</compoundname>
<briefdescription>This class is used to describe the animation end points, that is from which FPx2 values to which FPx2 values an animation goes. This class contains two properties to describe two animation components individually (e.g. width and height). But it's also possible to just have one value (e.g. opacity). In this case the definition of an FPx2 can be replaced by a single value.</briefdescription>
<sectiondef kind="property">
<memberdef kind="property" writable="yes">
<type>qreal</type>
<definition></definition>
<argsstring></argsstring>
<name>value1</name>
<read></read>
<detaileddescription></detaileddescription>
</memberdef>
<memberdef kind="property" writable="yes">
<type>qreal</type>
<definition></definition>
<argsstring></argsstring>
<name>value2</name>
<read></read>
<detaileddescription></detaileddescription>
</memberdef>
</sectiondef>
</compounddef>
</doxygen>

View file

@ -1,134 +0,0 @@
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.7.6.1">
<!-- Documentation for global KWin scripting methods. In doxygen XML format as this can be converted to MediaWiki -->
<!-- Use script and XSLT from kde:scratch/graesslin/kwin-scripting-api-generator to generate the documentation -->
<!-- This xml is not meant to be doxygen complient -->
<compounddef>
<compoundname>Global</compoundname>
<briefdescription>Methods and properties added to the global JavaScript object.</briefdescription>
<sectiondef kind="property">
<memberdef kind="property" writable="no">
<type>KWin::Options</type>
<definition></definition>
<argsstring></argsstring>
<name>options</name>
<read></read>
<detaileddescription>Global property to all configuration values of KWin core.</detaileddescription>
</memberdef>
<memberdef kind="property" writable="no">
<type>KWin::Workspace</type>
<definition></definition>
<argsstring></argsstring>
<name>workspace</name>
<read></read>
<detaileddescription>Global property to the core wrapper of KWin.</detaileddescription>
</memberdef>
<memberdef kind="property" writable="no">
<type>object</type>
<definition></definition>
<argsstring></argsstring>
<name>KWin</name>
<read></read>
<detaileddescription>Provides access to enums defined in KWin::WorkspaceWrapper</detaileddescription>
</memberdef>
</sectiondef>
<sectiondef kind="public-func">
<memberdef kind="function">
<type>Q_SCRIPTABLE void</type>
<definition>void KWin::Scripting::print</definition>
<argsstring>(QVariant ... values)</argsstring>
<name>print</name>
<read></read>
<detaileddescription>Prints all provided values to kDebug and as a D-Bus signal</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE QVariant</type>
<definition>QVariant KWin::Scripting::readConfig</definition>
<argsstring>(QString key, QVariant defaultValue = QVariant())</argsstring>
<name>readConfig</name>
<read></read>
<detaileddescription>Reads the config value for key in the Script's configuration with the optional default value. If not providing a default value and no value stored in the configuration an undefined value is returned.</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE bool</type>
<definition>bool KWin::Scripting::registerScreenEdge</definition>
<argsstring>(ElectricBorder border, QScriptValue callback)</argsstring>
<name>registerScreenEdge</name>
<read></read>
<detaileddescription>Registers the callback for the screen edge. When the mouse gets pushed against the given edge the callback will be invoked.</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE bool</type>
<definition>bool KWin::Scripting::registerShortcut</definition>
<argsstring>(QString title, QString text, QString keySequence, QScriptValue callback)</argsstring>
<name>registerShortcut</name>
<read></read>
<detaileddescription>Registers keySequence as a global shortcut. When the shortcut is invoked the callback will be called. Title and text are used to name the shortcut and make it available to the global shortcut configuration module.</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE bool</type>
<definition>bool KWin::Scripting::assert</definition>
<argsstring>(bool value, QString message = QString())</argsstring>
<name>assert</name>
<read></read>
<detaileddescription>Aborts the execution of the script if value does not evaluate to true. If message is provided an error is thrown with the given message, if not provided an error with default message is thrown.</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE bool</type>
<definition>bool KWin::Scripting::assertTrue</definition>
<argsstring>(bool value, QString message = QString())</argsstring>
<name>assertTrue</name>
<read></read>
<detaileddescription>Aborts the execution of the script if value does not evaluate to true. If message is provided an error is thrown with the given message, if not provided an error with default message is thrown.</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE bool</type>
<definition>bool KWin::Scripting::assertFalse</definition>
<argsstring>(bool value, QString message = QString())</argsstring>
<name>assertFalse</name>
<read></read>
<detaileddescription>Aborts the execution of the script if value does not evaluate to false. If message is provided an error is thrown with the given message, if not provided an error with default message is thrown.</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE bool</type>
<definition>bool KWin::Scripting::assertEquals</definition>
<argsstring>(QVariant expected, QVariant actual, QString message = QString())</argsstring>
<name>assertEquals</name>
<read></read>
<detaileddescription>Aborts the execution of the script if the actual value is not equal to the expected value. If message is provided an error is thrown with the given message, if not provided an error with default message is thrown.</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE bool</type>
<definition>bool KWin::Scripting::assertNull</definition>
<argsstring>(QVariant value, QString message = QString())</argsstring>
<name>assertNull</name>
<read></read>
<detaileddescription>Aborts the execution of the script if value is not null. If message is provided an error is thrown with the given message, if not provided an error with default message is thrown.</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE bool</type>
<definition>bool KWin::Scripting::assertNotNull</definition>
<argsstring>(QVariant value, QString message = QString())</argsstring>
<name>assertNotNull</name>
<read></read>
<detaileddescription>Aborts the execution of the script if value is null. If message is provided an error is thrown with the given message, if not provided an error with default message is thrown.</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE void</type>
<definition>void KWin::Scripting::callDBus</definition>
<argsstring>(QString service, QString path, QString interface, QString method, QVariant arg..., QScriptValue callback = QScriptValue())</argsstring>
<name>callDBus</name>
<read></read>
<detaileddescription>Call a D-Bus method at (service, path, interface and method). A variable number of arguments can be added to the method call. The D-Bus call is always performed in an async way invoking the callback provided as the last (optional) argument. The reply values of the D-Bus method call are passed to the callback.</detaileddescription>
</memberdef>
<memberdef kind="function">
<type>Q_SCRIPTABLE void</type>
<definition>void KWin::Scripting::registerUserActionsMenu</definition>
<argsstring>(QScriptValue callback)</argsstring>
<name>registerUserActionsMenu</name>
<read></read>
<detaileddescription>Registers the passed in callback to be invoked whenever the User actions menu (Alt+F3 or right click on window decoration) is about to be shown. The callback is invoked with a reference to the Client for which the menu is shown. The callback can return either a single menu entry to be added to the menu or an own sub menu with multiple entries. The object for a menu entry should be {title: "My Menu entry", checkable: true, checked: false, triggered: function (action) { // callback with triggered QAction}}, for a menu it should be {title: "My menu", items: [{...}, {...}, ...] /*list with entries as described*/}</detaileddescription>
</memberdef>
</sectiondef>
</compounddef>
</doxygen>

View file

@ -1,149 +0,0 @@
/*
* KWin - the KDE window manager
* This file is part of the KDE project.
*
* Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "genericscriptedconfig.h"
#include "config-kwin.h"
#include <KDE/KStandardDirs>
#include <KDE/KLocalizedString>
#include <Plasma/ConfigLoader>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QFile>
#include <QLabel>
#include <QUiLoader>
#include <QVBoxLayout>
namespace KWin {
GenericScriptedConfigFactory::GenericScriptedConfigFactory()
: KPluginFactory("kcm_kwin4_genericscripted")
{
}
QObject *GenericScriptedConfigFactory::create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword)
{
Q_UNUSED(iface)
Q_UNUSED(parent)
if (keyword.startsWith("kwin4_effect_")) {
return new ScriptedEffectConfig(componentData(), keyword, parentWidget, args);
} else {
return new ScriptingConfig(componentData(), keyword, parentWidget, args);
}
}
GenericScriptedConfig::GenericScriptedConfig(const KComponentData &data, const QString &keyword, QWidget *parent, const QVariantList &args)
: KCModule(data, parent, args)
, m_packageName(keyword)
{
}
GenericScriptedConfig::~GenericScriptedConfig()
{
}
void GenericScriptedConfig::createUi()
{
QVBoxLayout* layout = new QVBoxLayout(this);
const QString kconfigXTFile = KStandardDirs::locate("data", QLatin1String(KWIN_NAME) + '/' + typeName() + '/' + m_packageName + "/contents/config/main.xml");
const QString uiPath = KStandardDirs::locate("data", QLatin1String(KWIN_NAME) + '/' + typeName() + '/' + m_packageName + "/contents/ui/config.ui");
if (kconfigXTFile.isEmpty() || uiPath.isEmpty()) {
layout->addWidget(new QLabel(i18nc("Error message", "Plugin does not provide configuration file in expected location")));
return;
}
QFile xmlFile(kconfigXTFile);
KConfigGroup cg = configGroup();
Plasma::ConfigLoader *configLoader = new Plasma::ConfigLoader(&cg, &xmlFile, this);
// load the ui file
QUiLoader *loader = new QUiLoader(this);
QFile uiFile(uiPath);
uiFile.open(QFile::ReadOnly);
QWidget *customConfigForm = loader->load(&uiFile, this);
uiFile.close();
layout->addWidget(customConfigForm);
addConfig(configLoader, customConfigForm);
}
void GenericScriptedConfig::save()
{
KCModule::save();
reload();
}
void GenericScriptedConfig::reload()
{
}
ScriptedEffectConfig::ScriptedEffectConfig(const KComponentData &data, const QString &keyword, QWidget *parent, const QVariantList &args)
: GenericScriptedConfig(data, keyword, parent, args)
{
createUi();
}
ScriptedEffectConfig::~ScriptedEffectConfig()
{
}
QString ScriptedEffectConfig::typeName() const
{
return QString("effects");
}
KConfigGroup ScriptedEffectConfig::configGroup()
{
return KSharedConfig::openConfig(KWIN_CONFIG)->group("Effect-" + packageName());
}
void ScriptedEffectConfig::reload()
{
QDBusMessage message = QDBusMessage::createMethodCall("org.kde.kwin", "/KWin", "org.kde.KWin", "reconfigureEffect");
message << QString(packageName());
QDBusConnection::sessionBus().send(message);
}
ScriptingConfig::ScriptingConfig(const KComponentData &data, const QString &keyword, QWidget *parent, const QVariantList &args)
: GenericScriptedConfig(data, keyword, parent, args)
{
createUi();
}
ScriptingConfig::~ScriptingConfig()
{
}
KConfigGroup ScriptingConfig::configGroup()
{
return KSharedConfig::openConfig(KWIN_CONFIG)->group("Script-" + packageName());
}
QString ScriptingConfig::typeName() const
{
return QString("scripts");
}
void ScriptingConfig::reload()
{
// TODO: what to call
}
K_EXPORT_PLUGIN(GenericScriptedConfigFactory())
} // namespace

View file

@ -1,95 +0,0 @@
/*
* KWin - the KDE window manager
* This file is part of the KDE project.
*
* Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KWIN_GENERICSCRIPTEDCONFIG_H
#define KWIN_GENERICSCRIPTEDCONFIG_H
#include <KCModule>
#include <KPluginFactory>
namespace KWin
{
class GenericScriptedConfigFactory : public KPluginFactory
{
Q_OBJECT
public:
GenericScriptedConfigFactory();
protected:
virtual QObject *create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword);
};
class GenericScriptedConfig : public KCModule
{
Q_OBJECT
public:
GenericScriptedConfig(const KComponentData &data, const QString &keyword, QWidget *parent, const QVariantList &args);
virtual ~GenericScriptedConfig();
public slots:
virtual void save();
protected:
const QString &packageName() const;
void createUi();
virtual QString typeName() const = 0;
virtual KConfigGroup configGroup() = 0;
virtual void reload();
private:
QString m_packageName;
};
class ScriptedEffectConfig : public GenericScriptedConfig
{
Q_OBJECT
public:
ScriptedEffectConfig(const KComponentData &data, const QString &keyword, QWidget *parent, const QVariantList &args);
virtual ~ScriptedEffectConfig();
protected:
virtual QString typeName() const;
virtual KConfigGroup configGroup();
virtual void reload();
};
class ScriptingConfig : public GenericScriptedConfig
{
Q_OBJECT
public:
ScriptingConfig(const KComponentData &data, const QString &keyword, QWidget *parent, const QVariantList &args);
virtual ~ScriptingConfig();
protected:
virtual QString typeName() const;
virtual KConfigGroup configGroup();
virtual void reload();
};
inline
const QString &GenericScriptedConfig::packageName() const
{
return m_packageName;
}
}
#endif // KWIN_GENERICSCRIPTEDCONFIG_H

View file

@ -1,60 +0,0 @@
[Desktop Entry]
Type=ServiceType
X-KDE-ServiceType=KWin/Script
Comment=KWin Script
Comment[bs]=KWin skripta
Comment[ca]=Script del KWin
Comment[ca@valencia]=Script del KWin
Comment[cs]=Skript KWinu
Comment[da]=KWin-script
Comment[de]=KWin-Skript
Comment[el]=Σενάριο KWin
Comment[en_GB]=KWin Script
Comment[es]=Guion de KWin
Comment[et]=KWini skript
Comment[eu]=KWin scripta
Comment[fi]=KWin-skripti
Comment[fr]=Script KWin
Comment[ga]=Script KWin
Comment[gl]=Script do KWin
Comment[he]=תסריט של KWin
Comment[hu]=KWin parancsfájl
Comment[ia]=Script de kwin
Comment[it]=Script kwin
Comment[kk]=KWin скрипті
Comment[km]= KWin
Comment[ko]=KWin
Comment[lt]=KWin scenarijus
Comment[mr]=-ि ि
Comment[nb]=KWin-skript
Comment[nds]=KWin-Skript
Comment[nl]=KWin-script
Comment[pa]=KWin ਿ
Comment[pl]=Skrypt KWin
Comment[pt]=Programa do KWin
Comment[pt_BR]=Script do KWin
Comment[ro]=Script KWin
Comment[ru]=Сценарий KWin
Comment[sk]=KWin skript
Comment[sl]=Skript KWin
Comment[sr]=Квинова скрипта
Comment[sr@ijekavian]=Квинова скрипта
Comment[sr@ijekavianlatin]=KWinova skripta
Comment[sr@latin]=KWinova skripta
Comment[sv]=Kwin-skript
Comment[tr]=KWin Betiği
Comment[uk]=Скрипт KWin
Comment[vi]=Tp lnh KWin
Comment[x-test]=xxKWin Scriptxx
Comment[zh_CN]=KWin
Comment[zh_TW]=KWin 稿
[PropertyDef::X-Plasma-API]
Type=QString
[PropertyDef::X-Plasma-MainScript]
Type=QString
[PropertyDef::X-KWin-Exclude-Listing]
Type=bool

View file

@ -1,240 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "meta.h"
#include "client.h"
#include <QtScript/QScriptEngine>
using namespace KWin::MetaScripting;
// Meta for QPoint object
QScriptValue Point::toScriptValue(QScriptEngine* eng, const QPoint& point)
{
QScriptValue temp = eng->newObject();
temp.setProperty("x", point.x());
temp.setProperty("y", point.y());
return temp;
}
void Point::fromScriptValue(const QScriptValue& obj, QPoint& point)
{
QScriptValue x = obj.property("x", QScriptValue::ResolveLocal);
QScriptValue y = obj.property("y", QScriptValue::ResolveLocal);
if (!x.isUndefined() && !y.isUndefined()) {
point.setX(x.toInt32());
point.setY(y.toInt32());
}
}
// End of meta for QPoint object
// Meta for QSize object
QScriptValue Size::toScriptValue(QScriptEngine* eng, const QSize& size)
{
QScriptValue temp = eng->newObject();
temp.setProperty("w", size.width());
temp.setProperty("h", size.height());
return temp;
}
void Size::fromScriptValue(const QScriptValue& obj, QSize& size)
{
QScriptValue w = obj.property("w", QScriptValue::ResolveLocal);
QScriptValue h = obj.property("h", QScriptValue::ResolveLocal);
if (!w.isUndefined() && !h.isUndefined()) {
size.setWidth(w.toInt32());
size.setHeight(h.toInt32());
}
}
// End of meta for QSize object
// Meta for QRect object. Just a temporary measure, hope to
// add a much better wrapping of the QRect object soon
QScriptValue Rect::toScriptValue(QScriptEngine* eng, const QRect& rect)
{
QScriptValue temp = eng->newObject();
temp.setProperty("x", rect.x());
temp.setProperty("y", rect.y());
temp.setProperty("width", rect.width());
temp.setProperty("height", rect.height());
return temp;
}
void Rect::fromScriptValue(const QScriptValue& obj, QRect &rect)
{
QScriptValue w = obj.property("width", QScriptValue::ResolveLocal);
QScriptValue h = obj.property("height", QScriptValue::ResolveLocal);
QScriptValue x = obj.property("x", QScriptValue::ResolveLocal);
QScriptValue y = obj.property("y", QScriptValue::ResolveLocal);
if (!w.isUndefined() && !h.isUndefined() && !x.isUndefined() && !y.isUndefined()) {
rect.setX(x.toInt32());
rect.setY(y.toInt32());
rect.setWidth(w.toInt32());
rect.setHeight(h.toInt32());
}
}
// End of meta for QRect object
QScriptValue Client::toScriptValue(QScriptEngine *eng, const KClientRef &client)
{
return eng->newQObject(client, QScriptEngine::QtOwnership,
QScriptEngine::ExcludeChildObjects |
QScriptEngine::ExcludeDeleteLater |
QScriptEngine::PreferExistingWrapperObject |
QScriptEngine::AutoCreateDynamicProperties);
}
void Client::fromScriptValue(const QScriptValue &value, KWin::Client* &client)
{
client = qobject_cast<KWin::Client*>(value.toQObject());
}
QScriptValue Toplevel::toScriptValue(QScriptEngine *eng, const KToplevelRef &client)
{
return eng->newQObject(client, QScriptEngine::QtOwnership,
QScriptEngine::ExcludeChildObjects |
QScriptEngine::ExcludeDeleteLater |
QScriptEngine::PreferExistingWrapperObject |
QScriptEngine::AutoCreateDynamicProperties);
}
void Toplevel::fromScriptValue(const QScriptValue &value, KToplevelRef &client)
{
client = qobject_cast<KWin::Toplevel*>(value.toQObject());
}
// Other helper functions
void KWin::MetaScripting::registration(QScriptEngine* eng)
{
qScriptRegisterMetaType<QPoint>(eng, Point::toScriptValue, Point::fromScriptValue);
qScriptRegisterMetaType<QSize>(eng, Size::toScriptValue, Size::fromScriptValue);
qScriptRegisterMetaType<QRect>(eng, Rect::toScriptValue, Rect::fromScriptValue);
qScriptRegisterMetaType<KClientRef>(eng, Client::toScriptValue, Client::fromScriptValue);
qScriptRegisterMetaType<KToplevelRef>(eng, Toplevel::toScriptValue, Toplevel::fromScriptValue);
qScriptRegisterSequenceMetaType<QStringList>(eng);
qScriptRegisterSequenceMetaType< QList<KWin::Client*> >(eng);
}
QScriptValue KWin::MetaScripting::configExists(QScriptContext* ctx, QScriptEngine* eng)
{
QHash<QString, QVariant> scriptConfig = (((ctx->thisObject()).data()).toVariant()).toHash();
QVariant val = scriptConfig.value((ctx->argument(0)).toString(), QVariant());
return eng->toScriptValue<bool>(val.isValid());
}
QScriptValue KWin::MetaScripting::getConfigValue(QScriptContext* ctx, QScriptEngine* eng)
{
int num = ctx->argumentCount();
QHash<QString, QVariant> scriptConfig = (((ctx->thisObject()).data()).toVariant()).toHash();
/*
* Handle config.get() separately. Compute and return immediately.
**/
if (num == 0) {
QHash<QString, QVariant>::const_iterator i;
QScriptValue ret = eng->newArray();
for (i = scriptConfig.constBegin(); i != scriptConfig.constEnd(); ++i) {
ret.setProperty(i.key(), eng->newVariant(i.value()));
}
return ret;
}
if ((num == 1) && !((ctx->argument(0)).isArray())) {
QVariant val = scriptConfig.value((ctx->argument(0)).toString(), QVariant());
if (val.isValid()) {
return eng->newVariant(val);
} else {
return QScriptValue();
}
} else {
QScriptValue ret = eng->newArray();
int j = 0;
if ((ctx->argument(0)).isArray()) {
bool simple = (num == 1) ? 0 : (ctx->argument(1)).toBool();
QScriptValue array = (ctx->argument(0));
int len = (array.property("length").isValid()) ? array.property("length").toNumber() : 0;
for (int i = 0; i < len; i++) {
QVariant val = scriptConfig.value(array.property(i).toString(), QVariant());
if (val.isValid()) {
if (simple) {
ret.setProperty(j, eng->newVariant(val));
} else {
ret.setProperty(array.property(i).toString(), eng->newVariant(val));
}
j++;
}
}
} else {
for (int i = 0; i < num; i++) {
QVariant val = scriptConfig.value((ctx->argument(i)).toString(), QVariant());
if (val.isValid()) {
ret.setProperty((ctx->argument(i)).toString(), eng->newVariant(val));
j = 1;
}
}
}
if (j == 0) {
return QScriptValue();
} else {
return ret;
}
}
}
void KWin::MetaScripting::supplyConfig(QScriptEngine* eng, const QVariant& scriptConfig)
{
QScriptValue configObject = eng->newObject();
configObject.setData(eng->newVariant(scriptConfig));
configObject.setProperty("get", eng->newFunction(getConfigValue, 0), QScriptValue::Undeletable);
configObject.setProperty("exists", eng->newFunction(configExists, 0), QScriptValue::Undeletable);
configObject.setProperty("loaded", ((scriptConfig.toHash().empty()) ? eng->newVariant((bool)0) : eng->newVariant((bool)1)), QScriptValue::Undeletable);
(eng->globalObject()).setProperty("config", configObject);
}
void KWin::MetaScripting::supplyConfig(QScriptEngine* eng)
{
KWin::MetaScripting::supplyConfig(eng, QVariant(QHash<QString, QVariant>()));
}
void KWin::MetaScripting::valueMerge(QScriptValue& first, QScriptValue second)
{
QScriptValueIterator value_it(second);
while (value_it.hasNext()) {
value_it.next();
first.setProperty(value_it.name(), value_it.value());
}
}

View file

@ -1,127 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_SCRIPTING_META_H
#define KWIN_SCRIPTING_META_H
#include <QScriptValueIterator>
// forward declarations
class QPoint;
class QRect;
class QScriptContext;
class QSize;
namespace KWin {
class Client;
class Toplevel;
}
typedef KWin::Client* KClientRef;
typedef KWin::Toplevel* KToplevelRef;
namespace KWin
{
namespace MetaScripting
{
/**
* The toScriptValue and fromScriptValue functions used in qScriptRegisterMetaType.
* Conversion functions for QPoint
*/
namespace Point
{
QScriptValue toScriptValue(QScriptEngine*, const QPoint&);
void fromScriptValue(const QScriptValue&, QPoint&);
}
/**
* The toScriptValue and fromScriptValue functions used in qScriptRegisterMetaType.
* Conversion functions for QSize
*/
namespace Size
{
QScriptValue toScriptValue(QScriptEngine*, const QSize&);
void fromScriptValue(const QScriptValue&, QSize&);
}
/**
* The toScriptValue and fromScriptValue functions used in qScriptRegisterMetaType.
* Conversion functions for QRect
* TODO: QRect conversions have to be linked from plasma as they provide a lot more
* features. As for QSize and QPoint, I don't really plan any such thing.
*/
namespace Rect
{
QScriptValue toScriptValue(QScriptEngine*, const QRect&);
void fromScriptValue(const QScriptValue&, QRect&);
}
namespace Client
{
QScriptValue toScriptValue(QScriptEngine *eng, const KClientRef &client);
void fromScriptValue(const QScriptValue &value, KClientRef& client);
}
namespace Toplevel
{
QScriptValue toScriptValue(QScriptEngine *eng, const KToplevelRef &client);
void fromScriptValue(const QScriptValue &value, KToplevelRef& client);
}
/**
* Merges the second QScriptValue in the first one.
*/
void valueMerge(QScriptValue&, QScriptValue);
/**
* Registers all the meta conversion to the provided QScriptEngine
*/
void registration(QScriptEngine* eng);
/**
* Functions for the JS function objects, config.exists and config.get.
* Read scripting/IMPLIST for details on how they work
*/
QScriptValue configExists(QScriptContext*, QScriptEngine*);
QScriptValue getConfigValue(QScriptContext*, QScriptEngine*);
/**
* Provide a config object to the given QScriptEngine depending
* on the keys provided in the QVariant. The provided QVariant
* MUST returns (true) on isHash()
*/
void supplyConfig(QScriptEngine*, const QVariant&);
/**
* For engines whose scripts have no associated configuration.
*/
void supplyConfig(QScriptEngine*);
}
}
/**
* Code linked from plasma for QTimer.
*/
QScriptValue constructTimerClass(QScriptEngine *eng);
#endif

View file

@ -1,642 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "scriptedeffect.h"
#include "meta.h"
#include "scriptingutils.h"
#include "workspace_wrapper.h"
#ifdef KWIN_BUILD_SCREENEDGES
#include "../screenedge.h"
#endif
// KDE
#include <KDE/KConfigGroup>
#include <KDE/KDebug>
#include <KDE/KStandardDirs>
#include <Plasma/ConfigLoader>
// Qt
#include <QFile>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptValueIterator>
typedef KWin::EffectWindow* KEffectWindowRef;
Q_DECLARE_METATYPE(KWin::AnimationData*)
Q_SCRIPT_DECLARE_QMETAOBJECT(KWin::AnimationData, QObject*)
namespace KWin
{
QScriptValue kwinEffectScriptPrint(QScriptContext *context, QScriptEngine *engine)
{
ScriptedEffect *script = qobject_cast<ScriptedEffect*>(context->callee().data().toQObject());
QString result;
for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0) {
result.append(" ");
}
result.append(context->argument(i).toString());
}
kDebug(1212) << script->scriptFile() << ":" << result;
return engine->undefinedValue();
}
QScriptValue kwinEffectScriptAnimationTime(QScriptContext *context, QScriptEngine *engine)
{
if (context->argumentCount() != 1) {
return engine->undefinedValue();
}
if (!context->argument(0).isNumber()) {
return engine->undefinedValue();
}
return Effect::animationTime(context->argument(0).toInteger());
}
QScriptValue kwinEffectDisplayWidth(QScriptContext *context, QScriptEngine *engine)
{
Q_UNUSED(context)
Q_UNUSED(engine)
return Effect::displayWidth();
}
QScriptValue kwinEffectDisplayHeight(QScriptContext *context, QScriptEngine *engine)
{
Q_UNUSED(context)
Q_UNUSED(engine)
return Effect::displayHeight();
}
QScriptValue kwinScriptGlobalShortcut(QScriptContext *context, QScriptEngine *engine)
{
return globalShortcut<KWin::ScriptedEffect*>(context, engine);
}
QScriptValue kwinScriptScreenEdge(QScriptContext *context, QScriptEngine *engine)
{
return registerScreenEdge<KWin::ScriptedEffect*>(context, engine);
}
struct AnimationSettings {
enum { Type = 1<<0, Curve = 1<<1, Delay = 1<<2, Duration = 1<<3 };
AnimationEffect::Attribute type;
QEasingCurve::Type curve;
FPx2 from;
FPx2 to;
int delay;
uint duration;
uint set;
};
AnimationSettings animationSettingsFromObject(QScriptValue &object)
{
AnimationSettings settings;
settings.set = 0;
settings.to = qscriptvalue_cast<FPx2>(object.property("to"));
settings.from = qscriptvalue_cast<FPx2>(object.property("from"));
QScriptValue duration = object.property("duration");
if (duration.isValid() && duration.isNumber()) {
settings.duration = duration.toUInt32();
settings.set |= AnimationSettings::Duration;
} else {
settings.duration = 0;
}
QScriptValue delay = object.property("delay");
if (delay.isValid() && delay.isNumber()) {
settings.delay = delay.toInt32();
settings.set |= AnimationSettings::Delay;
} else {
settings.delay = 0;
}
QScriptValue curve = object.property("curve");
if (curve.isValid() && curve.isNumber()) {
settings.curve = static_cast<QEasingCurve::Type>(curve.toInt32());
settings.set |= AnimationSettings::Curve;
} else {
settings.curve = QEasingCurve::Linear;
}
QScriptValue type = object.property("type");
if (type.isValid() && type.isNumber()) {
settings.type = static_cast<AnimationEffect::Attribute>(type.toInt32());
settings.set |= AnimationSettings::Type;
} else {
settings.type = static_cast<AnimationEffect::Attribute>(-1);
}
return settings;
}
QList<AnimationSettings> animationSettings(QScriptContext *context, ScriptedEffect *effect, EffectWindow **window)
{
QList<AnimationSettings> settings;
if (!effect) {
context->throwError(QScriptContext::ReferenceError, "Internal Scripted KWin Effect error");
return settings;
}
if (context->argumentCount() != 1) {
context->throwError(QScriptContext::SyntaxError, "Exactly one argument expected");
return settings;
}
if (!context->argument(0).isObject()) {
context->throwError(QScriptContext::TypeError, "Argument needs to be an object");
return settings;
}
QScriptValue object = context->argument(0);
QScriptValue windowProperty = object.property("window");
if (!windowProperty.isValid() || !windowProperty.isObject()) {
context->throwError(QScriptContext::TypeError, "Window property missing in animation options");
return settings;
}
*window = qobject_cast<EffectWindow*>(windowProperty.toQObject());
settings << animationSettingsFromObject(object); // global
QScriptValue animations = object.property("animations"); // array
if (animations.isValid()) {
if (!animations.isArray()) {
context->throwError(QScriptContext::TypeError, "Animations provided but not an array");
settings.clear();
return settings;
}
const int length = static_cast<int>(animations.property("length").toInteger());
for (int i=0; i<length; ++i) {
QScriptValue value = animations.property(QString::number(i));
if (!value.isValid()) {
continue;
}
if (value.isObject()) {
AnimationSettings s = animationSettingsFromObject(value);
const uint set = s.set | settings.at(0).set;
// Catch show stoppers (incompletable animation)
if (!(set & AnimationSettings::Type)) {
context->throwError(QScriptContext::TypeError, "Type property missing in animation options");
continue;
}
if (!(set & AnimationSettings::Duration)) {
context->throwError(QScriptContext::TypeError, "Duration property missing in animation options");
continue;
}
// Complete local animations from global settings
if (!(s.set & AnimationSettings::Duration)) {
s.duration = settings.at(0).duration;
}
if (!(s.set & AnimationSettings::Curve)) {
s.curve = settings.at(0).curve;
}
if (!(s.set & AnimationSettings::Delay)) {
s.delay = settings.at(0).delay;
}
settings << s;
}
}
}
if (settings.count() == 1) {
const uint set = settings.at(0).set;
if (!(set & AnimationSettings::Type)) {
context->throwError(QScriptContext::TypeError, "Type property missing in animation options");
settings.clear();
}
if (!(set & AnimationSettings::Duration)) {
context->throwError(QScriptContext::TypeError, "Duration property missing in animation options");
settings.clear();
}
} else if (!(settings.at(0).set & AnimationSettings::Type)) { // invalid global
settings.removeAt(0); // -> get rid of it, only used to complete the others
}
return settings;
}
QScriptValue kwinEffectAnimate(QScriptContext *context, QScriptEngine *engine)
{
ScriptedEffect *effect = qobject_cast<ScriptedEffect*>(context->callee().data().toQObject());
EffectWindow *window;
QList<AnimationSettings> settings = animationSettings(context, effect, &window);
if (settings.empty()) {
context->throwError(QScriptContext::TypeError, "No animations provided");
return engine->undefinedValue();
}
if (!window) {
context->throwError(QScriptContext::TypeError, "Window property does not contain an EffectWindow");
return engine->undefinedValue();
}
QList<QVariant> animIds;
foreach (const AnimationSettings &setting, settings) {
animIds << QVariant(effect->animate(window,
setting.type,
setting.duration,
setting.to,
setting.from,
NULL,
setting.curve,
setting.delay));
}
return engine->newVariant(animIds);
}
QScriptValue kwinEffectSet(QScriptContext *context, QScriptEngine *engine)
{
ScriptedEffect *effect = qobject_cast<ScriptedEffect*>(context->callee().data().toQObject());
EffectWindow *window;
QList<AnimationSettings> settings = animationSettings(context, effect, &window);
if (settings.empty()) {
context->throwError(QScriptContext::TypeError, "No animations provided");
return engine->undefinedValue();
}
if (!window) {
context->throwError(QScriptContext::TypeError, "Window property does not contain an EffectWindow");
return engine->undefinedValue();
}
QList<QVariant> animIds;
foreach (const AnimationSettings &setting, settings) {
animIds << QVariant(effect->set(window,
setting.type,
setting.duration,
setting.to,
setting.from,
NULL,
setting.curve,
setting.delay));
}
return engine->newVariant(animIds);
}
QScriptValue kwinEffectCancel(QScriptContext *context, QScriptEngine *engine)
{
ScriptedEffect *effect = qobject_cast<ScriptedEffect*>(context->callee().data().toQObject());
if (context->argumentCount() != 1) {
context->throwError(QScriptContext::SyntaxError, "Exactly one argument expected");
return engine->undefinedValue();
}
QVariant v = context->argument(0).toVariant();
QList<quint64> animIds;
bool ok = false;
if (v.isValid()) {
quint64 animId = v.toULongLong(&ok);
if (ok)
animIds << animId;
}
if (!ok) { // may still be a variantlist of variants being quint64
QList<QVariant> list = v.toList();
if (!list.isEmpty()) {
foreach (const QVariant &vv, list) {
quint64 animId = vv.toULongLong(&ok);
if (ok)
animIds << animId;
}
ok = !animIds.isEmpty();
}
}
if (!ok) {
context->throwError(QScriptContext::TypeError, "Argument needs to be one or several quint64");
return engine->undefinedValue();
}
foreach (const quint64 &animId, animIds) {
ok |= engine->newVariant(effect->cancel(animId)).toBool();
}
return engine->newVariant(ok);
}
QScriptValue effectWindowToScriptValue(QScriptEngine *eng, const KEffectWindowRef &window)
{
return eng->newQObject(window, QScriptEngine::QtOwnership,
QScriptEngine::ExcludeChildObjects | QScriptEngine::ExcludeDeleteLater | QScriptEngine::PreferExistingWrapperObject);
}
void effectWindowFromScriptValue(const QScriptValue &value, EffectWindow* &window)
{
window = qobject_cast<EffectWindow*>(value.toQObject());
}
QScriptValue fpx2ToScriptValue(QScriptEngine *eng, const KWin::FPx2 &fpx2)
{
QScriptValue val = eng->newObject();
val.setProperty("value1", fpx2[0]);
val.setProperty("value2", fpx2[1]);
return val;
}
void fpx2FromScriptValue(const QScriptValue &value, KWin::FPx2 &fpx2)
{
if (value.isNull()) {
fpx2 = FPx2();
return;
}
if (value.isNumber()) {
fpx2 = FPx2(value.toNumber());
return;
}
if (value.isObject()) {
QScriptValue value1 = value.property("value1");
QScriptValue value2 = value.property("value2");
if (!value1.isValid() || !value2.isValid() || !value1.isNumber() || !value2.isNumber()) {
kDebug(1212) << "Cannot cast scripted FPx2 to C++";
fpx2 = FPx2();
return;
}
fpx2 = FPx2(value1.toNumber(), value2.toNumber());
}
}
ScriptedEffect *ScriptedEffect::create(const QString& effectName, const QString& pathToScript)
{
ScriptedEffect *effect = new ScriptedEffect();
if (!effect->init(effectName, pathToScript)) {
delete effect;
return NULL;
}
return effect;
}
ScriptedEffect::ScriptedEffect()
: AnimationEffect()
, m_engine(new QScriptEngine(this))
, m_scriptFile(QString())
, m_config(NULL)
{
connect(m_engine, SIGNAL(signalHandlerException(QScriptValue)), SLOT(signalHandlerException(QScriptValue)));
}
ScriptedEffect::~ScriptedEffect()
{
}
bool ScriptedEffect::init(const QString &effectName, const QString &pathToScript)
{
QFile scriptFile(pathToScript);
if (!scriptFile.open(QIODevice::ReadOnly)) {
kDebug(1212) << "Could not open script file: " << pathToScript;
return false;
}
m_effectName = effectName;
m_scriptFile = pathToScript;
// does the effect contain an KConfigXT file?
const QString kconfigXTFile = KStandardDirs::locate("data", QLatin1String(KWIN_NAME) + "/effects/" + m_effectName + "/contents/config/main.xml");
if (!kconfigXTFile.isNull()) {
KConfigGroup cg = effects->effectConfig(m_effectName);
QFile xmlFile(kconfigXTFile);
m_config = new Plasma::ConfigLoader(&cg, &xmlFile, this);
m_config->readConfig();
}
QScriptValue effectsObject = m_engine->newQObject(effects, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater);
m_engine->globalObject().setProperty("effects", effectsObject, QScriptValue::Undeletable);
m_engine->globalObject().setProperty("Effect", m_engine->newQMetaObject(&ScriptedEffect::staticMetaObject));
m_engine->globalObject().setProperty("KWin", m_engine->newQMetaObject(&WorkspaceWrapper::staticMetaObject));
m_engine->globalObject().setProperty("QEasingCurve", m_engine->newQMetaObject(&QEasingCurve::staticMetaObject));
m_engine->globalObject().setProperty("effect", m_engine->newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater), QScriptValue::Undeletable);
m_engine->globalObject().setProperty("AnimationData", m_engine->scriptValueFromQMetaObject<AnimationData>());
MetaScripting::registration(m_engine);
qScriptRegisterMetaType<KEffectWindowRef>(m_engine, effectWindowToScriptValue, effectWindowFromScriptValue);
qScriptRegisterMetaType<KWin::FPx2>(m_engine, fpx2ToScriptValue, fpx2FromScriptValue);
qScriptRegisterSequenceMetaType<QList< KWin::EffectWindow* > >(m_engine);
// add our print
QScriptValue printFunc = m_engine->newFunction(kwinEffectScriptPrint);
printFunc.setData(m_engine->newQObject(this));
m_engine->globalObject().setProperty("print", printFunc);
// add our animationTime
QScriptValue animationTimeFunc = m_engine->newFunction(kwinEffectScriptAnimationTime);
animationTimeFunc.setData(m_engine->newQObject(this));
m_engine->globalObject().setProperty("animationTime", animationTimeFunc);
// add displayWidth and displayHeight
QScriptValue displayWidthFunc = m_engine->newFunction(kwinEffectDisplayWidth);
m_engine->globalObject().setProperty("displayWidth", displayWidthFunc);
QScriptValue displayHeightFunc = m_engine->newFunction(kwinEffectDisplayHeight);
m_engine->globalObject().setProperty("displayHeight", displayHeightFunc);
// add global Shortcut
registerGlobalShortcutFunction(this, m_engine, kwinScriptGlobalShortcut);
registerScreenEdgeFunction(this, m_engine, kwinScriptScreenEdge);
// add the animate method
QScriptValue animateFunc = m_engine->newFunction(kwinEffectAnimate);
animateFunc.setData(m_engine->newQObject(this));
m_engine->globalObject().setProperty("animate", animateFunc);
// and the set variant
QScriptValue setFunc = m_engine->newFunction(kwinEffectSet);
setFunc.setData(m_engine->newQObject(this));
m_engine->globalObject().setProperty("set", setFunc);
// cancel...
QScriptValue cancelFunc = m_engine->newFunction(kwinEffectCancel);
cancelFunc.setData(m_engine->newQObject(this));
m_engine->globalObject().setProperty("cancel", cancelFunc);
QScriptValue ret = m_engine->evaluate(scriptFile.readAll());
if (ret.isError()) {
signalHandlerException(ret);
return false;
}
scriptFile.close();
return true;
}
void ScriptedEffect::signalHandlerException(const QScriptValue &value)
{
if (value.isError()) {
kDebug(1212) << "KWin Effect script encountered an error at [Line " << m_engine->uncaughtExceptionLineNumber() << "]";
kDebug(1212) << "Message: " << value.toString();
QScriptValueIterator iter(value);
while (iter.hasNext()) {
iter.next();
kDebug(1212) << " " << iter.name() << ": " << iter.value().toString();
}
}
}
uint metaFromData(KWin::AnimationData* data)
{
uint meta = 0;
if (data) {
if (data->axis() != 0) {
AnimationEffect::setMetaData(AnimationEffect::Axis, data->axis() -1, meta);
}
if (data->sourceAnchor() != 0) {
AnimationEffect::setMetaData(AnimationEffect::SourceAnchor, data->sourceAnchor(), meta);
}
if (data->targetAnchor() != 0) {
AnimationEffect::setMetaData(AnimationEffect::TargetAnchor, data->targetAnchor(), meta);
}
if (data->relativeSourceX() != 0) {
AnimationEffect::setMetaData(AnimationEffect::RelativeSourceX, data->relativeSourceX(), meta);
}
if (data->relativeSourceY() != 0) {
AnimationEffect::setMetaData(AnimationEffect::RelativeSourceY, data->relativeSourceY(), meta);
}
if (data->relativeTargetX() != 0) {
AnimationEffect::setMetaData(AnimationEffect::RelativeTargetX, data->relativeTargetX(), meta);
}
if (data->relativeTargetY() != 0) {
AnimationEffect::setMetaData(AnimationEffect::RelativeTargetY, data->relativeTargetY(), meta);
}
}
return meta;
}
quint64 ScriptedEffect::animate(KWin::EffectWindow* w, KWin::AnimationEffect::Attribute a, int ms, KWin::FPx2 to, KWin::FPx2 from, KWin::AnimationData* data, QEasingCurve::Type curve, int delay)
{
return AnimationEffect::animate(w, a, metaFromData(data), ms, to, QEasingCurve(curve), delay, from);
}
quint64 ScriptedEffect::set(KWin::EffectWindow* w, KWin::AnimationEffect::Attribute a, int ms, KWin::FPx2 to, KWin::FPx2 from, KWin::AnimationData* data, QEasingCurve::Type curve, int delay)
{
return AnimationEffect::set(w, a, metaFromData(data), ms, to, QEasingCurve(curve), delay, from);
}
bool ScriptedEffect::isGrabbed(EffectWindow* w, ScriptedEffect::DataRole grabRole)
{
void *e = w->data(static_cast<KWin::DataRole>(grabRole)).value<void*>();
if (e) {
return e != this;
} else {
return false;
}
}
void ScriptedEffect::reconfigure(ReconfigureFlags flags)
{
AnimationEffect::reconfigure(flags);
if (m_config) {
m_config->readConfig();
}
emit configChanged();
}
void ScriptedEffect::registerShortcut(QAction *a, QScriptValue callback)
{
m_shortcutCallbacks.insert(a, callback);
connect(a, SIGNAL(triggered(bool)), SLOT(globalShortcutTriggered()));
}
void ScriptedEffect::globalShortcutTriggered()
{
callGlobalShortcutCallback<KWin::ScriptedEffect*>(this, sender());
}
bool ScriptedEffect::borderActivated(ElectricBorder edge)
{
screenEdgeActivated(this, edge);
return true;
}
QVariant ScriptedEffect::readConfig(const QString &key, const QVariant defaultValue)
{
if (!m_config) {
return defaultValue;
}
return m_config->property(key);
}
AnimationData::AnimationData (QObject* parent)
: QObject (parent)
, m_sourceAnchor((AnimationEffect::Anchor)0)
, m_targetAnchor((AnimationEffect::Anchor)0)
, m_relativeSourceX(0)
, m_relativeSourceY(0)
, m_relativeTargetX(0)
, m_relativeTargetY(0)
, m_axis((AnimationData::Axis)0)
{
}
AnimationData::Axis AnimationData::axis() const
{
return m_axis;
}
int AnimationData::relativeSourceX() const
{
return m_relativeSourceX;
}
int AnimationData::relativeSourceY() const
{
return m_relativeSourceY;
}
int AnimationData::relativeTargetX() const
{
return m_relativeTargetX;
}
int AnimationData::relativeTargetY() const
{
return m_relativeTargetY;
}
void AnimationData::setRelativeSourceX(int relativeSourceX)
{
m_relativeSourceX = relativeSourceX;
}
void AnimationData::setRelativeSourceY(int relativeSourceY)
{
m_relativeSourceY = relativeSourceY;
}
void AnimationData::setRelativeTargetX(int relativeTargetX)
{
m_relativeTargetX = relativeTargetX;
}
void AnimationData::setRelativeTargetY(int relativeTargetY)
{
m_relativeTargetY = relativeTargetY;
}
void AnimationData::setAxis(AnimationData::Axis axis)
{
m_axis = axis;
}
void AnimationData::setSourceAnchor(AnimationEffect::Anchor sourceAnchor)
{
m_sourceAnchor = sourceAnchor;
}
void AnimationData::setTargetAnchor(AnimationEffect::Anchor targetAnchor)
{
m_targetAnchor = targetAnchor;
}
AnimationEffect::Anchor AnimationData::sourceAnchor() const
{
return m_sourceAnchor;
}
AnimationEffect::Anchor AnimationData::targetAnchor() const
{
return m_targetAnchor;
}
} // namespace

View file

@ -1,161 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_SCRIPTEDEFFECT_H
#define KWIN_SCRIPTEDEFFECT_H
#include <kwinanimationeffect.h>
class QScriptEngine;
class QScriptValue;
namespace Plasma {
class ConfigLoader;
}
namespace KWin
{
class ScriptedEffect;
class AnimationData : public QObject
{
Q_OBJECT
Q_ENUMS(Axis)
Q_PROPERTY(KWin::AnimationEffect::Anchor sourceAnchor READ sourceAnchor WRITE setSourceAnchor)
Q_PROPERTY(KWin::AnimationEffect::Anchor targetAnchor READ targetAnchor WRITE setTargetAnchor)
Q_PROPERTY(int relativeSourceX READ relativeSourceX WRITE setRelativeSourceX)
Q_PROPERTY(int relativeSourceY READ relativeSourceY WRITE setRelativeSourceY)
Q_PROPERTY(int relativeTargetX READ relativeTargetX WRITE setRelativeTargetX)
Q_PROPERTY(int relativeTargetY READ relativeTargetY WRITE setRelativeTargetY)
Q_PROPERTY(Axis axis READ axis WRITE setAxis)
public:
enum Axis {
XAxis = 1,
YAxis,
ZAxis
};
explicit AnimationData(QObject* parent = 0);
// getter
AnimationEffect::Anchor sourceAnchor() const;
AnimationEffect::Anchor targetAnchor() const;
int relativeSourceX() const;
int relativeSourceY() const;
int relativeTargetX() const;
int relativeTargetY() const;
Axis axis() const;
// setter
void setSourceAnchor(AnimationEffect::Anchor sourceAnchor);
void setTargetAnchor(AnimationEffect::Anchor targetAnchor);
void setRelativeSourceX(int relativeSourceX);
void setRelativeSourceY(int relativeSourceY);
void setRelativeTargetX(int relativeTargetX);
void setRelativeTargetY(int relativeTargetY);
void setAxis(Axis axis);
private:
AnimationEffect::Anchor m_sourceAnchor;
AnimationEffect::Anchor m_targetAnchor;
int m_relativeSourceX;
int m_relativeSourceY;
int m_relativeTargetX;
int m_relativeTargetY;
Axis m_axis;
};
class ScriptedEffect : public KWin::AnimationEffect
{
Q_OBJECT
Q_ENUMS(DataRole)
Q_ENUMS(KWin::AnimationData::Axis)
Q_ENUMS(Anchor)
Q_ENUMS(MetaType)
public:
// copied from kwineffects.h
enum DataRole {
// Grab roles are used to force all other animations to ignore the window.
// The value of the data is set to the Effect's `this` value.
WindowAddedGrabRole = 1,
WindowClosedGrabRole,
WindowMinimizedGrabRole,
WindowUnminimizedGrabRole,
WindowForceBlurRole, ///< For fullscreen effects to enforce blurring of windows,
WindowBlurBehindRole, ///< For single windows to blur behind
LanczosCacheRole
};
const QString &scriptFile() const {
return m_scriptFile;
}
virtual void reconfigure(ReconfigureFlags flags);
QString activeConfig() const;
void setActiveConfig(const QString &name);
static ScriptedEffect *create(const QString &effectName, const QString &pathToScript);
virtual ~ScriptedEffect();
/**
* Whether another effect has grabbed the @p w with the given @p grabRole.
* @param w The window to check
* @param grabRole The grab role to check
* @returns @c true if another window has grabbed the effect, @c false otherwise
**/
Q_SCRIPTABLE bool isGrabbed(KWin::EffectWindow *w, DataRole grabRole);
/**
* Reads the value from the configuration data for the given key.
* @param key The key to search for
* @param defaultValue The value to return if the key is not found
* @returns The config value if present
**/
Q_SCRIPTABLE QVariant readConfig(const QString &key, const QVariant defaultValue = QVariant());
void registerShortcut(QAction *a, QScriptValue callback);
const QHash<QAction*, QScriptValue> &shortcutCallbacks() const {
return m_shortcutCallbacks;
}
QHash<int, QList<QScriptValue > > &screenEdgeCallbacks() {
return m_screenEdgeCallbacks;
}
public Q_SLOTS:
quint64 animate(KWin::EffectWindow *w, Attribute a, int ms, KWin::FPx2 to, KWin::FPx2 from = KWin::FPx2(), KWin::AnimationData *data = NULL, QEasingCurve::Type curve = QEasingCurve::Linear, int delay = 0);
quint64 set(KWin::EffectWindow *w, Attribute a, int ms, KWin::FPx2 to, KWin::FPx2 from = KWin::FPx2(), KWin::AnimationData *data = NULL, QEasingCurve::Type curve = QEasingCurve::Linear, int delay = 0);
bool cancel(quint64 animationId) { return AnimationEffect::cancel(animationId); }
virtual bool borderActivated(ElectricBorder border);
Q_SIGNALS:
/**
* Signal emitted whenever the effect's config changed.
**/
void configChanged();
private Q_SLOTS:
void signalHandlerException(const QScriptValue &value);
void globalShortcutTriggered();
private:
ScriptedEffect();
bool init(const QString &effectName, const QString &pathToScript);
QScriptEngine *m_engine;
QString m_effectName;
QString m_scriptFile;
QHash<QAction*, QScriptValue> m_shortcutCallbacks;
QHash<int, QList<QScriptValue> > m_screenEdgeCallbacks;
Plasma::ConfigLoader *m_config;
};
}
#endif // KWIN_SCRIPTEDEFFECT_H

View file

@ -1,770 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "scripting.h"
// own
#include "meta.h"
#include "scriptingutils.h"
#include "workspace_wrapper.h"
#include "scripting_model.h"
#include "../client.h"
#include "../thumbnailitem.h"
#include "../options.h"
#include "../workspace.h"
// KDE
#include <kstandarddirs.h>
#include <KDE/KConfigGroup>
#include <KDE/KDebug>
#include <KDE/KGlobal>
#include <KDE/KPluginInfo>
#include <KDE/KServiceTypeTrader>
#include <kdeclarative.h>
// Qt
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusPendingCallWatcher>
#include <QFutureWatcher>
#include <QSettings>
#include <QtConcurrentRun>
#include <QtDeclarative/QDeclarativeContext>
#include <QtDeclarative/QDeclarativeEngine>
#include <QtDeclarative/QDeclarativeView>
#include <QtDeclarative/qdeclarative.h>
#include <QMenu>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptValue>
QScriptValue kwinScriptPrint(QScriptContext *context, QScriptEngine *engine)
{
KWin::AbstractScript *script = qobject_cast<KWin::Script*>(context->callee().data().toQObject());
if (!script) {
return engine->undefinedValue();
}
QString result;
QTextStream stream(&result);
for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0) {
stream << " ";
}
QScriptValue argument = context->argument(i);
if (KWin::Client *client = qscriptvalue_cast<KWin::Client*>(argument)) {
client->print<QTextStream>(stream);
} else {
stream << argument.toString();
}
}
script->printMessage(result);
return engine->undefinedValue();
}
QScriptValue kwinScriptReadConfig(QScriptContext *context, QScriptEngine *engine)
{
KWin::AbstractScript *script = qobject_cast<KWin::AbstractScript*>(context->callee().data().toQObject());
if (!script) {
return engine->undefinedValue();
}
if (context->argumentCount() < 1 || context->argumentCount() > 2) {
kDebug(1212) << "Incorrect number of arguments";
return engine->undefinedValue();
}
const QString key = context->argument(0).toString();
QVariant defaultValue;
if (context->argumentCount() == 2) {
defaultValue = context->argument(1).toVariant();
}
return engine->newVariant(script->config().readEntry(key, defaultValue));
}
QScriptValue kwinScriptGlobalShortcut(QScriptContext *context, QScriptEngine *engine)
{
return KWin::globalShortcut<KWin::AbstractScript*>(context, engine);
}
QScriptValue kwinAssertTrue(QScriptContext *context, QScriptEngine *engine)
{
return KWin::scriptingAssert<bool>(context, engine, 1, 2, true);
}
QScriptValue kwinAssertFalse(QScriptContext *context, QScriptEngine *engine)
{
return KWin::scriptingAssert<bool>(context, engine, 1, 2, false);
}
QScriptValue kwinAssertEquals(QScriptContext *context, QScriptEngine *engine)
{
return KWin::scriptingAssert<QVariant>(context, engine, 2, 3);
}
QScriptValue kwinAssertNull(QScriptContext *context, QScriptEngine *engine)
{
if (!KWin::validateParameters(context, 1, 2)) {
return engine->undefinedValue();
}
if (!context->argument(0).isNull()) {
if (context->argumentCount() == 2) {
context->throwError(QScriptContext::UnknownError, context->argument(1).toString());
} else {
context->throwError(QScriptContext::UnknownError,
i18nc("Assertion failed in KWin script with given value",
"Assertion failed: %1 is not null", context->argument(0).toString()));
}
return engine->undefinedValue();
}
return true;
}
QScriptValue kwinAssertNotNull(QScriptContext *context, QScriptEngine *engine)
{
if (!KWin::validateParameters(context, 1, 2)) {
return engine->undefinedValue();
}
if (context->argument(0).isNull()) {
if (context->argumentCount() == 2) {
context->throwError(QScriptContext::UnknownError, context->argument(1).toString());
} else {
context->throwError(QScriptContext::UnknownError,
i18nc("Assertion failed in KWin script",
"Assertion failed: argument is null"));
}
return engine->undefinedValue();
}
return true;
}
QScriptValue kwinRegisterScreenEdge(QScriptContext *context, QScriptEngine *engine)
{
return KWin::registerScreenEdge<KWin::AbstractScript*>(context, engine);
}
QScriptValue kwinRegisterUserActionsMenu(QScriptContext *context, QScriptEngine *engine)
{
return KWin::registerUserActionsMenu<KWin::AbstractScript*>(context, engine);
}
QScriptValue kwinCallDBus(QScriptContext *context, QScriptEngine *engine)
{
KWin::AbstractScript *script = qobject_cast<KWin::AbstractScript*>(context->callee().data().toQObject());
if (!script) {
context->throwError(QScriptContext::UnknownError, "Internal Error: script not registered");
return engine->undefinedValue();
}
if (context->argumentCount() < 4) {
context->throwError(QScriptContext::SyntaxError,
i18nc("Error in KWin Script",
"Invalid number of arguments. At least service, path, interface and method need to be provided"));
return engine->undefinedValue();
}
if (!KWin::validateArgumentType<QString, QString, QString, QString>(context)) {
context->throwError(QScriptContext::SyntaxError,
i18nc("Error in KWin Script",
"Invalid type. Service, path, interface and method need to be string values"));
return engine->undefinedValue();
}
const QString service = context->argument(0).toString();
const QString path = context->argument(1).toString();
const QString interface = context->argument(2).toString();
const QString method = context->argument(3).toString();
int argumentsCount = context->argumentCount();
if (context->argument(argumentsCount-1).isFunction()) {
--argumentsCount;
}
QDBusMessage msg = QDBusMessage::createMethodCall(service, path, interface, method);
QVariantList arguments;
for (int i=4; i<argumentsCount; ++i) {
if (context->argument(i).isArray()) {
QStringList stringArray = engine->fromScriptValue<QStringList>(context->argument(i));
arguments << qVariantFromValue(stringArray);
} else {
arguments << context->argument(i).toVariant();
}
}
if (!arguments.isEmpty()) {
msg.setArguments(arguments);
}
if (argumentsCount == context->argumentCount()) {
// no callback, just fire and forget
QDBusConnection::sessionBus().asyncCall(msg);
} else {
// with a callback
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(QDBusConnection::sessionBus().asyncCall(msg), script);
watcher->setProperty("callback", script->registerCallback(context->argument(context->argumentCount()-1)));
QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), script, SLOT(slotPendingDBusCall(QDBusPendingCallWatcher*)));
}
return engine->undefinedValue();
}
KWin::AbstractScript::AbstractScript(int id, QString scriptName, QString pluginName, QObject *parent)
: QObject(parent)
, m_scriptId(id)
, m_pluginName(pluginName)
, m_running(false)
, m_workspace(new WorkspaceWrapper(this))
{
m_scriptFile.setFileName(scriptName);
if (m_pluginName.isNull()) {
m_pluginName = scriptName;
}
}
KWin::AbstractScript::~AbstractScript()
{
}
KConfigGroup KWin::AbstractScript::config() const
{
return KGlobal::config()->group("Script-" + m_pluginName);
}
void KWin::AbstractScript::stop()
{
deleteLater();
}
void KWin::AbstractScript::printMessage(const QString &message)
{
kDebug(1212) << scriptFile().fileName() << ":" << message;
emit print(message);
}
void KWin::AbstractScript::registerShortcut(QAction *a, QScriptValue callback)
{
m_shortcutCallbacks.insert(a, callback);
connect(a, SIGNAL(triggered(bool)), SLOT(globalShortcutTriggered()));
}
void KWin::AbstractScript::globalShortcutTriggered()
{
callGlobalShortcutCallback<KWin::AbstractScript*>(this, sender());
}
bool KWin::AbstractScript::borderActivated(KWin::ElectricBorder edge)
{
screenEdgeActivated(this, edge);
return true;
}
void KWin::AbstractScript::installScriptFunctions(QScriptEngine* engine)
{
// add our print
QScriptValue printFunc = engine->newFunction(kwinScriptPrint);
printFunc.setData(engine->newQObject(this));
engine->globalObject().setProperty("print", printFunc);
// add read config
QScriptValue configFunc = engine->newFunction(kwinScriptReadConfig);
configFunc.setData(engine->newQObject(this));
engine->globalObject().setProperty("readConfig", configFunc);
QScriptValue dbusCallFunc = engine->newFunction(kwinCallDBus);
dbusCallFunc.setData(engine->newQObject(this));
engine->globalObject().setProperty("callDBus", dbusCallFunc);
// add global Shortcut
registerGlobalShortcutFunction(this, engine, kwinScriptGlobalShortcut);
// add screen edge
registerScreenEdgeFunction(this, engine, kwinRegisterScreenEdge);
// add user actions menu register function
regesterUserActionsMenuFunction(this, engine, kwinRegisterUserActionsMenu);
// add assertions
QScriptValue assertTrueFunc = engine->newFunction(kwinAssertTrue);
engine->globalObject().setProperty("assertTrue", assertTrueFunc);
engine->globalObject().setProperty("assert", assertTrueFunc);
QScriptValue assertFalseFunc = engine->newFunction(kwinAssertFalse);
engine->globalObject().setProperty("assertFalse", assertFalseFunc);
QScriptValue assertEqualsFunc = engine->newFunction(kwinAssertEquals);
engine->globalObject().setProperty("assertEquals", assertEqualsFunc);
QScriptValue assertNullFunc = engine->newFunction(kwinAssertNull);
engine->globalObject().setProperty("assertNull", assertNullFunc);
engine->globalObject().setProperty("assertEquals", assertEqualsFunc);
QScriptValue assertNotNullFunc = engine->newFunction(kwinAssertNotNull);
engine->globalObject().setProperty("assertNotNull", assertNotNullFunc);
// global properties
engine->globalObject().setProperty("KWin", engine->newQMetaObject(&WorkspaceWrapper::staticMetaObject));
QScriptValue workspace = engine->newQObject(AbstractScript::workspace(), QScriptEngine::QtOwnership,
QScriptEngine::ExcludeSuperClassContents | QScriptEngine::ExcludeDeleteLater);
engine->globalObject().setProperty("workspace", workspace, QScriptValue::Undeletable);
// install meta functions
KWin::MetaScripting::registration(engine);
}
int KWin::AbstractScript::registerCallback(QScriptValue value)
{
int id = m_callbacks.size();
m_callbacks.insert(id, value);
return id;
}
void KWin::AbstractScript::slotPendingDBusCall(QDBusPendingCallWatcher* watcher)
{
if (watcher->isError()) {
kDebug(1212) << "Received D-Bus message is error";
watcher->deleteLater();
return;
}
const int id = watcher->property("callback").toInt();
QDBusMessage reply = watcher->reply();
QScriptValue callback (m_callbacks.value(id));
QScriptValueList arguments;
foreach (const QVariant &argument, reply.arguments()) {
arguments << callback.engine()->newVariant(argument);
}
callback.call(QScriptValue(), arguments);
m_callbacks.remove(id);
watcher->deleteLater();
}
void KWin::AbstractScript::registerUseractionsMenuCallback(QScriptValue callback)
{
m_userActionsMenuCallbacks.append(callback);
}
QList< QAction * > KWin::AbstractScript::actionsForUserActionMenu(KWin::Client *c, QMenu *parent)
{
QList<QAction*> returnActions;
for (QList<QScriptValue>::const_iterator it = m_userActionsMenuCallbacks.constBegin(); it != m_userActionsMenuCallbacks.constEnd(); ++it) {
QScriptValue callback(*it);
QScriptValueList arguments;
arguments << callback.engine()->newQObject(c);
QScriptValue actions = callback.call(QScriptValue(), arguments);
if (!actions.isValid() || actions.isUndefined() || actions.isNull()) {
// script does not want to handle this Client
continue;
}
if (actions.isObject()) {
QAction *a = scriptValueToAction(actions, parent);
if (a) {
returnActions << a;
}
}
}
return returnActions;
}
QAction *KWin::AbstractScript::scriptValueToAction(QScriptValue &value, QMenu *parent)
{
QScriptValue titleValue = value.property("text");
QScriptValue checkableValue = value.property("checkable");
QScriptValue checkedValue = value.property("checked");
QScriptValue itemsValue = value.property("items");
QScriptValue triggeredValue = value.property("triggered");
if (!titleValue.isValid()) {
// title not specified - does not make any sense to include
return NULL;
}
const QString title = titleValue.toString();
const bool checkable = checkableValue.isValid() && checkableValue.toBool();
const bool checked = checkable && checkedValue.isValid() && checkedValue.toBool();
// either a menu or a menu item
if (itemsValue.isValid()) {
if (!itemsValue.isArray()) {
// not an array, so cannot be a menu
return NULL;
}
QScriptValue lengthValue = itemsValue.property("length");
if (!lengthValue.isValid() || !lengthValue.isNumber() || lengthValue.toInteger() == 0) {
// length property missing
return NULL;
}
return createMenu(title, itemsValue, parent);
} else if (triggeredValue.isValid()) {
// normal item
return createAction(title, checkable, checked, triggeredValue, parent);
}
return NULL;
}
QAction *KWin::AbstractScript::createAction(const QString &title, bool checkable, bool checked, QScriptValue &callback, QMenu *parent)
{
QAction *action = new QAction(title, parent);
action->setCheckable(checkable);
action->setChecked(checked);
// TODO: rename m_shortcutCallbacks
m_shortcutCallbacks.insert(action, callback);
connect(action, SIGNAL(triggered(bool)), SLOT(globalShortcutTriggered()));
connect(action, SIGNAL(destroyed(QObject*)), SLOT(actionDestroyed(QObject*)));
return action;
}
QAction *KWin::AbstractScript::createMenu(const QString &title, QScriptValue &items, QMenu *parent)
{
QMenu *menu = new QMenu(title, parent);
const int length = static_cast<int>(items.property("length").toInteger());
for (int i=0; i<length; ++i) {
QScriptValue value = items.property(QString::number(i));
if (!value.isValid()) {
continue;
}
if (value.isObject()) {
QAction *a = scriptValueToAction(value, menu);
if (a) {
menu->addAction(a);
}
}
}
return menu->menuAction();
}
void KWin::AbstractScript::actionDestroyed(QObject *object)
{
// TODO: Qt 5 - change to lambda function
m_shortcutCallbacks.remove(static_cast<QAction*>(object));
}
KWin::Script::Script(int id, QString scriptName, QString pluginName, QObject* parent)
: AbstractScript(id, scriptName, pluginName, parent)
, m_engine(new QScriptEngine(this))
, m_starting(false)
, m_agent(new ScriptUnloaderAgent(this))
{
QDBusConnection::sessionBus().registerObject('/' + QString::number(scriptId()), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportScriptableInvokables);
}
KWin::Script::~Script()
{
QDBusConnection::sessionBus().unregisterObject('/' + QString::number(scriptId()));
}
void KWin::Script::run()
{
if (running() || m_starting) {
return;
}
m_starting = true;
QFutureWatcher<QByteArray> *watcher = new QFutureWatcher<QByteArray>(this);
connect(watcher, SIGNAL(finished()), SLOT(slotScriptLoadedFromFile()));
watcher->setFuture(QtConcurrent::run(this, &KWin::Script::loadScriptFromFile));
}
QByteArray KWin::Script::loadScriptFromFile()
{
if (!scriptFile().open(QIODevice::ReadOnly)) {
return QByteArray();
}
QByteArray result(scriptFile().readAll());
scriptFile().close();
return result;
}
void KWin::Script::slotScriptLoadedFromFile()
{
QFutureWatcher<QByteArray> *watcher = dynamic_cast< QFutureWatcher< QByteArray>* >(sender());
if (!watcher) {
// not invoked from a QFutureWatcher
return;
}
if (watcher->result().isNull()) {
// do not load empty script
deleteLater();
watcher->deleteLater();
return;
}
QScriptValue optionsValue = m_engine->newQObject(options, QScriptEngine::QtOwnership,
QScriptEngine::ExcludeSuperClassContents | QScriptEngine::ExcludeDeleteLater);
m_engine->globalObject().setProperty("options", optionsValue, QScriptValue::Undeletable);
m_engine->globalObject().setProperty("QTimer", constructTimerClass(m_engine));
QObject::connect(m_engine, SIGNAL(signalHandlerException(QScriptValue)), this, SLOT(sigException(QScriptValue)));
KWin::MetaScripting::supplyConfig(m_engine);
installScriptFunctions(m_engine);
QScriptValue ret = m_engine->evaluate(watcher->result());
if (ret.isError()) {
sigException(ret);
deleteLater();
}
watcher->deleteLater();
setRunning(true);
m_starting = false;
}
void KWin::Script::sigException(const QScriptValue& exception)
{
QScriptValue ret = exception;
if (ret.isError()) {
kDebug(1212) << "defaultscript encountered an error at [Line " << m_engine->uncaughtExceptionLineNumber() << "]";
kDebug(1212) << "Message: " << ret.toString();
kDebug(1212) << "-----------------";
QScriptValueIterator iter(ret);
while (iter.hasNext()) {
iter.next();
qDebug() << " " << iter.name() << ": " << iter.value().toString();
}
}
emit printError(exception.toString());
stop();
}
KWin::ScriptUnloaderAgent::ScriptUnloaderAgent(KWin::Script *script)
: QScriptEngineAgent(script->engine())
, m_script(script)
{
script->engine()->setAgent(this);
}
void KWin::ScriptUnloaderAgent::scriptUnload(qint64 id)
{
Q_UNUSED(id)
m_script->stop();
}
KWin::DeclarativeScript::DeclarativeScript(int id, QString scriptName, QString pluginName, QObject* parent)
: AbstractScript(id, scriptName, pluginName, parent)
, m_engine(new QDeclarativeEngine(this))
, m_component(new QDeclarativeComponent(m_engine, this))
, m_scene(new QGraphicsScene(this))
{
}
KWin::DeclarativeScript::~DeclarativeScript()
{
}
void KWin::DeclarativeScript::run()
{
if (running()) {
return;
}
// add read config
KDeclarative kdeclarative;
kdeclarative.setDeclarativeEngine(m_engine);
kdeclarative.initialize();
kdeclarative.setupBindings();
installScriptFunctions(kdeclarative.scriptEngine());
qmlRegisterType<DesktopThumbnailItem>("org.kde.kwin", 0, 1, "DesktopThumbnailItem");
qmlRegisterType<WindowThumbnailItem>("org.kde.kwin", 0, 1, "ThumbnailItem");
qmlRegisterType<KWin::ScriptingClientModel::ClientModel>();
qmlRegisterType<KWin::ScriptingClientModel::SimpleClientModel>("org.kde.kwin", 0, 1, "ClientModel");
qmlRegisterType<KWin::ScriptingClientModel::ClientModelByScreen>("org.kde.kwin", 0, 1, "ClientModelByScreen");
qmlRegisterType<KWin::ScriptingClientModel::ClientModelByScreenAndDesktop>("org.kde.kwin", 0, 1, "ClientModelByScreenAndDesktop");
qmlRegisterType<KWin::ScriptingClientModel::ClientFilterModel>("org.kde.kwin", 0, 1, "ClientFilterModel");
qmlRegisterType<KWin::Client>();
m_engine->rootContext()->setContextProperty("options", options);
m_component->loadUrl(QUrl::fromLocalFile(scriptFile().fileName()));
if (m_component->isLoading()) {
connect(m_component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), SLOT(createComponent()));
} else {
createComponent();
}
}
void KWin::DeclarativeScript::createComponent()
{
if (m_component->isError()) {
kDebug(1212) << "Component failed to load: " << m_component->errors();
} else {
m_scene->addItem(qobject_cast<QDeclarativeItem*>(m_component->create()));
}
setRunning(true);
}
KWin::Scripting *KWin::Scripting::s_self = NULL;
KWin::Scripting *KWin::Scripting::create(QObject *parent)
{
Q_ASSERT(!s_self);
s_self = new Scripting(parent);
return s_self;
}
KWin::Scripting::Scripting(QObject *parent)
: QObject(parent)
, m_scriptsLock(new QMutex(QMutex::Recursive))
{
QDBusConnection::sessionBus().registerObject("/Scripting", this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportScriptableInvokables);
QDBusConnection::sessionBus().registerService("org.kde.kwin.Scripting");
connect(Workspace::self(), SIGNAL(configChanged()), SLOT(start()));
connect(Workspace::self(), SIGNAL(workspaceInitialized()), SLOT(start()));
}
void KWin::Scripting::start()
{
#if 0
// TODO make this threaded again once KConfigGroup is sufficiently thread safe, bug #305361 and friends
// perform querying for the services in a thread
QFutureWatcher<LoadScriptList> *watcher = new QFutureWatcher<LoadScriptList>(this);
connect(watcher, SIGNAL(finished()), this, SLOT(slotScriptsQueried()));
watcher->setFuture(QtConcurrent::run(this, &KWin::Scripting::queryScriptsToLoad, pluginStates, offers));
#else
LoadScriptList scriptsToLoad = queryScriptsToLoad();
for (LoadScriptList::const_iterator it = scriptsToLoad.constBegin();
it != scriptsToLoad.constEnd();
++it) {
if (it->first) {
loadScript(it->second.first, it->second.second);
} else {
loadDeclarativeScript(it->second.first, it->second.second);
}
}
runScripts();
#endif
}
LoadScriptList KWin::Scripting::queryScriptsToLoad()
{
KSharedConfig::Ptr _config = KGlobal::config();
static bool s_started = false;
if (s_started) {
_config->reparseConfiguration();
} else {
s_started = true;
}
QMap<QString,QString> pluginStates = KConfigGroup(_config, "Plugins").entryMap();
KService::List offers = KServiceTypeTrader::self()->query("KWin/Script");
LoadScriptList scriptsToLoad;
foreach (const KService::Ptr & service, offers) {
KPluginInfo plugininfo(service);
const QString value = pluginStates.value(plugininfo.pluginName() + QString::fromLatin1("Enabled"), QString());
plugininfo.setPluginEnabled(value.isNull() ? plugininfo.isPluginEnabledByDefault() : QVariant(value).toBool());
const bool javaScript = service->property("X-Plasma-API").toString() == "javascript";
const bool declarativeScript = service->property("X-Plasma-API").toString() == "declarativescript";
if (!javaScript && !declarativeScript) {
continue;
}
if (!plugininfo.isPluginEnabled()) {
if (isScriptLoaded(plugininfo.pluginName())) {
// unload the script
unloadScript(plugininfo.pluginName());
}
continue;
}
const QString pluginName = service->property("X-KDE-PluginInfo-Name").toString();
const QString scriptName = service->property("X-Plasma-MainScript").toString();
const QString file = KStandardDirs::locate("data", QLatin1String(KWIN_NAME) + "/scripts/" + pluginName + "/contents/" + scriptName);
if (file.isNull()) {
kDebug(1212) << "Could not find script file for " << pluginName;
continue;
}
scriptsToLoad << qMakePair(javaScript, qMakePair(file, pluginName));
}
return scriptsToLoad;
}
void KWin::Scripting::slotScriptsQueried()
{
QFutureWatcher<LoadScriptList> *watcher = dynamic_cast< QFutureWatcher<LoadScriptList>* >(sender());
if (!watcher) {
// slot invoked not from a FutureWatcher
return;
}
LoadScriptList scriptsToLoad = watcher->result();
for (LoadScriptList::const_iterator it = scriptsToLoad.constBegin();
it != scriptsToLoad.constEnd();
++it) {
if (it->first) {
loadScript(it->second.first, it->second.second);
} else {
loadDeclarativeScript(it->second.first, it->second.second);
}
}
runScripts();
watcher->deleteLater();
}
bool KWin::Scripting::isScriptLoaded(const QString &pluginName) const
{
QMutexLocker locker(m_scriptsLock.data());
foreach (AbstractScript *script, scripts) {
if (script->pluginName() == pluginName) {
return true;
}
}
return false;
}
bool KWin::Scripting::unloadScript(const QString &pluginName)
{
QMutexLocker locker(m_scriptsLock.data());
foreach (AbstractScript *script, scripts) {
if (script->pluginName() == pluginName) {
script->deleteLater();
return true;
}
}
return false;
}
void KWin::Scripting::runScripts()
{
QMutexLocker locker(m_scriptsLock.data());
for (int i = 0; i < scripts.size(); i++) {
scripts.at(i)->run();
}
}
void KWin::Scripting::scriptDestroyed(QObject *object)
{
QMutexLocker locker(m_scriptsLock.data());
scripts.removeAll(static_cast<KWin::Script*>(object));
}
int KWin::Scripting::loadScript(const QString &filePath, const QString& pluginName)
{
QMutexLocker locker(m_scriptsLock.data());
if (isScriptLoaded(pluginName)) {
return -1;
}
const int id = scripts.size();
KWin::Script *script = new KWin::Script(id, filePath, pluginName, this);
connect(script, SIGNAL(destroyed(QObject*)), SLOT(scriptDestroyed(QObject*)));
scripts.append(script);
return id;
}
int KWin::Scripting::loadDeclarativeScript(const QString& filePath, const QString& pluginName)
{
QMutexLocker locker(m_scriptsLock.data());
if (isScriptLoaded(pluginName)) {
return -1;
}
const int id = scripts.size();
KWin::DeclarativeScript *script = new KWin::DeclarativeScript(id, filePath, pluginName, this);
connect(script, SIGNAL(destroyed(QObject*)), SLOT(scriptDestroyed(QObject*)));
scripts.append(script);
return id;
}
KWin::Scripting::~Scripting()
{
QDBusConnection::sessionBus().unregisterObject("/Scripting");
QDBusConnection::sessionBus().unregisterService("org.kde.kwin.Scripting");
s_self = NULL;
}
QList< QAction * > KWin::Scripting::actionsForUserActionMenu(KWin::Client *c, QMenu *parent)
{
QList<QAction*> actions;
foreach (AbstractScript *script, scripts) {
actions << script->actionsForUserActionMenu(c, parent);
}
return actions;
}
#include "scripting.moc"

View file

@ -1,346 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
Copyright (C) 2011 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_SCRIPTING_H
#define KWIN_SCRIPTING_H
#include <kwinglobals.h>
#include <kservice.h>
#include <QFile>
#include <QHash>
#include <QStringList>
#include <QtScript/QScriptEngineAgent>
class QDeclarativeComponent;
class QDeclarativeEngine;
class QAction;
class QDBusPendingCallWatcher;
class QGraphicsScene;
class QMenu;
class QMutex;
class QScriptEngine;
class QScriptValue;
class KConfigGroup;
/// @c true == javascript, @c false == qml
typedef QList< QPair<bool, QPair<QString, QString > > > LoadScriptList;
namespace KWin
{
class Client;
class ScriptUnloaderAgent;
class WorkspaceWrapper;
class AbstractScript : public QObject
{
Q_OBJECT
public:
AbstractScript(int id, QString scriptName, QString pluginName, QObject *parent = NULL);
~AbstractScript();
QString fileName() const {
return m_scriptFile.fileName();
}
const QString &pluginName() {
return m_pluginName;
}
void printMessage(const QString &message);
void registerShortcut(QAction *a, QScriptValue callback);
/**
* @brief Registers the given @p callback to be invoked whenever the UserActionsMenu is about
* to be showed. In the callback the script can create a further sub menu or menu entry to be
* added to the UserActionsMenu.
*
* @param callback Script method to execute when the UserActionsMenu is about to be shown.
* @return void
* @see actionsForUserActionMenu
**/
void registerUseractionsMenuCallback(QScriptValue callback);
/**
* @brief Creates actions for the UserActionsMenu by invoking the registered callbacks.
*
* This method invokes all the callbacks previously registered with registerUseractionsMenuCallback.
* The Client @p c is passed in as an argument to the invoked method.
*
* The invoked method is supposed to return a JavaScript object containing either the menu or
* menu entry to be added. In case the callback returns a null or undefined or any other invalid
* value, it is not considered for adding to the menu.
*
* The JavaScript object structure for a menu entry looks like the following:
* @code
* {
* title: "My Menu Entry",
* checkable: true,
* checked: false,
* triggered: function (action) {
* // callback when the menu entry is triggered with the QAction as argument
* }
* }
* @endcode
*
* To construct a complete Menu the JavaScript object looks like the following:
* @code
* {
* title: "My Menu Title",
* items: [{...}, {...}, ...] // list of menu entries as described above
* }
* @endcode
*
* The returned JavaScript object is introspected and for a menu entry a QAction is created,
* while for a menu a QMenu is created and QActions for the individual entries. Of course it
* is allowed to have nested structures.
*
* All created objects are (grand) children to the passed in @p parent menu, so that they get
* deleted whenever the menu is destroyed.
*
* @param c The Client for which the menu is invoked, passed to the callback
* @param parent The Parent for the created Menus or Actions
* @return QList< QAction* > List of QActions obtained from asking the registered callbacks
* @see registerUseractionsMenuCallback
**/
QList<QAction*> actionsForUserActionMenu(Client *c, QMenu *parent);
KConfigGroup config() const;
const QHash<QAction*, QScriptValue> &shortcutCallbacks() const {
return m_shortcutCallbacks;
}
QHash<int, QList<QScriptValue > > &screenEdgeCallbacks() {
return m_screenEdgeCallbacks;
}
int registerCallback(QScriptValue value);
public Q_SLOTS:
Q_SCRIPTABLE void stop();
Q_SCRIPTABLE virtual void run() = 0;
void slotPendingDBusCall(QDBusPendingCallWatcher *watcher);
private Q_SLOTS:
void globalShortcutTriggered();
bool borderActivated(ElectricBorder edge);
/**
* @brief Slot invoked when a menu action is destroyed. Used to remove the action and callback
* from the map of actions.
*
* @param object The destroyed action
**/
void actionDestroyed(QObject *object);
Q_SIGNALS:
Q_SCRIPTABLE void print(const QString &text);
protected:
QFile &scriptFile() {
return m_scriptFile;
}
bool running() const {
return m_running;
}
void setRunning(bool running) {
m_running = running;
}
int scriptId() const {
return m_scriptId;
}
WorkspaceWrapper *workspace() {
return m_workspace;
}
void installScriptFunctions(QScriptEngine *engine);
private:
/**
* @brief Parses the @p value to either a QMenu or QAction.
*
* @param value The ScriptValue describing either a menu or action
* @param parent The parent to use for the created menu or action
* @return QAction* The parsed action or menu action, if parsing fails returns @c null.
**/
QAction *scriptValueToAction(QScriptValue &value, QMenu *parent);
/**
* @brief Creates a new QAction from the provided data and registers it for invoking the
* @p callback when the action is triggered.
*
* The created action is added to the map of actions and callbacks shared with the global
* shortcuts.
*
* @param title The title of the action
* @param checkable Whether the action is checkable
* @param checked Whether the checkable action is checked
* @param callback The callback to invoke when the action is triggered
* @param parent The parent to be used for the new created action
* @return QAction* The created action
**/
QAction *createAction(const QString &title, bool checkable, bool checked, QScriptValue &callback, QMenu *parent);
/**
* @brief Parses the @p items and creates a QMenu from it.
*
* @param title The title of the Menu.
* @param items JavaScript Array containing Menu items.
* @param parent The parent to use for the new created menu
* @return QAction* The menu action for the new Menu
**/
QAction *createMenu(const QString &title, QScriptValue &items, QMenu *parent);
int m_scriptId;
QFile m_scriptFile;
QString m_pluginName;
bool m_running;
WorkspaceWrapper *m_workspace;
QHash<QAction*, QScriptValue> m_shortcutCallbacks;
QHash<int, QList<QScriptValue> > m_screenEdgeCallbacks;
QHash<int, QScriptValue> m_callbacks;
/**
* @brief List of registered functions to call when the UserActionsMenu is about to show
* to add further entries.
**/
QList<QScriptValue> m_userActionsMenuCallbacks;
};
class Script : public AbstractScript
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Scripting")
public:
Script(int id, QString scriptName, QString pluginName, QObject *parent = NULL);
virtual ~Script();
QScriptEngine *engine() {
return m_engine;
}
public Q_SLOTS:
Q_SCRIPTABLE void run();
Q_SIGNALS:
Q_SCRIPTABLE void printError(const QString &text);
private slots:
/**
* A nice clean way to handle exceptions in scripting.
* TODO: Log to file, show from notifier..
*/
void sigException(const QScriptValue &exception);
/**
* Callback for when loadScriptFromFile has finished.
**/
void slotScriptLoadedFromFile();
private:
/**
* Read the script from file into a byte array.
* If file cannot be read an empty byte array is returned.
**/
QByteArray loadScriptFromFile();
QScriptEngine *m_engine;
bool m_starting;
QScopedPointer<ScriptUnloaderAgent> m_agent;
};
class ScriptUnloaderAgent : public QScriptEngineAgent
{
public:
explicit ScriptUnloaderAgent(Script *script);
virtual void scriptUnload(qint64 id);
private:
Script *m_script;
};
class DeclarativeScript : public AbstractScript
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Scripting")
public:
explicit DeclarativeScript(int id, QString scriptName, QString pluginName, QObject *parent = 0);
virtual ~DeclarativeScript();
public Q_SLOTS:
Q_SCRIPTABLE void run();
private Q_SLOTS:
void createComponent();
private:
QDeclarativeEngine *m_engine;
QDeclarativeComponent *m_component;
QGraphicsScene *m_scene;
};
/**
* The heart of KWin::Scripting. Infinite power lies beyond
*/
class Scripting : public QObject
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.Scripting")
private:
explicit Scripting(QObject *parent);
QStringList scriptList;
QList<KWin::AbstractScript*> scripts;
/**
* Lock to protect the scripts member variable.
**/
QScopedPointer<QMutex> m_scriptsLock;
// Preferably call ONLY at load time
void runScripts();
public:
~Scripting();
Q_SCRIPTABLE Q_INVOKABLE int loadScript(const QString &filePath, const QString &pluginName = QString());
Q_SCRIPTABLE Q_INVOKABLE int loadDeclarativeScript(const QString &filePath, const QString &pluginName = QString());
Q_SCRIPTABLE Q_INVOKABLE bool isScriptLoaded(const QString &pluginName) const;
Q_SCRIPTABLE Q_INVOKABLE bool unloadScript(const QString &pluginName);
/**
* @brief Invokes all registered callbacks to add actions to the UserActionsMenu.
*
* @param c The Client for which the UserActionsMenu is about to be shown
* @param parent The parent menu to which to add created child menus and items
* @return QList< QAction* > List of all actions aggregated from all scripts.
**/
QList<QAction*> actionsForUserActionMenu(Client *c, QMenu *parent);
static Scripting *self();
static Scripting *create(QObject *parent);
public Q_SLOTS:
void scriptDestroyed(QObject *object);
Q_SCRIPTABLE void start();
private Q_SLOTS:
void slotScriptsQueried();
private:
LoadScriptList queryScriptsToLoad();
static Scripting *s_self;
};
inline
Scripting *Scripting::self()
{
return s_self;
}
}
#endif

View file

@ -1,852 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "scripting_model.h"
#include "activities.h"
#include "client.h"
#include "screens.h"
#include "workspace.h"
#include <KDE/KDebug>
namespace KWin {
namespace ScriptingClientModel {
static quint32 nextId() {
static quint32 counter = 0;
return ++counter;
}
ClientLevel::ClientLevel(ClientModel *model, AbstractLevel *parent)
: AbstractLevel(model, parent)
{
connect(Workspace::self(), SIGNAL(clientAdded(KWin::Client*)), SLOT(clientAdded(KWin::Client*)));
connect(Workspace::self(), SIGNAL(clientRemoved(KWin::Client*)), SLOT(clientRemoved(KWin::Client*)));
connect(model, SIGNAL(exclusionsChanged()), SLOT(reInit()));
}
ClientLevel::~ClientLevel()
{
}
void ClientLevel::clientAdded(Client *client)
{
setupClientConnections(client);
checkClient(client);
}
void ClientLevel::clientRemoved(Client *client)
{
removeClient(client);
}
void ClientLevel::setupClientConnections(Client *client)
{
connect(client, SIGNAL(desktopChanged()), SLOT(checkClient()));
connect(client, SIGNAL(screenChanged()), SLOT(checkClient()));
connect(client, SIGNAL(activitiesChanged(KWin::Toplevel*)), SLOT(checkClient()));
}
void ClientLevel::checkClient()
{
checkClient(static_cast<Client*>(sender()));
}
void ClientLevel::checkClient(Client *client)
{
const bool shouldInclude = !exclude(client) && shouldAdd(client);
const bool contains = containsClient(client);
if (shouldInclude && !contains) {
addClient(client);
} else if (!shouldInclude && contains) {
removeClient(client);
}
}
bool ClientLevel::exclude(Client *client) const
{
ClientModel::Exclusions exclusions = model()->exclusions();
if (exclusions == ClientModel::NoExclusion) {
return false;
}
if (exclusions & ClientModel::DesktopWindowsExclusion) {
if (client->isDesktop()) {
return true;
}
}
if (exclusions & ClientModel::DockWindowsExclusion) {
if (client->isDock()) {
return true;
}
}
if (exclusions & ClientModel::UtilityWindowsExclusion) {
if (client->isUtility()) {
return true;
}
}
if (exclusions & ClientModel::SpecialWindowsExclusion) {
if (client->isSpecialWindow()) {
return true;
}
}
if (exclusions & ClientModel::SkipTaskbarExclusion) {
if (client->skipTaskbar()) {
return true;
}
}
if (exclusions & ClientModel::SkipPagerExclusion) {
if (client->skipPager()) {
return true;
}
}
if (exclusions & ClientModel::SwitchSwitcherExclusion) {
if (client->skipSwitcher()) {
return true;
}
}
if (exclusions & ClientModel::OtherDesktopsExclusion) {
if (!client->isOnCurrentDesktop()) {
return true;
}
}
if (exclusions & ClientModel::OtherActivitiesExclusion) {
if (!client->isOnCurrentActivity()) {
return true;
}
}
if (exclusions & ClientModel::MinimizedExclusion) {
if (client->isMinimized()) {
return true;
}
}
if (exclusions & ClientModel::NonSelectedWindowTabExclusion) {
if (!client->isCurrentTab()) {
return true;
}
}
if (exclusions & ClientModel::NotAcceptingFocusExclusion) {
if (!client->wantsInput()) {
return true;
}
}
return false;
}
bool ClientLevel::shouldAdd(Client *client) const
{
if (restrictions() == ClientModel::NoRestriction) {
return true;
}
if (restrictions() & ClientModel::ActivityRestriction) {
if (!client->isOnActivity(activity())) {
return false;
}
}
if (restrictions() & ClientModel::VirtualDesktopRestriction) {
if (!client->isOnDesktop(virtualDesktop())) {
return false;
}
}
if (restrictions() & ClientModel::ScreenRestriction) {
if (client->screen() != int(screen())) {
return false;
}
}
return true;
}
void ClientLevel::addClient(Client *client)
{
if (containsClient(client)) {
return;
}
emit beginInsert(m_clients.count(), m_clients.count(), id());
m_clients.insert(nextId(), client);
emit endInsert();
}
void ClientLevel::removeClient(Client *client)
{
int index = 0;
QMap<quint32, Client*>::iterator it = m_clients.begin();
for (; it != m_clients.end(); ++it, ++index) {
if (it.value() == client) {
break;
}
}
if (it == m_clients.end()) {
return;
}
emit beginRemove(index, index, id());
m_clients.erase(it);
emit endRemove();
}
void ClientLevel::init()
{
const ClientList &clients = Workspace::self()->clientList();
for (ClientList::const_iterator it = clients.begin(); it != clients.end(); ++it) {
Client *client = *it;
setupClientConnections(client);
if (!exclude(client) && shouldAdd(client)) {
m_clients.insert(nextId(), client);
}
}
}
void ClientLevel::reInit()
{
const ClientList &clients = Workspace::self()->clientList();
for (ClientList::const_iterator it = clients.begin(); it != clients.end(); ++it) {
checkClient((*it));
}
}
quint32 ClientLevel::idForRow(int row) const
{
if (row >= m_clients.size()) {
return 0;
}
QMap<quint32, Client*>::const_iterator it = m_clients.constBegin();
for (int i=0; i<row; ++i) {
++it;
}
return it.key();
}
bool ClientLevel::containsId(quint32 id) const
{
return m_clients.contains(id);
}
int ClientLevel::rowForId(quint32 id) const
{
int row = 0;
for (QMap<quint32, Client*>::const_iterator it = m_clients.constBegin();
it != m_clients.constEnd();
++it, ++row) {
if (it.key() == id) {
return row;
}
}
return -1;
}
Client *ClientLevel::clientForId(quint32 child) const
{
QMap<quint32, Client*>::const_iterator it = m_clients.constFind(child);
if (it == m_clients.constEnd()) {
return NULL;
}
return it.value();
}
bool ClientLevel::containsClient(Client *client) const
{
for (QMap<quint32, Client*>::const_iterator it = m_clients.constBegin();
it != m_clients.constEnd();
++it) {
if (it.value() == client) {
return true;
}
}
return false;
}
const AbstractLevel *ClientLevel::levelForId(quint32 id) const
{
if (id == AbstractLevel::id()) {
return this;
}
return NULL;
}
AbstractLevel *ClientLevel::parentForId(quint32 child) const
{
if (child == id()) {
return parentLevel();
}
if (m_clients.contains(child)) {
return const_cast<ClientLevel*>(this);
}
return NULL;
}
AbstractLevel *AbstractLevel::create(const QList< ClientModel::LevelRestriction > &restrictions, ClientModel::LevelRestrictions parentRestrictions, ClientModel *model, AbstractLevel *parent)
{
if (restrictions.isEmpty() || restrictions.first() == ClientModel::NoRestriction) {
ClientLevel *leaf = new ClientLevel(model, parent);
leaf->setRestrictions(parentRestrictions);
if (!parent) {
leaf->setParent(model);
}
return leaf;
}
// create a level
QList<ClientModel::LevelRestriction> childRestrictions(restrictions);
ClientModel::LevelRestriction restriction = childRestrictions.takeFirst();
ClientModel::LevelRestrictions childrenRestrictions = restriction | parentRestrictions;
ForkLevel *currentLevel = new ForkLevel(childRestrictions, model, parent);
currentLevel->setRestrictions(childrenRestrictions);
currentLevel->setRestriction(restriction);
if (!parent) {
currentLevel->setParent(model);
}
switch (restriction) {
case ClientModel::ActivityRestriction: {
return NULL;
}
case ClientModel::ScreenRestriction:
for (int i=0; i<screens()->count(); ++i) {
AbstractLevel *childLevel = create(childRestrictions, childrenRestrictions, model, currentLevel);
if (!childLevel) {
continue;
}
childLevel->setScreen(i);
currentLevel->addChild(childLevel);
}
break;
case ClientModel::VirtualDesktopRestriction:
for (uint i=1; i<=VirtualDesktopManager::self()->count(); ++i) {
AbstractLevel *childLevel = create(childRestrictions, childrenRestrictions, model, currentLevel);
if (!childLevel) {
continue;
}
childLevel->setVirtualDesktop(i);
currentLevel->addChild(childLevel);
}
break;
default:
// invalid
return NULL;
}
return currentLevel;
}
AbstractLevel::AbstractLevel(ClientModel *model, AbstractLevel *parent)
: QObject(parent)
, m_model(model)
, m_parent(parent)
, m_screen(0)
, m_virtualDesktop(0)
, m_activity()
, m_restriction(ClientModel::ClientModel::NoRestriction)
, m_restrictions(ClientModel::NoRestriction)
, m_id(nextId())
{
}
AbstractLevel::~AbstractLevel()
{
}
void AbstractLevel::setRestriction(ClientModel::LevelRestriction restriction)
{
m_restriction = restriction;
}
void AbstractLevel::setActivity(const QString &activity)
{
m_activity = activity;
}
void AbstractLevel::setScreen(uint screen)
{
m_screen = screen;
}
void AbstractLevel::setVirtualDesktop(uint virtualDesktop)
{
m_virtualDesktop = virtualDesktop;
}
void AbstractLevel::setRestrictions(ClientModel::LevelRestrictions restrictions)
{
m_restrictions = restrictions;
}
ForkLevel::ForkLevel(const QList<ClientModel::LevelRestriction> &childRestrictions, ClientModel *model, AbstractLevel *parent)
: AbstractLevel(model, parent)
, m_childRestrictions(childRestrictions)
{
connect(VirtualDesktopManager::self(), SIGNAL(countChanged(uint,uint)), SLOT(desktopCountChanged(uint,uint)));
connect(screens(), SIGNAL(countChanged(int,int)), SLOT(screenCountChanged(int,int)));
}
ForkLevel::~ForkLevel()
{
}
void ForkLevel::desktopCountChanged(uint previousCount, uint newCount)
{
if (restriction() != ClientModel::ClientModel::VirtualDesktopRestriction) {
return;
}
if (previousCount != uint(count())) {
return;
}
if (previousCount > newCount) {
// desktops got removed
emit beginRemove(newCount, previousCount-1, id());
while (uint(m_children.count()) > newCount) {
delete m_children.takeLast();
}
emit endRemove();
} else {
// desktops got added
emit beginInsert(previousCount, newCount-1, id());
for (uint i=previousCount+1; i<=newCount; ++i) {
AbstractLevel *childLevel = AbstractLevel::create(m_childRestrictions, restrictions(), model(), this);
if (!childLevel) {
continue;
}
childLevel->setVirtualDesktop(i);
childLevel->init();
addChild(childLevel);
}
emit endInsert();
}
}
void ForkLevel::screenCountChanged(int previousCount, int newCount)
{
if (restriction() != ClientModel::ClientModel::ClientModel::ScreenRestriction) {
return;
}
if (newCount == previousCount || previousCount != count()) {
return;
}
if (previousCount > newCount) {
// screens got removed
emit beginRemove(newCount, previousCount-1, id());
while (m_children.count() > newCount) {
delete m_children.takeLast();
}
emit endRemove();
} else {
// screens got added
emit beginInsert(previousCount, newCount-1, id());
for (int i=previousCount; i<newCount; ++i) {
AbstractLevel *childLevel = AbstractLevel::create(m_childRestrictions, restrictions(), model(), this);
if (!childLevel) {
continue;
}
childLevel->setScreen(i);
childLevel->init();
addChild(childLevel);
}
emit endInsert();
}
}
void ForkLevel::activityAdded(const QString &activityId)
{
}
void ForkLevel::activityRemoved(const QString &activityId)
{
}
int ForkLevel::count() const
{
return m_children.count();
}
void ForkLevel::addChild(AbstractLevel *child)
{
m_children.append(child);
connect(child, SIGNAL(beginInsert(int,int,quint32)), SIGNAL(beginInsert(int,int,quint32)));
connect(child, SIGNAL(beginRemove(int,int,quint32)), SIGNAL(beginRemove(int,int,quint32)));
connect(child, SIGNAL(endInsert()), SIGNAL(endInsert()));
connect(child, SIGNAL(endRemove()), SIGNAL(endRemove()));
}
void ForkLevel::setActivity(const QString &activity)
{
AbstractLevel::setActivity(activity);
for (QList<AbstractLevel*>::iterator it = m_children.begin(); it != m_children.end(); ++it) {
(*it)->setActivity(activity);
}
}
void ForkLevel::setScreen(uint screen)
{
AbstractLevel::setScreen(screen);
for (QList<AbstractLevel*>::iterator it = m_children.begin(); it != m_children.end(); ++it) {
(*it)->setScreen(screen);
}
}
void ForkLevel::setVirtualDesktop(uint virtualDesktop)
{
AbstractLevel::setVirtualDesktop(virtualDesktop);
for (QList<AbstractLevel*>::iterator it = m_children.begin(); it != m_children.end(); ++it) {
(*it)->setVirtualDesktop(virtualDesktop);
}
}
void ForkLevel::init()
{
for (QList<AbstractLevel*>::iterator it = m_children.begin(); it != m_children.end(); ++it) {
(*it)->init();
}
}
quint32 ForkLevel::idForRow(int row) const
{
if (row >= m_children.length()) {
return 0;
}
return m_children.at(row)->id();
}
const AbstractLevel *ForkLevel::levelForId(quint32 id) const
{
if (id == AbstractLevel::id()) {
return this;
}
for (QList<AbstractLevel*>::const_iterator it = m_children.constBegin(); it != m_children.constEnd(); ++it) {
if (const AbstractLevel *child = (*it)->levelForId(id)) {
return child;
}
}
// not found
return NULL;
}
AbstractLevel *ForkLevel::parentForId(quint32 child) const
{
if (child == id()) {
return parentLevel();
}
for (QList<AbstractLevel*>::const_iterator it = m_children.constBegin(); it != m_children.constEnd(); ++it) {
if (AbstractLevel *parent = (*it)->parentForId(child)) {
return parent;
}
}
// not found
return NULL;
}
int ForkLevel::rowForId(quint32 child) const
{
if (id() == child) {
return 0;
}
for (int i=0; i<m_children.count(); ++i) {
if (m_children.at(i)->id() == child) {
return i;
}
}
// do recursion
for (QList<AbstractLevel*>::const_iterator it = m_children.constBegin(); it != m_children.constEnd(); ++it) {
int row = (*it)->rowForId(child);
if (row != -1) {
return row;
}
}
// not found
return -1;
}
Client *ForkLevel::clientForId(quint32 child) const
{
for (QList<AbstractLevel*>::const_iterator it = m_children.constBegin(); it != m_children.constEnd(); ++it) {
if (Client *client = (*it)->clientForId(child)) {
return client;
}
}
// not found
return NULL;
}
ClientModel::ClientModel(QObject *parent)
: QAbstractItemModel(parent)
, m_root(NULL)
, m_exclusions(NoExclusion)
{
QHash<int, QByteArray> roleNames;
roleNames.insert(Qt::DisplayRole, "display");
roleNames.insert(ClientRole, "client");
roleNames.insert(ScreenRole, "screen");
roleNames.insert(DesktopRole, "desktop");
roleNames.insert(ActivityRole, "activity");
setRoleNames(roleNames);
}
ClientModel::~ClientModel()
{
}
void ClientModel::setLevels(QList< ClientModel::LevelRestriction > restrictions)
{
beginResetModel();
if (m_root) {
delete m_root;
}
m_root = AbstractLevel::create(restrictions, NoRestriction, this);
connect(m_root, SIGNAL(beginInsert(int,int,quint32)), SLOT(levelBeginInsert(int,int,quint32)));
connect(m_root, SIGNAL(beginRemove(int,int,quint32)), SLOT(levelBeginRemove(int,int,quint32)));
connect(m_root, SIGNAL(endInsert()), SLOT(levelEndInsert()));
connect(m_root, SIGNAL(endRemove()), SLOT(levelEndRemove()));
m_root->init();
endResetModel();
}
void ClientModel::setExclusions(ClientModel::Exclusions exclusions)
{
if (exclusions == m_exclusions) {
return;
}
m_exclusions = exclusions;
emit exclusionsChanged();
}
QVariant ClientModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.column() != 0) {
return QVariant();
}
if (const AbstractLevel *level = getLevel(index)) {
LevelRestriction restriction = level->restriction();
if (restriction == ActivityRestriction && (role == Qt::DisplayRole || role == ActivityRole)) {
return level->activity();
} else if (restriction == VirtualDesktopRestriction && (role == Qt::DisplayRole || role == DesktopRole)) {
return level->virtualDesktop();
} else if (restriction ==ScreenRestriction && (role == Qt::DisplayRole || role == ScreenRole)) {
return level->screen();
} else {
return QVariant();
}
}
if (role == Qt::DisplayRole || role == ClientRole) {
if (Client *client = m_root->clientForId(index.internalId())) {
return qVariantFromValue(client);
}
}
return QVariant();
}
int ClientModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return 1;
}
int ClientModel::rowCount(const QModelIndex &parent) const
{
if (!m_root) {
return 0;
}
if (!parent.isValid()) {
return m_root->count();
}
if (const AbstractLevel *level = getLevel(parent)) {
if (level->id() != parent.internalId()) {
// not a real level - no children
return 0;
}
return level->count();
}
return 0;
}
QModelIndex ClientModel::parent(const QModelIndex &child) const
{
if (!child.isValid() || child.column() != 0) {
return QModelIndex();
}
return parentForId(child.internalId());
}
QModelIndex ClientModel::parentForId(quint32 childId) const
{
if (childId == m_root->id()) {
// asking for parent of our toplevel
return QModelIndex();
}
if (AbstractLevel *parentLevel = m_root->parentForId(childId)) {
if (parentLevel == m_root) {
return QModelIndex();
}
const int row = m_root->rowForId(parentLevel->id());
if (row == -1) {
// error
return QModelIndex();
}
return createIndex(row, 0, parentLevel->id());
}
return QModelIndex();
}
QModelIndex ClientModel::index(int row, int column, const QModelIndex &parent) const
{
if (column != 0 || row < 0 || !m_root) {
return QModelIndex();
}
if (!parent.isValid()) {
if (row >= rowCount()) {
return QModelIndex();
}
return createIndex(row, 0, m_root->idForRow(row));
}
const AbstractLevel *parentLevel = getLevel(parent);
if (!parentLevel) {
return QModelIndex();
}
if (row >= parentLevel->count()) {
return QModelIndex();
}
const quint32 id = parentLevel->idForRow(row);
if (id == 0) {
return QModelIndex();
}
return createIndex(row, column, id);
}
const AbstractLevel *ClientModel::getLevel(const QModelIndex &index) const
{
if (!index.isValid()) {
return m_root;
}
return m_root->levelForId(index.internalId());
}
void ClientModel::levelBeginInsert(int rowStart, int rowEnd, quint32 id)
{
const int row = m_root->rowForId(id);
QModelIndex parent;
if (row != -1) {
parent = createIndex(row, 0, id);
}
beginInsertRows(parent, rowStart, rowEnd);
}
void ClientModel::levelBeginRemove(int rowStart, int rowEnd, quint32 id)
{
const int row = m_root->rowForId(id);
QModelIndex parent;
if (row != -1) {
parent = createIndex(row, 0, id);
}
beginRemoveRows(parent, rowStart, rowEnd);
}
void ClientModel::levelEndInsert()
{
endInsertRows();
}
void ClientModel::levelEndRemove()
{
endRemoveRows();
}
#define CLIENT_MODEL_WRAPPER(name, levels) \
name::name(QObject *parent) \
: ClientModel(parent) \
{ \
setLevels(levels); \
} \
name::~name() {}
CLIENT_MODEL_WRAPPER(SimpleClientModel, QList<LevelRestriction>())
CLIENT_MODEL_WRAPPER(ClientModelByScreen, QList<LevelRestriction>() << ScreenRestriction)
CLIENT_MODEL_WRAPPER(ClientModelByScreenAndDesktop, QList<LevelRestriction>() << ScreenRestriction << VirtualDesktopRestriction)
#undef CLIENT_MODEL_WRAPPER
ClientFilterModel::ClientFilterModel(QObject *parent)
: QSortFilterProxyModel(parent)
, m_clientModel(NULL)
{
}
ClientFilterModel::~ClientFilterModel()
{
}
void ClientFilterModel::setClientModel(ClientModel *clientModel)
{
if (clientModel == m_clientModel) {
return;
}
m_clientModel = clientModel;
setSourceModel(m_clientModel);
emit clientModelChanged();
}
void ClientFilterModel::setFilter(const QString &filter)
{
if (filter == m_filter) {
return;
}
m_filter = filter;
emit filterChanged();
invalidateFilter();
}
bool ClientFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
if (!m_clientModel) {
return false;
}
if (m_filter.isEmpty()) {
return true;
}
QModelIndex index = m_clientModel->index(sourceRow, 0, sourceParent);
if (!index.isValid()) {
return false;
}
QVariant data = index.data();
if (!data.isValid()) {
// an invalid QVariant is valid data
return true;
}
// TODO: introduce a type as a data role and properly check, this seems dangerous
if (data.type() == QVariant::Int || data.type() == QVariant::UInt || data.type() == QVariant::String) {
// we do not filter out screen, desktop and activity
return true;
}
Client *client = qvariant_cast<KWin::Client *>(data);
if (!client) {
return false;
}
if (client->caption().contains(m_filter, Qt::CaseInsensitive)) {
return true;
}
const QString windowRole(client->windowRole());
if (windowRole.contains(m_filter, Qt::CaseInsensitive)) {
return true;
}
const QString resourceName(client->resourceName());
if (resourceName.contains(m_filter, Qt::CaseInsensitive)) {
return true;
}
const QString resourceClass(client->resourceClass());
if (resourceClass.contains(m_filter, Qt::CaseInsensitive)) {
return true;
}
return false;
}
} // namespace Scripting
} // namespace KWin

View file

@ -1,380 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_SCRIPTING_MODEL_H
#define KWIN_SCRIPTING_MODEL_H
#include <QAbstractItemModel>
#include <QSortFilterProxyModel>
#include <QList>
namespace KWin {
class Client;
namespace ScriptingClientModel {
class AbstractLevel;
class ClientModel : public QAbstractItemModel
{
Q_OBJECT
Q_ENUMS(Exclude)
Q_ENUMS(LevelRestriction)
Q_PROPERTY(Exclusions exclusions READ exclusions WRITE setExclusions NOTIFY exclusionsChanged)
public:
enum Exclusion {
NoExclusion = 0,
// window types
DesktopWindowsExclusion = 1 << 0,
DockWindowsExclusion = 1 << 1,
UtilityWindowsExclusion = 1 << 2,
SpecialWindowsExclusion = 1 << 3,
// windows with flags
SkipTaskbarExclusion = 1 << 4,
SkipPagerExclusion = 1 << 5,
SwitchSwitcherExclusion = 1 << 6,
// based on state
OtherDesktopsExclusion = 1 << 7,
OtherActivitiesExclusion = 1 << 8,
MinimizedExclusion = 1 << 9,
NonSelectedWindowTabExclusion = 1 << 10,
NotAcceptingFocusExclusion = 1 << 11
};
Q_DECLARE_FLAGS(Exclusions, Exclusion)
Q_FLAGS(Exclusions)
enum LevelRestriction {
NoRestriction = 0,
VirtualDesktopRestriction = 1 << 0,
ScreenRestriction = 1 << 1,
ActivityRestriction = 1 << 2
};
Q_DECLARE_FLAGS(LevelRestrictions, LevelRestriction)
Q_FLAGS(LevelRestrictions)
explicit ClientModel(QObject *parent);
virtual ~ClientModel();
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
virtual QModelIndex parent(const QModelIndex &child) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
void setExclusions(ClientModel::Exclusions exclusions);
Exclusions exclusions() const;
Q_SIGNALS:
void exclusionsChanged();
private Q_SLOTS:
void levelBeginInsert(int rowStart, int rowEnd, quint32 parentId);
void levelEndInsert();
void levelBeginRemove(int rowStart, int rowEnd, quint32 parentId);
void levelEndRemove();
protected:
enum ClientModelRoles {
ClientRole = Qt::UserRole,
ScreenRole,
DesktopRole,
ActivityRole
};
void setLevels(QList<LevelRestriction> restrictions);
private:
QModelIndex parentForId(quint32 childId) const;
const AbstractLevel *getLevel(const QModelIndex &index) const;
AbstractLevel *m_root;
Exclusions m_exclusions;
};
/**
* @brief The data structure of the Model.
*
* The model is implemented as a Tree consisting of AbstractLevels as the levels of the tree.
* A non leaf level is represented by the inheriting class @link ForkLevel, the last level above a
* leaf is represented by the inheriting class @link ClientLevel, which contains the Clients - each
* Client is one leaf.
*
* In case the tree would only consist of Clients - leafs - it has always one ClientLevel as the root
* of the tree.
*
* The number of levels in the tree is controlled by the LevelRestrictions. For each existing
* LevelRestriction a new Level is created, if there are no more restrictions a ClientLevel is created.
*
* To build up the tree the static factory method @link create has to be used. It will recursively
* build up the tree. After the tree has been build up use @link init to initialize the tree which
* will add the Clients to the ClientLevel.
*
* Each element of the tree has a unique id which can be used by the QAbstractItemModel as the
* internal id for its QModelIndex. Note: the ids have no ordering, if trying to get a specific element
* the tree performs a depth-first search.
*
*/
class AbstractLevel : public QObject
{
Q_OBJECT
public:
virtual ~AbstractLevel();
virtual int count() const = 0;
virtual void init() = 0;
virtual quint32 idForRow(int row) const = 0;
uint screen() const;
uint virtualDesktop() const;
const QString &activity() const;
ClientModel::LevelRestrictions restrictions() const;
void setRestrictions(ClientModel::LevelRestrictions restrictions);
ClientModel::LevelRestriction restriction() const;
void setRestriction(ClientModel::LevelRestriction restriction);
quint32 id() const;
AbstractLevel *parentLevel() const;
virtual const AbstractLevel *levelForId(quint32 id) const = 0;
virtual AbstractLevel *parentForId(quint32 child) const = 0;
virtual int rowForId(quint32 child) const = 0;
virtual Client *clientForId(quint32 child) const = 0;
virtual void setScreen(uint screen);
virtual void setVirtualDesktop(uint virtualDesktop);
virtual void setActivity(const QString &activity);
static AbstractLevel *create(const QList<ClientModel::LevelRestriction> &restrictions, ClientModel::LevelRestrictions parentRestrictions, ClientModel *model, AbstractLevel *parent = NULL);
Q_SIGNALS:
void beginInsert(int rowStart, int rowEnd, quint32 parentId);
void endInsert();
void beginRemove(int rowStart, int rowEnd, quint32 parentId);
void endRemove();
protected:
AbstractLevel(ClientModel *model, AbstractLevel *parent);
ClientModel *model() const;
private:
ClientModel *m_model;
AbstractLevel *m_parent;
uint m_screen;
uint m_virtualDesktop;
QString m_activity;
ClientModel::LevelRestriction m_restriction;
ClientModel::LevelRestrictions m_restrictions;
quint32 m_id;
};
class ForkLevel : public AbstractLevel
{
Q_OBJECT
public:
ForkLevel(const QList<ClientModel::LevelRestriction> &childRestrictions, ClientModel *model, AbstractLevel *parent);
virtual ~ForkLevel();
virtual int count() const;
virtual void init();
virtual quint32 idForRow(int row) const;
void addChild(AbstractLevel *child);
virtual void setScreen(uint screen);
virtual void setVirtualDesktop(uint virtualDesktop);
virtual void setActivity(const QString &activity);
virtual const AbstractLevel *levelForId(quint32 id) const;
virtual AbstractLevel *parentForId(quint32 child) const;
virtual int rowForId(quint32 child) const;
virtual Client *clientForId(quint32 child) const;
private Q_SLOTS:
void desktopCountChanged(uint previousCount, uint newCount);
void screenCountChanged(int previousCount, int newCount);
void activityAdded(const QString &id);
void activityRemoved(const QString &id);
private:
QList<AbstractLevel*> m_children;
QList<ClientModel::LevelRestriction> m_childRestrictions;
};
/**
* @brief The actual leafs of the model's tree containing the Client's in this branch of the tree.
*
* This class groups all the Clients of one branch of the tree and takes care of updating the tree
* when a Client changes its state in a way that it should be excluded/included or gets added or
* removed.
*
* The Clients in this group are not sorted in any particular way. It's a simple list which only
* gets added to. If some sorting should be applied, use a QSortFilterProxyModel.
*/
class ClientLevel : public AbstractLevel
{
Q_OBJECT
public:
explicit ClientLevel(ClientModel *model, AbstractLevel *parent);
virtual ~ClientLevel();
void init();
int count() const;
quint32 idForRow(int row) const;
bool containsId(quint32 id) const;
int rowForId(quint32 row) const;
Client *clientForId(quint32 child) const;
virtual const AbstractLevel *levelForId(quint32 id) const;
virtual AbstractLevel *parentForId(quint32 child) const;
public Q_SLOTS:
void clientAdded(KWin::Client *client);
void clientRemoved(KWin::Client *client);
private Q_SLOTS:
// uses sender()
void checkClient();
void reInit();
private:
void checkClient(KWin::Client *client);
void setupClientConnections(Client *client);
void addClient(Client *client);
void removeClient(Client *client);
bool shouldAdd(Client *client) const;
bool exclude(Client *client) const;
bool containsClient(Client *client) const;
QMap<quint32, Client*> m_clients;
};
class SimpleClientModel : public ClientModel
{
Q_OBJECT
public:
SimpleClientModel(QObject *parent = NULL);
virtual ~SimpleClientModel();
};
class ClientModelByScreen : public ClientModel
{
Q_OBJECT
public:
ClientModelByScreen(QObject *parent = NULL);
virtual ~ClientModelByScreen();
};
class ClientModelByScreenAndDesktop : public ClientModel
{
Q_OBJECT
public:
ClientModelByScreenAndDesktop(QObject *parent = NULL);
virtual ~ClientModelByScreenAndDesktop();
};
/**
* @brief Custom QSortFilterProxyModel to filter on Client caption, role and class.
*
*/
class ClientFilterModel : public QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY(KWin::ScriptingClientModel::ClientModel *clientModel READ clientModel WRITE setClientModel NOTIFY clientModelChanged)
Q_PROPERTY(QString filter READ filter WRITE setFilter NOTIFY filterChanged)
public:
ClientFilterModel(QObject *parent = 0);
virtual ~ClientFilterModel();
ClientModel *clientModel() const;
const QString &filter() const;
public Q_SLOTS:
void setClientModel(ClientModel *clientModel);
void setFilter(const QString &filter);
protected:
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
Q_SIGNALS:
void clientModelChanged();
void filterChanged();
private:
ClientModel *m_clientModel;
QString m_filter;
};
inline
int ClientLevel::count() const
{
return m_clients.count();
}
inline
const QString &AbstractLevel::activity() const
{
return m_activity;
}
inline
AbstractLevel *AbstractLevel::parentLevel() const
{
return m_parent;
}
inline
ClientModel *AbstractLevel::model() const
{
return m_model;
}
inline
uint AbstractLevel::screen() const
{
return m_screen;
}
inline
uint AbstractLevel::virtualDesktop() const
{
return m_virtualDesktop;
}
inline
ClientModel::LevelRestriction AbstractLevel::restriction() const
{
return m_restriction;
}
inline
ClientModel::LevelRestrictions AbstractLevel::restrictions() const
{
return m_restrictions;
}
inline
quint32 AbstractLevel::id() const
{
return m_id;
}
inline
ClientModel::Exclusions ClientModel::exclusions() const
{
return m_exclusions;
}
inline
ClientModel *ClientFilterModel::clientModel() const
{
return m_clientModel;
}
inline
const QString &ClientFilterModel::filter() const
{
return m_filter;
}
} // namespace Scripting
} // namespace KWin
Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::ScriptingClientModel::ClientModel::Exclusions)
Q_DECLARE_OPERATORS_FOR_FLAGS(KWin::ScriptingClientModel::ClientModel::LevelRestrictions)
#endif // KWIN_SCRIPTING_MODEL_H

View file

@ -1,46 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "scriptingutils.h"
namespace KWin
{
bool validateParameters(QScriptContext *context, int min, int max)
{
if (context->argumentCount() < min || context->argumentCount() > max) {
context->throwError(QScriptContext::SyntaxError,
i18nc("syntax error in KWin script", "Invalid number of arguments"));
return false;
}
return true;
}
template<>
bool validateArgumentType<QVariant>(QScriptContext *context, int argument)
{
const bool result =context->argument(argument).toVariant().isValid();
if (!result) {
context->throwError(QScriptContext::TypeError,
i18nc("KWin Scripting function received incorrect value for an expected type",
"%1 is not a variant type", context->argument(argument).toString()));
}
return result;
}
}

View file

@ -1,284 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_SCRIPTINGUTILS_H
#define KWIN_SCRIPTINGUTILS_H
#include "workspace.h"
#ifdef KWIN_BUILD_SCREENEDGES
#include "screenedge.h"
#endif
#include <KDE/KAction>
#include <KDE/KActionCollection>
#include <KDE/KDebug>
#include <KDE/KLocalizedString>
#include <QtScript/QScriptEngine>
namespace KWin
{
/**
* Validates that argument at @p index of given @p context is of required type.
* Throws a type error in the scripting context if there is a type mismatch.
* @param context The scripting context in which the argument type needs to be validated.
* @param index The argument index to validate
* @returns @c true if the argument is of required type, @c false otherwise
**/
template<class T>
bool validateArgumentType(QScriptContext *context, int index)
{
const bool result = context->argument(index).toVariant().canConvert<T>();
if (!result) {
context->throwError(QScriptContext::TypeError,
i18nc("KWin Scripting function received incorrect value for an expected type",
"%1 is not of required type", context->argument(index).toString()));
}
return result;
}
/**
* Validates that the argument of @p context is of specified type.
* Throws a type error in the scripting context if there is a type mismatch.
* @param context The scripting context in which the argument type needs to be validated.
* @returns @c true if the argument is of required type, @c false otherwise
**/
template<class T>
bool validateArgumentType(QScriptContext *context)
{
return validateArgumentType<T>(context, 0);
}
template<class T, class U>
bool validateArgumentType(QScriptContext *context)
{
if (!validateArgumentType<T>(context)) {
return false;
}
return validateArgumentType<U>(context, 1);
}
template<class T, class U, class V>
bool validateArgumentType(QScriptContext *context)
{
if (!validateArgumentType<T, U>(context)) {
return false;
}
return validateArgumentType<V>(context, 2);
}
template<class T, class U, class V, class W>
bool validateArgumentType(QScriptContext *context)
{
if (!validateArgumentType<T, U, V>(context)) {
return false;
}
return validateArgumentType<W>(context, 3);
}
/**
* Validates that the argument count of @p context is at least @p min and @p max.
* Throws a syntax error in the script context if argument count mismatch.
* @param context The ScriptContext for which the argument count needs to be validated
* @param min The minimum number of arguments.
* @param max The maximum number of arguments
* @returns @c true if the argument count is correct, otherwise @c false
**/
bool validateParameters(QScriptContext *context, int min, int max);
template<class T>
QScriptValue globalShortcut(QScriptContext *context, QScriptEngine *engine)
{
T script = qobject_cast<T>(context->callee().data().toQObject());
if (!script) {
return engine->undefinedValue();
}
if (context->argumentCount() != 4) {
kDebug(1212) << "Incorrect number of arguments! Expected: title, text, keySequence, callback";
return engine->undefinedValue();
}
KActionCollection* actionCollection = new KActionCollection(script);
KAction* a = (KAction*)actionCollection->addAction(context->argument(0).toString());
a->setText(context->argument(1).toString());
a->setGlobalShortcut(KShortcut(context->argument(2).toString()));
script->registerShortcut(a, context->argument(3));
return engine->newVariant(true);
}
template<class T>
void callGlobalShortcutCallback(T script, QObject *sender)
{
QAction *a = qobject_cast<QAction*>(sender);
if (!a) {
return;
}
QHash<QAction*, QScriptValue>::const_iterator it = script->shortcutCallbacks().find(a);
if (it == script->shortcutCallbacks().end()) {
return;
}
QScriptValue value(it.value());
QScriptValueList arguments;
arguments << value.engine()->newQObject(a);
value.call(QScriptValue(), arguments);
}
template<class T>
QScriptValue registerScreenEdge(QScriptContext *context, QScriptEngine *engine)
{
T script = qobject_cast<T>(context->callee().data().toQObject());
if (!script) {
return engine->undefinedValue();
}
if (!validateParameters(context, 2, 2)) {
return engine->undefinedValue();
}
if (!validateArgumentType<int>(context)) {
return engine->undefinedValue();
}
if (!context->argument(1).isFunction()) {
context->throwError(QScriptContext::SyntaxError, i18nc("KWin Scripting error thrown due to incorrect argument",
"Second argument to registerScreenEdge needs to be a callback"));
}
const int edge = context->argument(0).toVariant().toInt();
QHash<int, QList<QScriptValue> >::iterator it = script->screenEdgeCallbacks().find(edge);
if (it == script->screenEdgeCallbacks().end()) {
// not yet registered
#ifdef KWIN_BUILD_SCREENEDGES
ScreenEdges::self()->reserve(static_cast<KWin::ElectricBorder>(edge), script, "borderActivated");
#endif
script->screenEdgeCallbacks().insert(edge, QList<QScriptValue>() << context->argument(1));
} else {
it->append(context->argument(1));
}
return engine->newVariant(true);
}
template<class T>
QScriptValue registerUserActionsMenu(QScriptContext *context, QScriptEngine *engine)
{
T script = qobject_cast<T>(context->callee().data().toQObject());
if (!script) {
return engine->undefinedValue();
}
if (!validateParameters(context, 1, 1)) {
return engine->undefinedValue();
}
if (!context->argument(0).isFunction()) {
context->throwError(QScriptContext::SyntaxError, i18nc("KWin Scripting error thrown due to incorrect argument",
"Argument for registerUserActionsMenu needs to be a callback"));
return engine->undefinedValue();
}
script->registerUseractionsMenuCallback(context->argument(0));
return engine->newVariant(true);
}
template<class T>
void screenEdgeActivated(T *script, int edge)
{
QHash<int, QList<QScriptValue> >::iterator it = script->screenEdgeCallbacks().find(edge);
if (it != script->screenEdgeCallbacks().end()) {
foreach (const QScriptValue &value, it.value()) {
QScriptValue callback(value);
callback.call();
}
}
}
template<class T>
QScriptValue scriptingAssert(QScriptContext *context, QScriptEngine *engine, int min, int max, T defaultVal = T())
{
if (!validateParameters(context, min, max)) {
return engine->undefinedValue();
}
switch (context->argumentCount()) {
case 1:
if (!validateArgumentType<T>(context)) {
return engine->undefinedValue();
}
break;
case 2:
if (max == 2) {
if (!validateArgumentType<T, QString>(context)) {
return engine->undefinedValue();
}
} else {
if (!validateArgumentType<T, T>(context)) {
return engine->undefinedValue();
}
}
break;
case 3:
if (!validateArgumentType<T, T, QString>(context)) {
return engine->undefinedValue();
}
break;
}
if (max == 2) {
if (context->argument(0).toVariant().value<T>() != defaultVal) {
if (context->argumentCount() == max) {
context->throwError(QScriptContext::UnknownError, context->argument(max - 1).toString());
} else {
context->throwError(QScriptContext::UnknownError,
i18nc("Assertion failed in KWin script with given value",
"Assertion failed: %1", context->argument(0).toString()));
}
return engine->undefinedValue();
}
} else {
if (context->argument(0).toVariant().value<T>() != context->argument(1).toVariant().value<T>()) {
if (context->argumentCount() == max) {
context->throwError(QScriptContext::UnknownError, context->argument(max - 1).toString());
} else {
context->throwError(QScriptContext::UnknownError,
i18nc("Assertion failed in KWin script with expected value and actual value",
"Assertion failed: Expected %1, got %2",
context->argument(0).toString(), context->argument(1).toString()));
}
return engine->undefinedValue();
}
}
return engine->newVariant(true);
}
inline void registerGlobalShortcutFunction(QObject *parent, QScriptEngine *engine, QScriptEngine::FunctionSignature function)
{
QScriptValue shortcutFunc = engine->newFunction(function);
shortcutFunc.setData(engine->newQObject(parent));
engine->globalObject().setProperty("registerShortcut", shortcutFunc);
}
inline void registerScreenEdgeFunction(QObject *parent, QScriptEngine *engine, QScriptEngine::FunctionSignature function)
{
QScriptValue shortcutFunc = engine->newFunction(function);
shortcutFunc.setData(engine->newQObject(parent));
engine->globalObject().setProperty("registerScreenEdge", shortcutFunc);
}
inline void regesterUserActionsMenuFunction(QObject *parent, QScriptEngine *engine, QScriptEngine::FunctionSignature function)
{
QScriptValue shortcutFunc = engine->newFunction(function);
shortcutFunc.setData(engine->newQObject(parent));
engine->globalObject().setProperty("registerUserActionsMenu", shortcutFunc);
}
} // namespace KWin
#endif // KWIN_SCRIPTINGUTILS_H

View file

@ -1,43 +0,0 @@
/*
* Copyright 2007 Richard J. Moore <rich@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2 as
* published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <QtScript/QScriptValue>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptContext>
#include <QtScript/QScriptable>
#include <QTimer>
Q_DECLARE_METATYPE(QTimer*)
static QScriptValue newTimer(QScriptEngine *eng, QTimer *timer)
{
return eng->newQObject(timer, QScriptEngine::AutoOwnership);
}
static QScriptValue ctor(QScriptContext *ctx, QScriptEngine *eng)
{
return newTimer(eng, new QTimer(qscriptvalue_cast<QObject*>(ctx->argument(0))));
}
QScriptValue constructTimerClass(QScriptEngine *eng)
{
QScriptValue proto = newTimer(eng, new QTimer());
eng->setDefaultPrototype(qMetaTypeId<QTimer*>(), proto);
return eng->newFunction(ctor, proto);
}

View file

@ -1,280 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
Copyright (C) 2011, 2012 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "workspace_wrapper.h"
#include "../client.h"
#include "../outline.h"
#include "../screens.h"
#include "../virtualdesktops.h"
#include "../workspace.h"
#include <QDesktopWidget>
namespace KWin {
WorkspaceWrapper::WorkspaceWrapper(QObject* parent) : QObject(parent)
{
KWin::Workspace *ws = KWin::Workspace::self();
KWin::VirtualDesktopManager *vds = KWin::VirtualDesktopManager::self();
connect(ws, SIGNAL(desktopPresenceChanged(KWin::Client*,int)), SIGNAL(desktopPresenceChanged(KWin::Client*,int)));
connect(ws, SIGNAL(currentDesktopChanged(int,KWin::Client*)), SIGNAL(currentDesktopChanged(int,KWin::Client*)));
connect(ws, SIGNAL(clientAdded(KWin::Client*)), SIGNAL(clientAdded(KWin::Client*)));
connect(ws, SIGNAL(clientAdded(KWin::Client*)), SLOT(setupClientConnections(KWin::Client*)));
connect(ws, SIGNAL(clientRemoved(KWin::Client*)), SIGNAL(clientRemoved(KWin::Client*)));
connect(ws, SIGNAL(clientActivated(KWin::Client*)), SIGNAL(clientActivated(KWin::Client*)));
connect(vds, SIGNAL(countChanged(uint,uint)), SIGNAL(numberDesktopsChanged(uint)));
connect(vds, SIGNAL(layoutChanged(int,int)), SIGNAL(desktopLayoutChanged()));
connect(ws, SIGNAL(clientDemandsAttentionChanged(KWin::Client*,bool)), SIGNAL(clientDemandsAttentionChanged(KWin::Client*,bool)));
connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), SIGNAL(numberScreensChanged(int)));
connect(QApplication::desktop(), SIGNAL(resized(int)), SIGNAL(screenResized(int)));
foreach (KWin::Client *client, ws->clientList()) {
setupClientConnections(client);
}
}
int WorkspaceWrapper::currentDesktop() const
{
return VirtualDesktopManager::self()->current();
}
int WorkspaceWrapper::numberOfDesktops() const
{
return VirtualDesktopManager::self()->count();
}
void WorkspaceWrapper::setCurrentDesktop(int desktop)
{
VirtualDesktopManager::self()->setCurrent(desktop);
}
void WorkspaceWrapper::setNumberOfDesktops(int count)
{
VirtualDesktopManager::self()->setCount(count);
}
#define GETTER( rettype, getterName ) \
rettype WorkspaceWrapper::getterName( ) const { \
return Workspace::self()->getterName(); \
}
GETTER(KWin::Client*, activeClient)
GETTER(QList< KWin::Client* >, clientList)
#undef GETTER
QString WorkspaceWrapper::currentActivity() const
{
return QString();
}
QStringList WorkspaceWrapper::activityList() const
{
return QStringList();
}
#define SLOTWRAPPER(name) \
void WorkspaceWrapper::name( ) { \
Workspace::self()->name(); \
}
SLOTWRAPPER(slotSwitchToNextScreen)
SLOTWRAPPER(slotWindowToNextScreen)
SLOTWRAPPER(slotToggleShowDesktop)
SLOTWRAPPER(slotWindowMaximize)
SLOTWRAPPER(slotWindowMaximizeVertical)
SLOTWRAPPER(slotWindowMaximizeHorizontal)
SLOTWRAPPER(slotWindowMinimize)
SLOTWRAPPER(slotWindowShade)
SLOTWRAPPER(slotWindowRaise)
SLOTWRAPPER(slotWindowLower)
SLOTWRAPPER(slotWindowRaiseOrLower)
SLOTWRAPPER(slotActivateAttentionWindow)
SLOTWRAPPER(slotWindowPackLeft)
SLOTWRAPPER(slotWindowPackRight)
SLOTWRAPPER(slotWindowPackUp)
SLOTWRAPPER(slotWindowPackDown)
SLOTWRAPPER(slotWindowGrowHorizontal)
SLOTWRAPPER(slotWindowGrowVertical)
SLOTWRAPPER(slotWindowShrinkHorizontal)
SLOTWRAPPER(slotWindowShrinkVertical)
SLOTWRAPPER(slotWindowQuickTileLeft)
SLOTWRAPPER(slotWindowQuickTileRight)
SLOTWRAPPER(slotWindowQuickTileTopLeft)
SLOTWRAPPER(slotWindowQuickTileTopRight)
SLOTWRAPPER(slotWindowQuickTileBottomLeft)
SLOTWRAPPER(slotWindowQuickTileBottomRight)
SLOTWRAPPER(slotSwitchWindowUp)
SLOTWRAPPER(slotSwitchWindowDown)
SLOTWRAPPER(slotSwitchWindowRight)
SLOTWRAPPER(slotSwitchWindowLeft)
SLOTWRAPPER(slotIncreaseWindowOpacity)
SLOTWRAPPER(slotLowerWindowOpacity)
SLOTWRAPPER(slotWindowOperations)
SLOTWRAPPER(slotWindowClose)
SLOTWRAPPER(slotWindowMove)
SLOTWRAPPER(slotWindowResize)
SLOTWRAPPER(slotWindowAbove)
SLOTWRAPPER(slotWindowBelow)
SLOTWRAPPER(slotWindowOnAllDesktops)
SLOTWRAPPER(slotWindowFullScreen)
SLOTWRAPPER(slotWindowNoBorder)
SLOTWRAPPER(slotWindowToNextDesktop)
SLOTWRAPPER(slotWindowToPreviousDesktop)
SLOTWRAPPER(slotWindowToDesktopRight)
SLOTWRAPPER(slotWindowToDesktopLeft)
SLOTWRAPPER(slotWindowToDesktopUp)
SLOTWRAPPER(slotWindowToDesktopDown)
#undef SLOTWRAPPER
#define SLOTWRAPPER(name,direction) \
void WorkspaceWrapper::name( ) { \
VirtualDesktopManager::self()->moveTo<direction>(options->isRollOverDesktops()); \
}
SLOTWRAPPER(slotSwitchDesktopNext,DesktopNext)
SLOTWRAPPER(slotSwitchDesktopPrevious,DesktopPrevious)
SLOTWRAPPER(slotSwitchDesktopRight,DesktopRight)
SLOTWRAPPER(slotSwitchDesktopLeft,DesktopLeft)
SLOTWRAPPER(slotSwitchDesktopUp,DesktopAbove)
SLOTWRAPPER(slotSwitchDesktopDown,DesktopBelow)
#undef SLOTWRAPPER
void WorkspaceWrapper::setActiveClient(KWin::Client* client)
{
KWin::Workspace::self()->activateClient(client);
}
QSize WorkspaceWrapper::workspaceSize() const
{
return QSize(workspaceWidth(), workspaceHeight());
}
QSize WorkspaceWrapper::displaySize() const
{
return QSize(KWin::displayWidth(), KWin::displayHeight());
}
int WorkspaceWrapper::displayWidth() const
{
return KWin::displayWidth();
}
int WorkspaceWrapper::displayHeight() const
{
return KWin::displayHeight();
}
QRect WorkspaceWrapper::clientArea(ClientAreaOption option, const QPoint &p, int desktop) const
{
return Workspace::self()->clientArea(static_cast<clientAreaOption>(option), p, desktop);
}
QRect WorkspaceWrapper::clientArea(ClientAreaOption option, const KWin::Client *c) const
{
return Workspace::self()->clientArea(static_cast<clientAreaOption>(option), c);
}
QRect WorkspaceWrapper::clientArea(ClientAreaOption option, int screen, int desktop) const
{
return Workspace::self()->clientArea(static_cast<clientAreaOption>(option), screen, desktop);
}
QString WorkspaceWrapper::desktopName(int desktop) const
{
return VirtualDesktopManager::self()->name(desktop);
}
QString WorkspaceWrapper::supportInformation() const
{
return Workspace::self()->supportInformation();
}
void WorkspaceWrapper::setupClientConnections(KWin::Client *client)
{
connect(client, SIGNAL(clientMinimized(KWin::Client*,bool)), SIGNAL(clientMinimized(KWin::Client*)));
connect(client, SIGNAL(clientUnminimized(KWin::Client*,bool)), SIGNAL(clientUnminimized(KWin::Client*)));
connect(client, SIGNAL(clientManaging(KWin::Client*)), SIGNAL(clientManaging(KWin::Client*)));
connect(client, SIGNAL(clientFullScreenSet(KWin::Client*,bool,bool)), SIGNAL(clientFullScreenSet(KWin::Client*,bool,bool)));
connect(client, SIGNAL(clientMaximizedStateChanged(KWin::Client*,bool,bool)), SIGNAL(clientMaximizeSet(KWin::Client*,bool,bool)));
}
void WorkspaceWrapper::showOutline(const QRect &geometry)
{
outline()->show(geometry);
}
void WorkspaceWrapper::showOutline(int x, int y, int width, int height)
{
outline()->show(QRect(x, y, width, height));
}
void WorkspaceWrapper::hideOutline()
{
outline()->hide();
}
Client *WorkspaceWrapper::getClient(qulonglong windowId)
{
return Workspace::self()->findClient(WindowMatchPredicate(windowId));
}
QSize WorkspaceWrapper::desktopGridSize() const
{
return VirtualDesktopManager::self()->grid().size();
}
int WorkspaceWrapper::desktopGridWidth() const
{
return desktopGridSize().width();
}
int WorkspaceWrapper::desktopGridHeight() const
{
return desktopGridSize().height();
}
int WorkspaceWrapper::workspaceHeight() const
{
return desktopGridHeight() * displayHeight();
}
int WorkspaceWrapper::workspaceWidth() const
{
return desktopGridWidth() * displayWidth();
}
int WorkspaceWrapper::numScreens() const
{
return screens()->count();
}
int WorkspaceWrapper::activeScreen() const
{
return screens()->current();
}
} // KWin

View file

@ -1,322 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2010 Rohan Prabhu <rohan@rohanprabhu.com>
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_SCRIPTING_WORKSPACE_WRAPPER_H
#define KWIN_SCRIPTING_WORKSPACE_WRAPPER_H
#include <QObject>
#include <QSize>
#include <QStringList>
#include <QRect>
#include <kwinglobals.h>
namespace KWin
{
// forward declarations
class Client;
class WorkspaceWrapper : public QObject
{
Q_OBJECT
Q_ENUMS(ClientAreaOption)
Q_ENUMS(ElectricBorder)
Q_PROPERTY(int currentDesktop READ currentDesktop WRITE setCurrentDesktop NOTIFY currentDesktopChanged)
Q_PROPERTY(KWin::Client *activeClient READ activeClient WRITE setActiveClient NOTIFY clientActivated)
// TODO: write and notify?
Q_PROPERTY(QSize desktopGridSize READ desktopGridSize NOTIFY desktopLayoutChanged)
Q_PROPERTY(int desktopGridWidth READ desktopGridWidth NOTIFY desktopLayoutChanged)
Q_PROPERTY(int desktopGridHeight READ desktopGridHeight NOTIFY desktopLayoutChanged)
Q_PROPERTY(int workspaceWidth READ workspaceWidth)
Q_PROPERTY(int workspaceHeight READ workspaceHeight)
Q_PROPERTY(QSize workspaceSize READ workspaceSize)
/**
* The number of desktops currently used. Minimum number of desktops is 1, maximum 20.
**/
Q_PROPERTY(int desktops READ numberOfDesktops WRITE setNumberOfDesktops NOTIFY numberDesktopsChanged)
/**
* The same of the display, that is all screens.
**/
Q_PROPERTY(QSize displaySize READ displaySize)
/**
* The width of the display, that is width of all combined screens.
**/
Q_PROPERTY(int displayWidth READ displayWidth)
/**
* The height of the display, that is height of all combined screens.
**/
Q_PROPERTY(int displayHeight READ displayHeight)
Q_PROPERTY(int activeScreen READ activeScreen)
Q_PROPERTY(int numScreens READ numScreens NOTIFY numberScreensChanged)
Q_PROPERTY(QString currentActivity READ currentActivity NOTIFY currentActivityChanged)
Q_PROPERTY(QStringList activities READ activityList NOTIFY activitiesChanged)
private:
Q_DISABLE_COPY(WorkspaceWrapper)
signals:
void desktopPresenceChanged(KWin::Client *client, int desktop);
void currentDesktopChanged(int desktop, KWin::Client *client);
void clientAdded(KWin::Client *client);
void clientRemoved(KWin::Client *client);
void clientManaging(KWin::Client *client);
void clientMinimized(KWin::Client *client);
void clientUnminimized(KWin::Client *client);
void clientRestored(KWin::Client *client);
void clientMaximizeSet(KWin::Client *client, bool h, bool v);
void killWindowCalled(KWin::Client *client);
void clientActivated(KWin::Client *client);
void clientFullScreenSet(KWin::Client *client, bool fullScreen, bool user);
void clientSetKeepAbove(KWin::Client *client, bool keepAbove);
/**
* Signal emitted whenever the number of desktops changed.
* To get the current number of desktops use the property desktops.
* @param oldNumberOfDesktops The previous number of desktops.
**/
void numberDesktopsChanged(uint oldNumberOfDesktops);
/**
* Signal emitted whenever the layout of virtual desktops changed.
* That is desktopGrid(Size/Width/Height) will have new values.
* @since 4.11
**/
void desktopLayoutChanged();
/**
* The demands attention state for Client @p c changed to @p set.
* @param c The Client for which demands attention changed
* @param set New value of demands attention
**/
void clientDemandsAttentionChanged(KWin::Client *client, bool set);
/**
* Signal emitted when the number of screens changes.
* @param count The new number of screens
**/
void numberScreensChanged(int count);
/**
* This signal is emitted when the size of @p screen changes.
* Don't forget to fetch an updated client area.
**/
void screenResized(int screen);
/**
* Signal emitted whenever the current activity changed.
* @param id id of the new activity
**/
void currentActivityChanged(const QString &id);
/**
* Signal emitted whenever the list of activities changed.
* @param id id of the new activity
**/
void activitiesChanged(const QString &id);
/**
* This signal is emitted when a new activity is added
* @param id id of the new activity
*/
void activityAdded(const QString &id);
/**
* This signal is emitted when the activity
* is removed
* @param id id of the removed activity
*/
void activityRemoved(const QString &id);
public:
//------------------------------------------------------------------
//enums copy&pasted from kwinglobals.h because qtscript is evil
enum ClientAreaOption {
///< geometry where a window will be initially placed after being mapped
PlacementArea,
///< window movement snapping area? ignore struts
MovementArea,
///< geometry to which a window will be maximized
MaximizeArea,
///< like MaximizeArea, but ignore struts - used e.g. for topmenu
MaximizeFullArea,
///< area for fullscreen windows
FullScreenArea,
///< whole workarea (all screens together)
WorkArea,
///< whole area (all screens together), ignore struts
FullArea,
///< one whole screen, ignore struts
ScreenArea
};
enum ElectricBorder {
ElectricTop,
ElectricTopRight,
ElectricRight,
ElectricBottomRight,
ElectricBottom,
ElectricBottomLeft,
ElectricLeft,
ElectricTopLeft,
ELECTRIC_COUNT,
ElectricNone
};
explicit WorkspaceWrapper(QObject* parent = 0);
#define GETTERSETTERDEF( rettype, getter, setter ) \
rettype getter() const; \
void setter( rettype val );
GETTERSETTERDEF(int, numberOfDesktops, setNumberOfDesktops)
GETTERSETTERDEF(int, currentDesktop, setCurrentDesktop)
GETTERSETTERDEF(KWin::Client*, activeClient, setActiveClient)
#undef GETTERSETTERDEF
QSize desktopGridSize() const;
int desktopGridWidth() const;
int desktopGridHeight() const;
int workspaceWidth() const;
int workspaceHeight() const;
QSize workspaceSize() const;
int displayWidth() const;
int displayHeight() const;
QSize displaySize() const;
int activeScreen() const;
int numScreens() const;
QString currentActivity() const;
QStringList activityList() const;
/**
* List of Clients currently managed by KWin.
**/
Q_INVOKABLE QList< KWin::Client* > clientList() const;
/**
* Returns the geometry a Client can use with the specified option.
* This method should be preferred over other methods providing screen sizes as the
* various options take constraints such as struts set on panels into account.
* This method is also multi screen aware, but there are also options to get full areas.
* @param option The type of area which should be considered
* @param screen The screen for which the area should be considered
* @param desktop The desktop for which the area should be considered, in general there should not be a difference
* @returns The specified screen geometry
**/
Q_SCRIPTABLE QRect clientArea(ClientAreaOption option, int screen, int desktop) const;
/**
* Overloaded method for convenience.
* @param option The type of area which should be considered
* @param point The coordinates which have to be included in the area
* @param desktop The desktop for which the area should be considered, in general there should not be a difference
* @returns The specified screen geometry
**/
Q_SCRIPTABLE QRect clientArea(ClientAreaOption option, const QPoint& point, int desktop) const;
/**
* Overloaded method for convenience.
* @param client The Client for which the area should be retrieved
* @returns The specified screen geometry
**/
Q_SCRIPTABLE QRect clientArea(ClientAreaOption option, const KWin::Client* client) const;
/**
* Returns the name for the given @p desktop.
**/
Q_SCRIPTABLE QString desktopName(int desktop) const;
/**
* Provides support information about the currently running KWin instance.
**/
Q_SCRIPTABLE QString supportInformation() const;
/**
* Finds the Client with the given @p windowId.
* @param windowId The window Id of the Client
* @return The found Client or @c null
**/
Q_SCRIPTABLE KWin::Client *getClient(qulonglong windowId);
public Q_SLOTS:
// all the available key bindings
void slotSwitchDesktopNext();
void slotSwitchDesktopPrevious();
void slotSwitchDesktopRight();
void slotSwitchDesktopLeft();
void slotSwitchDesktopUp();
void slotSwitchDesktopDown();
void slotSwitchToNextScreen();
void slotWindowToNextScreen();
void slotToggleShowDesktop();
void slotWindowMaximize();
void slotWindowMaximizeVertical();
void slotWindowMaximizeHorizontal();
void slotWindowMinimize();
void slotWindowShade();
void slotWindowRaise();
void slotWindowLower();
void slotWindowRaiseOrLower();
void slotActivateAttentionWindow();
void slotWindowPackLeft();
void slotWindowPackRight();
void slotWindowPackUp();
void slotWindowPackDown();
void slotWindowGrowHorizontal();
void slotWindowGrowVertical();
void slotWindowShrinkHorizontal();
void slotWindowShrinkVertical();
void slotWindowQuickTileLeft();
void slotWindowQuickTileRight();
void slotWindowQuickTileTopLeft();
void slotWindowQuickTileTopRight();
void slotWindowQuickTileBottomLeft();
void slotWindowQuickTileBottomRight();
void slotSwitchWindowUp();
void slotSwitchWindowDown();
void slotSwitchWindowRight();
void slotSwitchWindowLeft();
void slotIncreaseWindowOpacity();
void slotLowerWindowOpacity();
void slotWindowOperations();
void slotWindowClose();
void slotWindowMove();
void slotWindowResize();
void slotWindowAbove();
void slotWindowBelow();
void slotWindowOnAllDesktops();
void slotWindowFullScreen();
void slotWindowNoBorder();
void slotWindowToNextDesktop();
void slotWindowToPreviousDesktop();
void slotWindowToDesktopRight();
void slotWindowToDesktopLeft();
void slotWindowToDesktopUp();
void slotWindowToDesktopDown();
/**
* Shows an outline at the specified @p geometry.
* If an outline is already shown the outline is moved to the new position.
* Use @link hideOutline to remove the outline again.
**/
void showOutline(const QRect &geometry);
/**
* Overloaded method for convenience.
**/
void showOutline(int x, int y, int width, int height);
/**
* Hides the outline previously shown by @link showOutline.
**/
void hideOutline();
private Q_SLOTS:
void setupClientConnections(KWin::Client* client);
};
}
#endif

View file

@ -1,9 +0,0 @@
# packages
install( DIRECTORY videowall DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/scripts )
install( DIRECTORY synchronizeskipswitcher DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/scripts )
install( DIRECTORY desktopchangeosd DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/scripts )
# service files
install( FILES videowall/metadata.desktop DESTINATION ${SERVICES_INSTALL_DIR} RENAME kwin-script-videowall.desktop )
install( FILES synchronizeskipswitcher/metadata.desktop DESTINATION ${SERVICES_INSTALL_DIR} RENAME kwin-script-synchronizeskipswitcher.desktop )
install( FILES desktopchangeosd/metadata.desktop DESTINATION ${SERVICES_INSTALL_DIR} RENAME kwin-script-desktopchangeosd.desktop )

View file

@ -1,4 +0,0 @@
#!/bin/bash
$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp
$XGETTEXT `find . -name \*.qml -o -name \*.cpp` -o $podir/kwin_scripts.pot
rm -f rc.cpp

View file

@ -1,37 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
import QtQuick 1.1;
Item {
id: root
Loader {
id: mainItemLoader
}
Connections {
target: workspace
onCurrentDesktopChanged: {
if (!mainItemLoader.item) {
mainItemLoader.source = "osd.qml";
}
}
}
}

View file

@ -1,297 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2012, 2013 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
import QtQuick 1.1;
import org.kde.plasma.core 0.1 as PlasmaCore;
import org.kde.plasma.components 0.1 as Plasma;
import org.kde.qtextracomponents 0.1 as QtExtra;
import org.kde.kwin 0.1;
PlasmaCore.Dialog {
id: dialog
visible: false
windowFlags: Qt.X11BypassWindowManagerHint
mainItem: Item {
function loadConfig() {
dialogItem.animationDuration = readConfig("PopupHideDelay", 1000);
if (readConfig("TextOnly", "false") == "true") {
dialogItem.showGrid = false;
} else {
dialogItem.showGrid = true;
}
}
function show() {
if (dialogItem.currentDesktop == workspace.currentDesktop - 1) {
return;
}
dialog.visible = true;
dialogItem.previousDesktop = dialogItem.currentDesktop;
timer.stop();
dialogItem.currentDesktop = workspace.currentDesktop - 1;
textElement.text = workspace.desktopName(workspace.currentDesktop);
// screen geometry might have changed
var screen = workspace.clientArea(KWin.FullScreenArea, workspace.activeScreen, workspace.currentDesktop);
dialogItem.screenWidth = screen.width;
dialogItem.screenHeight = screen.height;
if (dialogItem.showGrid) {
// non dependable properties might have changed
view.columns = workspace.desktopGridWidth;
view.rows = workspace.desktopGridHeight;
}
// position might have changed
dialog.x = screen.x + screen.width/2 - dialogItem.width/2;
dialog.y = screen.y + screen.height/2 - dialogItem.height/2;
// start the hide timer
timer.start();
}
id: dialogItem
property int screenWidth: 0
property int screenHeight: 0
// we count desktops starting from 0 to have it better match the layout in the Grid
property int currentDesktop: 0
property int previousDesktop: 0
property int animationDuration: 1000
property bool showGrid: true
width: dialogItem.showGrid ? view.itemWidth * view.columns : textElement.width
height: dialogItem.showGrid ? view.itemHeight * view.rows + textElement.height : textElement.height
Plasma.Label {
id: textElement
anchors.top: dialogItem.showGrid ? parent.top : undefined
anchors.horizontalCenter: parent.horizontalCenter
text: workspace.desktopName(workspace.currentDesktop)
}
Grid {
id: view
columns: 1
rows: 1
property int itemWidth: dialogItem.screenWidth * Math.min(0.8/columns, 0.1)
property int itemHeight: Math.min(itemWidth * (dialogItem.screenHeight / dialogItem.screenWidth), dialogItem.screenHeight * Math.min(0.8/rows, 0.1))
anchors {
top: textElement.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
visible: dialogItem.showGrid
Repeater {
id: repeater
model: workspace.desktops
Item {
width: view.itemWidth
height: view.itemHeight
PlasmaCore.FrameSvgItem {
anchors.fill: parent
imagePath: "widgets/pager"
prefix: "normal"
}
PlasmaCore.FrameSvgItem {
id: activeElement
anchors.fill: parent
imagePath: "widgets/pager"
prefix: "active"
opacity: 0.0
Behavior on opacity {
NumberAnimation { duration: dialogItem.animationDuration/2 }
}
}
Item {
id: arrowsContainer
anchors.fill: parent
QtExtra.QIconItem {
anchors.fill: parent
icon: "go-up"
visible: false
}
QtExtra.QIconItem {
anchors.fill: parent
icon: "go-down"
visible: {
if (dialogItem.currentDesktop <= index) {
// don't show for target desktop
return false;
}
if (index < dialogItem.previousDesktop) {
return false;
}
if (dialogItem.currentDesktop < dialogItem.previousDesktop) {
// we only go down if the new desktop is higher
return false;
}
if (Math.floor(dialogItem.currentDesktop/view.columns) == Math.floor(index/view.columns)) {
// don't show icons in same row as target desktop
return false;
}
if (dialogItem.previousDesktop % view.columns == index % view.columns) {
// show arrows for icons in same column as the previous desktop
return true;
}
return false;
}
}
QtExtra.QIconItem {
anchors.fill: parent
icon: "go-up"
visible: {
if (dialogItem.currentDesktop >= index) {
// don't show for target desktop
return false;
}
if (index > dialogItem.previousDesktop) {
return false;
}
if (dialogItem.currentDesktop > dialogItem.previousDesktop) {
// we only go down if the new desktop is higher
return false;
}
if (Math.floor(dialogItem.currentDesktop/view.columns) == Math.floor(index/view.columns)) {
// don't show icons in same row as target desktop
return false;
}
if (dialogItem.previousDesktop % view.columns == index % view.columns) {
// show arrows for icons in same column as the previous desktop
return true;
}
return false;
}
}
QtExtra.QIconItem {
anchors.fill: parent
icon: "go-next"
visible: {
if (dialogItem.currentDesktop <= index) {
// we don't show for desktops not on the path
return false;
}
if (index < dialogItem.previousDesktop) {
// we might have to show this icon in case we go up and to the right
if (Math.floor(dialogItem.currentDesktop/view.columns) == Math.floor(index/view.columns)) {
// can only happen in same row
if (index % view.columns >= dialogItem.previousDesktop % view.columns) {
// but only for items in the same column or after of the previous desktop
return true;
}
}
return false;
}
if (dialogItem.currentDesktop < dialogItem.previousDesktop) {
// we only go right if the new desktop is higher
return false;
}
if (Math.floor(dialogItem.currentDesktop/view.columns) == Math.floor(index/view.columns)) {
// show icons in same row as target desktop
if (index % view.columns < dialogItem.previousDesktop % view.columns) {
// but only for items in the same column or after of the previous desktop
return false;
}
return true;
}
return false;
}
}
QtExtra.QIconItem {
anchors.fill: parent
icon: "go-previous"
visible: {
if (dialogItem.currentDesktop >= index) {
// we don't show for desktops not on the path
return false;
}
if (index > dialogItem.previousDesktop) {
// we might have to show this icon in case we go down and to the left
if (Math.floor(dialogItem.currentDesktop/view.columns) == Math.floor(index/view.columns)) {
// can only happen in same row
if (index % view.columns <= dialogItem.previousDesktop % view.columns) {
// but only for items in the same column or before the previous desktop
return true;
}
}
return false;
}
if (dialogItem.currentDesktop > dialogItem.previousDesktop) {
// we only go left if the new desktop is lower
return false;
}
if (Math.floor(dialogItem.currentDesktop/view.columns) == Math.floor(index/view.columns)) {
// show icons in same row as target desktop
if (index % view.columns > dialogItem.previousDesktop % view.columns) {
// but only for items in the same column or before of the previous desktop
return false;
}
return true;
}
return false;
}
}
}
states: [
State {
name: "NORMAL"
when: index != dialogItem.currentDesktop
PropertyChanges {
target: activeElement
opacity: 0.0
}
},
State {
name: "SELECTED"
when: index == dialogItem.currentDesktop
PropertyChanges {
target: activeElement
opacity: 1.0
}
}
]
Component.onCompleted: {
view.state = (index == dialogItem.currentDesktop) ? "SELECTED" : "NORMAL"
}
}
}
}
Timer {
id: timer
repeat: false
interval: dialogItem.animationDuration
onTriggered: dialog.visible = false
}
Connections {
target: workspace
onCurrentDesktopChanged: dialogItem.show()
onNumberDesktopsChanged: {
repeater.model = workspace.desktops;
}
}
Connections {
target: options
onConfigChanged: dialogItem.loadConfig()
}
Component.onCompleted: {
columns = workspace.desktopGridWidth;
rows = workspace.desktopGridHeight;
dialogItem.loadConfig();
dialogItem.show();
}
}
}

View file

@ -1,105 +0,0 @@
[Desktop Entry]
Name=Desktop Change OSD
Name[bs]=Promjena podloge OSD
Name[ca]=OSD de canvi d'escriptori
Name[ca@valencia]=OSD de canvi d'escriptori
Name[cs]=OSD změny plochy
Name[da]=OSD til skrivebordsskift
Name[de]=OSD-Arbeitsflächenwechsel
Name[el]=OSD αλλαγής επιφάνειας εργασίας
Name[en_GB]=Desktop Change OSD
Name[es]=Información en pantalla sobre cambio de escritorio
Name[et]=Töölaua muutmise ekraaniesitus
Name[eu]=Mahaigain-aldaketari buruzko informazioa OSD
Name[fi]=Työpöydänvaihdon ilmoitus
Name[fr]=OSD pour le changement de bureau
Name[gl]=OSD de cambio de escritorio
Name[he]=תצוגה על המסך של החלפת מסך
Name[hu]=Asztal változtatás OSD
Name[ia]=Modifica OSD de scriptorio
Name[it]=Mostra lo scambia desktop
Name[kk]=Үстел ауыстыру панелі
Name[km]= OSD
Name[ko]= OSD
Name[lt]=Darbastalio pokyčio OSD
Name[mr]= OSD
Name[nb]=OSD for skrivebordsbytte
Name[nds]=Schriefdischwessel-OSD
Name[nl]=OSD voor bureaubladwijziging
Name[pa]= OSD
Name[pl]=OSD zmiany pulpitu
Name[pt]=OSD de Mudança do Ecrã
Name[pt_BR]=OSD de mudança de área de trabalho
Name[ru]=Экранные уведомления об изменении рабочего стола
Name[sk]=OSD zmeny plochy
Name[sl]=Prikaz na zaslonu spremembe namizja
Name[sr]=ОСД мењања површи
Name[sr@ijekavian]=ОСД мењања површи
Name[sr@ijekavianlatin]=OSD menjanja površi
Name[sr@latin]=OSD menjanja površi
Name[sv]=Skärmvisning av skrivbordsändring
Name[tr]=Masaüstü Değiştirme Ekran Bildirimi
Name[uk]=Панель зміни стільниць
Name[x-test]=xxDesktop Change OSDxx
Name[zh_CN]=
Name[zh_TW]=
Comment=An on screen display indicating the desktop change
Comment[bs]=Na zaslonu se ukazuju promjene radne površine
Comment[ca]=En un missatge per pantalla indicant el canvi d'escriptori
Comment[ca@valencia]=En un missatge per pantalla indicant el canvi d'escriptori
Comment[cs]=Displej označující změnu plochy
Comment[da]=Et on-screen-display som indikerer skift af skrivebord
Comment[de]=Ein On-Screen-Display (OSD), das den Wechsel der Arbeitsfläche anzeigt
Comment[el]=Μια ένδειξη στην οθόνη που δηλώνει την αλλαγή της επιφάνειας εργασίας
Comment[en_GB]=An on screen display indicating the desktop change
Comment[es]=Una información en pantalla que indica el cambio de escritorio
Comment[et]=Töölaua muutumist näitab ekraanikuva
Comment[eu]=Mahaigain-aldaketa adierazten duen pantailako informazioa
Comment[fi]=Näytölle ilmestyvä ilmoitus työpöydän vaihdosta
Comment[fr]=Un affichage sur l'écran (OSD) indiquant le changement de bureau
Comment[gl]=Un visor na pantalla que indica o cambio de escritorio
Comment[he]=תצוגת על המסך המודיעה על החלפת שולחן העבודה
Comment[hu]=Egy képernyőn megjelenő kijelzés, amely jelzi az asztal változásait
Comment[ia]=Un monstrator sur le schermo indicante le modification de scriptorio
Comment[it]=Un display sullo schermo che indica il cambio di desktop
Comment[kk]=Үстел ауыстыруын көрсететін экран дисплейі
Comment[km]=
Comment[ko]= OSD
Comment[lt]=Ekrano rodmuo nustatantis darbastalio keitimą
Comment[mr]= ि
Comment[nb]=En tekst på skjermen som viser skrivebordsbytte
Comment[nds]=En Op-Schirm-Dorstellen för't Wesseln vun den Schriefdisch
Comment[nl]=Een on screen display (OSD) die de wijziging van het bureaublad aangeeft
Comment[pa]=
Comment[pl]=Wyświetlacz na ekranie wskazujący zmianę pulpitu
Comment[pt]=Uma apresentação que indica a mudança do ecrã
Comment[pt_BR]=Uma apresentação que indica a mudança de área de trabalho
Comment[ro]=Afișaj pe ecran ce indică schimbarea biroului
Comment[ru]=Экранные уведомления об изменении рабочего стола
Comment[sk]=Displej na obrazovke indikujúci zmenu plochy
Comment[sl]=Prikaz na zaslonu, ki nakazuje spremembo namizja
Comment[sr]=Екрански приказ указује на промену површи
Comment[sr@ijekavian]=Екрански приказ указује на промену површи
Comment[sr@ijekavianlatin]=Ekranski prikaz ukazuje na promenu površi
Comment[sr@latin]=Ekranski prikaz ukazuje na promenu površi
Comment[sv]=En skärmvisning som anger skrivbordsändringen
Comment[tr]=Bir, ekranda beliren bilgi masaüstünün değiştirildiğini gösteriyor
Comment[uk]=Екранна панель спостереження за зміною стільниць
Comment[x-test]=xxAn on screen display indicating the desktop changexx
Comment[zh_CN]=
Comment[zh_TW]=OSD
Icon=preferences-system-windows-script-test
X-Plasma-API=declarativescript
X-Plasma-MainScript=ui/main.qml
X-KWin-Exclude-Listing=true
X-KDE-PluginInfo-Author=Martin Gräßlin
X-KDE-PluginInfo-Email=mgraesslin@kde.org
X-KDE-PluginInfo-Name=desktopchangeosd
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-ServiceTypes=KWin/Script
Type=Service

View file

@ -1,34 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
function synchronizeSwitcher(client) {
client.skipSwitcher = client.skipTaskbar;
}
function setupConnection(client) {
synchronizeSwitcher(client);
client.skipTaskbarChanged.connect(client, synchronizeSwitcher);
}
workspace.clientAdded.connect(setupConnection);
// connect all existing clients
var clients = workspace.clientList();
for (var i=0; i<clients.length; i++) {
setupConnection(clients[i]);
}

View file

@ -1,99 +0,0 @@
[Desktop Entry]
Name=Synchronize Skip Switcher with Taskbar
Name[bs]=Uskladite Skip Switcher s trake
Name[ca]=Sincronitza el «Ignora el commutador» amb la barra de tasques
Name[ca@valencia]=Sincronitza el «Ignora el commutador» amb la barra de tasques
Name[cs]=Synchronizovat přepínač přeskakování s pruhem úloh
Name[da]=Synkronisér skip-skifter med opgavelinjen
Name[de]=Fensterwechsler mit Fensterleiste abgleichen
Name[el]=Συγχρονισμός εναλλάκτη παράβλεψης με τη γραμμή εργασιών
Name[en_GB]=Synchronize Skip Switcher with Taskbar
Name[es]=Sincronizar «Omitir cambiador» con la barra de tareas
Name[et]=Vahelejätmise lülitaja sünkroonimine tegumiribaga
Name[eu]=Sinkronizatu Saltatu kommutadorea ataza-barrarekin
Name[fi]=Synkronoi tehtävävaihdon ohitus tehtäväpalkin kanssa
Name[fr]=Synchroniser le sélecteur de fenêtres à ignorer avec la barre de tâches
Name[gl]=Sincronizar o ignorar o alternador coa barra de tarefas
Name[hu]=Skip-váltó szinkronizálása a feladatsávval
Name[ia]=Synchronisa Commutator de salto con Barra de carga
Name[it]=Sincronizza Salta barra delle applicazioni con la barra delle applicazioni
Name[kk]=Терезе көрсету күйін ауыстырғышты тапсырма панелімен қадамдастыру
Name[km]=
Name[ko]=
Name[mr]= ि
Name[nb]=Synkroniser Hopp over bytter med Oppgavelinja
Name[nds]=Bi't Wesseln övergahn un Programmbalken synkroniseren
Name[nl]=Overslaanschakelaar met taakbalk synchroniseren
Name[pa]= ਿ ਿ
Name[pl]=Synchronizuj pomijanie przełącznika z paskiem zadań
Name[pt]=Sincronizar o 'Ignorar o Selector' com a Barra de Tarefas
Name[pt_BR]=Sincronizar o 'Ignorar seletor' com a barra de tarefas
Name[ru]=Синхронизация переключателя пропусков с панелью задач
Name[sk]=Synchronizovať Preskočiť prepínač s taskbarom
Name[sl]=Uskladi preskok preklapljanja z opravilno vrstico
Name[sr]=Синхронизовано прескакање мењача са траком задатака
Name[sr@ijekavian]=Синхронизовано прескакање мењача са траком задатака
Name[sr@ijekavianlatin]=Sinhronizovano preskakanje menjača sa trakom zadataka
Name[sr@latin]=Sinhronizovano preskakanje menjača sa trakom zadataka
Name[sv]=Synkronisera överhoppning av aktivitetsraden med fönsterbyte
Name[tr]=Görev Çubuğu ile Atlama Seçiciyi Eşzamanla
Name[uk]=Синхронізувати виключення вікон у перемикачі з панеллю задач
Name[x-test]=xxSynchronize Skip Switcher with Taskbarxx
Name[zh_CN]=
Name[zh_TW]=
Comment=Hides all windows marked as Skip Taskbar to be also excluded from window switchers (e.g. Alt+Tab)
Comment[bs]=Skriva sve prozorie označene kao Skip traka da će također biti isključeni iz prebacivanja prozora(npr. Alt + Tab)
Comment[ca]=Oculta totes les finestres marcades com a «Ignora la barra de tasques» que també s'excloguin del commutador de finestres (p. ex. Alt+Tab)
Comment[ca@valencia]=Oculta totes les finestres marcades com a «Ignora la barra de tasques» que també s'excloguin del commutador de finestres (p. ex. Alt+Tab)
Comment[cs]=Skryje všechna okna označená k přeskočení v pruhu úloh také pro přepínače oken (např. Alt+Tab)
Comment[da]=Skjuler alle vinduer der er markeret som "Skip opgavelinje", så de også udelades fra vinduesskiftere (f.eks. Alt+Tab)
Comment[de]=Alle Fenster, die so eingestellt sind, dass sie nicht in der Fensterleiste angezeigt werden, werden ebenfalls aus den Fensterwechslern (z. B. Alt+Tab) ausgeschlossen.
Comment[el]=Αποκρύπτει όλα τα παράθυρα που είναι σημειωμένα ως παράβλεψη γραμμής εργασιών για να αποκλειστούν και από εναλλάκτες παραθύρων (π.χ. Alt+Tab)
Comment[en_GB]=Hides all windows marked as Skip Taskbar to be also excluded from window switchers (e.g. Alt+Tab)
Comment[es]=Oculta todas las ventanas marcadas como «Omitir barra de tareas» para que también sean excluidas de los selectores de ventana (por ejemplo, Alt+Tab)
Comment[et]=Kõigi tegumiribalt väljajäetavaks märgitud akende peitmine, et neid ei kaasataks ka aknavahetajatesse (nt Alt+Tab)
Comment[eu]='Saltatu ataza-barra' gisa markatuta dauden leiho guztiak ezkutatzen ditu leiho-kommutadoretik kanpo ere uzteko (adib., Alt+Tab)
Comment[fi]=Piilottaa kaikki tehtäväpalkin ohittavat ikkunat myös tehtävävaihdosta (esim. Alt+sarkain)
Comment[fr]=Cache toutes les fenêtres marquées comme « À ignorer » dans la barre des tâches pour les exclure du sélecteur de fenêtres (c'est-à-dire « Alt »+ « Tab »)
Comment[gl]=Agocha todas as xanelas que deban ser ignoradas pola barra de tarefas tamén dos alternadores de xanelas (por ex. Alt+Tab)
Comment[hu]=A Skip feladatsávként megjelölt összes ablak elrejtése, kivéve az ablakváltókat (például Alt+Tab)
Comment[ia]=Cela omne fenestras marcate como barra de cargas de salto pro anque esser excludite ex commutatores de fenestra (p.ex.Alt+Tab)
Comment[it]=Nascondi tutte le finestre marcate come Salta barra delle applicazioni che sono escluse anche dallo scambiafinestre (es. Alt+Tab)
Comment[kk]=Көрсетілмейтін деп белгіленген бүкіл терезелерін терезе ауыстырғышында да (мысалы, Alt-Tab дегенде) көрсетпеу
Comment[km]= (. Alt+Tab)
Comment[ko]= (: Alt+Tab)
Comment[mr]=ि ि (. Alt+Tab) ि
Comment[nb]=Skjuler alle vinduer merket med Hopp over Oppgavelinja så de heller ikke blir tatt med i vindusbyttere (f.eks. Alt+TAB)
Comment[nds]=Finstern mit de Instellen, se dukt nich op den Programmbalken op, warrt bi't Finsterwesseln versteken (a.B. bi Alt+Tab)
Comment[nl]=Verbergt alle vensters gemarkeerd als Taakbalkoverslaan om ook te worden uitgesloten van vensterschakelaars (bijv. Alt+Tab)
Comment[pl]=Ukrywa wszystkie okna oznaczone jako "pomiń pasek zadań", tak aby były one wykluczone także z układów przełączania okien (np. Alt+Tab)
Comment[pt]=Esconde todas as janelas marcadas como 'Ignorar a Barra de Tarefas' para também serem excluídas dos selectores de janelas (p.ex., Alt+Tab)
Comment[pt_BR]=Oculta todas as janelas marcadas como 'Ignorar a barra de tarefas' para também serem excluídas dos seletores de janelas (p.ex., Alt+Tab)
Comment[ru]=Скрывает все окна, не показываемые на панели задач, чтобы исключить их также из переключателей окон (например, Alt+Tab)
Comment[sk]=Skryje všetky okná označené ako Preskočiť taskbar na ich vylúčenie z prepínačov okien (napr. Alt+Tab)
Comment[sl]=Vsa okna, ki so označena z »Preskoči opravilno vrstico«, bodo izločena tudi iz preklapljanja med okni (npr. z Alt+Tab)
Comment[sr]=Прозори са задатим скривањем на траци задатака такође бивају прескакани у мењачима прозора (нпр. на Alt-Tab)
Comment[sr@ijekavian]=Прозори са задатим скривањем на траци задатака такође бивају прескакани у мењачима прозора (нпр. на Alt-Tab)
Comment[sr@ijekavianlatin]=Prozori sa zadatim skrivanjem na traci zadataka takođe bivaju preskakani u menjačima prozora (npr. na Alt-Tab)
Comment[sr@latin]=Prozori sa zadatim skrivanjem na traci zadataka takođe bivaju preskakani u menjačima prozora (npr. na Alt-Tab)
Comment[sv]=Dölj alla fönster som är markerade att hoppa över aktivitetsraden så att de också utesluts vid fönsterbyte (t.ex. Alt+Tabulator)
Comment[tr]=Görev Çubuğunu Atla olarak seçilen tüm pencereleri gizler, ayrıca pencere seçiciler tarafından hariç tutulanları da gizler (Alt+Tab gibi)
Comment[uk]=Приховує всі вікна, позначені як такі, що не показуються на панелі задач, так, щоб їх не було показано у списках перемикання вікон (наприклад Alt+Tab)
Comment[vi]=n tt c ca s đưc đánh du "B qua trên thanh tác v" khi trình chuyn đi ca s (VD: Alt+Tab)
Comment[x-test]=xxHides all windows marked as Skip Taskbar to be also excluded from window switchers (e.g. Alt+Tab)xx
Comment[zh_CN]= (Alt+Tab)
Comment[zh_TW]= Alt+Tab
Icon=preferences-system-windows-script-synchronizeskipswitcher
X-Plasma-API=javascript
X-Plasma-MainScript=code/main.js
X-KDE-PluginInfo-Author=Martin Gräßlin
X-KDE-PluginInfo-Email=mgraesslin@kde.org
X-KDE-PluginInfo-Name=synchronizeskipswitcher
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-ServiceTypes=KWin/Script
Type=Service

View file

@ -1,45 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
function isVideoPlayer(client) {
if (client.resourceName == "vlc") {
return true;
}
if (client.resourceName == "smplayer") {
return true;
}
if (client.resourceName == "dragon") {
return true;
}
if (client.resourceName == "xv") { //mplayer
return true;
}
if (client.resourceName == "ffplay") {
return true;
}
return false;
}
var videowall = function(client, set) {
if (isVideoPlayer(client) && set) {
client.geometry = workspace.clientArea(KWin.FullArea, 0, 1);
}
};
workspace.clientFullScreenSet.connect(videowall);

View file

@ -1,102 +0,0 @@
[Desktop Entry]
Name=Video Wall
Name[bs]=Video zid
Name[ca]=Mur de vídeo
Name[ca@valencia]=Mur de vídeo
Name[cs]=Video stěna
Name[da]=Videovæg
Name[de]=Video-Wand
Name[el]=Τοίχος με οθόνες
Name[en_GB]=Video Wall
Name[es]=Panel de vídeo
Name[et]=Videosein
Name[eu]=Bideo-horma
Name[fi]=Videoseinä
Name[fr]=Mur de vidéos
Name[ga]=Balla Físe
Name[gl]=Parede de vídeo
Name[he]=חלון וידאו
Name[hu]=Videófal
Name[ia]=Muro de Video
Name[it]=Parete video
Name[kk]=Бейне қабырға
Name[km]=
Name[ko]=
Name[lt]=Video siena
Name[mr]=ि ि
Name[nb]=Videovegg
Name[nds]=Videowand
Name[nl]=Videomuur
Name[pa]=ਿ
Name[pl]=Ściana wideo
Name[pt]=Painel de Vídeo
Name[pt_BR]=Painel de vídeo
Name[ro]=Perete video
Name[ru]=Видеостена
Name[sk]=Video stena
Name[sl]=Video zid
Name[sr]=Видео зид
Name[sr@ijekavian]=Видео зид
Name[sr@ijekavianlatin]=Video zid
Name[sr@latin]=Video zid
Name[sv]=Videovägg
Name[tr]=Video Duvarı
Name[uk]=Відеостіна
Name[x-test]=xxVideo Wallxx
Name[zh_CN]=
Name[zh_TW]=
Comment=Spans fullscreen video player over all attached screens to create a Video Wall
Comment[bs]=Proteže punog zaslona gledanje videa nad svim priloženim ekranima stvoriti video zidu
Comment[ca]=Expandeix el reproductor de vídeo a pantalla completa per totes les pantalles enganxades per crear un mur de vídeo.
Comment[ca@valencia]=Expandeix el reproductor de vídeo a pantalla completa per totes les pantalles enganxades per crear un mur de vídeo.
Comment[da]=Udfolder videoafspiller i fuldskærm over alle tilsluttede skærme og danner derved en videovæg
Comment[de]=Erweitert einen Videospieler im Vollbildmodus über alle Bildschirme, um eine Video-Wand zu erzeugen
Comment[el]=Απλώνει πλήρη οθόνη για το πρόγραμμα αναπαραγωγής βίντεο σε όλες τις προσαρτημένες οθόνες για να δημιουργήσει ένα Video Wall
Comment[en_GB]=Spans fullscreen video player over all attached screens to create a Video Wall
Comment[es]=Extiende el reproductor de vídeo a pantalla completa sobre todas las pantallas conectadas para crear un panel de vídeo
Comment[et]=Täisekraan-videomängija laiendamine kõigile ühendatud ekraanile videoseina loomiseks
Comment[eu]=Bideo-jotzailea pantaila osoaren moduan erantsitako pantaila guztietan zabaltzen du bideo-horma bat sortzeko.
Comment[fi]=Levittää koko näytön tilassa olevan videotoistimen kaikkiin yhdistettyihin näyttöihin luoden videoseinän
Comment[fr]=Étend le lecteur vidéo en mode plein écran sur l'ensemble des écrans connectés afin de créer un mur de vidéos
Comment[gl]=Estende un reprodutor de vídeo a pantalla completa por todas as pantallas anexas para crear unha parede de vídeo
Comment[he]=מפעיל נגן וידאו במסך מלא על כל המסכים המחוברים ליצירה של קיר וידאו
Comment[hu]=Kiterjeszti a teljes képernyős videólejátszót az összes csatolt kijelzőre, hogy videófalat hozzon létre
Comment[ia]=Extende jocator de video de schermo plen super omne schermos attachate pro crea un Muro de Video
Comment[it]=Distribuisci il lettore video a schermo pieno su tutti gli schermi per creare una parete video
Comment[kk]=Видеоплейердің суретін бейне қабырғаны құратын экрандарға жайып көрсету
Comment[km]=
Comment[ko]=
Comment[mr]= ि ि ि ि
Comment[nb]=Sprer fullskjerms videospiller over alle tilkoblede skjermer for å lage en Videovegg
Comment[nds]=Wiest Videos in Heelschirmbedrief över all tokoppelt Schirmen, so dat en Videowand dor bi rutkummt
Comment[nl]=Verdeelt de videospeler in modus volledig scherm over alle aangesloten schermen om een Videomuur te creëren
Comment[pl]=Rozciąga pełnoekranowy odtwarzacz filmów na wszystkie podłączone ekrany, tworząc ścianę wideo
Comment[pt]=Espalha o leitor de vídeo em todos os ecrãs ligados para criar um painel de vídeo
Comment[pt_BR]=Espalha o reprodutor de vídeo em tela cheia sobre todas as telas ligadas para criar um painel de vídeo
Comment[ru]=Поверх всех прикреплённых экранов открывается видео проигрыватель для создания видео стены
Comment[sk]=Roztiahne na celú obrazovku video prehrávač cez všetky pripojené obrazovky na vytvorenie video steny
Comment[sl]=Celozaslonski predvajalnik videov bo razprostrt prek vseh priklopljenih zaslonov in tako ustvaril video zid
Comment[sr]=Видео плејер преко целог екрана бива проширен на све прикључене екране, стварајући видео зид
Comment[sr@ijekavian]=Видео плејер преко целог екрана бива проширен на све прикључене екране, стварајући видео зид
Comment[sr@ijekavianlatin]=Video plejer preko celog ekrana biva proširen na sve priključene ekrane, stvarajući video zid
Comment[sr@latin]=Video plejer preko celog ekrana biva proširen na sve priključene ekrane, stvarajući video zid
Comment[sv]=Utökar en videospelare med fullskärm över alla anslutna bildskärmar för att skapa en videovägg
Comment[tr]=Bir Video Duvarı oluşturmak için tüm ekranlara iliştirilen tam ekran video oynatıcıları koparır
Comment[uk]=Розподіл зображення відеопрогравача у повноекранному режимі на всі екрани з метою створення відеостіни
Comment[x-test]=xxSpans fullscreen video player over all attached screens to create a Video Wallxx
Comment[zh_CN]=
Comment[zh_TW]=
Icon=preferences-system-windows-script-test
X-Plasma-API=javascript
X-Plasma-MainScript=code/main.js
X-KDE-PluginInfo-Author=Martin Gräßlin
X-KDE-PluginInfo-Email=mgraesslin@kde.org
X-KDE-PluginInfo-Name=videowall
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-ServiceTypes=KWin/Script
Type=Service