From 42dfdb63b03a6beca314f61bd61981dc1724909b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sun, 25 Mar 2012 09:59:01 +0200 Subject: [PATCH] Global Shortcut support for KWin scripts and scripted Effects A global method "registerShortcut" is exported to the scripts which can be used to register a callback to be called when the global shortcut is triggered. The shared code between Scripts and Effects is moved into template functions defined in a new file scriptingutils.h. REVIEW: 104400 --- scripting/scriptedeffect.cpp | 19 +++++++++ scripting/scriptedeffect.h | 6 +++ scripting/scripting.cpp | 19 +++++++++ scripting/scripting.h | 10 +++++ scripting/scriptingutils.h | 74 ++++++++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+) create mode 100644 scripting/scriptingutils.h diff --git a/scripting/scriptedeffect.cpp b/scripting/scriptedeffect.cpp index cc0cf7382f..1fb2c28cf1 100644 --- a/scripting/scriptedeffect.cpp +++ b/scripting/scriptedeffect.cpp @@ -20,6 +20,7 @@ along with this program. If not, see . #include "scriptedeffect.h" #include "meta.h" +#include "scriptingutils.h" // KDE #include #include @@ -77,6 +78,11 @@ QScriptValue kwinEffectDisplayHeight(QScriptContext *context, QScriptEngine *eng return Effect::displayHeight(); } +QScriptValue kwinScriptGlobalShortcut(QScriptContext *context, QScriptEngine *engine) +{ + return globalShortcut(context, engine); +} + QScriptValue effectWindowToScriptValue(QScriptEngine *eng, const KEffectWindowRef &window) { return eng->newQObject(window, QScriptEngine::QtOwnership, @@ -168,6 +174,8 @@ bool ScriptedEffect::init(const QString &effectName, const QString &pathToScript 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); QScriptValue ret = m_engine->evaluate(scriptFile.readAll()); @@ -238,6 +246,17 @@ void ScriptedEffect::reconfigure(ReconfigureFlags flags) 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(this, sender()); +} + QVariant ScriptedEffect::readConfig(const QString &key, const QVariant defaultValue) { KConfigGroup cg = effects->effectConfig(m_effectName); diff --git a/scripting/scriptedeffect.h b/scripting/scriptedeffect.h index b0080bad08..85306d26e6 100644 --- a/scripting/scriptedeffect.h +++ b/scripting/scriptedeffect.h @@ -117,6 +117,10 @@ public: * @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 &shortcutCallbacks() const { + return m_shortcutCallbacks; + } public Q_SLOTS: void animate(KWin::EffectWindow *w, Attribute a, int ms, KWin::FPx2 to, KWin::FPx2 from = KWin::FPx2(), KWin::AnimationData *data = NULL, QEasingCurve curve = QEasingCurve(), int delay = 0); @@ -129,12 +133,14 @@ Q_SIGNALS: 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 m_shortcutCallbacks; }; } diff --git a/scripting/scripting.cpp b/scripting/scripting.cpp index b5b1a2e117..e791183a53 100644 --- a/scripting/scripting.cpp +++ b/scripting/scripting.cpp @@ -22,6 +22,7 @@ along with this program. If not, see . #include "scripting.h" // own #include "meta.h" +#include "scriptingutils.h" #include "workspace_wrapper.h" #include "../client.h" #include "../thumbnailitem.h" @@ -80,6 +81,11 @@ QScriptValue kwinScriptReadConfig(QScriptContext *context, QScriptEngine *engine return engine->newVariant(script->config().readEntry(key, defaultValue)); } +QScriptValue kwinScriptGlobalShortcut(QScriptContext *context, QScriptEngine *engine) +{ + return KWin::globalShortcut(context, engine); +} + KWin::AbstractScript::AbstractScript(int id, QString scriptName, QString pluginName, QObject *parent) : QObject(parent) , m_scriptId(id) @@ -113,6 +119,17 @@ void KWin::AbstractScript::printMessage(const QString &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(this, sender()); +} + void KWin::AbstractScript::installScriptFunctions(QScriptEngine* engine) { // add our print @@ -123,6 +140,8 @@ void KWin::AbstractScript::installScriptFunctions(QScriptEngine* engine) QScriptValue configFunc = engine->newFunction(kwinScriptReadConfig); configFunc.setData(engine->newQObject(this)); engine->globalObject().setProperty("readConfig", configFunc); + // add global Shortcut + registerGlobalShortcutFunction(this, engine, kwinScriptGlobalShortcut); } KWin::Script::Script(int id, QString scriptName, QString pluginName, QObject* parent) diff --git a/scripting/scripting.h b/scripting/scripting.h index 67184b4c60..5fefe87d26 100644 --- a/scripting/scripting.h +++ b/scripting/scripting.h @@ -23,8 +23,10 @@ along with this program. If not, see . #define KWIN_SCRIPTING_H #include +#include #include +class QAction; class QDeclarativeView; class QScriptEngine; class QScriptValue; @@ -48,13 +50,20 @@ public: } void printMessage(const QString &message); + void registerShortcut(QAction *a, QScriptValue callback); KConfigGroup config() const; + const QHash &shortcutCallbacks() const { + return m_shortcutCallbacks; + } public Q_SLOTS: Q_SCRIPTABLE void stop(); Q_SCRIPTABLE virtual void run() = 0; +private Q_SLOTS: + void globalShortcutTriggered(); + Q_SIGNALS: Q_SCRIPTABLE void print(const QString &text); @@ -84,6 +93,7 @@ private: QString m_pluginName; bool m_running; WorkspaceWrapper *m_workspace; + QHash m_shortcutCallbacks; }; class Script : public AbstractScript diff --git a/scripting/scriptingutils.h b/scripting/scriptingutils.h new file mode 100644 index 0000000000..9cc6906418 --- /dev/null +++ b/scripting/scriptingutils.h @@ -0,0 +1,74 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2012 Martin Gräßlin + +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 . +*********************************************************************/ + +#ifndef KWIN_SCRIPTINGUTILS_H +#define KWIN_SCRIPTINGUTILS_H + +#include +#include +#include +#include + +namespace KWin +{ + +template +QScriptValue globalShortcut(QScriptContext *context, QScriptEngine *engine) +{ + T script = qobject_cast(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 +void callGlobalShortcutCallback(T script, QObject *sender) +{ + QAction *a = qobject_cast(sender); + if (!a) { + return; + } + QHash::const_iterator it = script->shortcutCallbacks().find(a); + if (it == script->shortcutCallbacks().end()) { + return; + } + QScriptValue value(it.value()); + value.call(); +}; + +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); +}; +} // namespace KWin + +#endif // KWIN_SCRIPTINGUTILS_H