2014-03-23 08:23:30 +00:00
|
|
|
/********************************************************************
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
|
|
|
|
|
|
|
Copyright (C) 2014 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 "../effectloader.h"
|
|
|
|
#include "mock_effectshandler.h"
|
|
|
|
#include "../scripting/scriptedeffect.h"
|
|
|
|
// for mocking
|
2016-06-08 10:46:02 +00:00
|
|
|
#include "../cursor.h"
|
2014-03-23 08:23:30 +00:00
|
|
|
#include "../input.h"
|
|
|
|
#include "../screenedge.h"
|
|
|
|
// KDE
|
|
|
|
#include <KConfig>
|
|
|
|
#include <KConfigGroup>
|
2015-07-06 14:50:33 +00:00
|
|
|
#include <KPackage/PackageLoader>
|
2014-03-23 08:23:30 +00:00
|
|
|
// Qt
|
2018-06-05 10:52:57 +00:00
|
|
|
#include <QtTest>
|
2014-03-23 08:23:30 +00:00
|
|
|
#include <QStringList>
|
|
|
|
Q_DECLARE_METATYPE(KWin::LoadEffectFlag)
|
|
|
|
Q_DECLARE_METATYPE(KWin::LoadEffectFlags)
|
|
|
|
Q_DECLARE_METATYPE(KWin::Effect*)
|
2016-11-16 15:53:17 +00:00
|
|
|
Q_DECLARE_METATYPE(KSharedConfigPtr)
|
2014-03-23 08:23:30 +00:00
|
|
|
|
2014-12-05 10:42:15 +00:00
|
|
|
Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core")
|
|
|
|
|
2014-03-23 08:23:30 +00:00
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
ScreenEdges *ScreenEdges::s_self = nullptr;
|
|
|
|
|
|
|
|
void ScreenEdges::reserve(ElectricBorder, QObject *, const char *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-04-02 13:42:18 +00:00
|
|
|
void ScreenEdges::reserveTouch(ElectricBorder, QAction *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-03-23 08:23:30 +00:00
|
|
|
InputRedirection *InputRedirection::s_self = nullptr;
|
|
|
|
|
|
|
|
void InputRedirection::registerShortcut(const QKeySequence &, QAction *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace MetaScripting
|
|
|
|
{
|
|
|
|
void registration(QScriptEngine *)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class TestScriptedEffectLoader : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
private Q_SLOTS:
|
2016-11-16 15:53:17 +00:00
|
|
|
void initTestCase();
|
2014-03-23 08:23:30 +00:00
|
|
|
void testHasEffect_data();
|
|
|
|
void testHasEffect();
|
|
|
|
void testKnownEffects();
|
|
|
|
void testLoadEffect_data();
|
|
|
|
void testLoadEffect();
|
|
|
|
void testLoadScriptedEffect_data();
|
|
|
|
void testLoadScriptedEffect();
|
|
|
|
void testLoadAllEffects();
|
2016-04-26 12:55:47 +00:00
|
|
|
void testCancelLoadAllEffects();
|
2014-03-23 08:23:30 +00:00
|
|
|
};
|
|
|
|
|
2016-11-16 15:53:17 +00:00
|
|
|
void TestScriptedEffectLoader::initTestCase()
|
|
|
|
{
|
2018-11-05 13:08:12 +00:00
|
|
|
qputenv("XDG_DATA_DIRS", QCoreApplication::applicationDirPath().toUtf8());
|
2016-11-16 15:53:17 +00:00
|
|
|
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
|
|
|
QCoreApplication::instance()->setProperty("config", QVariant::fromValue(config));
|
2020-04-02 16:18:01 +00:00
|
|
|
|
|
|
|
KWin::Cursors::self()->setMouse(new KWin::Cursor(this));
|
2016-11-16 15:53:17 +00:00
|
|
|
}
|
|
|
|
|
2014-03-23 08:23:30 +00:00
|
|
|
void TestScriptedEffectLoader::testHasEffect_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("name");
|
|
|
|
QTest::addColumn<bool>("expected");
|
|
|
|
|
|
|
|
// all the built-in effects should fail
|
|
|
|
QTest::newRow("blur") << QStringLiteral("blur") << false;
|
2016-11-24 07:07:51 +00:00
|
|
|
QTest::newRow("Colorpicker") << QStringLiteral("colorpicker") << false;
|
2014-03-23 08:23:30 +00:00
|
|
|
QTest::newRow("Contrast") << QStringLiteral("contrast") << false;
|
|
|
|
QTest::newRow("CoverSwitch") << QStringLiteral("coverswitch") << false;
|
|
|
|
QTest::newRow("Cube") << QStringLiteral("cube") << false;
|
|
|
|
QTest::newRow("CubeSlide") << QStringLiteral("cubeslide") << false;
|
|
|
|
QTest::newRow("DesktopGrid") << QStringLiteral("desktopgrid") << false;
|
|
|
|
QTest::newRow("DimInactive") << QStringLiteral("diminactive") << false;
|
|
|
|
QTest::newRow("FallApart") << QStringLiteral("fallapart") << false;
|
|
|
|
QTest::newRow("FlipSwitch") << QStringLiteral("flipswitch") << false;
|
|
|
|
QTest::newRow("Glide") << QStringLiteral("glide") << false;
|
|
|
|
QTest::newRow("HighlightWindow") << QStringLiteral("highlightwindow") << false;
|
|
|
|
QTest::newRow("Invert") << QStringLiteral("invert") << false;
|
|
|
|
QTest::newRow("Kscreen") << QStringLiteral("kscreen") << false;
|
|
|
|
QTest::newRow("Logout") << QStringLiteral("logout") << false;
|
|
|
|
QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << false;
|
|
|
|
QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false;
|
|
|
|
QTest::newRow("Magnifier") << QStringLiteral("magnifier") << false;
|
|
|
|
QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << false;
|
|
|
|
QTest::newRow("MouseMark") << QStringLiteral("mousemark") << false;
|
|
|
|
QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << false;
|
|
|
|
QTest::newRow("Resize") << QStringLiteral("resize") << false;
|
|
|
|
QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << false;
|
|
|
|
QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << false;
|
|
|
|
QTest::newRow("Sheet") << QStringLiteral("sheet") << false;
|
|
|
|
QTest::newRow("ShowFps") << QStringLiteral("showfps") << false;
|
|
|
|
QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << false;
|
|
|
|
QTest::newRow("Slide") << QStringLiteral("slide") << false;
|
|
|
|
QTest::newRow("SlideBack") << QStringLiteral("slideback") << false;
|
|
|
|
QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << false;
|
|
|
|
QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << false;
|
|
|
|
QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false;
|
|
|
|
QTest::newRow("ThumbnailAside") << QStringLiteral("thumbnailaside") << false;
|
|
|
|
QTest::newRow("TrackMouse") << QStringLiteral("trackmouse") << false;
|
|
|
|
QTest::newRow("WindowGeometry") << QStringLiteral("windowgeometry") << false;
|
|
|
|
QTest::newRow("WobblyWindows") << QStringLiteral("wobblywindows") << false;
|
|
|
|
QTest::newRow("Zoom") << QStringLiteral("zoom") << false;
|
|
|
|
QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false;
|
|
|
|
QTest::newRow("Fade - without kwin4_effect") << QStringLiteral("fade") << false;
|
2018-11-21 12:22:32 +00:00
|
|
|
|
|
|
|
QTest::newRow("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << true;
|
|
|
|
QTest::newRow("DimScreen") << QStringLiteral("kwin4_effect_dimscreen") << true;
|
|
|
|
QTest::newRow("EyeOnScreen") << QStringLiteral("kwin4_effect_eyeonscreen") << true;
|
|
|
|
QTest::newRow("Fade + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << true;
|
|
|
|
QTest::newRow("Fade + kwin4_effect + CS") << QStringLiteral("kwin4_eFfect_fAde") << true;
|
|
|
|
QTest::newRow("FadeDesktop") << QStringLiteral("kwin4_effect_fadedesktop") << true;
|
|
|
|
QTest::newRow("FadingPopups") << QStringLiteral("kwin4_effect_fadingpopups") << true;
|
|
|
|
QTest::newRow("FrozenApp") << QStringLiteral("kwin4_effect_frozenapp") << true;
|
|
|
|
QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << true;
|
|
|
|
QTest::newRow("Logout") << QStringLiteral("kwin4_effect_logout") << true;
|
|
|
|
QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << true;
|
|
|
|
QTest::newRow("MorphingPopups") << QStringLiteral("kwin4_effect_morphingpopups") << true;
|
|
|
|
QTest::newRow("Scale") << QStringLiteral("kwin4_effect_scale") << true;
|
|
|
|
QTest::newRow("Squash") << QStringLiteral("kwin4_effect_squash") << true;
|
|
|
|
QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << true;
|
|
|
|
QTest::newRow("WindowAperture") << QStringLiteral("kwin4_effect_windowaperture") << true;
|
2014-03-23 08:23:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestScriptedEffectLoader::testHasEffect()
|
|
|
|
{
|
|
|
|
QFETCH(QString, name);
|
|
|
|
QFETCH(bool, expected);
|
|
|
|
|
2018-08-30 11:48:23 +00:00
|
|
|
QScopedPointer<MockEffectsHandler, QScopedPointerDeleteLater> mockHandler(new MockEffectsHandler(KWin::XRenderCompositing));
|
2014-03-23 08:23:30 +00:00
|
|
|
KWin::ScriptedEffectLoader loader;
|
|
|
|
QCOMPARE(loader.hasEffect(name), expected);
|
|
|
|
|
|
|
|
// each available effect should also be supported
|
|
|
|
QCOMPARE(loader.isEffectSupported(name), expected);
|
2016-08-10 07:24:53 +00:00
|
|
|
|
|
|
|
if (expected) {
|
2018-08-30 11:48:23 +00:00
|
|
|
mockHandler->setAnimationsSupported(false);
|
2016-08-10 07:24:53 +00:00
|
|
|
QVERIFY(!loader.isEffectSupported(name));
|
|
|
|
}
|
2014-03-23 08:23:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestScriptedEffectLoader::testKnownEffects()
|
|
|
|
{
|
|
|
|
QStringList expectedEffects;
|
|
|
|
expectedEffects << QStringLiteral("kwin4_effect_dialogparent")
|
2018-10-25 13:48:47 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_dimscreen")
|
2018-11-21 12:22:32 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_eyeonscreen")
|
2014-03-23 08:23:30 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_fade")
|
|
|
|
<< QStringLiteral("kwin4_effect_fadedesktop")
|
[effects] Split the Fade effect
Summary:
Currently, we have three effects that can be used to animate the
appearing of toplevel windows(fade, glide, scale) and one can enable
all three of them, which seems to be wrong. It doesn't make sense to have
glide and scale effect enabled, for example.
We couldn't put all three effects into an exclusive group before because
the fade effect animates not only toplevel windows but also popups. So,
if all three effects are in an exclusive group and you enable glide effect,
for example, then tooltips and other popups won't be faded in/out.
This patch splits the fade effect into two: the first effect (called Fade)
animates toplevel windows and the other one (called Fading Popups) animates
popup windows.
Test Plan:
Have been using the Fading Popups effect in combination with the Scale
effect for a couple of days. Haven't noticed any significant differences between
the new combination (Fading Popups + Scale) and the old combination
(Fade + Scale).
Reviewers: #kwin, #plasma, #vdg, graesslin
Reviewed By: #kwin, #plasma, graesslin
Subscribers: graesslin, abetts, ngraham, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D16836
2018-11-03 15:42:31 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_fadingpopups")
|
2017-04-05 09:16:23 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_frozenapp")
|
2014-03-23 08:23:30 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_login")
|
2017-03-15 16:47:13 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_logout")
|
2014-03-23 08:23:30 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_maximize")
|
2018-11-21 12:22:32 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_morphingpopups")
|
2018-10-27 21:27:25 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_scale")
|
2019-11-05 15:02:59 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_sessionquit")
|
[effects] Re-implement the Minimize Animation effect in JavaScript
Summary:
There were several reasons to rewrite the Minimize Animation effect in
JavaScript: to simplify code and to get rid of full repaints. One could
say that nothing prevents us from calculating the dirty region in
postPaintScreen or postPaintWindow and it is correct, but with the
scripting effects API the dirty region will be calculated for us, so we
can focus more on "what we want" instead of "how".
Visually, the "old" effect and the rewritten one look quite the same.
Except one tiny bit: if a window doesn't have an icon in the task manager,
it won't be animated. The reason for that is the purpose of this effect is
to show where the window will be after it's minimized, if the window
doesn't have icon in the task manager, one can't click at the center of
the screen to unminimize the window.
There is one significant change, the name of the effect was changed to
"Squash". If we put this effect and the Magic lamp effect under "Window
Minimize Animation" category (or if we add some "heading" label), then
the old name and the name of the category would "conflict". The new name
was suggested by Nate Graham and it very closely describes what the
effect does. "Scale" doesn't fit this effect because while a window is
being animated, its aspect ratio is not preserved.
Reviewers: #kwin, #plasma, davidedmundson
Reviewed By: #kwin, #plasma, davidedmundson
Subscribers: davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D16372
2018-09-23 17:07:48 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_squash")
|
2018-11-21 12:22:32 +00:00
|
|
|
<< QStringLiteral("kwin4_effect_translucency")
|
|
|
|
<< QStringLiteral("kwin4_effect_windowaperture");
|
2014-03-23 08:23:30 +00:00
|
|
|
|
|
|
|
KWin::ScriptedEffectLoader loader;
|
|
|
|
QStringList result = loader.listOfKnownEffects();
|
|
|
|
// at least as many effects as we expect - system running the test could have more effects
|
|
|
|
QVERIFY(result.size() >= expectedEffects.size());
|
|
|
|
for (const QString &effect : expectedEffects) {
|
|
|
|
QVERIFY(result.contains(effect));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestScriptedEffectLoader::testLoadEffect_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("name");
|
|
|
|
QTest::addColumn<bool>("expected");
|
|
|
|
|
2018-11-21 12:22:32 +00:00
|
|
|
QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false;
|
|
|
|
QTest::newRow("Fade - without kwin4_effect") << QStringLiteral("fade") << false;
|
|
|
|
QTest::newRow("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << true;
|
|
|
|
QTest::newRow("DimScreen") << QStringLiteral("kwin4_effect_dimscreen") << true;
|
|
|
|
QTest::newRow("EyeOnScreen") << QStringLiteral("kwin4_effect_eyeonscreen") << true;
|
|
|
|
QTest::newRow("Fade + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << true;
|
|
|
|
QTest::newRow("Fade + kwin4_effect + CS") << QStringLiteral("kwin4_eFfect_fAde") << true;
|
|
|
|
QTest::newRow("FadeDesktop") << QStringLiteral("kwin4_effect_fadedesktop") << true;
|
|
|
|
QTest::newRow("FadingPopups") << QStringLiteral("kwin4_effect_fadingpopups") << true;
|
|
|
|
QTest::newRow("FrozenApp") << QStringLiteral("kwin4_effect_frozenapp") << true;
|
|
|
|
QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << true;
|
|
|
|
QTest::newRow("Logout") << QStringLiteral("kwin4_effect_logout") << true;
|
|
|
|
QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << true;
|
|
|
|
QTest::newRow("MorphingPopups") << QStringLiteral("kwin4_effect_morphingpopups") << true;
|
|
|
|
QTest::newRow("Scale") << QStringLiteral("kwin4_effect_scale") << true;
|
2019-11-05 15:02:59 +00:00
|
|
|
QTest::newRow("SessionQuit") << QStringLiteral("kwin4_effect_sessionquit") << true;
|
2018-11-21 12:22:32 +00:00
|
|
|
QTest::newRow("Squash") << QStringLiteral("kwin4_effect_squash") << true;
|
|
|
|
QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << true;
|
|
|
|
QTest::newRow("WindowAperture") << QStringLiteral("kwin4_effect_windowaperture") << true;
|
2019-11-05 15:02:59 +00:00
|
|
|
|
2014-03-23 08:23:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestScriptedEffectLoader::testLoadEffect()
|
|
|
|
{
|
|
|
|
QFETCH(QString, name);
|
|
|
|
QFETCH(bool, expected);
|
|
|
|
|
2018-08-30 11:48:23 +00:00
|
|
|
QScopedPointer<MockEffectsHandler, QScopedPointerDeleteLater> mockHandler(new MockEffectsHandler(KWin::XRenderCompositing));
|
2014-03-23 08:23:30 +00:00
|
|
|
KWin::ScriptedEffectLoader loader;
|
|
|
|
KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
|
|
|
loader.setConfig(config);
|
|
|
|
|
|
|
|
qRegisterMetaType<KWin::Effect*>();
|
2019-07-29 19:45:19 +00:00
|
|
|
QSignalSpy spy(&loader, &KWin::ScriptedEffectLoader::effectLoaded);
|
2014-03-23 08:23:30 +00:00
|
|
|
// connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent
|
|
|
|
connect(&loader, &KWin::ScriptedEffectLoader::effectLoaded,
|
|
|
|
[&name](KWin::Effect *effect, const QString &effectName) {
|
|
|
|
QCOMPARE(effectName, name.toLower());
|
|
|
|
effect->deleteLater();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
// try to load the Effect
|
|
|
|
QCOMPARE(loader.loadEffect(name), expected);
|
|
|
|
// loading again should fail
|
|
|
|
QVERIFY(!loader.loadEffect(name));
|
|
|
|
|
|
|
|
// signal spy should have got the signal if it was expected
|
|
|
|
QCOMPARE(spy.isEmpty(), !expected);
|
|
|
|
if (!spy.isEmpty()) {
|
|
|
|
QCOMPARE(spy.count(), 1);
|
|
|
|
// if we caught a signal it should have the effect name we passed in
|
|
|
|
QList<QVariant> arguments = spy.takeFirst();
|
|
|
|
QCOMPARE(arguments.count(), 2);
|
|
|
|
QCOMPARE(arguments.at(1).toString(), name.toLower());
|
|
|
|
}
|
|
|
|
spy.clear();
|
|
|
|
QVERIFY(spy.isEmpty());
|
|
|
|
|
|
|
|
// now if we wait for the events being processed, the effect will get deleted and it should load again
|
|
|
|
QTest::qWait(1);
|
|
|
|
QCOMPARE(loader.loadEffect(name), expected);
|
|
|
|
// signal spy should have got the signal if it was expected
|
|
|
|
QCOMPARE(spy.isEmpty(), !expected);
|
|
|
|
if (!spy.isEmpty()) {
|
|
|
|
QCOMPARE(spy.count(), 1);
|
|
|
|
// if we caught a signal it should have the effect name we passed in
|
|
|
|
QList<QVariant> arguments = spy.takeFirst();
|
|
|
|
QCOMPARE(arguments.count(), 2);
|
|
|
|
QCOMPARE(arguments.at(1).toString(), name.toLower());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestScriptedEffectLoader::testLoadScriptedEffect_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("name");
|
|
|
|
QTest::addColumn<bool>("expected");
|
|
|
|
QTest::addColumn<KWin::LoadEffectFlags>("loadFlags");
|
|
|
|
|
|
|
|
const KWin::LoadEffectFlags checkDefault = KWin::LoadEffectFlag::Load | KWin::LoadEffectFlag::CheckDefaultFunction;
|
|
|
|
const KWin::LoadEffectFlags forceFlags = KWin::LoadEffectFlag::Load;
|
|
|
|
const KWin::LoadEffectFlags dontLoadFlags = KWin::LoadEffectFlags();
|
|
|
|
|
|
|
|
// enabled by default
|
2018-06-10 11:02:57 +00:00
|
|
|
QTest::newRow("Fade") << QStringLiteral("kwin4_effect_fade") << true << checkDefault;
|
2014-03-23 08:23:30 +00:00
|
|
|
// not enabled by default
|
2018-06-10 11:02:57 +00:00
|
|
|
QTest::newRow("EyeOnScreen") << QStringLiteral("kwin4_effect_eyeonscreen") << true << checkDefault;
|
2014-03-23 08:23:30 +00:00
|
|
|
// Force an Effect which will load
|
2018-06-10 11:02:57 +00:00
|
|
|
QTest::newRow("EyeOnScreen-Force") << QStringLiteral("kwin4_effect_eyeonscreen") << true << forceFlags;
|
2014-03-23 08:23:30 +00:00
|
|
|
// Enforce no load of effect which is enabled by default
|
2018-06-10 11:02:57 +00:00
|
|
|
QTest::newRow("Fade-DontLoad") << QStringLiteral("kwin4_effect_fade") << false << dontLoadFlags;
|
2014-03-23 08:23:30 +00:00
|
|
|
// Enforce no load of effect which is not enabled by default, but enforced
|
2018-06-10 11:02:57 +00:00
|
|
|
QTest::newRow("EyeOnScreen-DontLoad") << QStringLiteral("kwin4_effect_eyeonscreen") << false << dontLoadFlags;
|
2014-03-23 08:23:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestScriptedEffectLoader::testLoadScriptedEffect()
|
|
|
|
{
|
|
|
|
QFETCH(QString, name);
|
|
|
|
QFETCH(bool, expected);
|
|
|
|
QFETCH(KWin::LoadEffectFlags, loadFlags);
|
|
|
|
|
2018-08-30 11:48:23 +00:00
|
|
|
QScopedPointer<MockEffectsHandler, QScopedPointerDeleteLater> mockHandler(new MockEffectsHandler(KWin::XRenderCompositing));
|
2014-03-23 08:23:30 +00:00
|
|
|
KWin::ScriptedEffectLoader loader;
|
|
|
|
KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
|
|
|
loader.setConfig(config);
|
|
|
|
|
2015-07-06 14:50:33 +00:00
|
|
|
const auto services = KPackage::PackageLoader::self()->findPackages(QStringLiteral("KWin/Effect"), QStringLiteral("kwin/effects"),
|
|
|
|
[name] (const KPluginMetaData &metadata) {
|
|
|
|
return metadata.pluginId().compare(name, Qt::CaseInsensitive) == 0;
|
|
|
|
}
|
|
|
|
);
|
2014-03-23 08:23:30 +00:00
|
|
|
QCOMPARE(services.count(), 1);
|
|
|
|
|
|
|
|
qRegisterMetaType<KWin::Effect*>();
|
2019-07-29 19:45:19 +00:00
|
|
|
QSignalSpy spy(&loader, &KWin::ScriptedEffectLoader::effectLoaded);
|
2014-03-23 08:23:30 +00:00
|
|
|
// connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent
|
|
|
|
connect(&loader, &KWin::ScriptedEffectLoader::effectLoaded,
|
|
|
|
[&name](KWin::Effect *effect, const QString &effectName) {
|
|
|
|
QCOMPARE(effectName, name.toLower());
|
|
|
|
effect->deleteLater();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
// try to load the Effect
|
|
|
|
QCOMPARE(loader.loadEffect(services.first(), loadFlags), expected);
|
|
|
|
// loading again should fail
|
|
|
|
QVERIFY(!loader.loadEffect(services.first(), loadFlags));
|
|
|
|
|
|
|
|
// signal spy should have got the signal if it was expected
|
|
|
|
QCOMPARE(spy.isEmpty(), !expected);
|
|
|
|
if (!spy.isEmpty()) {
|
|
|
|
QCOMPARE(spy.count(), 1);
|
|
|
|
// if we caught a signal it should have the effect name we passed in
|
|
|
|
QList<QVariant> arguments = spy.takeFirst();
|
|
|
|
QCOMPARE(arguments.count(), 2);
|
|
|
|
QCOMPARE(arguments.at(1).toString(), name.toLower());
|
|
|
|
}
|
|
|
|
spy.clear();
|
|
|
|
QVERIFY(spy.isEmpty());
|
|
|
|
|
|
|
|
// now if we wait for the events being processed, the effect will get deleted and it should load again
|
|
|
|
QTest::qWait(1);
|
|
|
|
QCOMPARE(loader.loadEffect(services.first(), loadFlags), expected);
|
|
|
|
// signal spy should have got the signal if it was expected
|
|
|
|
QCOMPARE(spy.isEmpty(), !expected);
|
|
|
|
if (!spy.isEmpty()) {
|
|
|
|
QCOMPARE(spy.count(), 1);
|
|
|
|
// if we caught a signal it should have the effect name we passed in
|
|
|
|
QList<QVariant> arguments = spy.takeFirst();
|
|
|
|
QCOMPARE(arguments.count(), 2);
|
|
|
|
QCOMPARE(arguments.at(1).toString(), name.toLower());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestScriptedEffectLoader::testLoadAllEffects()
|
|
|
|
{
|
2018-08-30 11:48:23 +00:00
|
|
|
QScopedPointer<MockEffectsHandler, QScopedPointerDeleteLater> mockHandler(new MockEffectsHandler(KWin::XRenderCompositing));
|
2014-03-23 08:23:30 +00:00
|
|
|
KWin::ScriptedEffectLoader loader;
|
|
|
|
|
|
|
|
KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
|
|
|
|
|
|
|
const QString kwin4 = QStringLiteral("kwin4_effect_");
|
|
|
|
|
|
|
|
// prepare the configuration to hard enable/disable the effects we want to load
|
|
|
|
KConfigGroup plugins = config->group("Plugins");
|
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("dialogparentEnabled"), false);
|
2018-10-25 13:48:47 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("dimscreenEnabled"), false);
|
2014-03-23 08:23:30 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("fadeEnabled"), false);
|
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("fadedesktopEnabled"), false);
|
[effects] Split the Fade effect
Summary:
Currently, we have three effects that can be used to animate the
appearing of toplevel windows(fade, glide, scale) and one can enable
all three of them, which seems to be wrong. It doesn't make sense to have
glide and scale effect enabled, for example.
We couldn't put all three effects into an exclusive group before because
the fade effect animates not only toplevel windows but also popups. So,
if all three effects are in an exclusive group and you enable glide effect,
for example, then tooltips and other popups won't be faded in/out.
This patch splits the fade effect into two: the first effect (called Fade)
animates toplevel windows and the other one (called Fading Popups) animates
popup windows.
Test Plan:
Have been using the Fading Popups effect in combination with the Scale
effect for a couple of days. Haven't noticed any significant differences between
the new combination (Fading Popups + Scale) and the old combination
(Fade + Scale).
Reviewers: #kwin, #plasma, #vdg, graesslin
Reviewed By: #kwin, #plasma, graesslin
Subscribers: graesslin, abetts, ngraham, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D16836
2018-11-03 15:42:31 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("fadingpopupsEnabled"), false);
|
2017-04-05 09:16:23 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("frozenappEnabled"), false);
|
2014-03-23 08:23:30 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("loginEnabled"), false);
|
2017-03-15 16:47:13 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("logoutEnabled"), false);
|
2014-03-23 08:23:30 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("maximizeEnabled"), false);
|
2018-10-27 21:27:25 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("scaleEnabled"), false);
|
[effects] Re-implement the Minimize Animation effect in JavaScript
Summary:
There were several reasons to rewrite the Minimize Animation effect in
JavaScript: to simplify code and to get rid of full repaints. One could
say that nothing prevents us from calculating the dirty region in
postPaintScreen or postPaintWindow and it is correct, but with the
scripting effects API the dirty region will be calculated for us, so we
can focus more on "what we want" instead of "how".
Visually, the "old" effect and the rewritten one look quite the same.
Except one tiny bit: if a window doesn't have an icon in the task manager,
it won't be animated. The reason for that is the purpose of this effect is
to show where the window will be after it's minimized, if the window
doesn't have icon in the task manager, one can't click at the center of
the screen to unminimize the window.
There is one significant change, the name of the effect was changed to
"Squash". If we put this effect and the Magic lamp effect under "Window
Minimize Animation" category (or if we add some "heading" label), then
the old name and the name of the category would "conflict". The new name
was suggested by Nate Graham and it very closely describes what the
effect does. "Scale" doesn't fit this effect because while a window is
being animated, its aspect ratio is not preserved.
Reviewers: #kwin, #plasma, davidedmundson
Reviewed By: #kwin, #plasma, davidedmundson
Subscribers: davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D16372
2018-09-23 17:07:48 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("squashEnabled"), false);
|
2014-03-23 08:23:30 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("translucencyEnabled"), false);
|
2015-04-09 12:58:05 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("eyeonscreenEnabled"), false);
|
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("windowapertureEnabled"), false);
|
2016-02-17 14:27:06 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("morphingpopupsEnabled"), false);
|
2019-11-05 15:02:59 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("sessionquitEnabled"), false);
|
|
|
|
|
2014-03-23 08:23:30 +00:00
|
|
|
plugins.sync();
|
|
|
|
|
|
|
|
loader.setConfig(config);
|
|
|
|
|
|
|
|
qRegisterMetaType<KWin::Effect*>();
|
2019-07-29 19:45:19 +00:00
|
|
|
QSignalSpy spy(&loader, &KWin::ScriptedEffectLoader::effectLoaded);
|
2014-03-23 08:23:30 +00:00
|
|
|
// connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent
|
|
|
|
connect(&loader, &KWin::ScriptedEffectLoader::effectLoaded,
|
|
|
|
[](KWin::Effect *effect) {
|
|
|
|
effect->deleteLater();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
// the config is prepared so that no Effect gets loaded!
|
|
|
|
loader.queryAndLoadAll();
|
|
|
|
|
|
|
|
// we need to wait some time because it's queued and in a thread
|
|
|
|
QVERIFY(!spy.wait(100));
|
|
|
|
|
|
|
|
// now let's prepare a config which has one effect explicitly enabled
|
2018-06-10 11:02:57 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("eyeonscreenEnabled"), true);
|
2014-03-23 08:23:30 +00:00
|
|
|
plugins.sync();
|
|
|
|
|
|
|
|
loader.queryAndLoadAll();
|
|
|
|
// should load one effect in first go
|
|
|
|
QVERIFY(spy.wait(100));
|
|
|
|
// and afterwards it should not load another one
|
|
|
|
QVERIFY(!spy.wait(10));
|
|
|
|
|
|
|
|
QCOMPARE(spy.size(), 1);
|
|
|
|
// if we caught a signal it should have the effect name we passed in
|
|
|
|
QList<QVariant> arguments = spy.takeFirst();
|
|
|
|
QCOMPARE(arguments.count(), 2);
|
2018-06-10 11:02:57 +00:00
|
|
|
QCOMPARE(arguments.at(1).toString(), kwin4 + QStringLiteral("eyeonscreen"));
|
2014-03-23 08:23:30 +00:00
|
|
|
spy.clear();
|
|
|
|
|
|
|
|
// let's delete one of the default entries
|
|
|
|
plugins.deleteEntry(kwin4 + QStringLiteral("fadeEnabled"));
|
|
|
|
plugins.sync();
|
|
|
|
|
|
|
|
QVERIFY(spy.isEmpty());
|
|
|
|
loader.queryAndLoadAll();
|
|
|
|
|
|
|
|
// let's use qWait as we need to wait for two signals to be emitted
|
2016-08-16 12:07:14 +00:00
|
|
|
QTRY_COMPARE(spy.size(), 2);
|
2014-03-23 08:23:30 +00:00
|
|
|
QStringList loadedEffects;
|
|
|
|
for (auto &list : spy) {
|
|
|
|
QCOMPARE(list.size(), 2);
|
|
|
|
loadedEffects << list.at(1).toString();
|
|
|
|
}
|
2019-07-09 21:00:07 +00:00
|
|
|
std::sort(loadedEffects.begin(), loadedEffects.end());
|
2018-06-10 11:02:57 +00:00
|
|
|
QCOMPARE(loadedEffects.at(0), kwin4 + QStringLiteral("eyeonscreen"));
|
|
|
|
QCOMPARE(loadedEffects.at(1), kwin4 + QStringLiteral("fade"));
|
2014-03-23 08:23:30 +00:00
|
|
|
}
|
|
|
|
|
2016-04-26 12:55:47 +00:00
|
|
|
void TestScriptedEffectLoader::testCancelLoadAllEffects()
|
|
|
|
{
|
|
|
|
// this test verifies that no test gets loaded when the loader gets cleared
|
|
|
|
MockEffectsHandler mockHandler(KWin::XRenderCompositing);
|
|
|
|
KWin::ScriptedEffectLoader loader;
|
|
|
|
|
|
|
|
// prepare the configuration to hard enable/disable the effects we want to load
|
|
|
|
KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
|
|
|
const QString kwin4 = QStringLiteral("kwin4_effect_");
|
|
|
|
KConfigGroup plugins = config->group("Plugins");
|
2018-06-10 11:02:57 +00:00
|
|
|
plugins.writeEntry(kwin4 + QStringLiteral("eyeonscreenEnabled"), true);
|
2016-04-26 12:55:47 +00:00
|
|
|
plugins.sync();
|
|
|
|
|
|
|
|
loader.setConfig(config);
|
|
|
|
|
|
|
|
qRegisterMetaType<KWin::Effect*>();
|
|
|
|
QSignalSpy spy(&loader, &KWin::ScriptedEffectLoader::effectLoaded);
|
|
|
|
QVERIFY(spy.isValid());
|
|
|
|
|
|
|
|
loader.queryAndLoadAll();
|
|
|
|
loader.clear();
|
|
|
|
|
|
|
|
// Should not load any effect
|
|
|
|
QVERIFY(!spy.wait(100));
|
|
|
|
QVERIFY(spy.isEmpty());
|
|
|
|
}
|
|
|
|
|
2014-03-23 08:23:30 +00:00
|
|
|
QTEST_MAIN(TestScriptedEffectLoader)
|
|
|
|
#include "test_scripted_effectloader.moc"
|