diff --git a/effects/sheet/sheet.h b/effects/sheet/sheet.h --- a/effects/sheet/sheet.h +++ b/effects/sheet/sheet.h @@ -4,6 +4,7 @@ Copyright (C) 2007 Philip Falkner Copyright (C) 2009 Martin Gräßlin +Copyright (C) 2018 Vlad Zagorodniy 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 @@ -22,62 +23,63 @@ #ifndef KWIN_SHEET_H #define KWIN_SHEET_H +// kwineffects #include -class QTimeLine; - namespace KWin { -class SheetEffect - : public Effect +class SheetEffect : public Effect { Q_OBJECT - Q_PROPERTY(int duration READ configuredDuration) + Q_PROPERTY(int duration READ duration) + public: SheetEffect(); - virtual void reconfigure(ReconfigureFlags); - virtual void prePaintScreen(ScreenPrePaintData& data, int time); - virtual void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time); - virtual void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data); - virtual void postPaintWindow(EffectWindow* w); - virtual bool isActive() const; - int requestedEffectChainPosition() const override { - return 60; - } + void reconfigure(ReconfigureFlags flags) override; + + void prePaintScreen(ScreenPrePaintData &data, int time) override; + void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) override; + void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override; + void postPaintWindow(EffectWindow *w) override; + + bool isActive() const override; + int requestedEffectChainPosition() const override; static bool supported(); - // for properties - int configuredDuration() const { - return duration; - } -public Q_SLOTS: - void slotWindowAdded(KWin::EffectWindow* c); - void slotWindowClosed(KWin::EffectWindow *c); - void slotWindowDeleted(KWin::EffectWindow *w); + int duration() const; + +private Q_SLOTS: + void slotWindowAdded(EffectWindow *w); + void slotWindowClosed(EffectWindow *w); + void slotWindowDeleted(EffectWindow *w); + +private: + bool isSheetWindow(EffectWindow *w) const; + private: - class WindowInfo; - typedef QMap< const EffectWindow*, WindowInfo > InfoMap; - bool isSheetWindow(EffectWindow* w); - InfoMap windows; - float duration; - int screenTime; + std::chrono::milliseconds m_duration; + + struct Animation { + TimeLine timeLine; + int parentY; + }; + + QHash m_animations; }; -class SheetEffect::WindowInfo +inline int SheetEffect::requestedEffectChainPosition() const { -public: - WindowInfo(); - ~WindowInfo(); - bool deleted; - bool added; - bool closed; - QTimeLine *timeLine; - int parentY; -}; + return 60; +} + +inline int SheetEffect::duration() const +{ + return m_duration.count(); +} -} // namespace +} // namespace KWin #endif diff --git a/effects/sheet/sheet.cpp b/effects/sheet/sheet.cpp --- a/effects/sheet/sheet.cpp +++ b/effects/sheet/sheet.cpp @@ -4,6 +4,7 @@ Copyright (C) 2007 Philip Falkner Copyright (C) 2009 Martin Gräßlin +Copyright (C) 2018 Vlad Zagorodniy 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 @@ -19,73 +20,70 @@ along with this program. If not, see . *********************************************************************/ +// own #include "sheet.h" -#include "sheetconfig.h" -#include -#include -#include +// KConfigSkeleton +#include "sheetconfig.h" -// Effect is based on fade effect by Philip Falkner +// Qt +#include namespace KWin { SheetEffect::SheetEffect() { initConfig(); reconfigure(ReconfigureAll); - connect(effects, SIGNAL(windowAdded(KWin::EffectWindow*)), this, SLOT(slotWindowAdded(KWin::EffectWindow*))); - connect(effects, SIGNAL(windowClosed(KWin::EffectWindow*)), this, SLOT(slotWindowClosed(KWin::EffectWindow*))); - connect(effects, SIGNAL(windowDeleted(KWin::EffectWindow*)), this, SLOT(slotWindowDeleted(KWin::EffectWindow*))); -} -bool SheetEffect::supported() -{ - return effects->isOpenGLCompositing() && effects->animationsSupported(); + connect(effects, &EffectsHandler::windowAdded, this, &SheetEffect::slotWindowAdded); + connect(effects, &EffectsHandler::windowClosed, this, &SheetEffect::slotWindowClosed); + connect(effects, &EffectsHandler::windowDeleted, this, &SheetEffect::slotWindowDeleted); } -void SheetEffect::reconfigure(ReconfigureFlags) +void SheetEffect::reconfigure(ReconfigureFlags flags) { + Q_UNUSED(flags) + SheetConfig::self()->read(); - duration = animationTime(SheetConfig::animationTime() != 0 ? SheetConfig::animationTime() : 500); + + // TODO: Rename AnimationTime config key to Duration. + const int d = animationTime(SheetConfig::animationTime() != 0 + ? SheetConfig::animationTime() + : 500); + m_duration = std::chrono::milliseconds(static_cast(d)); } -void SheetEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void SheetEffect::prePaintScreen(ScreenPrePaintData &data, int time) { - if (!windows.isEmpty()) { - data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; - screenTime = time; + const std::chrono::milliseconds delta(time); + + auto animationIt = m_animations.begin(); + while (animationIt != m_animations.end()) { + (*animationIt).timeLine.update(delta); + ++animationIt; } + + data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; + effects->prePaintScreen(data, time); } -void SheetEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void SheetEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) { - InfoMap::iterator info = windows.find(w); - if (info != windows.end()) { + if (m_animations.contains(w)) { data.setTransformed(); - if (info->added) - info->timeLine->setCurrentTime(info->timeLine->currentTime() + screenTime); - else if (info->closed) { - info->timeLine->setCurrentTime(info->timeLine->currentTime() - screenTime); - if (info->deleted) - w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DELETE); - } + w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DELETE); } effects->prePaintWindow(w, data, time); - - // if the window isn't to be painted, then let's make sure - // to track its progress - if (info != windows.end() && !w->isPaintingEnabled() && !effects->activeFullScreenEffect()) - w->addRepaintFull(); } -void SheetEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) +void SheetEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) { - InfoMap::const_iterator info = windows.constFind(w); - if (info == windows.constEnd()) { + auto animationIt = m_animations.constFind(w); + if (animationIt == m_animations.constEnd()) { effects->paintWindow(w, mask, region, data); return; } @@ -109,124 +107,122 @@ const QPointF offset = screenGeo.center() - windowGeo.center(); data.translate(offset.x(), offset.y()); - const double progress = info->timeLine->currentValue(); - QGraphicsRotation rot; + const qreal t = (*animationIt).timeLine.value(); data.setRotationAxis(Qt::XAxis); - data.setRotationAngle(60.0 * (1.0 - progress)); - data *= QVector3D(1.0, progress, progress); - data.translate(0.0, - (w->y() - info->parentY) * (1.0 - progress)); + data.setRotationAngle(interpolate(60.0, 0.0, t)); + data *= QVector3D(1.0, t, t); + data.translate(0.0, -interpolate(w->y() - (*animationIt).parentY, 0.0, t)); effects->paintWindow(w, mask, region, data); } -void SheetEffect::postPaintWindow(EffectWindow* w) +void SheetEffect::postPaintWindow(EffectWindow *w) { - InfoMap::iterator info = windows.find(w); - if (info != windows.end()) { - if (info->added && info->timeLine->currentValue() == 1.0) { - windows.remove(w); - effects->addRepaintFull(); - } else if (info->closed && info->timeLine->currentValue() == 0.0) { - info->closed = false; - if (info->deleted) { - windows.remove(w); + auto animationIt = m_animations.begin(); + while (animationIt != m_animations.end()) { + EffectWindow *w = animationIt.key(); + w->addRepaintFull(); + if ((*animationIt).timeLine.done()) { + if (w->isDeleted()) { w->unrefWindow(); } - effects->addRepaintFull(); + animationIt = m_animations.erase(animationIt); + } else { + ++animationIt; } - if (info->added || info->closed) - w->addRepaintFull(); } + + if (m_animations.isEmpty()) { + effects->addRepaintFull(); + } + effects->postPaintWindow(w); } -void SheetEffect::slotWindowAdded(EffectWindow* w) +bool SheetEffect::isActive() const { - if (!isSheetWindow(w)) + return !m_animations.isEmpty(); +} + +bool SheetEffect::supported() +{ + return effects->isOpenGLCompositing() + && effects->animationsSupported(); +} + +void SheetEffect::slotWindowAdded(EffectWindow *w) +{ + if (effects->activeFullScreenEffect()) { return; + } - InfoMap::iterator it = windows.find(w); - WindowInfo *info = (it == windows.end()) ? &windows[w] : &it.value(); - info->added = true; - info->closed = false; - info->deleted = false; - delete info->timeLine; - info->timeLine = new QTimeLine(duration); - const EffectWindowList stack = effects->stackingOrder(); - // find parent - foreach (EffectWindow * window, stack) { - if (window->findModal() == w) { - info->parentY = window->y(); - break; - } + if (!isSheetWindow(w)) { + return; + } + + Animation &animation = m_animations[w]; + animation.parentY = 0; + animation.timeLine.reset(); + animation.timeLine.setDuration(m_duration); + animation.timeLine.setDirection(TimeLine::Forward); + animation.timeLine.setEasingCurve(QEasingCurve::Linear); + + const auto windows = effects->stackingOrder(); + auto parentIt = std::find_if(windows.constBegin(), windows.constEnd(), + [w](EffectWindow *p) { + return p->findModal() == w; + }); + if (parentIt != windows.constEnd()) { + animation.parentY = (*parentIt)->y(); } w->setData(WindowAddedGrabRole, QVariant::fromValue(static_cast(this))); w->addRepaintFull(); } -void SheetEffect::slotWindowClosed(EffectWindow* w) +void SheetEffect::slotWindowClosed(EffectWindow *w) { - if (!isSheetWindow(w)) + if (effects->activeFullScreenEffect()) { return; + } + + if (!isSheetWindow(w)) { + return; + } w->refWindow(); - InfoMap::iterator it = windows.find(w); - WindowInfo *info = (it == windows.end()) ? &windows[w] : &it.value(); - info->added = false; - info->closed = true; - info->deleted = true; - delete info->timeLine; - info->timeLine = new QTimeLine(duration); - info->timeLine->setCurrentTime(duration); - - bool found = false; - // find parent - const EffectWindowList stack = effects->stackingOrder(); - foreach (EffectWindow * window, stack) { - if (window->findModal() == w) { - info->parentY = window->y(); - found = true; - break; - } + Animation &animation = m_animations[w]; + + animation.timeLine.reset(); + animation.parentY = 0; + animation.timeLine.setDuration(m_duration); + animation.timeLine.setDirection(TimeLine::Backward); + animation.timeLine.setEasingCurve(QEasingCurve::Linear); + + const auto windows = effects->stackingOrder(); + auto parentIt = std::find_if(windows.constBegin(), windows.constEnd(), + [w](EffectWindow *p) { + return p->findModal() == w; + }); + if (parentIt != windows.constEnd()) { + animation.parentY = (*parentIt)->y(); } - if (!found) - info->parentY = 0; w->setData(WindowClosedGrabRole, QVariant::fromValue(static_cast(this))); w->addRepaintFull(); } -void SheetEffect::slotWindowDeleted(EffectWindow* w) +void SheetEffect::slotWindowDeleted(EffectWindow *w) { - windows.remove(w); + m_animations.remove(w); } -bool SheetEffect::isSheetWindow(EffectWindow* w) +bool SheetEffect::isSheetWindow(EffectWindow *w) const { return w->isModal(); } -bool SheetEffect::isActive() const -{ - return !windows.isEmpty(); -} - -SheetEffect::WindowInfo::WindowInfo() - : deleted(false) - , added(false) - , closed(false) - , timeLine(0) - , parentY(0) -{ -} - -SheetEffect::WindowInfo::~WindowInfo() -{ - delete timeLine; -} - -} // namespace +} // namespace KWin