#include #include #include #include #include #include #include #define foreach BOOST_FOREACH #include #include "animation_options.h" typedef std::vector CompWindowVector; typedef std::vector ExtensionPluginVector; typedef std::vector AnimEffectVector; class RestackInfo { public: RestackInfo (CompWindow *wRestacked, CompWindow *wStart, CompWindow *wEnd, CompWindow *wOldAbove, bool raised); CompWindow *wRestacked, *wStart, *wEnd, *wOldAbove; bool raised; }; class IdValuePair { public: IdValuePair () : pluginInfo (0), optionId (-1), value () {} bool matchesPluginOption (ExtensionPluginInfo *pluginInfo, int optionId); const ExtensionPluginInfo *pluginInfo; int optionId; CompOption::Value value; }; typedef std::vector IdValuePairVector; class OptionSet { public: OptionSet () {} IdValuePairVector pairs; }; typedef std::vector OptionSetVector; class OptionSets { public: OptionSets () {} OptionSetVector sets; }; class EffectSet { public: EffectSet () {} AnimEffectVector effects; }; extern AnimEffect AnimEffectNone; extern AnimEffect AnimEffectRandom; extern AnimEffect AnimEffectCurvedFold; extern AnimEffect AnimEffectDodge; extern AnimEffect AnimEffectDream; extern AnimEffect AnimEffectFade; extern AnimEffect AnimEffectFocusFade; extern AnimEffect AnimEffectGlide1; extern AnimEffect AnimEffectGlide2; extern AnimEffect AnimEffectHorizontalFolds; extern AnimEffect AnimEffectMagicLamp; extern AnimEffect AnimEffectMagicLampWavy; extern AnimEffect AnimEffectRollUp; extern AnimEffect AnimEffectSidekick; extern AnimEffect AnimEffectWave; extern AnimEffect AnimEffectZoom; #define NUM_EFFECTS 16 extern int customOptionOptionIds[AnimEventNum]; typedef struct _PluginEventInfo { const char *pluginName; const char *activateEventName; } PluginEventInfo; typedef enum { WatchedPluginSwitcher = 0, WatchedPluginRing, WatchedPluginShift, WatchedPluginScale, WatchedPluginGroup, WatchedPluginFadedesktop, WatchedScreenPluginNum } WatchedScreenPlugin; typedef enum { WatchedPluginKDECompat, WatchedWindowPluginNum } WatchedWindowPlugin; // This must have the value of the first "effect setting" above // in PrivateAnimScreenOptions #define NUM_NONEFFECT_OPTIONS AnimationOptions::CurvedFoldAmpMult class ExtensionPluginAnimation : public ExtensionPluginInfo { public: ExtensionPluginAnimation (const CompString &name, unsigned int nEffects, AnimEffect *effects, CompOption::Vector *effectOptions, unsigned int firstEffectOptionIndex); ~ExtensionPluginAnimation (); // Overriden methods from ExtensionPluginInfo void postPreparePaintGeneral (); void prePreparePaintGeneral (); void handleRestackNotify (AnimWindow *aw); // Always reset stacking related info when a window is opened, closed, // minimized, or unminimized. void preInitiateOpenAnim (AnimWindow *aw); void preInitiateCloseAnim (AnimWindow *aw); void preInitiateMinimizeAnim (AnimWindow *aw); void preInitiateUnminimizeAnim (AnimWindow *aw); void initPersistentData (AnimWindow *aw); void destroyPersistentData (AnimWindow *aw); void postUpdateEventEffects (AnimEvent e, bool forRandom); void cleanUpAnimation (bool closing, bool destructing); void postStartupCountdown (); // Other methods void handleSingleRestack (AnimWindow *aw); void prePaintWindowsBackToFront (); bool paintShouldSkipWindow (CompWindow *w); const CompWindowList & getWindowPaintList (); void resetStackingInfo (); static CompWindow *getBottommostInExtendedFocusChain (CompWindow *wStartPoint); static CompWindow *getBottommostInRestackChain (CompWindow *wStartPoint); void resetMarks (); bool markNewCopy (CompWindow *w); CompWindow * walkFirst (); CompWindow * walkNext (CompWindow *w); void incrementCurRestackAnimCount (); void decrementCurRestackAnimCount (); bool wontCreateCircularChain (CompWindow *wCur, CompWindow *wNext); static void cleanUpParentChildChainItem (AnimWindow *aw); static bool relevantForRestackAnim (CompWindow *w); /// Is restackInfo still good? static bool restackInfoStillGood (RestackInfo *restackInfo); void updateLastClientList (); /// A window was restacked this paint round. bool mAWinWasRestackedJustNow; private: CompWindowVector mLastClientList; ///< Last known stacking order CompWindowVector mPrevClientList; ///< The stacking order before mLastClientList int mRestackAnimCount; ///< Count of how many windows are currently involved in ///< animations that require walker (dodge & focus fade). std::vector mRestackedWindows; CompWindowList mWindowList; }; class PrivateAnimScreen : public ScreenInterface, public CompositeScreenInterface, public GLScreenInterface, public AnimationOptions { friend class PrivateAnimWindow; friend class AnimWindow; public: CompositeScreen *cScreen; GLScreen *gScreen; AnimScreen *aScreen; private: struct timeval mLastRedrawTime; bool mLastRedrawTimeFresh; bool mPluginActive[WatchedScreenPluginNum]; int mSwitcherPostWait; int mStartCountdown; ///< To mark windows as "created" if they were opened before compiz ///< was started and to prevent already opened windows from doing ///< open animation. Window mLastActiveWindow; ///< Last known active window bool mAnimInProgress; ///< Is an animation currently being played? bool mStartingNewPaintRound; ///< Is a new round of glPaints starting? bool mPrePaintWindowsBackToFrontEnabled; EffectSet mRandomEffects[AnimEventNum]; OptionSets mEventOptionSets[AnimEventNum]; // Effect extension plugins ExtensionPluginVector mExtensionPlugins; // Possible effects for each event AnimEffectVector mEventEffectsAllowed[AnimEventNum]; // List of chosen effects for each event EffectSet mEventEffects[AnimEventNum]; CompOutput *mOutput; Window mActiveWindow; CompMatch mNeverAnimateMatch; void updateEventEffects (AnimEvent e, bool forRandom, bool callPost = true); void updateAllEventEffects (); void updateOptionSets (AnimEvent e); void updateOptionSet (OptionSet *os, const char *optNamesValuesOrig); void activateEvent (bool activating); bool isWinVisible (CompWindow *w); AnimEvent getCorrespondingAnimEvent (AnimationOptions::Options optionId); void eventMatchesChanged (CompOption *opt, AnimationOptions::Options num); void eventOptionsChanged (CompOption *opt, AnimationOptions::Options num); void eventEffectsChanged (CompOption *opt, AnimationOptions::Options num); void eventRandomEffectsChanged (CompOption *opt, AnimationOptions::Options num); CompRect getIcon (CompWindow *w, bool alwaysUseMouse); void updateAnimStillInProgress (); bool isAnimEffectInList (AnimEffect theEffect, EffectSet &effectList); bool isAnimEffectPossibleForEvent (AnimEffect theEffect, AnimEvent event); public: PrivateAnimScreen (CompScreen *s, AnimScreen *); ~PrivateAnimScreen (); // Utility methods void initiateOpenAnim (PrivateAnimWindow *aw); void initiateCloseAnim (PrivateAnimWindow *aw); void initiateMinimizeAnim (PrivateAnimWindow *aw); void initiateUnminimizeAnim (PrivateAnimWindow *aw); void initiateShadeAnim (PrivateAnimWindow *aw); void initiateUnshadeAnim (PrivateAnimWindow *aw); bool initiateFocusAnim (PrivateAnimWindow *aw); /// Is a restacking animation currently possible? bool isRestackAnimPossible (); void initAnimationList (); bool isAnimEffectPossible (AnimEffect theEffect); inline CompOutput &output () { return *mOutput; } AnimEffect getActualEffect (AnimEffect effect, AnimEvent animEvent); bool shouldIgnoreWindowForAnim (CompWindow *w, bool checkPixmap); OptionSet *getOptionSetForSelectedRow (PrivateAnimWindow *aw, Animation *anim); void addExtension (ExtensionPluginInfo *extensionPluginInfo, bool shouldInitPersistentData); void removeExtension (ExtensionPluginInfo *extensionPluginInfo); AnimEffect getMatchingAnimSelection (CompWindow *w, AnimEvent e, int *duration); bool otherPluginsActive (); void enablePrePaintWindowsBackToFront (bool enabled); void prePaintWindowsBackToFront (); // CompositeScreenInterface methods void preparePaint (int); void donePaint (); const CompWindowList & getWindowPaintList (); // GLScreenInterface methods bool glPaintOutput (const GLScreenPaintAttrib &, const GLMatrix &, const CompRegion &, CompOutput *, unsigned int); // ScreenInterface methods void handleCompizEvent (const char * plugin, const char *event, CompOption::Vector &options); }; class PrivateAnimWindow : public WindowInterface, public GLWindowInterface { friend class PrivateAnimScreen; friend class AnimWindow; public: PrivateAnimWindow (CompWindow *, AnimWindow *aw); ~PrivateAnimWindow (); void createFocusAnimation (AnimEffect effect, int duration); inline void setShaded (bool shaded) { mNowShaded = shaded; } inline Animation *curAnimation () { return mCurAnimation; } inline PrivateAnimScreen *paScreen () { return mPAScreen; } inline AnimWindow *aWindow () { return mAWindow; } inline Box &BB () { return mBB; } inline int curAnimSelectionRow () { return mCurAnimSelectionRow; } void damageThisAndLastStepRegion (); void postAnimationCleanUp (); void copyResetStepRegion (); GLWindow *gWindow; private: CompWindow *mWindow; AnimWindow *mAWindow; PrivateAnimScreen *mPAScreen; unsigned int mState; unsigned int mNewState; Animation *mCurAnimation; bool mUnshadePending; bool mEventNotOpenClose; bool mNowShaded; bool mGrabbed; int mUnmapCnt; int mDestroyCnt; bool mUnreparentInterrupted; bool mIgnoreDamage; bool mFinishingAnim; int mCurAnimSelectionRow; int mPrevAnimSelectionRow; ///< For the case when one event interrupts another Box mBB; ///< Bounding box of area to be damaged CompRegion mStepRegion; ///< Region to damage this step CompRegion mLastStepRegion; ///< Region damaged last step bool mPluginActive[WatchedWindowPluginNum]; // Utility methods unsigned int getState (); void updateSelectionRow (unsigned int i); void postAnimationCleanUpPrev (bool closing, bool clearMatchingRow); void postAnimationCleanUpCustom (bool closing, bool destructing, bool clearMatchingRow); void reverseAnimation (); void enablePainting (bool enabling); void notifyAnimation (bool activation); // WindowInterface methods void resizeNotify (int dx, int dy, int dwidth, int dheight); void moveNotify (int dx, int dy, bool immediate); void windowNotify (CompWindowNotify n); void grabNotify (int x, int y, unsigned int state, unsigned int mask); void ungrabNotify (); // GLWindowInterface methods bool glPaint (const GLWindowPaintAttrib &, const GLMatrix &, const CompRegion &, unsigned int); void glAddGeometry (const GLTexture::MatrixList &, const CompRegion &, const CompRegion &, unsigned int = MAXSHORT, unsigned int = MAXSHORT); void glDrawTexture (GLTexture *texture, GLFragment::Attrib &, unsigned int); void glDrawGeometry (); }; class RollUpAnim : public GridAnim { public: RollUpAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); protected: static const float kDurationFactor; void initGrid (); void step (); }; class MagicLampAnim : public GridAnim { public: MagicLampAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); virtual ~MagicLampAnim (); protected: bool mTargetTop; GridModel::GridObject *mTopLeftCornerObject; GridModel::GridObject *mBottomLeftCornerObject; void initGrid (); void step (); void updateBB (CompOutput &output); inline bool stepRegionUsed () { return true; } void adjustPointerIconSize (); virtual bool hasMovingEnd (); virtual void filterTargetX (float &targetX, float x) { } }; class MagicLampWavyAnim : public MagicLampAnim { public: MagicLampWavyAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); ~MagicLampWavyAnim (); protected: struct WaveParam { float halfWidth; float amp; float pos; }; unsigned int mNumWaves; WaveParam *mWaves; void initGrid (); void updateBB (CompOutput &output); inline bool stepRegionUsed () { return false; } void adjustPointerIconSize (); bool hasMovingEnd (); void filterTargetX (float &targetX, float x); }; class SidekickAnim : public ZoomAnim { public: SidekickAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); protected: float mNumRotations; float getSpringiness (); bool isZoomFromCenter (); inline bool hasExtraTransform () { return true; } void applyExtraTransform (float progress); inline bool shouldAvoidParallelogramLook () { return true; } }; class WaveAnim : public GridTransformAnim { public: WaveAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); protected: void adjustDuration (); void initGrid (); inline bool using3D () { return true; } void step (); static const float kMinDuration; }; class GlideAnim : public ZoomAnim { public: GlideAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); protected: void prePaintWindow (); inline bool postPaintWindowUsed () { return true; } void postPaintWindow (); void adjustDuration (); bool zoomToIcon (); void applyTransform (); float getFadeProgress (); float getProgress (); virtual void getParams (float *finalDistFac, float *finalRotAng, float *thickness); float glideModRotAngle; ///< The angle of rotation, modulo 360. }; class Glide2Anim : public GlideAnim { public: Glide2Anim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); protected: bool zoomToIcon (); void getParams (float *finalDistFac, float *finalRotAng, float *thickness); }; class RestackPersistentData; class RestackAnim : virtual public Animation { public: RestackAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); void cleanUp (bool closing, bool destructing); bool initiateRestackAnim (int duration); inline bool moveUpdate () { return false; } static bool onSameRestackChain (CompWindow *wSubject, CompWindow *wOther); /// Find union of restack chain (group) static CompRegion unionRestackChain (CompWindow *w); virtual bool paintedElsewhere () { return false; } protected: // Overridable methods virtual void processCandidate (CompWindow *candidateWin, CompWindow *subjectWin, CompRegion &candidateAndSubjectIntersection, int &numSelectedCandidates) {} virtual void postInitiateRestackAnim (int numSelectedCandidates, int duration, CompWindow *wStart, CompWindow *wEnd, bool raised) {} // Other methods bool overNewCopy (); ///< Is glPaint on the copy at the new position? RestackPersistentData *mRestackData; }; class RestackPersistentData : public PersistentData { friend class ExtensionPluginAnimation; friend class RestackAnim; friend class FocusFadeAnim; friend class DodgeAnim; public: RestackPersistentData (); ~RestackPersistentData (); protected: inline RestackInfo *restackInfo () { return mRestackInfo; } void resetRestackInfo (bool alsoResetChain = false); void setRestackInfo (CompWindow *wRestacked, CompWindow *wStart, CompWindow *wEnd, CompWindow *wOldAbove, bool raised); void getHostedOnWin (CompWindow *wGuest, CompWindow *wHost); RestackInfo *mRestackInfo; ///< restack info if window was restacked this paint round CompWindow *mWinToBePaintedBeforeThis; ///< Window which should be painted before this CompWindow *mWinThisIsPaintedBefore; ///< the inverse relation of mWinToBePaintedBeforeThis CompWindow *mMoreToBePaintedPrev; CompWindow *mMoreToBePaintedNext; ///< doubly linked list for windows underneath that ///< raise together with this one bool mConfigureNotified; ///< was mConfigureNotified before restack check CompWindow *mWinPassingThrough; ///< win. passing through this one during focus effect bool mWalkerOverNewCopy; ///< whether walker is on the copy at the new pos. int mVisitCount; ///< how many times walker/glPaint has visited this window bool mIsSecondary; ///< whether this is one of the secondary (non-topmost) in its restack chain }; class FocusFadeAnim : public RestackAnim, public FadeAnim { public: FocusFadeAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); void updateAttrib (GLWindowPaintAttrib &attrib); void cleanUp (bool closing, bool destructing); protected: void processCandidate (CompWindow *candidateWin, CompWindow *subjectWin, CompRegion &candidateAndSubjectIntersection, int &numSelectedCandidates); GLushort computeOpacity (GLushort opacityInt); }; typedef enum { DodgeDirectionUp = 0, DodgeDirectionRight, DodgeDirectionDown, DodgeDirectionLeft, DodgeDirectionXY, // movement possibly in both X and Y (for subjects) DodgeDirectionNone } DodgeDirection; class DodgePersistentData; class DodgeAnim : public RestackAnim, public TransformAnim { public: DodgeAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); void cleanUp (bool closing, bool destructing); static int getDodgeAmount (CompRect &rect, CompWindow *dw, DodgeDirection dir); void step (); void updateTransform (GLMatrix &wTransform); bool shouldDamageWindowOnStart (); void updateBB (CompOutput &output); void postPreparePaint (); void calculateDodgeAmounts (); bool moveUpdate (); protected: void processCandidate (CompWindow *candidateWin, CompWindow *subjectWin, CompRegion &candidateAndSubjectIntersection, int &numSelectedCandidates); void postInitiateRestackAnim (int numSelectedCandidates, int duration, CompWindow *wStart, CompWindow *wEnd, bool raised); bool paintedElsewhere (); void applyDodgeTransform (); float dodgeProgress (); void updateDodgerDodgeAmount (); DodgePersistentData *mDodgeData; CompWindow *mDodgeSubjectWin;///< The window being dodged float mDodgeMaxAmountX; ///< max # pixels it should dodge ///< (neg. value dodges leftward) float mDodgeMaxAmountY; ///< max # pixels it should dodge ///< (neg. value dodges upward) DodgeDirection mDodgeDirection; int mDodgeMode; }; class DodgePersistentData : public PersistentData { friend class ExtensionPluginAnimation; friend class DodgeAnim; public: DodgePersistentData (); private: int dodgeOrder; ///< dodge order (used temporarily) // TODO mov the below members into DodgeAnim bool isDodgeSubject; ///< true if this window is the cause of dodging bool skipPostPrepareScreen; CompWindow *dodgeChainStart;///< for the subject window CompWindow *dodgeChainPrev; ///< for dodging windows CompWindow *dodgeChainNext; ///< for dodging windows }; class DreamAnim : public GridZoomAnim { public: DreamAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); protected: void init (); void initGrid (); void step (); void adjustDuration (); float getFadeProgress (); bool zoomToIcon (); static const float kDurationFactor; }; class FoldAnim : public GridZoomAnim { public: FoldAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); protected: inline bool using3D () { return true; } float getFadeProgress (); void updateWindowAttrib (GLWindowPaintAttrib &attrib); }; class CurvedFoldAnim : public FoldAnim { public: CurvedFoldAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); protected: void initGrid (); void step (); void updateBB (CompOutput &output); bool zoomToIcon (); float getObjectZ (GridAnim::GridModel *mModel, float forwardProgress, float sinForProg, float relDistToCenter, float curveMaxAmp); }; class HorizontalFoldsAnim : public FoldAnim { public: HorizontalFoldsAnim (CompWindow *w, WindowEvent curWindowEvent, float duration, const AnimEffect info, const CompRect &icon); protected: void initGrid (); void step (); bool zoomToIcon (); float getObjectZ (GridAnim::GridModel *mModel, float forwardProgress, float sinForProg, float relDistToFoldCenter, float foldMaxAmp); };