You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
355 lines
12 KiB
355 lines
12 KiB
/******************************************************************** |
|
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 "chelate.h" |
|
#include "meta.h" |
|
|
|
QList<KWin::Chelate::ChelateProxy*> KWin::Chelate::ChelateProxy::chMap; |
|
|
|
/** |
|
* ChelateProxy | functions |
|
*/ |
|
|
|
KWin::Chelate::ChelateProxy::ChelateProxy() |
|
{ |
|
engine = 0; |
|
} |
|
|
|
void KWin::Chelate::ChelateProxy::setEngine(QScriptEngine* _engine) |
|
{ |
|
engine = _engine; |
|
} |
|
|
|
void KWin::Chelate::ChelateProxy::setConnectors(QScriptValueList _connectors) |
|
{ |
|
connectors = _connectors; |
|
} |
|
|
|
void KWin::Chelate::ChelateProxy::setAction(QScriptValue _action) |
|
{ |
|
action = _action; |
|
} |
|
|
|
void KWin::Chelate::ChelateProxy::setEventStrings(QStringList _on) |
|
{ |
|
on = _on; |
|
} |
|
|
|
void KWin::Chelate::ChelateProxy::setFilter(QScriptValue _filter) |
|
{ |
|
filter = _filter; |
|
} |
|
|
|
void KWin::Chelate::ChelateProxy::setId(int _id) |
|
{ |
|
id = _id; |
|
} |
|
|
|
QScriptValue KWin::Chelate::ChelateProxy::getAction() |
|
{ |
|
return action; |
|
} |
|
|
|
QScriptValue KWin::Chelate::ChelateProxy::getFilter() |
|
{ |
|
return filter; |
|
} |
|
|
|
void KWin::Chelate::ChelateProxy::process(int index) |
|
{ |
|
if (engine == 0) { |
|
return; |
|
} |
|
|
|
QScriptValue connector = connectors.at(index).property("connect"); |
|
QScriptValue _scanner = engine->newFunction(KWin::Chelate::scanner, 0); |
|
_scanner.setData(engine->fromScriptValue<int>(id)); |
|
QScriptValueList args; |
|
|
|
args << _scanner; |
|
connector.call(connectors.at(index), args); |
|
} |
|
|
|
void KWin::Chelate::ChelateProxy::processAll() |
|
{ |
|
for (int i = 0; i < connectors.size(); i++) { |
|
process(i); |
|
} |
|
} |
|
/** */ |
|
// END of ChelateProxy | functions |
|
/** */ |
|
|
|
/** |
|
* KWin::Chelate | functions |
|
*/ |
|
|
|
QScriptValue KWin::Chelate::scanner(QScriptContext* ctx, QScriptEngine* eng) |
|
{ |
|
QScriptValue index = (ctx->callee()).data(); |
|
KWin::Chelate::ChelateProxy* proxy = KWin::Chelate::ChelateProxy::chMap.at(index.toNumber()); |
|
QScriptValue filter = proxy->getFilter(); |
|
bool ret = (filter.call(QScriptValue(), ctx->argumentsObject())).toBool(); |
|
|
|
if (ret == true) { |
|
QScriptValue action = proxy->getAction(); |
|
action.call(QScriptValue(), ctx->argumentsObject()); |
|
} |
|
|
|
return eng->undefinedValue(); |
|
} |
|
|
|
QScriptValue KWin::Chelate::rule(QScriptContext* ctx, QScriptEngine* eng) |
|
{ |
|
ChelateProxy* proxy = new ChelateProxy(); |
|
QScriptValue chRule = eng->newObject(); |
|
QScriptValue ruleObj; |
|
|
|
if (ctx->argumentCount() > 0) { |
|
ruleObj = ctx->argument(0); |
|
} else { |
|
return eng->undefinedValue(); |
|
} |
|
|
|
/** |
|
* First, process the events that are to be hooked on to |
|
*/ |
|
if (ruleObj.property("on").isValid() && !ruleObj.property("on").isUndefined()) { |
|
QStringList eventStrings; |
|
QScriptValueList connectors; |
|
QScriptValueIterator it(ruleObj.property("on")); |
|
|
|
while (it.hasNext()) { |
|
it.next(); |
|
QScriptValue connector = (eng->globalObject()).property("workspace").property(it.value().toString()); |
|
|
|
if (connector.isValid() && !connector.isUndefined()) { |
|
eventStrings << it.value().toString(); |
|
connectors << connector; |
|
} |
|
} |
|
|
|
proxy->setConnectors(connectors); |
|
proxy->setEventStrings(eventStrings); |
|
} |
|
|
|
/** |
|
* Then we have our filters.. the most daring part of KWin Scripting yet :) |
|
* Actually this is pretty simple here, but just wait to see |
|
* Chelate LazyLogic (tm) |
|
*/ |
|
if (ruleObj.property("filter").isValid() && !ruleObj.property("filter").isUndefined()) { |
|
QScriptValue filter = ruleObj.property("filter"); |
|
|
|
if (filter.isFunction()) { |
|
proxy->setFilter(filter); |
|
} |
|
} |
|
|
|
if (ruleObj.property("action").isValid() && !ruleObj.property("action").isUndefined()) { |
|
QScriptValue action = ruleObj.property("action"); |
|
|
|
if (action.isFunction()) { |
|
proxy->setAction(action); |
|
} |
|
} |
|
|
|
proxy->setEngine(eng); |
|
proxy->setId(KWin::Chelate::ChelateProxy::chMap.size()); |
|
KWin::Chelate::ChelateProxy::chMap.append(proxy); |
|
proxy->processAll(); |
|
return chRule; |
|
} |
|
|
|
QScriptValue KWin::Chelate::publishChelate(QScriptEngine* eng) |
|
{ |
|
QScriptValue temp = eng->newObject(); |
|
temp.setProperty("rule", eng->newFunction(KWin::Chelate::rule, 1), QScriptValue::Undeletable); |
|
|
|
temp.setProperty("and", KWin::MetaScripting::getLazyLogicFunction(eng, "ll_and"), QScriptValue::Undeletable); |
|
temp.setProperty("or", KWin::MetaScripting::getLazyLogicFunction(eng, "ll_or"), QScriptValue::Undeletable); |
|
temp.setProperty("not", KWin::MetaScripting::getLazyLogicFunction(eng, "ll_not"), QScriptValue::Undeletable); |
|
|
|
temp.setProperty("equiv", eng->newFunction(KWin::Chelate::chelationEquivGen, 0), QScriptValue::Undeletable); |
|
temp.setProperty("regex", eng->newFunction(KWin::Chelate::chelationRegexGen, 0), QScriptValue::Undeletable); |
|
return temp; |
|
} |
|
|
|
/** |
|
* Chelation functions. These functions are used to filter |
|
* the incoming clients. |
|
*/ |
|
|
|
QScriptValue KWin::Chelate::chelationRegex(QScriptContext* ctx, QScriptEngine* eng) |
|
{ |
|
QScriptValue key = ((ctx->callee()).data()).property("key"); |
|
QScriptValue regex = ((ctx->callee()).data()).property("regex"); |
|
QScriptValue post = ((ctx->callee()).data()).property("post"); |
|
QRegExp re(regex.toString()); |
|
|
|
if (!key.isUndefined() && !regex.isUndefined()) { |
|
QScriptValue scCentral = ctx->argument(0); |
|
QScriptValue callBase = scCentral.property(key.toString()); |
|
QString final = (callBase.isFunction()) ? ((callBase.call(scCentral)).toString()) : (callBase.toString()); |
|
int pos = re.indexIn(final); |
|
|
|
if (post.isUndefined()) { |
|
if (pos > -1) { |
|
return eng->toScriptValue<bool>(1); |
|
} else { |
|
return eng->toScriptValue<bool>(0); |
|
} |
|
} else { |
|
QScriptValueList args; |
|
QStringList list = re.capturedTexts(); |
|
args << eng->toScriptValue<QStringList>(re.capturedTexts()); |
|
return eng->toScriptValue<bool>((post.call(QScriptValue(), args)).toBool()); |
|
} |
|
} else { |
|
return eng->toScriptValue<bool>(0); |
|
} |
|
} |
|
|
|
QScriptValue KWin::Chelate::chelationRegexGen(QScriptContext* ctx, QScriptEngine* eng) |
|
{ |
|
QScriptValue func = eng->newFunction(chelationRegex, 0); |
|
QScriptValue data = eng->newObject(); |
|
data.setProperty("key", ctx->argument(0)); |
|
data.setProperty("regex", ctx->argument(1)); |
|
data.setProperty("post", ctx->argument(2)); |
|
func.setData(data); |
|
return func; |
|
} |
|
|
|
QScriptValue KWin::Chelate::chelationEquiv(QScriptContext* ctx, QScriptEngine* eng) |
|
{ |
|
QScriptValue key = ((ctx->callee()).data()).property("key"); |
|
QScriptValue value = ((ctx->callee()).data()).property("value"); |
|
|
|
if (!key.isUndefined() && !value.isUndefined()) { |
|
QScriptValue scCentral = ctx->argument(0); |
|
QScriptValue callBase = scCentral.property(key.toString()); |
|
QString final = (callBase.isFunction()) ? ((callBase.call(scCentral)).toString()) : (callBase.toString()); |
|
|
|
return eng->toScriptValue<bool>(final.compare(value.toString(), Qt::CaseInsensitive) == 0); |
|
} else { |
|
return eng->toScriptValue<bool>(0); |
|
} |
|
} |
|
|
|
QScriptValue KWin::Chelate::chelationEquivGen(QScriptContext* ctx, QScriptEngine* eng) |
|
{ |
|
QScriptValue func = eng->newFunction(chelationEquiv, 0); |
|
QScriptValue data = eng->newObject(); |
|
data.setProperty("key", ctx->argument(0)); |
|
data.setProperty("value", ctx->argument(1)); |
|
func.setData(data); |
|
return func; |
|
} |
|
|
|
QScriptValue KWin::Chelate::chelationCheck(QScriptContext* ctx, QScriptEngine* eng) |
|
{ |
|
Q_UNUSED(eng) |
|
QScriptValue key = ((ctx->callee()).data()).property("key"); |
|
|
|
if (!key.isUndefined()) { |
|
QScriptValue scCentral = ctx->argument(0); |
|
QScriptValue callBase = scCentral.property(key.toString()); |
|
return (callBase.isFunction()) ? ((callBase.call(scCentral)).toBool()) : (callBase.toBool()); |
|
} |
|
|
|
return eng->toScriptValue<bool>(0); |
|
} |
|
|
|
QScriptValue KWin::Chelate::chelationCheckGen(QScriptContext* ctx, QScriptEngine* eng) |
|
{ |
|
QScriptValue func = eng->newFunction(chelationCheck, 0); |
|
QScriptValue data = eng->newObject(); |
|
data.setProperty("key", ctx->argument(0)); |
|
func.setData(data); |
|
return func; |
|
} |
|
|
|
/** */ |
|
/** LazyLogic (tm) */ |
|
/** */ |
|
|
|
QScriptValue KWin::Chelate::lazyLogicGenerate(QScriptContext* ctx, QScriptEngine* eng) |
|
{ |
|
// Assume everything as necessary. If enough or wrong parameters |
|
// are provided, undefined values are used and then the function call |
|
// fails silently (it is non-fatal) |
|
QScriptValue type = (((ctx->callee()).data()).property("lazylogic_type")); |
|
QString typeString = type.toString(); |
|
|
|
if (!((typeString == "ll_and") || (typeString == "ll_or") || (typeString == "ll_not") || (typeString == "ll_xor"))) { |
|
return eng->undefinedValue(); |
|
} |
|
|
|
QScriptValue func = eng->newFunction(KWin::Chelate::lazyLogic, 0); |
|
QScriptValue data = eng->newObject(); |
|
data.setProperty("lazylogic_type", type); |
|
data.setProperty("lazylogic_operands", ctx->argumentsObject()); |
|
func.setData(data); |
|
return func; |
|
} |
|
|
|
QScriptValue KWin::Chelate::lazyLogic(QScriptContext* ctx, QScriptEngine* eng) |
|
{ |
|
bool init; |
|
QString type = (((ctx->callee()).data()).property("lazylogic_type")).toString(); |
|
QScriptValue operands = ((ctx->callee()).data()).property("lazylogic_operands"); |
|
|
|
if (type == "ll_and") { |
|
init = 1; |
|
} else if (type == "ll_or") { |
|
init = 0; |
|
} else if (type == "ll_not") { |
|
QScriptValue current = operands.property("0"); |
|
|
|
return !(current.isFunction()) ? ((current.call(QScriptValue(), ctx->argumentsObject())).toBool()) : (current.toBool()); |
|
} else if (type == "ll_xor") { |
|
QScriptValue _current = operands.property("0"); |
|
QScriptValue current = operands.property("1"); |
|
|
|
return ((current.isFunction()) ? ((current.call(QScriptValue(), ctx->argumentsObject())).toBool()) : current.toBool() ^ |
|
(_current.isFunction()) ? ((_current.call(QScriptValue(), ctx->argumentsObject())).toBool()) : _current.toBool() |
|
); |
|
} else { |
|
return eng->toScriptValue<bool>(0); |
|
} |
|
|
|
for (int i = 0; i < operands.property("length").toNumber(); i++) { |
|
QScriptValue current = operands.property(QString::number(i)); |
|
if (current.isFunction()) { |
|
if (type == "ll_and") { |
|
init = init && (current.isFunction()) ? ((current.call(QScriptValue(), ctx->argumentsObject())).toBool()) : (current.toBool()); |
|
} else if (type == "ll_or") { |
|
init = init || (current.isFunction()) ? ((current.call(QScriptValue(), ctx->argumentsObject())).toBool()) : (current.toBool()); |
|
} |
|
} |
|
} |
|
|
|
return eng->toScriptValue<bool>(init); |
|
} |
|
|
|
/** */ |
|
// END of KWin::Chelate | functions |
|
/** */
|
|
|