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.

  1. Select a damage policy – The eAVarDamagePolicy enumeration determines what region must be redrawn when the variable changes. Options include AVARDAMAGE_ENTIRE (full window), AVARDAMAGE_NONE (no additional damage), or specialized modes for borders and shadows.

  2. Call CHyprAnimationManager::createAnimation – This template method accepts the target value, a smart pointer to hold the resulting CAnimatedVariable, an SAnimationPropertyConfig (duration, easing curve), and an optional context reference (PHLWINDOW, PHLWORKSPACE, PHLLS).

  3. Variable registration – The manager constructs a CAnimatedVariable and registers it with the underlying CAnimationManager, which begins tracking the interpolation timeline.

  4. 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:

Summary

  • Hyprland's animation system relies on hyprutils for generic value interpolation, wrapped by CAnimatedVariable to add compositor context.
  • SAnimationContext and eAVarDamagePolicy connect animated values to the damage system, ensuring efficient repaints of only affected regions.
  • CHyprAnimationManager orchestrates 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →