diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -433,6 +433,7 @@ scripting/scriptingutils.cpp scripting/timer.cpp scripting/scripting_model.cpp + scripting/cursorwrapper.cpp scripting/dbuscall.cpp scripting/screenedgeitem.cpp scripting/scripting_logging.cpp diff --git a/autotests/integration/scripting/CMakeLists.txt b/autotests/integration/scripting/CMakeLists.txt --- a/autotests/integration/scripting/CMakeLists.txt +++ b/autotests/integration/scripting/CMakeLists.txt @@ -1 +1,2 @@ integrationTest(NAME testScriptingScreenEdge SRCS screenedge_test.cpp) +integrationTest(NAME testScriptingCursor SRCS cursor_test.cpp) diff --git a/autotests/integration/scripting/cursor_test.cpp b/autotests/integration/scripting/cursor_test.cpp new file mode 100644 --- /dev/null +++ b/autotests/integration/scripting/cursor_test.cpp @@ -0,0 +1,110 @@ +/******************************************************************** +KWin - the KDE window manager +This file is part of the KDE project. + +Copyright (C) 2016 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 . +*********************************************************************/ +#include "kwin_wayland_test.h" +#include "cursor.h" +#include "effectloader.h" +#include "platform.h" +#include "wayland_server.h" +#include "workspace.h" +#include "scripting/scripting.h" +#include "effect_builtins.h" +#include "workspace.h" + +#include + +using namespace KWin; + +static const QString s_socketName = QStringLiteral("wayland_test_kwin_scripting_cursor-0"); + +class CursorTest : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void initTestCase(); + void init(); + + void testCursor(); +}; + +void CursorTest::initTestCase() +{ + QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); + QVERIFY(workspaceCreatedSpy.isValid()); + kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); + QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); + + // empty config to have defaults + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + + // disable all effects to prevent them grabbing edges + KConfigGroup plugins(config, QStringLiteral("Plugins")); + ScriptedEffectLoader loader; + const auto builtinNames = BuiltInEffects::availableEffectNames() << loader.listOfKnownEffects(); + for (QString name : builtinNames) { + plugins.writeEntry(name + QStringLiteral("Enabled"), false); + } + + config->sync(); + kwinApp()->setConfig(config); + + kwinApp()->start(); + QVERIFY(workspaceCreatedSpy.wait()); + QVERIFY(Scripting::self()); +} + +void CursorTest::init() +{ + KWin::Cursor::setPos(10, 10); + if (workspace()->showingDesktop()) { + workspace()->slotToggleShowDesktop(); + } + QVERIFY(!workspace()->showingDesktop()); +} + + +void CursorTest::testCursor() +{ + const QString scriptToLoad = QFINDTESTDATA("./scripts/cursortest.qml"); + QVERIFY(!scriptToLoad.isEmpty()); + QVERIFY(Scripting::self()->loadDeclarativeScript(scriptToLoad) != -1); + QVERIFY(Scripting::self()->isScriptLoaded(scriptToLoad)); + + auto s = Scripting::self()->findScript(scriptToLoad); + QSignalSpy runningChangedSpy(s, &AbstractScript::runningChanged); + s->run(); + QTRY_COMPARE(runningChangedSpy.count(), 1); + + QSignalSpy showDesktopSpy(workspace(), &Workspace::showingDesktopChanged); + QVERIFY(showDesktopSpy.isValid()); + + //moving the cursor should work, but we don't do anything here + KWin::Cursor::setPos(400, 200); + QVERIFY(!workspace()->showingDesktop()); + + //move mouse to the "magic location" that will make the script toggle desktop + KWin::Cursor::setPos(500, 400); + QVERIFY(workspace()->showingDesktop()); + + //cleanup + workspace()->slotToggleShowDesktop(); +} + +WAYLANDTEST_MAIN(CursorTest) +#include "cursor_test.moc" diff --git a/autotests/integration/scripting/scripts/cursortest.qml b/autotests/integration/scripting/scripts/cursortest.qml new file mode 100644 --- /dev/null +++ b/autotests/integration/scripting/scripts/cursortest.qml @@ -0,0 +1,12 @@ +import QtQuick 2.0; +import org.kde.kwin 2.0; + +Cursor +{ + onXChanged: { + if (x == 500 && y == 400) { + workspace.slotToggleShowDesktop(); + console.log("DAVE DAVE DAVE"); + } + } +} diff --git a/scripting/cursorwrapper.h b/scripting/cursorwrapper.h new file mode 100644 --- /dev/null +++ b/scripting/cursorwrapper.h @@ -0,0 +1,64 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2017 David Edmundson + +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_CURSORWRAPPER_H +#define KWIN_CURSORWRAPPER_H + +#include + +namespace KWin +{ + +/** + * @brief Qml export for providing the current cursor position + * + * Mouse positions under X11 are only tracked when this item is enabled + * It is enabled by default + */ +class CursorWrapper : public QObject +{ + Q_OBJECT + Q_PROPERTY(int x READ x NOTIFY positionChanged) + Q_PROPERTY(int y READ y NOTIFY positionChanged) + Q_PROPERTY(bool enabled MEMBER m_enabled WRITE setEnabled NOTIFY enabledChanged) + +public: + CursorWrapper(QObject *parent=0); + ~CursorWrapper(); + /** + * The current global x position + */ + int x() const; + /** + * The current global y position + */ + int y() const; + + void setEnabled(bool); + +Q_SIGNALS: + void positionChanged(); + void enabledChanged(); +private: + bool m_enabled = true; +}; + +} // KWin + +#endif // KWIN_SCRIPTING_DBUSCALL_H diff --git a/scripting/cursorwrapper.cpp b/scripting/cursorwrapper.cpp new file mode 100644 --- /dev/null +++ b/scripting/cursorwrapper.cpp @@ -0,0 +1,65 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2017 David Edmundson + +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 . +*********************************************************************/ +#include "cursorwrapper.h" + +#include "cursor.h" + +namespace KWin { + +CursorWrapper::CursorWrapper(QObject *parent) + :QObject(parent) +{ + connect(Cursor::self(), &Cursor::posChanged, this, &CursorWrapper::positionChanged); + Cursor::self()->startCursorTracking(); +} + +CursorWrapper::~CursorWrapper() +{ + if (m_enabled) { + Cursor::self()->stopCursorTracking(); + } +} + +int CursorWrapper::x() const +{ + return Cursor::pos().x(); +} + +int CursorWrapper::y() const +{ + return Cursor::pos().y(); +} + +void CursorWrapper::setEnabled(bool enabled) +{ + if (enabled == m_enabled) { + return; + } + m_enabled = enabled; + if (enabled) { + Cursor::self()->startCursorTracking(); + } else { + Cursor::self()->stopCursorTracking(); + } + + emit enabledChanged(); +} + +} // KWin diff --git a/scripting/scripting.cpp b/scripting/scripting.cpp --- a/scripting/scripting.cpp +++ b/scripting/scripting.cpp @@ -22,6 +22,7 @@ #include "scripting.h" // own #include "dbuscall.h" +#include "cursorwrapper.h" #include "meta.h" #include "scriptingutils.h" #include "workspace_wrapper.h" @@ -685,6 +686,7 @@ qmlRegisterType("org.kde.kwin", 2, 0, "ThumbnailItem"); qmlRegisterType("org.kde.kwin", 2, 0, "DBusCall"); qmlRegisterType("org.kde.kwin", 2, 0, "ScreenEdgeItem"); + qmlRegisterType("org.kde.kwin", 2, 0, "Cursor"); qmlRegisterType(); qmlRegisterType("org.kde.kwin", 2, 0, "ClientModel"); qmlRegisterType("org.kde.kwin", 2, 0, "ClientModelByScreen");