File indexing completed on 2025-12-07 12:25:07

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2022 David Edmundson <davidedmundson@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 // own
0010 #include "blendchanges.h"
0011 #include "kwinglutils.h"
0012 
0013 #include <QDBusConnection>
0014 #include <QTimer>
0015 
0016 namespace KWin
0017 {
0018 BlendChanges::BlendChanges()
0019     : CrossFadeEffect()
0020 {
0021     QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/kde/KWin/BlendChanges"),
0022                                                  QStringLiteral("org.kde.KWin.BlendChanges"),
0023                                                  this,
0024                                                  QDBusConnection::ExportAllSlots);
0025 
0026     m_timeline.setEasingCurve(QEasingCurve::InOutCubic);
0027 }
0028 
0029 BlendChanges::~BlendChanges() = default;
0030 
0031 bool BlendChanges::supported()
0032 {
0033     return effects->compositingType() == OpenGLCompositing && effects->animationsSupported();
0034 }
0035 
0036 void KWin::BlendChanges::start(int delay)
0037 {
0038     int animationDuration = animationTime(400);
0039 
0040     if (!supported() || m_state != Off) {
0041         return;
0042     }
0043     if (effects->hasActiveFullScreenEffect()) {
0044         return;
0045     }
0046 
0047     const EffectWindowList allWindows = effects->stackingOrder();
0048     for (auto window : allWindows) {
0049         if (!window->isFullScreen()) {
0050             redirect(window);
0051         }
0052     }
0053 
0054     QTimer::singleShot(delay, this, [this, animationDuration]() {
0055         m_timeline.setDuration(std::chrono::milliseconds(animationDuration));
0056         effects->addRepaintFull();
0057         m_state = Blending;
0058     });
0059 
0060     m_state = ShowingCache;
0061 }
0062 
0063 bool BlendChanges::isActive() const
0064 {
0065     return m_state != Off;
0066 }
0067 
0068 void BlendChanges::postPaintScreen()
0069 {
0070     if (m_timeline.done()) {
0071         m_timeline.reset();
0072         m_state = Off;
0073 
0074         const EffectWindowList allWindows = effects->stackingOrder();
0075         for (auto window : allWindows) {
0076             unredirect(window);
0077         }
0078     }
0079     effects->addRepaintFull();
0080 }
0081 
0082 void BlendChanges::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data)
0083 {
0084     data.setCrossFadeProgress(m_timeline.value());
0085     effects->paintWindow(w, mask, region, data);
0086 }
0087 
0088 void BlendChanges::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime)
0089 {
0090     if (m_state == Off) {
0091         return;
0092     }
0093     if (m_state == Blending) {
0094         m_timeline.advance(presentTime);
0095     }
0096 
0097     effects->prePaintScreen(data, presentTime);
0098 }
0099 
0100 } // namespace KWin