mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-23 18:32:50 +00:00
remove kwin scripting support
This commit is contained in:
parent
26551d36f0
commit
cfb6741c02
30 changed files with 0 additions and 5878 deletions
|
@ -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)
|
||||
|
|
|
@ -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} )
|
|
@ -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
|
|
@ -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<quint64></type>
|
||||
<definition>QList<quint64> 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:
|
||||
<syntaxhighlight lang="javascript">
|
||||
{
|
||||
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
|
||||
}
|
||||
]
|
||||
}
|
||||
</syntaxhighlight>
|
||||
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<quint64></type>
|
||||
<definition>QList<quint64> 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<quint64>)</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>
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
|
@ -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]=Tập lệnh 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
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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 )
|
|
@ -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
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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]);
|
||||
}
|
|
@ -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 tất cả cửa sổ được đánh dấu "Bỏ qua trên thanh tác vụ" khỏi trình chuyển đổi cửa 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
|
|
@ -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);
|
|
@ -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
|
Loading…
Add table
Reference in a new issue