File indexing completed on 2024-11-10 04:57:09

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2007 Lubos Lunak <l.lunak@kde.org>
0006     SPDX-FileCopyrightText: 2008 Lucas Murray <lmurray@undefinedfire.com>
0007     SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 
0012 #pragma once
0013 
0014 // kwineffects
0015 #include "effect/effect.h"
0016 #include "effect/effectwindow.h"
0017 #include "plugins/slide/springmotion.h"
0018 
0019 namespace KWin
0020 {
0021 
0022 /*
0023  * How it Works:
0024  *
0025  * This effect doesn't change the current desktop, only recieves changes from the VirtualDesktopManager.
0026  * The only visually aparent inputs are desktopChanged() and desktopChanging().
0027  *
0028  * When responding to desktopChanging(), the draw position is only affected by what's recieved from there.
0029  * After desktopChanging() is done, or without desktopChanging() having been called at all, desktopChanged() is called.
0030  * The desktopChanged() function configures the m_startPos and m_endPos for the animation, and the duration.
0031  *
0032  * m_currentPosition and everything else not labeled "drawCoordinate" uses desktops as a unit.
0033  * Exmp: 1.2 means the dekstop at index 1 shifted over by .2 desktops.
0034  * All coords must be positive.
0035  *
0036  * For the wrapping effect, the render loop has to handle desktop coordinates larger than the total grid's width.
0037  * 1. It uses modulus to keep the desktop coords in the range [0, gridWidth].
0038  * 2. It will draw the desktop at index 0 at index gridWidth if it has to.
0039  * I will not draw any thing farther outside the range than that.
0040  *
0041  * I've put an explanation of all the important private vars down at the bottom.
0042  *
0043  * Good luck :)
0044  */
0045 
0046 class SlideEffect : public Effect
0047 {
0048     Q_OBJECT
0049     Q_PROPERTY(int horizontalGap READ horizontalGap)
0050     Q_PROPERTY(int verticalGap READ verticalGap)
0051     Q_PROPERTY(bool slideBackground READ slideBackground)
0052 
0053 public:
0054     SlideEffect();
0055     ~SlideEffect() override;
0056 
0057     void reconfigure(ReconfigureFlags) override;
0058 
0059     void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override;
0060     void paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion &region, Output *screen) override;
0061     void postPaintScreen() override;
0062 
0063     void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override;
0064     void paintWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override;
0065 
0066     bool isActive() const override;
0067     int requestedEffectChainPosition() const override;
0068 
0069     static bool supported();
0070 
0071     int horizontalGap() const;
0072     int verticalGap() const;
0073     bool slideBackground() const;
0074 
0075 private Q_SLOTS:
0076     void desktopChanged(VirtualDesktop *old, VirtualDesktop *current, EffectWindow *with);
0077     void desktopChanging(VirtualDesktop *old, QPointF desktopOffset, EffectWindow *with);
0078     void desktopChangingCancelled();
0079     void windowAdded(EffectWindow *w);
0080     void windowDeleted(EffectWindow *w);
0081 
0082 private:
0083     QPoint getDrawCoords(QPointF pos, Output *screen);
0084     bool isTranslated(const EffectWindow *w) const;
0085     bool willBePainted(const EffectWindow *w) const;
0086     bool shouldElevate(const EffectWindow *w) const;
0087     QPointF moveInsideDesktopGrid(QPointF p);
0088     QPointF constrainToDrawableRange(QPointF p);
0089     QPointF forcePositivePosition(QPointF p) const;
0090     void optimizePath(); // Find the best path to target desktop
0091 
0092     void startAnimation(VirtualDesktop *old, VirtualDesktop *current, EffectWindow *movingWindow = nullptr);
0093     void prepareSwitching();
0094     void finishedSwitching();
0095 
0096 private:
0097     int m_hGap;
0098     int m_vGap;
0099     bool m_slideBackground;
0100 
0101     enum class State {
0102         Inactive,
0103         ActiveAnimation,
0104         ActiveGesture,
0105     };
0106 
0107     State m_state = State::Inactive;
0108     SpringMotion m_motionX;
0109     SpringMotion m_motionY;
0110 
0111     // When the desktop isn't desktopChanging(), these two variables are used to control the animation path.
0112     // They use desktops as a unit.
0113     QPointF m_startPos;
0114     QPointF m_endPos;
0115 
0116     EffectWindow *m_movingWindow = nullptr;
0117     std::chrono::milliseconds m_lastPresentTime = std::chrono::milliseconds::zero();
0118     QPointF m_currentPosition; // Should always be kept up to date with where on the grid we're seeing.
0119 
0120     struct
0121     {
0122         bool wrap;
0123         QList<VirtualDesktop *> visibleDesktops;
0124     } m_paintCtx;
0125 
0126     struct WindowData
0127     {
0128         EffectWindowVisibleRef visibilityRef;
0129     };
0130 
0131     QList<EffectWindow *> m_elevatedWindows;
0132     QHash<EffectWindow *, WindowData> m_windowData;
0133 };
0134 
0135 inline int SlideEffect::horizontalGap() const
0136 {
0137     return m_hGap;
0138 }
0139 
0140 inline int SlideEffect::verticalGap() const
0141 {
0142     return m_vGap;
0143 }
0144 
0145 inline bool SlideEffect::slideBackground() const
0146 {
0147     return m_slideBackground;
0148 }
0149 
0150 inline bool SlideEffect::isActive() const
0151 {
0152     return m_state != State::Inactive;
0153 }
0154 
0155 inline int SlideEffect::requestedEffectChainPosition() const
0156 {
0157     return 50;
0158 }
0159 
0160 } // namespace KWin