diff --git a/autotests/test_builtin_effectloader.cpp b/autotests/test_builtin_effectloader.cpp index 0f3dab789..6dd331305 100644 --- a/autotests/test_builtin_effectloader.cpp +++ b/autotests/test_builtin_effectloader.cpp @@ -1,569 +1,575 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2014 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 "../effectloader.h" #include "../effects/effect_builtins.h" #include "mock_effectshandler.h" #include "../scripting/scriptedeffect.h" // for mocking ScriptedEffect::create #include "testutils.h" // KDE #include #include // Qt #include #include Q_DECLARE_METATYPE(KWin::CompositingType) Q_DECLARE_METATYPE(KWin::LoadEffectFlag) Q_DECLARE_METATYPE(KWin::LoadEffectFlags) Q_DECLARE_METATYPE(KWin::BuiltInEffect) Q_DECLARE_METATYPE(KWin::Effect*) Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core") namespace KWin { ScriptedEffect *ScriptedEffect::create(const KPluginMetaData&) { return nullptr; } bool ScriptedEffect::supported() { return true; } } class TestBuiltInEffectLoader : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void testHasEffect_data(); void testHasEffect(); void testKnownEffects(); void testSupported_data(); void testSupported(); void testLoadEffect_data(); void testLoadEffect(); void testLoadBuiltInEffect_data(); void testLoadBuiltInEffect(); void testLoadAllEffects(); }; void TestBuiltInEffectLoader::initTestCase() { qApp->setProperty("x11Connection", QVariant::fromValue(QX11Info::connection())); } void TestBuiltInEffectLoader::testHasEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::newRow("blur") << QStringLiteral("blur") << true; QTest::newRow("with kwin4_effect_ prefix") << QStringLiteral("kwin4_effect_blur") << false; QTest::newRow("case sensitive") << QStringLiteral("BlUR") << true; + QTest::newRow("Colorpicker") << QStringLiteral("colorpicker") << true; QTest::newRow("Contrast") << QStringLiteral("contrast") << true; QTest::newRow("CoverSwitch") << QStringLiteral("coverswitch") << true; QTest::newRow("Cube") << QStringLiteral("cube") << true; QTest::newRow("CubeSlide") << QStringLiteral("cubeslide") << true; QTest::newRow("DesktopGrid") << QStringLiteral("desktopgrid") << true; QTest::newRow("DimInactive") << QStringLiteral("diminactive") << true; QTest::newRow("DimScreen") << QStringLiteral("dimscreen") << true; QTest::newRow("FallApart") << QStringLiteral("fallapart") << true; QTest::newRow("FlipSwitch") << QStringLiteral("flipswitch") << true; QTest::newRow("Glide") << QStringLiteral("glide") << true; QTest::newRow("HighlightWindow") << QStringLiteral("highlightwindow") << true; QTest::newRow("Invert") << QStringLiteral("invert") << true; QTest::newRow("Kscreen") << QStringLiteral("kscreen") << true; QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << true; QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << true; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << true; QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << true; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << true; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true; QTest::newRow("Resize") << QStringLiteral("resize") << true; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << true; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << true; QTest::newRow("Sheet") << QStringLiteral("sheet") << true; QTest::newRow("ShowFps") << QStringLiteral("showfps") << true; QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << true; QTest::newRow("Slide") << QStringLiteral("slide") << true; QTest::newRow("SlideBack") << QStringLiteral("slideback") << true; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << true; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << true; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << true; QTest::newRow("ThumbnailAside") << QStringLiteral("thumbnailaside") << true; QTest::newRow("Touchpoints") << QStringLiteral("touchpoints") << true; QTest::newRow("TrackMouse") << QStringLiteral("trackmouse") << true; QTest::newRow("WindowGeometry") << QStringLiteral("windowgeometry") << true; QTest::newRow("WobblyWindows") << QStringLiteral("wobblywindows") << true; QTest::newRow("Zoom") << QStringLiteral("zoom") << true; QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false; QTest::newRow("Fade - Scripted") << QStringLiteral("fade") << false; QTest::newRow("Fade - Scripted + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << false; } void TestBuiltInEffectLoader::testHasEffect() { QFETCH(QString, name); QFETCH(bool, expected); KWin::BuiltInEffectLoader loader; QCOMPARE(loader.hasEffect(name), expected); } void TestBuiltInEffectLoader::testKnownEffects() { QStringList expectedEffects; expectedEffects << QStringLiteral("blur") + << QStringLiteral("colorpicker") << QStringLiteral("contrast") << QStringLiteral("coverswitch") << QStringLiteral("cube") << QStringLiteral("cubeslide") << QStringLiteral("desktopgrid") << QStringLiteral("diminactive") << QStringLiteral("dimscreen") << QStringLiteral("fallapart") << QStringLiteral("flipswitch") << QStringLiteral("glide") << QStringLiteral("highlightwindow") << QStringLiteral("invert") << QStringLiteral("kscreen") << QStringLiteral("lookingglass") << QStringLiteral("magiclamp") << QStringLiteral("magnifier") << QStringLiteral("minimizeanimation") << QStringLiteral("mouseclick") << QStringLiteral("mousemark") << QStringLiteral("presentwindows") << QStringLiteral("resize") << QStringLiteral("screenedge") << QStringLiteral("screenshot") << QStringLiteral("sheet") << QStringLiteral("showfps") << QStringLiteral("showpaint") << QStringLiteral("slide") << QStringLiteral("slideback") << QStringLiteral("slidingpopups") << QStringLiteral("snaphelper") << QStringLiteral("startupfeedback") << QStringLiteral("thumbnailaside") << QStringLiteral("touchpoints") << QStringLiteral("trackmouse") << QStringLiteral("windowgeometry") << QStringLiteral("wobblywindows") << QStringLiteral("zoom"); KWin::BuiltInEffectLoader loader; QStringList result = loader.listOfKnownEffects(); QCOMPARE(result.size(), expectedEffects.size()); qSort(result); for (int i = 0; i < expectedEffects.size(); ++i) { QCOMPARE(result.at(i), expectedEffects.at(i)); } } void TestBuiltInEffectLoader::testSupported_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("type"); QTest::addColumn("animationsSupported"); const KWin::CompositingType xc = KWin::XRenderCompositing; const KWin::CompositingType oc = KWin::OpenGL2Compositing; QTest::newRow("blur") << QStringLiteral("blur") << false << xc << true; // fails for GL as it does proper tests on what's supported and doesn't just check whether it's GL QTest::newRow("blur-GL") << QStringLiteral("blur") << false << oc << true; + QTest::newRow("Colorpicker") << QStringLiteral("colorpicker") << false << xc << true; + QTest::newRow("Colorpicker-GL") << QStringLiteral("colorpicker") << true << oc << true; QTest::newRow("Contrast") << QStringLiteral("contrast") << false << xc << true; // fails for GL as it does proper tests on what's supported and doesn't just check whether it's GL QTest::newRow("Contrast-GL") << QStringLiteral("contrast") << false << oc << true; QTest::newRow("CoverSwitch") << QStringLiteral("coverswitch") << false << xc << true; QTest::newRow("CoverSwitch-GL") << QStringLiteral("coverswitch") << true << oc << true; QTest::newRow("CoverSwitch-GL-no-anim") << QStringLiteral("coverswitch") << false << oc << false; QTest::newRow("Cube") << QStringLiteral("cube") << false << xc << true; QTest::newRow("Cube-GL") << QStringLiteral("cube") << true << oc << true; QTest::newRow("CubeSlide") << QStringLiteral("cubeslide") << false << xc << true; QTest::newRow("CubeSlide-GL") << QStringLiteral("cubeslide") << true << oc << true; QTest::newRow("CubeSlide-GL-no-anim") << QStringLiteral("cubeslide") << false << oc << false; QTest::newRow("DesktopGrid") << QStringLiteral("desktopgrid") << true << xc << true; QTest::newRow("DimInactive") << QStringLiteral("diminactive") << true << xc << true; QTest::newRow("DimScreen") << QStringLiteral("dimscreen") << true << xc << true; QTest::newRow("FallApart") << QStringLiteral("fallapart") << false << xc << true; QTest::newRow("FallApart-GL") << QStringLiteral("fallapart") << true << oc << true; QTest::newRow("FlipSwitch") << QStringLiteral("flipswitch") << false << xc << true; QTest::newRow("FlipSwitch-GL") << QStringLiteral("flipswitch") << true << oc << true; QTest::newRow("FlipSwitch-GL-no-anim") << QStringLiteral("flipswitch") << false << oc << false; QTest::newRow("Glide") << QStringLiteral("glide") << false << xc << true; QTest::newRow("Glide-GL") << QStringLiteral("glide") << true << oc << true; QTest::newRow("Glide-GL-no-anim") << QStringLiteral("glide") << false << oc << false; QTest::newRow("HighlightWindow") << QStringLiteral("highlightwindow") << true << xc << true; QTest::newRow("Invert") << QStringLiteral("invert") << false << xc << true; QTest::newRow("Invert-GL") << QStringLiteral("invert") << true << oc << true; QTest::newRow("Kscreen") << QStringLiteral("kscreen") << true << xc << true; QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << false << xc << true; QTest::newRow("LookingGlass-GL") << QStringLiteral("lookingglass") << true << oc << true; QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false << xc << true; QTest::newRow("MagicLamp-GL") << QStringLiteral("magiclamp") << true << oc << true; QTest::newRow("MagicLamp-GL-no-anim") << QStringLiteral("magiclamp") << false << oc << false; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << true << xc << true; QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << true << xc << true; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << true << xc << true; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true << xc << true; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true << xc << true; QTest::newRow("Resize") << QStringLiteral("resize") << true << xc << true; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << true << xc << true; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << true << xc << true; QTest::newRow("Sheet") << QStringLiteral("sheet") << false << xc << true; QTest::newRow("Sheet-GL") << QStringLiteral("sheet") << true << oc << true; QTest::newRow("Sheet-GL-no-anim") << QStringLiteral("sheet") << false << oc << false; QTest::newRow("ShowFps") << QStringLiteral("showfps") << true << xc << true; QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << true << xc << true; QTest::newRow("Slide") << QStringLiteral("slide") << true << xc << true; QTest::newRow("SlideBack") << QStringLiteral("slideback") << true << xc << true; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << true << xc << true; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << true << xc << true; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false << xc << true; QTest::newRow("StartupFeedback-GL") << QStringLiteral("startupfeedback") << true << oc << true; QTest::newRow("ThumbnailAside") << QStringLiteral("thumbnailaside") << true << xc << true; QTest::newRow("TouchPoints") << QStringLiteral("touchpoints") << true << xc << true; QTest::newRow("TrackMouse") << QStringLiteral("trackmouse") << true << xc << true; QTest::newRow("WindowGeometry") << QStringLiteral("windowgeometry") << true << xc << true; QTest::newRow("WobblyWindows") << QStringLiteral("wobblywindows") << false << xc << true; QTest::newRow("WobblyWindows-GL") << QStringLiteral("wobblywindows") << true << oc << true; QTest::newRow("WobblyWindows-GL-no-anim") << QStringLiteral("wobblywindows") << false << oc << false; QTest::newRow("Zoom") << QStringLiteral("zoom") << true << xc << true; QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false << xc << true; QTest::newRow("Fade - Scripted") << QStringLiteral("fade") << false << xc << true; QTest::newRow("Fade - Scripted + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << false << xc << true; } void TestBuiltInEffectLoader::testSupported() { QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::CompositingType, type); QFETCH(bool, animationsSupported); MockEffectsHandler mockHandler(type); mockHandler.setAnimationsSupported(animationsSupported); QCOMPARE(mockHandler.animationsSupported(), animationsSupported); KWin::BuiltInEffectLoader loader; QCOMPARE(loader.isEffectSupported(name), expected); } void TestBuiltInEffectLoader::testLoadEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("type"); const KWin::CompositingType xc = KWin::XRenderCompositing; const KWin::CompositingType oc = KWin::OpenGL2Compositing; QTest::newRow("blur") << QStringLiteral("blur") << false << xc; // fails for GL as it does proper tests on what's supported and doesn't just check whether it's GL QTest::newRow("blur-GL") << QStringLiteral("blur") << false << oc; + QTest::newRow("Colorpicker") << QStringLiteral("colorpicker") << false << xc; + QTest::newRow("Colorpicker-GL") << QStringLiteral("colorpicker") << true << oc; QTest::newRow("Contrast") << QStringLiteral("contrast") << false << xc; // fails for GL as it does proper tests on what's supported and doesn't just check whether it's GL QTest::newRow("Contrast-GL") << QStringLiteral("contrast") << false << oc; QTest::newRow("CoverSwitch") << QStringLiteral("coverswitch") << false << xc; // TODO: needs GL mocking // QTest::newRow("CoverSwitch-GL") << QStringLiteral("coverswitch") << true << oc; QTest::newRow("Cube") << QStringLiteral("cube") << false << xc; // TODO: needs GL mocking // QTest::newRow("Cube-GL") << QStringLiteral("cube") << true << oc; QTest::newRow("CubeSlide") << QStringLiteral("cubeslide") << false << xc; QTest::newRow("CubeSlide-GL") << QStringLiteral("cubeslide") << true << oc; QTest::newRow("DesktopGrid") << QStringLiteral("desktopgrid") << true << xc; QTest::newRow("DimInactive") << QStringLiteral("diminactive") << true << xc; QTest::newRow("DimScreen") << QStringLiteral("dimScreen") << true << xc; QTest::newRow("FallApart") << QStringLiteral("fallapart") << false << xc; QTest::newRow("FallApart-GL") << QStringLiteral("fallapart") << true << oc; QTest::newRow("FlipSwitch") << QStringLiteral("flipswitch") << false << xc; QTest::newRow("FlipSwitch-GL") << QStringLiteral("flipswitch") << true << oc; QTest::newRow("Glide") << QStringLiteral("glide") << false << xc; QTest::newRow("Glide-GL") << QStringLiteral("glide") << true << oc; QTest::newRow("HighlightWindow") << QStringLiteral("highlightwindow") << true << xc; QTest::newRow("Invert") << QStringLiteral("invert") << false << xc; QTest::newRow("Invert-GL") << QStringLiteral("invert") << true << oc; QTest::newRow("Kscreen") << QStringLiteral("kscreen") << true << xc; QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << false << xc; QTest::newRow("LookingGlass-GL") << QStringLiteral("lookingglass") << true << oc; QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false << xc; QTest::newRow("MagicLamp-GL") << QStringLiteral("magiclamp") << true << oc; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << true << xc; QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << true << xc; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << true << xc; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true << xc; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true << xc; QTest::newRow("Resize") << QStringLiteral("resize") << true << xc; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << true << xc; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << true << xc; QTest::newRow("Sheet") << QStringLiteral("sheet") << false << xc; QTest::newRow("Sheet-GL") << QStringLiteral("sheet") << true << oc; // TODO: Accesses EffectFrame and crashes // QTest::newRow("ShowFps") << QStringLiteral("showfps") << true << xc; QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << true << xc; QTest::newRow("Slide") << QStringLiteral("slide") << true << xc; QTest::newRow("SlideBack") << QStringLiteral("slideback") << true << xc; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << true << xc; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << true << xc; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false << xc; // Tries to load shader and makes our test abort // QTest::newRow("StartupFeedback-GL") << QStringLiteral("startupfeedback") << true << oc; QTest::newRow("ThumbnailAside") << QStringLiteral("thumbnailaside") << true << xc; QTest::newRow("Touchpoints") << QStringLiteral("touchpoints") << true << xc; QTest::newRow("TrackMouse") << QStringLiteral("trackmouse") << true << xc; // TODO: Accesses EffectFrame and crashes // QTest::newRow("WindowGeometry") << QStringLiteral("windowgeometry") << true << xc; QTest::newRow("WobblyWindows") << QStringLiteral("wobblywindows") << false << xc; QTest::newRow("WobblyWindows-GL") << QStringLiteral("wobblywindows") << true << oc; QTest::newRow("Zoom") << QStringLiteral("zoom") << true << xc; QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false << xc; QTest::newRow("Fade - Scripted") << QStringLiteral("fade") << false << xc; QTest::newRow("Fade - Scripted + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << false << xc; } void TestBuiltInEffectLoader::testLoadEffect() { QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::CompositingType, type); MockEffectsHandler mockHandler(type); KWin::BuiltInEffectLoader loader; KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::BuiltInEffectLoader::effectLoaded, [&name](KWin::Effect *effect, const QString &effectName) { QCOMPARE(effectName, name); 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 arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name); } 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 arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name); } } void TestBuiltInEffectLoader::testLoadBuiltInEffect_data() { // TODO: this test cannot yet test the checkEnabledByDefault functionality as that requires // mocking enough of GL to get the blur effect to think it's supported and enabled by default QTest::addColumn("effect"); QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("type"); QTest::addColumn("loadFlags"); const KWin::CompositingType xc = KWin::XRenderCompositing; const KWin::CompositingType oc = KWin::OpenGL2Compositing; 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, but not supported QTest::newRow("blur") << KWin::BuiltInEffect::Blur << QStringLiteral("blur") << false << oc << checkDefault; // enabled by default QTest::newRow("HighlightWindow") << KWin::BuiltInEffect::HighlightWindow << QStringLiteral("highlightwindow") << true << xc << checkDefault; // supported but not enabled by default QTest::newRow("LookingGlass-GL") << KWin::BuiltInEffect::LookingGlass << QStringLiteral("lookingglass") << true << oc << checkDefault; // not enabled by default QTest::newRow("MouseClick") << KWin::BuiltInEffect::MouseClick << QStringLiteral("mouseclick") << true << xc << checkDefault; // Force an Effect which will load QTest::newRow("MouseClick-Force") << KWin::BuiltInEffect::MouseClick << QStringLiteral("mouseclick") << true << xc << forceFlags; // Force an Effect which is not supported QTest::newRow("LookingGlass-Force") << KWin::BuiltInEffect::LookingGlass << QStringLiteral("lookingglass") << false << xc << forceFlags; // Force the Effect as supported QTest::newRow("LookingGlass-Force-GL") << KWin::BuiltInEffect::LookingGlass << QStringLiteral("lookingglass") << true << oc << forceFlags; // Enforce no load of effect which is enabled by default QTest::newRow("HighlightWindow-DontLoad") << KWin::BuiltInEffect::HighlightWindow << QStringLiteral("highlightwindow") << false << xc << dontLoadFlags; // Enforce no load of effect which is not enabled by default, but enforced QTest::newRow("MouseClick-DontLoad") << KWin::BuiltInEffect::MouseClick << QStringLiteral("mouseclick") << false << xc << dontLoadFlags; } void TestBuiltInEffectLoader::testLoadBuiltInEffect() { QFETCH(KWin::BuiltInEffect, effect); QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::CompositingType, type); QFETCH(KWin::LoadEffectFlags, loadFlags); MockEffectsHandler mockHandler(type); KWin::BuiltInEffectLoader loader; KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::BuiltInEffectLoader::effectLoaded, [&name](KWin::Effect *effect, const QString &effectName) { QCOMPARE(effectName, name); effect->deleteLater(); } ); // try to load the Effect QCOMPARE(loader.loadEffect(effect, loadFlags), expected); // loading again should fail QVERIFY(!loader.loadEffect(effect, 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 arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name); } 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(effect, 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 arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name); } } void TestBuiltInEffectLoader::testLoadAllEffects() { MockEffectsHandler mockHandler(KWin::XRenderCompositing); KWin::BuiltInEffectLoader loader; KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); // prepare the configuration to hard enable/disable the effects we want to load KConfigGroup plugins = config->group("Plugins"); plugins.writeEntry(QStringLiteral("desktopgridEnabled"), false); plugins.writeEntry(QStringLiteral("highlightwindowEnabled"), false); plugins.writeEntry(QStringLiteral("kscreenEnabled"), false); plugins.writeEntry(QStringLiteral("minimizeanimationEnabled"), false); plugins.writeEntry(QStringLiteral("presentwindowsEnabled"), false); plugins.writeEntry(QStringLiteral("screenedgeEnabled"), false); plugins.writeEntry(QStringLiteral("screenshotEnabled"), false); plugins.writeEntry(QStringLiteral("slideEnabled"), false); plugins.writeEntry(QStringLiteral("slidingpopupsEnabled"), false); plugins.writeEntry(QStringLiteral("startupfeedbackEnabled"), false); plugins.writeEntry(QStringLiteral("zoomEnabled"), false); // enable lookingglass as it's not supported plugins.writeEntry(QStringLiteral("lookingglassEnabled"), true); plugins.sync(); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::BuiltInEffectLoader::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 QVERIFY(!spy.wait(10)); // now let's prepare a config which has one effect explicitly enabled plugins.writeEntry(QStringLiteral("mouseclickEnabled"), true); plugins.sync(); loader.queryAndLoadAll(); // should load one effect in first go QVERIFY(spy.wait(10)); // 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 arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), QStringLiteral("mouseclick")); spy.clear(); // let's delete one of the default entries plugins.deleteEntry(QStringLiteral("kscreenEnabled")); plugins.sync(); QVERIFY(spy.isEmpty()); loader.queryAndLoadAll(); // let's use qWait as we need to wait for two signals to be emitted QTest::qWait(100); QCOMPARE(spy.size(), 2); QStringList loadedEffects; for (auto &list : spy) { QCOMPARE(list.size(), 2); loadedEffects << list.at(1).toString(); } qSort(loadedEffects); QCOMPARE(loadedEffects.at(0), QStringLiteral("kscreen")); QCOMPARE(loadedEffects.at(1), QStringLiteral("mouseclick")); } Q_CONSTRUCTOR_FUNCTION(forceXcb) QTEST_MAIN(TestBuiltInEffectLoader) #include "test_builtin_effectloader.moc" diff --git a/autotests/test_plugin_effectloader.cpp b/autotests/test_plugin_effectloader.cpp index f010847f2..ddea2caff 100644 --- a/autotests/test_plugin_effectloader.cpp +++ b/autotests/test_plugin_effectloader.cpp @@ -1,417 +1,418 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2014 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 "../effectloader.h" #include "mock_effectshandler.h" #include "../scripting/scriptedeffect.h" // for mocking ScriptedEffect::create // KDE #include #include #include // Qt #include #include Q_DECLARE_METATYPE(KWin::CompositingType) Q_DECLARE_METATYPE(KWin::LoadEffectFlag) Q_DECLARE_METATYPE(KWin::LoadEffectFlags) Q_DECLARE_METATYPE(KWin::Effect*) Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core") namespace KWin { ScriptedEffect *ScriptedEffect::create(const KPluginMetaData&) { return nullptr; } bool ScriptedEffect::supported() { return true; } } class TestPluginEffectLoader : public QObject { Q_OBJECT private Q_SLOTS: void testHasEffect_data(); void testHasEffect(); void testKnownEffects(); void testSupported_data(); void testSupported(); void testLoadEffect_data(); void testLoadEffect(); void testLoadPluginEffect_data(); void testLoadPluginEffect(); void testLoadAllEffects(); void testCancelLoadAllEffects(); }; void TestPluginEffectLoader::testHasEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); // all the built-in effects should fail QTest::newRow("blur") << QStringLiteral("blur") << false; + QTest::newRow("ColorPicker") << QStringLiteral("colorpicker") << false; 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("DimScreen") << QStringLiteral("dimscreen") << 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("LookingGlass") << QStringLiteral("lookingglass") << false; QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << false; QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << 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; // all the scripted effects should fail QTest::newRow("Fade") << QStringLiteral("kwin4_effect_fade") << false; QTest::newRow("FadeDesktop") << QStringLiteral("kwin4_effect_fadedesktop") << false; QTest::newRow("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << false; QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << false; QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << false; QTest::newRow("ScaleIn") << QStringLiteral("kwin4_effect_scalein") << false; QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << false; // and the fake effects we use here QTest::newRow("fakeeffectplugin") << QStringLiteral("fakeeffectplugin") << true; QTest::newRow("fakeeffectplugin CS") << QStringLiteral("fakeEffectPlugin") << true; QTest::newRow("effectversion") << QStringLiteral("effectversion") << true; } void TestPluginEffectLoader::testHasEffect() { QFETCH(QString, name); QFETCH(bool, expected); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); QCOMPARE(loader.hasEffect(name), expected); } void TestPluginEffectLoader::testKnownEffects() { QStringList expectedEffects; expectedEffects << QStringLiteral("fakeeffectplugin") << QStringLiteral("effectversion"); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); 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 TestPluginEffectLoader::testSupported_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("type"); const KWin::CompositingType xc = KWin::XRenderCompositing; const KWin::CompositingType oc = KWin::OpenGL2Compositing; QTest::newRow("invalid") << QStringLiteral("blur") << false << xc; QTest::newRow("fake - xrender") << QStringLiteral("fakeeffectplugin") << false << xc; QTest::newRow("fake - opengl") << QStringLiteral("fakeeffectplugin") << true << oc; QTest::newRow("fake - CS") << QStringLiteral("fakeEffectPlugin") << true << oc; QTest::newRow("version") << QStringLiteral("effectversion") << false << xc; } void TestPluginEffectLoader::testSupported() { QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::CompositingType, type); MockEffectsHandler mockHandler(type); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); QCOMPARE(loader.isEffectSupported(name), expected); } void TestPluginEffectLoader::testLoadEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("type"); const KWin::CompositingType xc = KWin::XRenderCompositing; const KWin::CompositingType oc = KWin::OpenGL2Compositing; QTest::newRow("invalid") << QStringLiteral("slide") << false << xc; QTest::newRow("fake - xrender") << QStringLiteral("fakeeffectplugin") << false << xc; QTest::newRow("fake - opengl") << QStringLiteral("fakeeffectplugin") << true << oc; QTest::newRow("fake - CS") << QStringLiteral("fakeEffectPlugin") << true << oc; QTest::newRow("version") << QStringLiteral("effectversion") << false << xc; } void TestPluginEffectLoader::testLoadEffect() { QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::CompositingType, type); MockEffectsHandler mockHandler(type); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::PluginEffectLoader::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 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 arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name.toLower()); } } void TestPluginEffectLoader::testLoadPluginEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("type"); QTest::addColumn("loadFlags"); QTest::addColumn("enabledByDefault"); const KWin::CompositingType xc = KWin::XRenderCompositing; const KWin::CompositingType oc = KWin::OpenGL2Compositing; 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, but not supported QTest::newRow("fakeeffectplugin") << QStringLiteral("fakeeffectplugin") << false << xc << checkDefault << false; // enabled by default, check default false QTest::newRow("supported, check default error") << QStringLiteral("fakeeffectplugin") << false << oc << checkDefault << false; // enabled by default, check default true QTest::newRow("supported, check default") << QStringLiteral("fakeeffectplugin") << true << oc << checkDefault << true; // enabled by default, check default false QTest::newRow("supported, check default error, forced") << QStringLiteral("fakeeffectplugin") << true << oc << forceFlags << false; // enabled by default, check default true QTest::newRow("supported, check default, don't load") << QStringLiteral("fakeeffectplugin") << false << oc << dontLoadFlags << true; // incorrect version QTest::newRow("Version") << QStringLiteral("effectversion") << false << xc << forceFlags << true; } void TestPluginEffectLoader::testLoadPluginEffect() { QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::CompositingType, type); QFETCH(KWin::LoadEffectFlags, loadFlags); QFETCH(bool, enabledByDefault); MockEffectsHandler mockHandler(type); mockHandler.setProperty("testEnabledByDefault", enabledByDefault); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); loader.setConfig(config); const auto plugins = KPluginLoader::findPlugins(QString(), [name] (const KPluginMetaData &data) { return data.pluginId().compare(name, Qt::CaseInsensitive) == 0 && data.serviceTypes().contains(QStringLiteral("KWin/Effect")); } ); QCOMPARE(plugins.size(), 1); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::PluginEffectLoader::effectLoaded, [&name](KWin::Effect *effect, const QString &effectName) { QCOMPARE(effectName, name); effect->deleteLater(); } ); // try to load the Effect QCOMPARE(loader.loadEffect(plugins.first(), loadFlags), expected); // loading again should fail QVERIFY(!loader.loadEffect(plugins.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 arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name); } 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(plugins.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 arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name); } } void TestPluginEffectLoader::testLoadAllEffects() { MockEffectsHandler mockHandler(KWin::OpenGL2Compositing); mockHandler.setProperty("testEnabledByDefault", true); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); // prepare the configuration to hard enable/disable the effects we want to load KConfigGroup plugins = config->group("Plugins"); plugins.writeEntry(QStringLiteral("fakeeffectpluginEnabled"), false); plugins.sync(); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::PluginEffectLoader::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 plugins.writeEntry(QStringLiteral("fakeeffectpluginEnabled"), true); 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 arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), QStringLiteral("fakeeffectplugin")); spy.clear(); } void TestPluginEffectLoader::testCancelLoadAllEffects() { // this test verifies that no test gets loaded when the loader gets cleared MockEffectsHandler mockHandler(KWin::OpenGL2Compositing); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); // prepare the configuration to hard enable/disable the effects we want to load KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); KConfigGroup plugins = config->group("Plugins"); plugins.writeEntry(QStringLiteral("fakeeffectpluginEnabled"), true); plugins.sync(); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, &KWin::PluginEffectLoader::effectLoaded); QVERIFY(spy.isValid()); loader.queryAndLoadAll(); loader.clear(); // Should not load any effect QVERIFY(!spy.wait(100)); QVERIFY(spy.isEmpty()); } QTEST_MAIN(TestPluginEffectLoader) #include "test_plugin_effectloader.moc" diff --git a/autotests/test_scripted_effectloader.cpp b/autotests/test_scripted_effectloader.cpp index f0e2049a0..84b1e9051 100644 --- a/autotests/test_scripted_effectloader.cpp +++ b/autotests/test_scripted_effectloader.cpp @@ -1,432 +1,433 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2014 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 "../effectloader.h" #include "mock_effectshandler.h" #include "../scripting/scriptedeffect.h" // for mocking #include "../input.h" #include "../screenedge.h" // KDE #include #include #include // Qt #include #include Q_DECLARE_METATYPE(KWin::LoadEffectFlag) Q_DECLARE_METATYPE(KWin::LoadEffectFlags) Q_DECLARE_METATYPE(KWin::Effect*) Q_DECLARE_METATYPE(KSharedConfigPtr) Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core") namespace KWin { ScreenEdges *ScreenEdges::s_self = nullptr; void ScreenEdges::reserve(ElectricBorder, QObject *, const char *) { } 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: void initTestCase(); void testHasEffect_data(); void testHasEffect(); void testKnownEffects(); void testLoadEffect_data(); void testLoadEffect(); void testLoadScriptedEffect_data(); void testLoadScriptedEffect(); void testLoadAllEffects(); void testCancelLoadAllEffects(); }; void TestScriptedEffectLoader::initTestCase() { auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); QCoreApplication::instance()->setProperty("config", QVariant::fromValue(config)); } void TestScriptedEffectLoader::testHasEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); // all the built-in effects should fail QTest::newRow("blur") << QStringLiteral("blur") << false; + QTest::newRow("Colorpicker") << QStringLiteral("colorpicker") << false; 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("DimScreen") << QStringLiteral("dimscreen") << 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("MinimizeAnimation") << QStringLiteral("minimizeanimation") << 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; 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("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << true; QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << true; QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << true; QTest::newRow("ScaleIn") << QStringLiteral("kwin4_effect_scalein") << true; QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << true; } void TestScriptedEffectLoader::testHasEffect() { QFETCH(QString, name); QFETCH(bool, expected); MockEffectsHandler mockHandler(KWin::XRenderCompositing); KWin::ScriptedEffectLoader loader; QCOMPARE(loader.hasEffect(name), expected); // each available effect should also be supported QCOMPARE(loader.isEffectSupported(name), expected); if (expected) { mockHandler.setAnimationsSupported(false); QVERIFY(!loader.isEffectSupported(name)); } } void TestScriptedEffectLoader::testKnownEffects() { QStringList expectedEffects; expectedEffects << QStringLiteral("kwin4_effect_dialogparent") << QStringLiteral("kwin4_effect_fade") << QStringLiteral("kwin4_effect_fadedesktop") << QStringLiteral("kwin4_effect_login") << QStringLiteral("kwin4_effect_maximize") << QStringLiteral("kwin4_effect_scalein") << QStringLiteral("kwin4_effect_translucency"); 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("name"); QTest::addColumn("expected"); QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false; QTest::newRow("Fade - without kwin4_effect") << QStringLiteral("fade") << false; 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("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << true; QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << true; QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << true; QTest::newRow("ScaleIn") << QStringLiteral("kwin4_effect_scalein") << true; QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << true; } void TestScriptedEffectLoader::testLoadEffect() { QFETCH(QString, name); QFETCH(bool, expected); MockEffectsHandler mockHandler(KWin::XRenderCompositing); KWin::ScriptedEffectLoader loader; KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // 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 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 arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name.toLower()); } } void TestScriptedEffectLoader::testLoadScriptedEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("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 QTest::newRow("Fade") << QStringLiteral("kwin4_effect_fade") << true << checkDefault; // not enabled by default QTest::newRow("Scalein") << QStringLiteral("kwin4_effect_scalein") << true << checkDefault; // Force an Effect which will load QTest::newRow("Scalein-Force") << QStringLiteral("kwin4_effect_scalein") << true << forceFlags; // Enforce no load of effect which is enabled by default QTest::newRow("Fade-DontLoad") << QStringLiteral("kwin4_effect_fade") << false << dontLoadFlags; // Enforce no load of effect which is not enabled by default, but enforced QTest::newRow("Scalein-DontLoad") << QStringLiteral("kwin4_effect_scalein") << false << dontLoadFlags; } void TestScriptedEffectLoader::testLoadScriptedEffect() { QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::LoadEffectFlags, loadFlags); MockEffectsHandler mockHandler(KWin::XRenderCompositing); KWin::ScriptedEffectLoader loader; KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); loader.setConfig(config); 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; } ); QCOMPARE(services.count(), 1); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // 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 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 arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name.toLower()); } } void TestScriptedEffectLoader::testLoadAllEffects() { MockEffectsHandler mockHandler(KWin::XRenderCompositing); 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); plugins.writeEntry(kwin4 + QStringLiteral("fadeEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("fadedesktopEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("loginEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("maximizeEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("minimizeanimationEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("scaleinEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("translucencyEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("eyeonscreenEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("windowapertureEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("morphingpopupsEnabled"), false); plugins.sync(); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // 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 plugins.writeEntry(kwin4 + QStringLiteral("scaleinEnabled"), true); 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 arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), kwin4 + QStringLiteral("scalein")); 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 QTRY_COMPARE(spy.size(), 2); QStringList loadedEffects; for (auto &list : spy) { QCOMPARE(list.size(), 2); loadedEffects << list.at(1).toString(); } qSort(loadedEffects); QCOMPARE(loadedEffects.at(0), kwin4 + QStringLiteral("fade")); QCOMPARE(loadedEffects.at(1), kwin4 + QStringLiteral("scalein")); } 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"); plugins.writeEntry(kwin4 + QStringLiteral("scaleinEnabled"), true); plugins.sync(); loader.setConfig(config); qRegisterMetaType(); 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()); } QTEST_MAIN(TestScriptedEffectLoader) #include "test_scripted_effectloader.moc" diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt index 9142a5738..74a0b1be0 100644 --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -1,187 +1,188 @@ # KI18N Translation Domain for this library add_definitions(-DTRANSLATION_DOMAIN=\"kwin_effects\" -DEFFECT_BUILTINS) include_directories(${KWIN_SOURCE_DIR}) # for xcbutils.h set(kwin_effect_OWN_LIBS kwineffects ) if( KWIN_HAVE_XRENDER_COMPOSITING ) set(kwin_effect_OWN_LIBS ${kwin_effect_OWN_LIBS} kwinxrenderutils) endif() set(kwin_effect_KDE_LIBS KF5::ConfigGui KF5::ConfigWidgets KF5::GlobalAccel KF5::I18n KF5::WindowSystem KF5::Plasma # screenedge effect KF5::IconThemes KF5::Service KF5::Notifications # screenshot effect ) set(kwin_effect_QT_LIBS Qt5::Concurrent Qt5::DBus Qt5::Quick Qt5::X11Extras ) set(kwin_effect_XLIB_LIBS ${X11_X11_LIB} ) set(kwin_effect_XCB_LIBS XCB::XCB XCB::IMAGE XCB::XFIXES ) if( KWIN_HAVE_XRENDER_COMPOSITING ) set(kwin_effect_XCB_LIBS ${kwin_effect_XCB_LIBS} XCB::RENDER) endif() set(kwin_effect_OWN_LIBS ${kwin_effect_OWN_LIBS} kwinglutils) macro( KWIN4_ADD_EFFECT_BACKEND name ) add_library( ${name} SHARED ${ARGN} ) target_link_libraries( ${name} PRIVATE ${kwin_effect_OWN_LIBS} ${kwin_effect_KDE_LIBS} ${kwin_effect_QT_LIBS} ${kwin_effect_XLIB_LIBS} ${kwin_effect_XCB_LIBS}) endmacro() # Adds effect plugin with given name. Sources are given after the name macro( KWIN4_ADD_EFFECT name ) kwin4_add_effect_backend(kwin4_effect_${name} ${ARGN}) set_target_properties(kwin4_effect_${name} PROPERTIES VERSION 1.0.0 SOVERSION 1 ) set_target_properties(kwin4_effect_${name} PROPERTIES OUTPUT_NAME ${KWIN_NAME}4_effect_${name}) install(TARGETS kwin4_effect_${name} ${INSTALL_TARGETS_DEFAULT_ARGS} ) endmacro() # Install the KWin/Effect service type install( FILES kwineffect.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR} ) # Create initial variables set( kwin4_effect_include_directories ) set( kwin4_effect_builtins_sources logging.cpp effect_builtins.cpp blur/blur.cpp blur/blurshader.cpp + colorpicker/colorpicker.cpp cube/cube.cpp cube/cube_proxy.cpp cube/cubeslide.cpp coverswitch/coverswitch.cpp desktopgrid/desktopgrid.cpp diminactive/diminactive.cpp flipswitch/flipswitch.cpp glide/glide.cpp invert/invert.cpp lookingglass/lookingglass.cpp magiclamp/magiclamp.cpp magnifier/magnifier.cpp mouseclick/mouseclick.cpp mousemark/mousemark.cpp presentwindows/presentwindows.cpp presentwindows/presentwindows_proxy.cpp resize/resize.cpp showfps/showfps.cpp thumbnailaside/thumbnailaside.cpp touchpoints/touchpoints.cpp trackmouse/trackmouse.cpp windowgeometry/windowgeometry.cpp wobblywindows/wobblywindows.cpp zoom/zoom.cpp ) qt5_add_resources( kwin4_effect_builtins_sources shaders.qrc ) kconfig_add_kcfg_files(kwin4_effect_builtins_sources blur/blurconfig.kcfgc cube/cubeslideconfig.kcfgc cube/cubeconfig.kcfgc coverswitch/coverswitchconfig.kcfgc desktopgrid/desktopgridconfig.kcfgc diminactive/diminactiveconfig.kcfgc fallapart/fallapartconfig.kcfgc flipswitch/flipswitchconfig.kcfgc glide/glideconfig.kcfgc lookingglass/lookingglassconfig.kcfgc magiclamp/magiclampconfig.kcfgc magnifier/magnifierconfig.kcfgc mouseclick/mouseclickconfig.kcfgc mousemark/mousemarkconfig.kcfgc presentwindows/presentwindowsconfig.kcfgc resize/resizeconfig.kcfgc showfps/showfpsconfig.kcfgc slidingpopups/slidingpopupsconfig.kcfgc thumbnailaside/thumbnailasideconfig.kcfgc trackmouse/trackmouseconfig.kcfgc windowgeometry/windowgeometryconfig.kcfgc wobblywindows/wobblywindowsconfig.kcfgc zoom/zoomconfig.kcfgc ) # scripted effects add_subdirectory( dialogparent ) add_subdirectory( eyeonscreen ) add_subdirectory( fade ) add_subdirectory( fadedesktop ) add_subdirectory( login ) add_subdirectory( maximize ) add_subdirectory( morphingpopups ) add_subdirectory( scalein ) add_subdirectory( translucency ) add_subdirectory( windowaperture ) ############################################################################### # Built-in effects go here # Common effects add_subdirectory( desktopgrid ) add_subdirectory( diminactive ) include( dimscreen/CMakeLists.txt ) include( fallapart/CMakeLists.txt ) include( highlightwindow/CMakeLists.txt ) include( kscreen/CMakeLists.txt ) add_subdirectory( magiclamp ) include( minimizeanimation/CMakeLists.txt ) add_subdirectory( presentwindows ) add_subdirectory( resize ) include( screenedge/CMakeLists.txt ) add_subdirectory( showfps ) include( showpaint/CMakeLists.txt ) include( slide/CMakeLists.txt ) include( slideback/CMakeLists.txt ) include( slidingpopups/CMakeLists.txt ) add_subdirectory( thumbnailaside ) add_subdirectory( windowgeometry ) add_subdirectory( zoom ) # OpenGL-specific effects add_subdirectory( blur ) include( backgroundcontrast/CMakeLists.txt ) add_subdirectory( coverswitch ) add_subdirectory( cube ) add_subdirectory( flipswitch ) add_subdirectory( glide ) add_subdirectory( invert ) add_subdirectory( lookingglass ) add_subdirectory( magnifier ) add_subdirectory( mouseclick ) add_subdirectory( mousemark ) include( screenshot/CMakeLists.txt ) include( sheet/CMakeLists.txt ) include( snaphelper/CMakeLists.txt ) include( startupfeedback/CMakeLists.txt ) add_subdirectory( trackmouse ) add_subdirectory( wobblywindows ) ############################################################################### # Add the builtins plugin kwin4_add_effect( builtins ${kwin4_effect_builtins_sources} ) diff --git a/effects/colorpicker/colorpicker.cpp b/effects/colorpicker/colorpicker.cpp new file mode 100644 index 000000000..200bfc8a6 --- /dev/null +++ b/effects/colorpicker/colorpicker.cpp @@ -0,0 +1,143 @@ +/******************************************************************** + 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 "colorpicker.h" +#include +#include +#include +#include +#include + +Q_DECLARE_METATYPE(QColor) + +QDBusArgument &operator<< (QDBusArgument &argument, const QColor &color) +{ + argument.beginStructure(); + argument << color.rgba(); + argument.endStructure(); + return argument; +} + +const QDBusArgument &operator>>(const QDBusArgument &argument, QColor &color) +{ + argument.beginStructure(); + QRgb rgba; + argument >> rgba; + argument.endStructure(); + color = QColor::fromRgba(rgba); + return argument; +} + +namespace KWin +{ + +bool ColorPickerEffect::supported() +{ + return effects->isOpenGLCompositing(); +} + +ColorPickerEffect::ColorPickerEffect() + : m_scheduledPosition(QPoint(-1, -1)) +{ + qDBusRegisterMetaType(); + QDBusConnection::sessionBus().registerObject(QStringLiteral("/ColorPicker"), this, QDBusConnection::ExportScriptableContents); +} + +ColorPickerEffect::~ColorPickerEffect() = default; + +void ColorPickerEffect::paintScreen(int mask, QRegion region, ScreenPaintData &data) +{ + m_cachedOutputGeometry = data.outputGeometry(); + effects->paintScreen(mask, region, data); + + if (m_infoFrame) { + m_infoFrame->render(region); + } +} + +void ColorPickerEffect::postPaintScreen() +{ + effects->postPaintScreen(); + + if (m_scheduledPosition != QPoint(-1, -1) && (m_cachedOutputGeometry.isEmpty() || m_cachedOutputGeometry.contains(m_scheduledPosition))) { + uint8_t data[3]; + const QRect geo = GLRenderTarget::virtualScreenGeometry(); + glReadnPixels(m_scheduledPosition.x() - geo.x(), geo.height() - geo.y() - m_scheduledPosition.y(), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, 3, data); + QDBusConnection::sessionBus().send(m_replyMessage.createReply(QColor(data[0], data[1], data[2]))); + m_picking = false; + m_scheduledPosition = QPoint(-1, -1); + } +} + +QColor ColorPickerEffect::pick() +{ + if (!calledFromDBus()) { + return QColor(); + } + if (m_picking) { + sendErrorReply(QDBusError::Failed, "Color picking is already in progress"); + return QColor(); + } + m_picking = true; + m_replyMessage = message(); + setDelayedReply(true); + showInfoMessage(); + effects->startInteractivePositionSelection( + [this] (const QPoint &p) { + hideInfoMessage(); + if (p == QPoint(-1, -1)) { + // error condition + QDBusConnection::sessionBus().send(m_replyMessage.createErrorReply(QStringLiteral("org.kde.kwin.ColorPicker.Error.Cancelled"), "Color picking got cancelled")); + m_picking = false; + } else { + m_scheduledPosition = p; + effects->addRepaintFull(); + } + } + ); + return QColor(); +} + +void ColorPickerEffect::showInfoMessage() +{ + if (!m_infoFrame.isNull()) { + return; + } + // TODO: turn the info message into a system wide service which performs hiding on mouse over + m_infoFrame.reset(effects->effectFrame(EffectFrameStyled, false)); + QFont font; + font.setBold(true); + m_infoFrame->setFont(font); + QRect area = effects->clientArea(ScreenArea, effects->activeScreen(), effects->currentDesktop()); + m_infoFrame->setPosition(QPoint(area.x() + area.width() / 2, area.y() + area.height() / 3)); + m_infoFrame->setText(i18n("Select a position for color picking with left click or enter.\nEscape or right click to cancel.")); + effects->addRepaintFull(); +} + +void ColorPickerEffect::hideInfoMessage() +{ + m_infoFrame.reset(); +} + +bool ColorPickerEffect::isActive() const +{ + return m_picking && ((m_scheduledPosition != QPoint(-1, -1)) || !m_infoFrame.isNull()) && !effects->isScreenLocked(); +} + +} // namespace diff --git a/effects/colorpicker/colorpicker.h b/effects/colorpicker/colorpicker.h new file mode 100644 index 000000000..eab9410d8 --- /dev/null +++ b/effects/colorpicker/colorpicker.h @@ -0,0 +1,66 @@ +/******************************************************************** + 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 . +*********************************************************************/ +#ifndef KWIN_COLORPICKER_H +#define KWIN_COLORPICKER_H + +#include +#include +#include +#include +#include +#include + +namespace KWin +{ + +class ColorPickerEffect : public Effect, protected QDBusContext +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.ColorPicker") +public: + ColorPickerEffect(); + virtual ~ColorPickerEffect(); + void paintScreen(int mask, QRegion region, ScreenPaintData &data) override; + void postPaintScreen() override; + bool isActive() const override; + + int requestedEffectChainPosition() const override { + return 50; + } + + static bool supported(); + +public Q_SLOTS: + Q_SCRIPTABLE QColor pick(); + +private: + void showInfoMessage(); + void hideInfoMessage(); + + QDBusMessage m_replyMessage; + QRect m_cachedOutputGeometry; + QPoint m_scheduledPosition; + bool m_picking = false; + QScopedPointer m_infoFrame; +}; + +} // namespace + +#endif diff --git a/effects/effect_builtins.cpp b/effects/effect_builtins.cpp index ea16a6e22..2783cf586 100644 --- a/effects/effect_builtins.cpp +++ b/effects/effect_builtins.cpp @@ -1,772 +1,788 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2014 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 "effect_builtins.h" #ifdef EFFECT_BUILTINS // common effects #include "backgroundcontrast/contrast.h" #include "blur/blur.h" +#include "colorpicker/colorpicker.h" #include "kscreen/kscreen.h" #include "presentwindows/presentwindows.h" #include "screenedge/screenedgeeffect.h" #include "screenshot/screenshot.h" #include "slidingpopups/slidingpopups.h" // Common effects only relevant to desktop #include "desktopgrid/desktopgrid.h" #include "diminactive/diminactive.h" #include "dimscreen/dimscreen.h" #include "fallapart/fallapart.h" #include "highlightwindow/highlightwindow.h" #include "magiclamp/magiclamp.h" #include "minimizeanimation/minimizeanimation.h" #include "resize/resize.h" #include "showfps/showfps.h" #include "showpaint/showpaint.h" #include "slide/slide.h" #include "slideback/slideback.h" #include "thumbnailaside/thumbnailaside.h" #include "touchpoints/touchpoints.h" #include "windowgeometry/windowgeometry.h" #include "zoom/zoom.h" // OpenGL-specific effects for desktop #include "coverswitch/coverswitch.h" #include "cube/cube.h" #include "cube/cubeslide.h" #include "flipswitch/flipswitch.h" #include "glide/glide.h" #include "invert/invert.h" #include "lookingglass/lookingglass.h" #include "magnifier/magnifier.h" #include "mouseclick/mouseclick.h" #include "mousemark/mousemark.h" #include "sheet/sheet.h" #include "snaphelper/snaphelper.h" #include "startupfeedback/startupfeedback.h" #include "trackmouse/trackmouse.h" #include "wobblywindows/wobblywindows.h" #endif #include #include #ifndef EFFECT_BUILTINS #define EFFECT_FALLBACK nullptr, nullptr, nullptr #else #define EFFECT_FALLBACK #endif namespace KWin { namespace BuiltInEffects { template inline Effect *createHelper() { return new T(); } static const QVector s_effectData = { { QString(), QString(), QString(), QString(), QString(), QUrl(), false, false, nullptr, nullptr, nullptr }, { QStringLiteral("blur"), i18ndc("kwin_effects", "Name of a KWin Effect", "Blur"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Blurs the background behind semi-transparent windows"), QStringLiteral("Appearance"), QString(), QUrl(), true, false, #ifdef EFFECT_BUILTINS &createHelper, &BlurEffect::supported, &BlurEffect::enabledByDefault #endif +EFFECT_FALLBACK + }, { + QStringLiteral("colorpicker"), + i18ndc("kwin_effects", "Name of a KWin Effect", "Color Picker"), + i18ndc("kwin_effects", "Comment describing the KWin Effect", "Supports picking a color"), + QStringLiteral("Accessibility"), + QString(), + QUrl(), + true, + true, +#ifdef EFFECT_BUILTINS + &createHelper, + &ColorPickerEffect::supported, + nullptr +#endif EFFECT_FALLBACK }, { QStringLiteral("contrast"), i18ndc("kwin_effects", "Name of a KWin Effect", "Background contrast"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Improve contrast and readability behind semi-transparent windows"), QStringLiteral("Appearance"), QString(), QUrl(), true, false, #ifdef EFFECT_BUILTINS &createHelper, &ContrastEffect::supported, &ContrastEffect::enabledByDefault #endif EFFECT_FALLBACK }, { QStringLiteral("coverswitch"), i18ndc("kwin_effects", "Name of a KWin Effect", "Cover Switch"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Display a Cover Flow effect for the alt+tab window switcher"), QStringLiteral("Window Management"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/cover_switch.mp4")), false, true, #ifdef EFFECT_BUILTINS &createHelper, &CoverSwitchEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("cube"), i18ndc("kwin_effects", "Name of a KWin Effect", "Desktop Cube"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Display each virtual desktop on a side of a cube"), QStringLiteral("Window Management"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/desktop_cube.ogv")), false, false, #ifdef EFFECT_BUILTINS &createHelper, &CubeEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("cubeslide"), i18ndc("kwin_effects", "Name of a KWin Effect", "Desktop Cube Animation"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Animate desktop switching with a cube"), QStringLiteral("Virtual Desktop Switching Animation"), QStringLiteral("desktop-animations"), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/desktop_cube_animation.ogv")), false, false, #ifdef EFFECT_BUILTINS &createHelper, &CubeSlideEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("desktopgrid"), i18ndc("kwin_effects", "Name of a KWin Effect", "Desktop Grid"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Zoom out so all desktops are displayed side-by-side in a grid"), QStringLiteral("Window Management"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/desktop_grid.mp4")), true, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("diminactive"), i18ndc("kwin_effects", "Name of a KWin Effect", "Dim Inactive"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Darken inactive windows"), QStringLiteral("Focus"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/dim_inactive.mp4")), false, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("dimscreen"), i18ndc("kwin_effects", "Name of a KWin Effect", "Dim Screen for Administrator Mode"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Darkens the entire screen when requesting root privileges"), QStringLiteral("Focus"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/dim_administration.mp4")), false, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("fallapart"), i18ndc("kwin_effects", "Name of a KWin Effect", "Fall Apart"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Closed windows fall into pieces"), QStringLiteral("Appearance"), QString(), QUrl(), false, false, #ifdef EFFECT_BUILTINS &createHelper, &FallApartEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("flipswitch"), i18ndc("kwin_effects", "Name of a KWin Effect", "Flip Switch"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Flip through windows that are in a stack for the alt+tab window switcher"), QStringLiteral("Window Management"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/flip_switch.mp4")), false, false, #ifdef EFFECT_BUILTINS &createHelper, &FlipSwitchEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("glide"), i18ndc("kwin_effects", "Name of a KWin Effect", "Glide"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Windows Glide Effect as they are open and closed"), QStringLiteral("Appearance"), QString(), QUrl(), false, false, #ifdef EFFECT_BUILTINS &createHelper, &GlideEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("highlightwindow"), i18ndc("kwin_effects", "Name of a KWin Effect", "Highlight Window"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Highlight the appropriate window when hovering over taskbar entries"), QStringLiteral("Appearance"), QString(), QUrl(), true, true, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("invert"), i18ndc("kwin_effects", "Name of a KWin Effect", "Invert"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Inverts the color of the desktop and windows"), QStringLiteral("Accessibility"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/invert.mp4")), false, false, #ifdef EFFECT_BUILTINS &createHelper, &InvertEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("kscreen"), i18ndc("kwin_effects", "Name of a KWin Effect", "Kscreen"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Helper Effect for KScreen"), QStringLiteral("Appearance"), QString(), QUrl(), true, true, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("lookingglass"), i18ndc("kwin_effects", "Name of a KWin Effect", "Looking Glass"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "A screen magnifier that looks like a fisheye lens"), QStringLiteral("Accessibility"), QStringLiteral("magnifiers"), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/looking_glass.ogv")), false, false, #ifdef EFFECT_BUILTINS &createHelper, &LookingGlassEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("magiclamp"), i18ndc("kwin_effects", "Name of a KWin Effect", "Magic Lamp"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Simulate a magic lamp when minimizing windows"), QStringLiteral("Appearance"), QStringLiteral("minimize"), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/magic_lamp.ogv")), false, false, #ifdef EFFECT_BUILTINS &createHelper, &MagicLampEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("magnifier"), i18ndc("kwin_effects", "Name of a KWin Effect", "Magnifier"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Magnify the section of the screen that is near the mouse cursor"), QStringLiteral("Accessibility"), QStringLiteral("magnifiers"), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/magnifier.ogv")), false, false, #ifdef EFFECT_BUILTINS &createHelper, &MagnifierEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("minimizeanimation"), i18ndc("kwin_effects", "Name of a KWin Effect", "Minimize Animation"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Animate the minimizing of windows"), QStringLiteral("Appearance"), QStringLiteral("minimize"), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/minimize.ogv")), true, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("mouseclick"), i18ndc("kwin_effects", "Name of a KWin Effect", "Mouse Click Animation"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Creates an animation whenever a mouse button is clicked. This is useful for screenrecordings/presentations"), QStringLiteral("Accessibility"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/mouse_click.mp4")), false, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("mousemark"), i18ndc("kwin_effects", "Name of a KWin Effect", "Mouse Mark"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Allows you to draw lines on the desktop"), QStringLiteral("Appearance"), QString(), QUrl(), false, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("presentwindows"), i18ndc("kwin_effects", "Name of a KWin Effect", "Present Windows"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Zoom out until all opened windows can be displayed side-by-side"), QStringLiteral("Window Management"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/present_windows.mp4")), true, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("resize"), i18ndc("kwin_effects", "Name of a KWin Effect", "Resize Window"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Resizes windows with a fast texture scale instead of updating contents"), QStringLiteral("Window Management"), QString(), QUrl(), false, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("screenedge"), i18ndc("kwin_effects", "Name of a KWin Effect", "Screen Edge"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Highlights a screen edge when approaching"), QStringLiteral("Appearance"), QString(), QUrl(), true, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("screenshot"), i18ndc("kwin_effects", "Name of a KWin Effect", "Screenshot"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Helper effect for KSnapshot"), QStringLiteral("Appearance"), QString(), QUrl(), true, true, #ifdef EFFECT_BUILTINS &createHelper, &ScreenShotEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("sheet"), i18ndc("kwin_effects", "Name of a KWin Effect", "Sheet"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Make modal dialogs smoothly fly in and out when they are shown or hidden"), QStringLiteral("Appearance"), QString(), QUrl(), false, false, #ifdef EFFECT_BUILTINS &createHelper, &SheetEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("showfps"), i18ndc("kwin_effects", "Name of a KWin Effect", "Show FPS"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Display KWin's performance in the corner of the screen"), QStringLiteral("Tools"), QString(), QUrl(), false, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("showpaint"), i18ndc("kwin_effects", "Name of a KWin Effect", "Show Paint"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Highlight areas of the desktop that have been recently updated"), QStringLiteral("Tools"), QString(), QUrl(), false, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("slide"), i18ndc("kwin_effects", "Name of a KWin Effect", "Slide"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Slide windows across the screen when switching virtual desktops"), QStringLiteral("Virtual Desktop Switching Animation"), QStringLiteral("desktop-animations"), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/slide.ogv")), true, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("slideback"), i18ndc("kwin_effects", "Name of a KWin Effect", "Slide Back"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Slide back windows when another window is raised"), QStringLiteral("Focus"), QString(), QUrl(), false, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("slidingpopups"), i18ndc("kwin_effects", "Name of a KWin Effect", "Sliding popups"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Sliding animation for Plasma popups"), QStringLiteral("Appearance"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/sliding_popups.mp4")), true, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("snaphelper"), i18ndc("kwin_effects", "Name of a KWin Effect", "Snap Helper"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Help you locate the center of the screen when moving a window"), QStringLiteral("Accessibility"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/snap_helper.mp4")), false, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("startupfeedback"), i18ndc("kwin_effects", "Name of a KWin Effect", "Startup Feedback"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Helper effect for startup feedback"), QStringLiteral("Candy"), QString(), QUrl(), true, true, #ifdef EFFECT_BUILTINS &createHelper, &StartupFeedbackEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("thumbnailaside"), i18ndc("kwin_effects", "Name of a KWin Effect", "Thumbnail Aside"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Display window thumbnails on the edge of the screen"), QStringLiteral("Appearance"), QString(), QUrl(), false, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("touchpoints"), i18ndc("kwin_effects", "Name of a KWin Effect", "Touch Points"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Visualize touch points"), QStringLiteral("Appearance"), QString(), QUrl(), false, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("trackmouse"), i18ndc("kwin_effects", "Name of a KWin Effect", "Track Mouse"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Display a mouse cursor locating effect when activated"), QStringLiteral("Accessibility"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/track_mouse.mp4")), false, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("windowgeometry"), i18ndc("kwin_effects", "Name of a KWin Effect", "Window Geometry"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Display window geometries on move/resize"), QStringLiteral("Appearance"), QString(), QUrl(), false, true, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("wobblywindows"), i18ndc("kwin_effects", "Name of a KWin Effect", "Wobbly Windows"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Deform windows while they are moving"), QStringLiteral("Appearance"), QString(), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/wobbly_windows.ogv")), false, false, #ifdef EFFECT_BUILTINS &createHelper, &WobblyWindowsEffect::supported, nullptr #endif EFFECT_FALLBACK }, { QStringLiteral("zoom"), i18ndc("kwin_effects", "Name of a KWin Effect", "Zoom"), i18ndc("kwin_effects", "Comment describing the KWin Effect", "Magnify the entire desktop"), QStringLiteral("Accessibility"), QStringLiteral("magnifiers"), QUrl(QStringLiteral("http://files.kde.org/plasma/kwin/effect-videos/zoom.ogv")), true, false, #ifdef EFFECT_BUILTINS &createHelper, nullptr, nullptr #endif EFFECT_FALLBACK } }; static inline int index(BuiltInEffect effect) { return static_cast(effect); } Effect *create(BuiltInEffect effect) { const EffectData &effectData = s_effectData.at(index(effect)); if (effectData.createFunction == nullptr) { return nullptr; } return effectData.createFunction(); } bool available(const QString &name) { auto it = std::find_if(s_effectData.begin(), s_effectData.end(), [name](const EffectData &data) { return data.name == name; } ); return it != s_effectData.end(); } bool supported(BuiltInEffect effect) { if (effect == BuiltInEffect::Invalid) { return false; } const EffectData &effectData = s_effectData.at(index(effect)); if (effectData.supportedFunction == nullptr) { return true; } return effectData.supportedFunction(); } bool checkEnabledByDefault(BuiltInEffect effect) { if (effect == BuiltInEffect::Invalid) { return false; } const EffectData &effectData = s_effectData.at(index(effect)); if (effectData.enabledFunction == nullptr) { return true; } return effectData.enabledFunction(); } bool enabledByDefault(BuiltInEffect effect) { const EffectData &effectData = s_effectData.at(index(effect)); return effectData.enabled; } QStringList availableEffectNames() { QStringList result; for (const EffectData &data : s_effectData) { if (data.name.isEmpty()) { continue; } result << data.name; } return result; } QList< BuiltInEffect > availableEffects() { QList result; for (int i = index(BuiltInEffect::Invalid) + 1; i <= index(BuiltInEffect::Zoom); ++i) { result << BuiltInEffect(i); } return result; } BuiltInEffect builtInForName(const QString &name) { auto it = std::find_if(s_effectData.begin(), s_effectData.end(), [name](const EffectData &data) { return data.name == name; } ); if (it == s_effectData.end()) { return BuiltInEffect::Invalid; } return BuiltInEffect(std::distance(s_effectData.begin(), it)); } QString nameForEffect(BuiltInEffect effect) { return s_effectData.at(index(effect)).name; } const EffectData &effectData(BuiltInEffect effect) { return s_effectData.at(index(effect)); } } // BuiltInEffects } // namespace diff --git a/effects/effect_builtins.h b/effects/effect_builtins.h index 7ccb768ea..77e18c605 100644 --- a/effects/effect_builtins.h +++ b/effects/effect_builtins.h @@ -1,108 +1,109 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2014 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_EFFECT_BUILTINS_H #define KWIN_EFFECT_BUILTINS_H #include #include #include #include namespace KWin { class Effect; /** * Defines all the built in effects. **/ enum class BuiltInEffect { Invalid, ///< not a valid Effect Blur, + ColorPicker, Contrast, CoverSwitch, Cube, CubeSlide, DesktopGrid, DimInactive, DimScreen, FallApart, FlipSwitch, Glide, HighlightWindow, Invert, Kscreen, LookingGlass, MagicLamp, Magnifier, MinimizeAnimation, MouseClick, MouseMark, PresentWindows, Resize, ScreenEdge, ScreenShot, Sheet, ShowFps, ShowPaint, Slide, SlideBack, SlidingPopups, SnapHelper, StartupFeedback, ThumbnailAside, TouchPoints, TrackMouse, WindowGeometry, WobblyWindows, Zoom }; namespace BuiltInEffects { struct EffectData { QString name; QString displayName; QString comment; QString category; QString exclusiveCategory; QUrl video; bool enabled; bool internal; std::function createFunction; std::function supportedFunction; std::function enabledFunction; }; KWINEFFECTS_EXPORT Effect *create(BuiltInEffect effect); KWINEFFECTS_EXPORT bool available(const QString &name); KWINEFFECTS_EXPORT bool supported(BuiltInEffect effect); KWINEFFECTS_EXPORT bool checkEnabledByDefault(BuiltInEffect effect); KWINEFFECTS_EXPORT bool enabledByDefault(BuiltInEffect effect); KWINEFFECTS_EXPORT QString nameForEffect(BuiltInEffect effect); KWINEFFECTS_EXPORT BuiltInEffect builtInForName(const QString &name); KWINEFFECTS_EXPORT QStringList availableEffectNames(); KWINEFFECTS_EXPORT QList availableEffects(); KWINEFFECTS_EXPORT const EffectData &effectData(BuiltInEffect effect); } } #endif