2020-08-02 22:22:19 +00:00
|
|
|
/*
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
2012-03-25 07:59:01 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
|
2012-03-25 07:59:01 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2012-03-25 07:59:01 +00:00
|
|
|
|
|
|
|
#ifndef KWIN_SCRIPTINGUTILS_H
|
|
|
|
#define KWIN_SCRIPTINGUTILS_H
|
|
|
|
|
2013-07-10 09:45:51 +00:00
|
|
|
#include "input.h"
|
2012-05-10 14:09:36 +00:00
|
|
|
#include "workspace.h"
|
2013-01-21 08:04:06 +00:00
|
|
|
#include "screenedge.h"
|
2015-07-31 11:24:56 +00:00
|
|
|
#include "scripting_logging.h"
|
2012-05-10 14:09:36 +00:00
|
|
|
|
2014-03-17 15:24:10 +00:00
|
|
|
#include <KGlobalAccel>
|
|
|
|
#include <KLocalizedString>
|
2013-12-10 08:09:35 +00:00
|
|
|
#include <QAction>
|
2012-03-25 07:59:01 +00:00
|
|
|
#include <QtScript/QScriptEngine>
|
|
|
|
|
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
2012-05-06 10:06:10 +00:00
|
|
|
/**
|
|
|
|
* 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
|
2019-07-29 18:58:33 +00:00
|
|
|
*/
|
2012-05-06 10:06:10 +00:00
|
|
|
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
|
2019-07-29 18:58:33 +00:00
|
|
|
*/
|
2012-05-06 10:06:10 +00:00
|
|
|
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
|
2019-07-29 18:58:33 +00:00
|
|
|
*/
|
2012-05-06 10:06:10 +00:00
|
|
|
bool validateParameters(QScriptContext *context, int min, int max);
|
|
|
|
|
2012-03-25 07:59:01 +00:00
|
|
|
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) {
|
2015-07-31 11:24:56 +00:00
|
|
|
qCDebug(KWIN_SCRIPTING) << "Incorrect number of arguments! Expected: title, text, keySequence, callback";
|
2012-03-25 07:59:01 +00:00
|
|
|
return engine->undefinedValue();
|
|
|
|
}
|
2013-12-10 08:09:35 +00:00
|
|
|
QAction* a = new QAction(script);
|
|
|
|
a->setObjectName(context->argument(0).toString());
|
2012-03-25 07:59:01 +00:00
|
|
|
a->setText(context->argument(1).toString());
|
2013-07-10 09:45:51 +00:00
|
|
|
const QKeySequence shortcut = QKeySequence(context->argument(2).toString());
|
|
|
|
KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>() << shortcut);
|
2012-03-25 07:59:01 +00:00
|
|
|
script->registerShortcut(a, context->argument(3));
|
2013-07-10 09:45:51 +00:00
|
|
|
input()->registerShortcut(shortcut, a);
|
2012-03-25 07:59:01 +00:00
|
|
|
return engine->newVariant(true);
|
2012-06-06 22:38:13 +00:00
|
|
|
}
|
2012-03-25 07:59:01 +00:00
|
|
|
|
|
|
|
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());
|
2012-08-31 11:28:31 +00:00
|
|
|
QScriptValueList arguments;
|
|
|
|
arguments << value.engine()->newQObject(a);
|
|
|
|
value.call(QScriptValue(), arguments);
|
2012-06-06 22:38:13 +00:00
|
|
|
}
|
2012-03-25 07:59:01 +00:00
|
|
|
|
2012-05-10 14:09:36 +00:00
|
|
|
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
|
2013-01-25 09:15:00 +00:00
|
|
|
ScreenEdges::self()->reserve(static_cast<KWin::ElectricBorder>(edge), script, "borderActivated");
|
2012-05-10 14:09:36 +00:00
|
|
|
script->screenEdgeCallbacks().insert(edge, QList<QScriptValue>() << context->argument(1));
|
|
|
|
} else {
|
|
|
|
it->append(context->argument(1));
|
|
|
|
}
|
|
|
|
return engine->newVariant(true);
|
2012-06-06 22:38:13 +00:00
|
|
|
}
|
2012-05-10 14:09:36 +00:00
|
|
|
|
2017-04-02 13:42:18 +00:00
|
|
|
template<class T>
|
|
|
|
QScriptValue registerTouchScreenEdge(QScriptContext *context, QScriptEngine *engine)
|
|
|
|
{
|
|
|
|
auto 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 registerTouchScreenEdge needs to be a callback"));
|
|
|
|
}
|
|
|
|
const int edge = context->argument(0).toVariant().toInt();
|
|
|
|
const auto ret = script->registerTouchScreenCallback(edge, context->argument(1));
|
|
|
|
return engine->newVariant(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
QScriptValue unregisterTouchScreenEdge(QScriptContext *context, QScriptEngine *engine)
|
|
|
|
{
|
|
|
|
auto script = qobject_cast<T>(context->callee().data().toQObject());
|
|
|
|
if (!script) {
|
|
|
|
return engine->undefinedValue();
|
|
|
|
}
|
|
|
|
if (!validateParameters(context, 1, 1)) {
|
|
|
|
return engine->undefinedValue();
|
|
|
|
}
|
|
|
|
if (!validateArgumentType<int>(context)) {
|
|
|
|
return engine->undefinedValue();
|
|
|
|
}
|
|
|
|
const int edge = context->argument(0).toVariant().toInt();
|
|
|
|
const auto ret = script->unregisterTouchScreenCallback(edge);
|
|
|
|
return engine->newVariant(ret);
|
|
|
|
}
|
|
|
|
|
2012-05-10 14:09:36 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
2012-06-06 22:38:13 +00:00
|
|
|
}
|
2012-05-10 14:09:36 +00:00
|
|
|
|
2012-03-25 07:59:01 +00:00
|
|
|
inline void registerGlobalShortcutFunction(QObject *parent, QScriptEngine *engine, QScriptEngine::FunctionSignature function)
|
|
|
|
{
|
|
|
|
QScriptValue shortcutFunc = engine->newFunction(function);
|
|
|
|
shortcutFunc.setData(engine->newQObject(parent));
|
2013-07-23 05:02:52 +00:00
|
|
|
engine->globalObject().setProperty(QStringLiteral("registerShortcut"), shortcutFunc);
|
2012-06-06 22:38:13 +00:00
|
|
|
}
|
2012-05-10 14:09:36 +00:00
|
|
|
|
|
|
|
inline void registerScreenEdgeFunction(QObject *parent, QScriptEngine *engine, QScriptEngine::FunctionSignature function)
|
|
|
|
{
|
|
|
|
QScriptValue shortcutFunc = engine->newFunction(function);
|
|
|
|
shortcutFunc.setData(engine->newQObject(parent));
|
2013-07-23 05:02:52 +00:00
|
|
|
engine->globalObject().setProperty(QStringLiteral("registerScreenEdge"), shortcutFunc);
|
2012-06-06 22:38:13 +00:00
|
|
|
}
|
2012-08-31 11:28:31 +00:00
|
|
|
|
2017-04-02 13:42:18 +00:00
|
|
|
inline void registerTouchScreenEdgeFunction(QObject *parent, QScriptEngine *engine, QScriptEngine::FunctionSignature function)
|
|
|
|
{
|
|
|
|
QScriptValue touchScreenFunc = engine->newFunction(function);
|
|
|
|
touchScreenFunc.setData(engine->newQObject(parent));
|
|
|
|
engine->globalObject().setProperty(QStringLiteral("registerTouchScreenEdge"), touchScreenFunc);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void unregisterTouchScreenEdgeFunction(QObject *parent, QScriptEngine *engine, QScriptEngine::FunctionSignature function)
|
|
|
|
{
|
|
|
|
QScriptValue touchScreenFunc = engine->newFunction(function);
|
|
|
|
touchScreenFunc.setData(engine->newQObject(parent));
|
|
|
|
engine->globalObject().setProperty(QStringLiteral("unregisterTouchScreenEdge"), touchScreenFunc);
|
|
|
|
}
|
|
|
|
|
2021-01-24 11:56:42 +00:00
|
|
|
QVariant dbusToVariant(const QVariant &variant);
|
2012-08-31 11:28:31 +00:00
|
|
|
|
2012-03-25 07:59:01 +00:00
|
|
|
} // namespace KWin
|
|
|
|
|
|
|
|
#endif // KWIN_SCRIPTINGUTILS_H
|