Hyprland Animation System Explained: How AnimatedVariable Powers Smooth Transitions
Hyprland's animation system uses the AnimatedVariable template class to interpolate values over time according to easing curves, triggering damage callbacks that repaint specific window regions on each global tick.
The Hyprland compositor delivers its signature smooth visual effects—window movements, scaling transformations, opacity fades, and border-glow transitions—through a lightweight animation framework defined in the hyprutils library. Within the Hyprland source code, this framework is wrapped by compositor-specific types that attach context about which window, workspace, or layer surface requires repainting when values change.
Core Components of the Animation Framework
The Hyprland animation system is built on a layered architecture that separates the generic interpolation engine from the compositor-specific damage tracking.
CGenericAnimatedVariable (hyprutils)
The foundation is CGenericAnimatedVariable<VarType>, defined in [hyprutils/animation/AnimatedVariable.hpp](https://github.com/hyprutils/hyprutils/blob/main/include/hyprutils/animation/AnimatedVariable.hpp). This template class stores a value of any type (float, Vector2D, etc.) and interpolates it over time according to an SAnimationPropertyConfig. It emits a tick callback whenever the interpolated value changes, allowing the compositor to schedule repaints.
CAnimatedVariable (Hyprland Wrapper)
Hyprland defines a specialized alias in [src/helpers/AnimatedVariable.hpp](https://github.com/hyprwm/Hyprland/blob/main/src/helpers/AnimatedVariable.hpp):
using CAnimatedVariable = Hyprutils::Animation::CGenericAnimatedVariable<VarType, SAnimationContext>;
This alias enriches the generic variable with an SAnimationContext that identifies where the change occurred (window, workspace, or layer surface) and specifies how to damage the scene through the eAVarDamagePolicy enum.
CHyprAnimationManager
The [src/animation/AnimationManager.hpp](https://github.com/hyprwm/Hyprland/blob/main/src/animation/AnimationManager.hpp) file houses CHyprAnimationManager, which owns a hyprutils::Animation::CAnimationManager. This central manager schedules ticks, updates global time, and provides the createAnimation helper that constructs CAnimatedVariable instances and attaches the proper damage policy to each.
ViewAnimationController
For higher-level coordination, [src/animation/controller/ViewAnimationController.hpp](https://github.com/hyprwm/Hyprland/blob/main/src/animation/controller/ViewAnimationController.hpp) groups multiple CAnimatedVariables into a SAnimatedMovement struct. This controller manages related properties (position, size, alpha) simultaneously for a given view, ensuring synchronized animation updates.
Animated View Mix-ins
Concrete view classes inherit animation capabilities through mix-ins like GeometricAnimated, found in [src/desktop/view/types/GeometricAnimated.hpp](https://github.com/hyprwm/Hyprland/blob/main/src/desktop/view/types/GeometricAnimated.hpp). These classes expose animated properties as part of the view hierarchy, allowing CWindow and CLayerSurface objects to store and update animated state directly.
How AnimatedVariable Creates Animations
Creating an animation in Hyprland follows a strict four-step flow that connects the generic interpolation engine to the compositor's damage system.
-
Select a damage policy – The
eAVarDamagePolicyenumeration determines what region must be redrawn when the variable changes. Options includeAVARDAMAGE_ENTIRE(full window),AVARDAMAGE_NONE(no additional damage), or specialized modes for borders and shadows. -
Call
CHyprAnimationManager::createAnimation– This template method accepts the target value, a smart pointer to hold the resultingCAnimatedVariable, anSAnimationPropertyConfig(duration, easing curve), and an optional context reference (PHLWINDOW,PHLWORKSPACE,PHLLS). -
Variable registration – The manager constructs a
CAnimatedVariableand registers it with the underlyingCAnimationManager, which begins tracking the interpolation timeline. -
Global tick advancement – On each call to
CHyprAnimationManager::tick, the manager advances all active variables, triggers their callbacks, and marks the affected regions for repaint based on the selected damage policy.
Practical Implementation Examples
Window Opacity Fade
To animate a window fading to transparent over 300ms:
PHLWINDOW pWin = /* window pointer */;
float finalOpacity = 0.0f;
auto pConfig = std::make_shared<Hyprutils::Animation::SAnimationPropertyConfig>();
pConfig->duration = 300; // milliseconds
pConfig->easing = Hyprutils::Animation::EASE_LINEAR;
PHLANIMVAR<float> pOpacityVar;
Animation::mgr()->createAnimation(
finalOpacity,
pOpacityVar,
pConfig,
pWin, // context for damage tracking
AVARDAMAGE_ENTIRE); // repaint entire window each tick
As the animation runs, pOpacityVar interpolates from the current opacity to 0.0f, triggering window repaints until completion.
Position Animation with Bounce Easing
To move a window with a bounce effect:
PHLWINDOW pWin = /* window pointer */;
Vector2D targetPos = {1920.f, 1080.f};
auto pConfig = std::make_shared<Hyprutils::Animation::SAnimationPropertyConfig>();
pConfig->duration = 500;
pConfig->easing = Hyprutils::Animation::EASE_OUT_BOUNCE;
PHLANIMVAR<Vector2D> pPosVar;
Animation::mgr()->createAnimation(
targetPos,
pPosVar,
pConfig,
pWin,
AVARDAMAGE_NONE); // position changes handled by existing damage logic
The Vector2D specialization smoothly moves the window while the bounce curve adds an overshoot effect.
View Controller Integration
Inside a view class, animated properties are typically pre-declared and updated through the controller:
void CWindow::animateScale(const Vector2D& newScale) {
auto pConfig = std::make_shared<Hyprutils::Animation::SAnimationPropertyConfig>();
pConfig->duration = 200;
pConfig->easing = Hyprutils::Animation::EASE_IN_OUT_QUAD;
// m_sScale is a CAnimatedVariable<Vector2D> owned by ViewAnimationController
Animation::mgr()->createAnimation(
newScale,
m_sScale,
pConfig,
this, // view context
AVARDAMAGE_ENTIRE);
}
The controller automatically updates the window's transformation matrix each tick, abstracting the interpolation details from the view logic.
Key Source Files
Understanding the complete animation flow requires examining these specific files in the Hyprland repository:
src/helpers/AnimatedVariable.hpp– DefineseAVarDamagePolicy,SAnimationContext, and theCAnimatedVariablealias used throughout the compositor.src/animation/AnimationManager.hpp– ContainsCHyprAnimationManager, which bridges the generic animation library with Hyprland's damage system.src/animation/controller/ViewAnimationController.hpp– Groups per-view animated variables into theSAnimatedMovementstruct for coordinated updates.src/desktop/view/types/GeometricAnimated.hpp– Demonstrates the mix-in pattern for adding animated geometry to view classes.src/desktop/view/Window.hpp– Real-world usage showingCAnimatedVariableinstances for border angles, shadow opacity, and window alpha.
Summary
- Hyprland's animation system relies on
hyprutilsfor generic value interpolation, wrapped byCAnimatedVariableto add compositor context. SAnimationContextandeAVarDamagePolicyconnect animated values to the damage system, ensuring efficient repaints of only affected regions.CHyprAnimationManagerorchestrates the global tick, advancing all active interpolations and triggering callbacks.- ViewAnimationController provides high-level grouping of related animations (position, size, alpha) for window management.
- The template-based design allows animating any value type (
float,Vector2D,CColor) with configurable duration and easing curves.
Frequently Asked Questions
What is the difference between CGenericAnimatedVariable and CAnimatedVariable?
CGenericAnimatedVariable is the base template class from the hyprutils library that handles value interpolation and stores animation configuration. CAnimatedVariable is a Hyprland-specific alias that specializes the template with SAnimationContext, adding a pointer to the window, workspace, or layer surface that owns the animation, plus the damage policy for repaint scheduling.
How does Hyprland know which part of the screen to repaint during an animation?
Each CAnimatedVariable carries an eAVarDamagePolicy set during creation via createAnimation(). When the variable ticks and updates its value, the animation manager checks this policy—options include AVARDAMAGE_ENTIRE for full window redraws, AVARDAMAGE_BORDER for border-only updates, or AVARDAMAGE_NONE when the change doesn't require explicit damage.
Can AnimatedVariable handle complex types like colors or vectors?
Yes. CAnimatedVariable is a template that supports any type implementing the necessary arithmetic operators. The Hyprland codebase uses specializations for float (opacity), Vector2D (position, size), and CColor (border colors). The interpolation logic automatically applies to each component of the complex type.
Where are animation durations and easing curves configured?
Animation properties are defined in SAnimationPropertyConfig objects passed to createAnimation(). These configurations specify the duration in milliseconds and the easing function (such as EASE_LINEAR, EASE_OUT_BOUNCE, or EASE_IN_OUT_QUAD). Hyprland typically loads these values from user configuration files and applies them when creating animations for window events.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →