kwin/libkwineffects/anidata.cpp
Vlad Zagorodniy 5e104fbc12 [scripting] Introduce redirect function
Summary:
Consider current implementation of the Squash effect: if a window was
minimized, an animation will be started; if the window is unminimized
and the animation is still active (that can happen when user clicks on
app's icon really fast), the animation will be stopped and a new one will
be created. Such behavior can lead to rapid jumps in the observed
"animation".

A better approach would be first try to **reverse** the already active
animation, and if that attempt wasn't successful, start a new animation.

This patch introduces a new function to the scripted effects API that
lets JavaScript effects to control direction of animations. The
prototype of the function looks as follows:

    redirect(<animation id(s)>, <direction>, [<termination policy>])

the first argument is an animation id or a list of animation ids, the
second argument specifies the new direction of the animation or
animations if a list of ids was passed as the first argument. The
third argument specifies whether the animation(s) should be terminated
when it(they) reaches the source position, currently it's relevant only
for animations that are created with set() function. The termination
policy argument is optional, by default it's Effect.TerminateAtSource.

We can use this function to fix issues with rapid jumps in the Squash
effect. Also, redirect() lets us to write effects for simple animations
in slightly different style: first, we have to start the main animation
(e.g. for the Dialog Parent effect, it would be dimming of main windows)
and then change direction of the animation depending on external events,
e.g. when the Desktop Cube effect is activated.

Reviewers: #kwin, davidedmundson

Reviewed By: #kwin, davidedmundson

Subscribers: davidedmundson, abetts, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D16449
2018-11-17 13:44:16 +02:00

133 lines
4.3 KiB
C++

/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2011 Thomas Lübking <thomas.luebking@web.de>
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/>.
*********************************************************************/
#include "anidata_p.h"
#include "logging_p.h"
QDebug operator<<(QDebug dbg, const KWin::AniData &a)
{
dbg.nospace() << a.debugInfo();
return dbg.space();
}
using namespace KWin;
FullScreenEffectLock::FullScreenEffectLock(Effect *effect)
{
effects->setActiveFullScreenEffect(effect);
}
FullScreenEffectLock::~FullScreenEffectLock()
{
effects->setActiveFullScreenEffect(nullptr);
}
KeepAliveLock::KeepAliveLock(EffectWindow *w)
: m_window(w)
{
m_window->refWindow();
}
KeepAliveLock::~KeepAliveLock()
{
m_window->unrefWindow();
}
PreviousWindowPixmapLock::PreviousWindowPixmapLock(EffectWindow *w)
: m_window(w)
{
m_window->referencePreviousWindowPixmap();
}
PreviousWindowPixmapLock::~PreviousWindowPixmapLock()
{
m_window->unreferencePreviousWindowPixmap();
// Add synthetic repaint to prevent glitches after cross-fading
// translucent windows.
effects->addRepaint(m_window->expandedGeometry());
}
AniData::AniData()
: attribute(AnimationEffect::Opacity)
, customCurve(0) // Linear
, meta(0)
, startTime(0)
, waitAtSource(false)
, keepAlive(true)
{
}
AniData::AniData(AnimationEffect::Attribute a, int meta_, const FPx2 &to_,
int delay, const FPx2 &from_, bool waitAtSource_,
FullScreenEffectLockPtr fullScreenEffectLock_, bool keepAlive,
PreviousWindowPixmapLockPtr previousWindowPixmapLock_)
: attribute(a)
, from(from_)
, to(to_)
, meta(meta_)
, startTime(AnimationEffect::clock() + delay)
, fullScreenEffectLock(fullScreenEffectLock_)
, waitAtSource(waitAtSource_)
, keepAlive(keepAlive)
, previousWindowPixmapLock(previousWindowPixmapLock_)
{
}
bool AniData::isActive() const
{
if (!timeLine.done()) {
return true;
}
if (timeLine.direction() == TimeLine::Backward) {
return !(terminationFlags & AnimationEffect::TerminateAtSource);
}
return !(terminationFlags & AnimationEffect::TerminateAtTarget);
}
static QString attributeString(KWin::AnimationEffect::Attribute attribute)
{
switch (attribute) {
case KWin::AnimationEffect::Opacity: return QStringLiteral("Opacity");
case KWin::AnimationEffect::Brightness: return QStringLiteral("Brightness");
case KWin::AnimationEffect::Saturation: return QStringLiteral("Saturation");
case KWin::AnimationEffect::Scale: return QStringLiteral("Scale");
case KWin::AnimationEffect::Translation: return QStringLiteral("Translation");
case KWin::AnimationEffect::Rotation: return QStringLiteral("Rotation");
case KWin::AnimationEffect::Position: return QStringLiteral("Position");
case KWin::AnimationEffect::Size: return QStringLiteral("Size");
case KWin::AnimationEffect::Clip: return QStringLiteral("Clip");
default: return QStringLiteral(" ");
}
}
QString AniData::debugInfo() const
{
return QLatin1String("Animation: ") + attributeString(attribute) +
QLatin1String("\n From: ") + from.toString() +
QLatin1String("\n To: ") + to.toString() +
QLatin1String("\n Started: ") + QString::number(AnimationEffect::clock() - startTime) + QLatin1String("ms ago\n") +
QLatin1String( " Duration: ") + QString::number(timeLine.duration().count()) + QLatin1String("ms\n") +
QLatin1String( " Passed: ") + QString::number(timeLine.elapsed().count()) + QLatin1String("ms\n");
}