[effects/dimscreen] Port to JavaScript

Summary:
The ported effect looks quite similar to the C++ version except one
thing: it works correctly when user activates/deactivates a full
screen effect, for example the Desktop Cube effect.

Other than that, there are no behavioral or visual differences.

Reviewers: #kwin, davidedmundson

Reviewed By: #kwin, davidedmundson

Subscribers: davidedmundson, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D16452
icc-effect-5.17.5
Vlad Zagorodniy 2018-10-25 16:48:47 +03:00
parent 900f242a39
commit ea1873f975
12 changed files with 277 additions and 225 deletions

View File

@ -89,7 +89,6 @@ void TestBuiltInEffectLoader::testHasEffect_data()
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;
@ -144,7 +143,6 @@ void TestBuiltInEffectLoader::testKnownEffects()
<< QStringLiteral("cubeslide")
<< QStringLiteral("desktopgrid")
<< QStringLiteral("diminactive")
<< QStringLiteral("dimscreen")
<< QStringLiteral("fallapart")
<< QStringLiteral("flipswitch")
<< QStringLiteral("glide")
@ -212,7 +210,6 @@ void TestBuiltInEffectLoader::testSupported_data()
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;
@ -302,7 +299,6 @@ void TestBuiltInEffectLoader::testLoadEffect_data()
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;

View File

@ -80,7 +80,6 @@ void TestPluginEffectLoader::testHasEffect_data()
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;
@ -111,6 +110,7 @@ void TestPluginEffectLoader::testHasEffect_data()
QTest::newRow("Zoom") << QStringLiteral("zoom") << false;
QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false;
// all the scripted effects should fail
QTest::newRow("DimScreen") << QStringLiteral("kwin4_effect_dimscreen") << false;
QTest::newRow("Fade") << QStringLiteral("kwin4_effect_fade") << false;
QTest::newRow("FadeDesktop") << QStringLiteral("kwin4_effect_fadedesktop") << false;
QTest::newRow("FadingPopups") << QStringLiteral("kwin4_effect_fadingpopups") << false;

View File

@ -110,7 +110,6 @@ void TestScriptedEffectLoader::testHasEffect_data()
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;
@ -148,6 +147,7 @@ void TestScriptedEffectLoader::testHasEffect_data()
QTest::newRow("FadingPopups") << QStringLiteral("kwin4_effect_fadingpopups") << true;
QTest::newRow("FrozenApp") << QStringLiteral("kwin4_effect_frozenapp") << true;
QTest::newRow("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << true;
QTest::newRow("DimScreen") << QStringLiteral("kwin4_effect_dimscreen") << true;
QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << true;
QTest::newRow("Logout") << QStringLiteral("kwin4_effect_logout") << true;
QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << true;
@ -178,6 +178,7 @@ void TestScriptedEffectLoader::testKnownEffects()
{
QStringList expectedEffects;
expectedEffects << QStringLiteral("kwin4_effect_dialogparent")
<< QStringLiteral("kwin4_effect_dimscreen")
<< QStringLiteral("kwin4_effect_fade")
<< QStringLiteral("kwin4_effect_fadedesktop")
<< QStringLiteral("kwin4_effect_fadingpopups")
@ -211,6 +212,7 @@ void TestScriptedEffectLoader::testLoadEffect_data()
QTest::newRow("FadingPopups") << QStringLiteral("kwin4_effect_fadingpopups") << true;
QTest::newRow("FrozenApp") << QStringLiteral("kwin4_effect_frozenapp") << true;
QTest::newRow("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << true;
QTest::newRow("DimScreen") << QStringLiteral("kwin4_effect_dimscreen") << true;
QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << true;
QTest::newRow("Logout") << QStringLiteral("kwin4_effect_logout") << true;
QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << true;
@ -361,6 +363,7 @@ void TestScriptedEffectLoader::testLoadAllEffects()
// 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("dimscreenEnabled"), false);
plugins.writeEntry(kwin4 + QStringLiteral("fadeEnabled"), false);
plugins.writeEntry(kwin4 + QStringLiteral("fadedesktopEnabled"), false);
plugins.writeEntry(kwin4 + QStringLiteral("fadingpopupsEnabled"), false);

View File

@ -132,6 +132,7 @@ kconfig_add_kcfg_files(kwin4_effect_builtins_sources
# scripted effects
add_subdirectory( dialogparent )
add_subdirectory( dimscreen )
add_subdirectory( eyeonscreen )
add_subdirectory( fade )
add_subdirectory( fadedesktop )
@ -152,7 +153,6 @@ add_subdirectory( windowaperture )
# Common effects
add_subdirectory( desktopgrid )
add_subdirectory( diminactive )
include( dimscreen/CMakeLists.txt )
include( fallapart/CMakeLists.txt )
include( highlightwindow/CMakeLists.txt )
include( kscreen/CMakeLists.txt )

View File

@ -1,7 +1 @@
#######################################
# Effect
# Source files
set( kwin4_effect_builtins_sources ${kwin4_effect_builtins_sources}
dimscreen/dimscreen.cpp
)
add_subdirectory(package)

View File

@ -1,137 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2008, 2009 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "dimscreen.h"
#include <kwinglutils.h>
#include <QSet>
namespace KWin
{
static const QSet<QString> s_authWindows {
QStringLiteral("kdesu kdesu"),
QStringLiteral("kdesudo kdesudo"),
QStringLiteral("pinentry pinentry"),
QStringLiteral("polkit-kde-authentication-agent-1 polkit-kde-authentication-agent-1"),
QStringLiteral("polkit-kde-manager polkit-kde-manager"),
// On Wayland, the resource name is filename of executable. It's empty for
// authentication agents because KWayland can't get their executable paths.
QStringLiteral(" org.kde.kdesu"),
QStringLiteral(" org.kde.polkit-kde-authentication-agent-1")
};
DimScreenEffect::DimScreenEffect()
: mActivated(false)
, activateAnimation(false)
, deactivateAnimation(false)
{
reconfigure(ReconfigureAll);
connect(effects, SIGNAL(windowActivated(KWin::EffectWindow*)), this, SLOT(slotWindowActivated(KWin::EffectWindow*)));
}
DimScreenEffect::~DimScreenEffect()
{
}
void DimScreenEffect::reconfigure(ReconfigureFlags)
{
timeline.setDuration(animationTime(250));
}
void DimScreenEffect::prePaintScreen(ScreenPrePaintData& data, int time)
{
if (mActivated && activateAnimation && !effects->activeFullScreenEffect())
timeline.setCurrentTime(timeline.currentTime() + time);
if (mActivated && deactivateAnimation)
timeline.setCurrentTime(timeline.currentTime() - time);
if (mActivated && effects->activeFullScreenEffect())
timeline.setCurrentTime(timeline.currentTime() - time);
if (mActivated && !activateAnimation && !deactivateAnimation && !effects->activeFullScreenEffect() && timeline.currentValue() != 1.0)
timeline.setCurrentTime(timeline.currentTime() + time);
effects->prePaintScreen(data, time);
}
void DimScreenEffect::postPaintScreen()
{
if (mActivated) {
if (activateAnimation && timeline.currentValue() == 1.0) {
activateAnimation = false;
effects->addRepaintFull();
}
if (deactivateAnimation && timeline.currentValue() == 0.0) {
deactivateAnimation = false;
mActivated = false;
effects->addRepaintFull();
}
// still animating
if (timeline.currentValue() > 0.0 && timeline.currentValue() < 1.0)
effects->addRepaintFull();
}
effects->postPaintScreen();
}
static inline bool isDimWindow(const EffectWindow *w)
{
if (w->isPopupWindow()) {
return false;
}
if (w->isX11Client() && !w->isManaged()) {
return false;
}
return true;
}
void DimScreenEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data)
{
if (mActivated && (w != window) && isDimWindow(w)) {
data.multiplyBrightness((1.0 - 0.33 * timeline.currentValue()));
data.multiplySaturation((1.0 - 0.33 * timeline.currentValue()));
}
effects->paintWindow(w, mask, region, data);
}
void DimScreenEffect::slotWindowActivated(EffectWindow *w)
{
if (!w) return;
if (s_authWindows.contains(w->windowClass())) {
mActivated = true;
activateAnimation = true;
deactivateAnimation = false;
window = w;
effects->addRepaintFull();
} else {
if (mActivated) {
activateAnimation = false;
deactivateAnimation = true;
effects->addRepaintFull();
}
}
}
bool DimScreenEffect::isActive() const
{
return mActivated;
}
} // namespace

View File

@ -1,57 +0,0 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2008, 2009 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_DIMSCREEN_H
#define KWIN_DIMSCREEN_H
#include <kwineffects.h>
#include <QTimeLine>
namespace KWin
{
class DimScreenEffect
: public Effect
{
Q_OBJECT
public:
DimScreenEffect();
~DimScreenEffect();
virtual void reconfigure(ReconfigureFlags);
virtual void prePaintScreen(ScreenPrePaintData& data, int time);
virtual void postPaintScreen();
virtual void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data);
virtual bool isActive() const;
public Q_SLOTS:
void slotWindowActivated(KWin::EffectWindow *w);
private:
bool mActivated;
bool activateAnimation;
bool deactivateAnimation;
QTimeLine timeline;
EffectWindow* window;
};
} // namespace
#endif

View File

@ -0,0 +1,12 @@
install(DIRECTORY contents
DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/effects/kwin4_effect_dimscreen)
install(FILES metadata.desktop
DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/effects/kwin4_effect_dimscreen)
install(FILES metadata.desktop
DESTINATION ${SERVICES_INSTALL_DIR}/${KWIN_NAME}
RENAME kwin4_effect_dimscreen.desktop)
file(COPY contents metadata.desktop
DESTINATION ${CMAKE_BINARY_DIR}/bin/kwin/effects/kwin4_effect_dimscreen)

View File

@ -0,0 +1,238 @@
/********************************************************************
This file is part of the KDE project.
Copyright (C) 2018 Vlad Zagorodniy <vladzzag@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
"use strict";
var authenticationAgents = [
"kdesu kdesu",
"kdesudo kdesudo",
"pinentry pinentry",
"polkit-kde-authentication-agent-1 polkit-kde-authentication-agent-1",
"polkit-kde-manager polkit-kde-manager",
// On Wayland, the resource name is filename of executable. It's empty for
// authentication agents because KWayland can't get their executable paths.
" org.kde.kdesu",
" org.kde.polkit-kde-authentication-agent-1"
];
function activeAuthenticationAgent() {
var activeWindow = effects.activeWindow;
if (!activeWindow) {
return null;
}
if (authenticationAgents.indexOf(activeWindow.windowClass) == -1) {
return null;
}
return activeWindow;
}
var dimScreenEffect = {
loadConfig: function () {
dimScreenEffect.duration = animationTime(250);
dimScreenEffect.brightness = 0.67;
dimScreenEffect.saturation = 0.67;
},
startAnimation: function (window) {
if (!window.visible) {
return;
}
if (window.popupWindow) {
return;
}
if (window.x11Client && !window.managed) {
return;
}
if (window.dimAnimation) {
if (redirect(window.dimAnimation, Effect.Forward)) {
return;
}
cancel(window.dimAnimation);
}
window.dimAnimation = set({
window: window,
curve: QEasingCurve.InOutSine,
duration: dimScreenEffect.duration,
keepAlive: false,
animations: [
{
type: Effect.Saturation,
to: dimScreenEffect.saturation
},
{
type: Effect.Brightness,
to: dimScreenEffect.brightness
}
]
});
},
startAnimationSmooth: function (window) {
dimScreenEffect.startAnimation(window);
},
startAnimationInstant: function (window) {
dimScreenEffect.startAnimation(window);
if (window.dimAnimation) {
complete(window.dimAnimation);
}
},
cancelAnimationSmooth: function (window) {
if (!window.dimAnimation) {
return;
}
if (redirect(window.dimAnimation, Effect.Backward)) {
return;
}
cancel(window.dimAnimation);
delete window.dimAnimation;
},
cancelAnimationInstant: function (window) {
if (window.dimAnimation) {
cancel(window.dimAnimation);
delete window.dimAnimation;
}
},
dimScreen: function (agent, animationFunc, cancelFunc) {
// Keep track of currently active authentication agent so we don't have
// to re-scan the stacking order in brightenScreen each time when some
// window is activated.
dimScreenEffect.authenticationAgent = agent;
var windows = effects.stackingOrder;
for (var i = 0; i < windows.length; ++i) {
var window = windows[i];
if (window == agent) {
// The agent might have been dimmed before (because there are
// several authentication agents on the screen), so we need to
// cancel previous animations for it if there are any.
cancelFunc(agent);
continue;
}
animationFunc(window);
}
},
dimScreenSmooth: function (agent) {
dimScreenEffect.dimScreen(
agent,
dimScreenEffect.startAnimationSmooth,
dimScreenEffect.cancelAnimationSmooth
);
},
dimScreenInstant: function (agent) {
dimScreenEffect.dimScreen(
agent,
dimScreenEffect.startAnimationInstant,
dimScreenEffect.cancelAnimationInstant
);
},
brightenScreen: function (cancelFunc) {
if (!dimScreenEffect.authenticationAgent) {
return;
}
dimScreenEffect.authenticationAgent = null;
var windows = effects.stackingOrder;
for (var i = 0; i < windows.length; ++i) {
cancelFunc(windows[i]);
}
},
brightenScreenSmooth: function () {
dimScreenEffect.brightenScreen(dimScreenEffect.cancelAnimationSmooth);
},
brightenScreenInstant: function () {
dimScreenEffect.brightenScreen(dimScreenEffect.cancelAnimationInstant);
},
slotWindowActivated: function (window) {
if (!window) {
return;
}
if (authenticationAgents.indexOf(window.windowClass) != -1) {
dimScreenEffect.dimScreenSmooth(window);
} else {
dimScreenEffect.brightenScreenSmooth();
}
},
slotWindowAdded: function (window) {
// Don't dim authentication agents that just opened.
var agent = activeAuthenticationAgent();
if (agent == window) {
return;
}
// If a window appeared while the screen is dimmed, dim the window too.
if (agent) {
dimScreenEffect.startAnimationInstant(window);
}
},
slotActiveFullScreenEffectChanged: function () {
// If some full screen effect has been activated, for example the desktop
// cube effect, then brighten screen back. We need to do that because the
// full screen effect can dim windows on its own.
if (effects.hasActiveFullScreenEffect) {
dimScreenEffect.brightenScreenSmooth();
return;
}
// If user left the full screen effect, try to dim screen back.
var agent = activeAuthenticationAgent();
if (agent) {
dimScreenEffect.dimScreenSmooth(agent);
}
},
slotDesktopChanged: function () {
// If there is an active full screen effect, then try smoothly dim/brighten
// the screen. Keep in mind that in order for this to work properly, this
// effect has to come after the full screen effect in the effect chain,
// otherwise this slot will be invoked before the full screen effect can mark
// itself as a full screen effect.
if (effects.hasActiveFullScreenEffect) {
return;
}
// Try to brighten windows on the previous virtual desktop.
dimScreenEffect.brightenScreenInstant();
// Try to dim windows on the current virtual desktop.
var agent = activeAuthenticationAgent();
if (agent) {
dimScreenEffect.dimScreenInstant(agent);
}
},
restartAnimation: function (window) {
if (activeAuthenticationAgent()) {
dimScreenEffect.startAnimationInstant(window);
}
},
init: function () {
dimScreenEffect.loadConfig();
effect.configChanged.connect(dimScreenEffect.loadConfig);
effects.windowActivated.connect(dimScreenEffect.slotWindowActivated);
effects.windowAdded.connect(dimScreenEffect.slotWindowAdded);
effects.windowMinimized.connect(dimScreenEffect.cancelAnimationInstant);
effects.windowUnminimized.connect(dimScreenEffect.restartAnimation);
effects.activeFullScreenEffectChanged.connect(
dimScreenEffect.slotActiveFullScreenEffectChanged);
effects['desktopChanged(int,int)'].connect(dimScreenEffect.slotDesktopChanged);
}
};
dimScreenEffect.init();

View File

@ -0,0 +1,20 @@
[Desktop Entry]
Comment=Darkens the entire screen when requesting root privileges
Icon=preferences-system-windows-effect-dimscreen
Name=Dim Screen for Administrator Mode
Type=Service
X-KDE-ParentApp=
X-KDE-PluginInfo-Author=Martin Flöser, Vlad Zagorodniy
X-KDE-PluginInfo-Category=Focus
X-KDE-PluginInfo-Email=mgraesslin@kde.org, vladzzag@gmail.com
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-Name=kwin4_effect_dimscreen
X-KDE-PluginInfo-Version=1
X-KDE-PluginInfo-Website=
X-KDE-ServiceTypes=KWin/Effect
X-KDE-PluginInfo-EnabledByDefault=false
X-KDE-Ordering=60
X-Plasma-API=javascript
X-Plasma-MainScript=code/main.js
X-KWin-Video-Url=http://files.kde.org/plasma/kwin/effect-videos/dim_administration.mp4

View File

@ -31,7 +31,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// 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"
@ -217,21 +216,6 @@ EFFECT_FALLBACK
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<DimScreenEffect>,
nullptr,
nullptr
#endif
EFFECT_FALLBACK
}, {
QStringLiteral("fallapart"),

View File

@ -42,7 +42,6 @@ enum class BuiltInEffect
CubeSlide,
DesktopGrid,
DimInactive,
DimScreen,
FallApart,
FlipSwitch,
Glide,