Sweets
Configuration

Animations

Configure window and workspace transitions.

Animations are disabled by default. Enable the master switch to use the accepted transition families. Unsupported operations keep the normal immediate presentation.

Configuration

Declare sweets.animations({ ... }) at most once in each installed or personal configuration layer. Personal fields override installed fields. Omitted fields inherit the lower layer or built-in default.

sweets.animations({
    enabled = true,

    workspace_switch = {
        enabled = true,
        duration = 220,
        direction = "auto",
        curve = { 0.33, 1.0, 0.68, 1.0 },
    },

    window_open = {
        enabled = true,
        type = "fade",
        scale = 0.8,
        direction = "down",
        distance = 48,
        duration = 160,
        curve = { 0.33, 1.0, 0.68, 1.0 },
    },

    window_move = {
        enabled = true,
        duration = 220,
        curve = { 0.33, 1.0, 0.68, 1.0 },
    },

    window_resize = {
        enabled = true,
        duration = 220,
        curve = { 0.33, 1.0, 0.68, 1.0 },
    },

    window_close = {
        enabled = true,
        type = "fade",
        scale = 0.8,
        direction = "down",
        distance = 48,
        duration = 160,
        curve = { 0.33, 1.0, 0.68, 1.0 },
    },

    window_minimize = {
        enabled = true,
        type = "fade",
        scale = 0.8,
        direction = "down",
        distance = 48,
        duration = 160,
        curve = { 0.33, 1.0, 0.68, 1.0 },
    },
})
KeyDefaultBehavior
enabledfalseMaster switch for every animation family
workspace_switchEnabled, 220 msTranslates explicit numbered-workspace switches on one output
window_openFade, 0.8 scale, down 48 px, 160 msFades, zooms, or rigidly slides the first complete map of a managed window
window_moveEnabled, 220 msTranslates eligible same-output, same-size window moves
window_resizeEnabled, 220 msAnimates eligible same-output discrete resize batches
window_closeFade, 0.8 scale, down 48 px, 160 msFades, shrinks, or rigidly slides the retained final image after an irreversible close
window_minimizeFade, 0.8 scale, down 48 px, 160 msReversibly fades, zooms, or rigidly slides a complete window during minimize and restore

The child switches matter only when the top-level enabled value is true. A duration of zero also makes that family immediate.

Window open and close

window_open starts after a newly managed window has complete content ready to display. type = "fade" retains the original fade. type = "zoom" uniformly scales one complete content-and-border object from scale to its exact ready size while fading it in. type = "slide" keeps that complete object at its natural size and translates it from the configured hidden endpoint while fading it in. Text, content, border, and the backdrop mask follow one sample. Remapping an existing window does not replay the effect.

scale defaults to 0.8 and accepts finite values from 0.1 through 1.0. The field remains validated and retained when type = "fade", so changing the type later does not discard its tuning. direction accepts "left", "right", "up", or "down"; distance is an integer from 0 through 4096 logical pixels. They default to "down" and 48 and affect only slide. A pointer button or interactive window grab settles an active zoom or slide before input routing; keyboard focus and client geometry remain at the ready endpoint throughout.

window_close starts only after the client actually unmaps or destroys its window. A close request that the client refuses does not animate. Fade retains the final geometry while alpha reaches zero. Zoom flattens the detached content and border into one renderer-owned object, then uniformly shrinks it from scale 1.0 to the independently configured window_close.scale while fading out. Slide translates that same detached object toward its configured hidden endpoint without resizing it. Sibling reflow uses its own timeline, and client destruction cannot produce an empty frame or a second live copy beneath translucent pixels. Opening and closing slides remain clipped to their owning output even when the configured offset crosses an adjacent output.

Opening and closing apply to managed Wayland toplevels and normal managed X11 windows. Popups, layer surfaces, input methods, and X11 override-redirect windows do not use these families.

Window minimize and restore

window_minimize accepts the same type, scale, direction, and distance fields as window open and close, in addition to enabled, duration, and curve. Fade changes only alpha. Zoom scales the complete window uniformly about its center. Slide translates it rigidly toward the configured offset; Sweets does not infer a taskbar or panel target.

Minimize changes focus and logical state immediately. A non-interactive, renderer-owned image of the complete window starts fading after sibling reflow is ready, then releases its snapshot and frame demand at zero alpha. Restore waits for complete current client content and final layout geometry.

When restore interrupts a compatible outgoing effect, the same image reverses from the last alpha, scale, and translation accepted for presentation. A workspace, output, or geometry change uses a conservative ready effect at the destination instead, never a copy on both outputs. Activation and foreign- toplevel restore use the same path, and minimized-window recency is unchanged.

If another minimize or restore arrives before the previous layout transaction has produced complete ready geometry, Sweets uses the immediate latest result for that operation. It does not layer an obsolete grid or stack slot over the new topology. Reversal remains continuous once the first ready handoff has started the fade.

Calling restore-minimized when no minimized window remains is a true no-op; it does not capture or hold an unrelated in-progress resize animation.

Window movement and resize

window_move animates a complete window between ready positions on one output. The client content, popups, border, corners, and backdrop effect move together.

window_resize handles ready, discrete layout changes on one output. It can animate coordinated changes to several windows with one shared timeline. Sweets crops a complete natural-size image during a size change. It does not stretch or crossfade client content.

Some size changes cannot be represented from one complete image. During an explicit layout or master-position action, Sweets then keeps each affected window at its complete final ready size and translates it from the old slot origin to the new slot using window_move. Width and height are not animated in this fallback. Other unrepresentable resize operations remain immediate. Popup pixels also wait for the resize endpoint.

Interactive pointer move and resize stay pointer-matched and immediate. During a tiled move, vacated siblings may use coordinated relayout and a same-output drop may animate the dragged window from its released geometry into the selected slot. Cross-output window movement, visibility-changing Deck/Monocle membership, multi-window fullscreen changes, and recovery operations remain immediate.

Closing a tiled window is a safe removal-only exception. Sweets retains the departing complete window, waits for all affected survivor buffers, then starts the close effect and coordinated survivor resize together. Rapid closes follow the latest client-ready transaction. A change that also reveals or adds a window, times out, or cannot preserve complete natural-size content stays on the immediate path.

Workspace switching

workspace_switch animates successful explicit switches between numbered workspaces on one output. The outgoing and incoming windows remain clipped to that output.

direction accepts these values:

ValueBehavior
"auto"Horizontal movement based on workspace number
"horizontal"Always use the horizontal axis
"vertical"Always use the vertical axis

Special-workspace changes, cross-output window migration, output repair, and workspace changes interrupted by a grab or secure lock remain immediate.

Interruptions and fallback

A compatible rapid reversal continues from the most recently displayed visual position. It does not restart from the old endpoint.

If another discrete operation arrives before the earlier layout transaction has reached its first renderer materialization fence, Sweets skips the unshown intermediate target and prepares only the latest result from the last displayed presentation. Close and minimize readiness ownership follows that latest transaction, so a rapid mixed sequence cannot strand a detached image.

If that operation arrives while a newly opened window has not yet submitted its first animation frame, Sweets waits for that one renderer-owned image before continuing the transaction. The newcomer remains owned exclusively by its opening effect at final geometry; it is never treated as part of the old layout. Only windows that were already displayed enter sibling relayout, so they animate from pixels that actually appeared instead of dropping the entire resize batch to an immediate fallback.

Interactive pointer move and resize are intentionally different. Every ready intermediate client geometry is displayed immediately, then the next queued pointer target begins. Resize suppresses cosmetic relayout and retains that ownership through its last client-ready completion after release, so it has no movement or resize animation tail. A tiled move instead keeps only the dragged root pointer-matched; vacated siblings and final same-output placement remain animation-eligible. Direct manipulation stays responsive whether animations are enabled or disabled. While the first sibling reflow waits for client-ready buffers, Sweets keeps the last complete source object below the live roots as a vacated-slot cover. The cover retires with that exact transaction barrier, so neither animated nor non-animated grabs briefly expose the wallpaper.

After an animation has displayed a frame, a compatible operation starts from that renderer-accepted frame. An incompatible operation, missing renderer resources, output change, secure lock, or client-readiness timeout uses one complete ready result. A pointer grab takes over on its first motion. Sweets does not show a placeholder, empty slot, duplicated window, or partially prepared sibling layout.

Reloading a changed animation family settles that family's active transition once; the new curve, duration, or effect applies to later transitions. Turning off the master switch settles all active families without changing the final non-animated layout.

Whole-output screenshots and recordings include the displayed animation. A detached closing image is visual-only and is not available through isolated window capture.

Family settings

Every family accepts these fields:

FieldTypeDefaultAllowed values
enabledBooleantruetrue or false
durationIntegerFamily-specific0 through 5000 milliseconds
curveFour-number array{ 0.33, 1.0, 0.68, 1.0 }A bounded cubic Bézier curve

Workspace, move, and resize durations default to 220 ms. Open and close durations default to 160 ms.

window_open, window_close, and window_minimize additionally accept these fields independently:

FieldTypeDefaultAllowed values
typeString"fade""fade", "zoom", or "slide"
scaleNumber0.8Finite 0.1 through 1.0
directionString"down""left", "right", "up", or "down"
distanceInteger480 through 4096 logical pixels

initial_scale is not a valid field; the public zoom field is named scale.

Curves

curve is a Lua array in CSS cubic Bézier order:

local quick = { 0.46, 1.0, 0.29, 0.99 }

sweets.animations({
    enabled = true,
    window_move = { duration = 180, curve = quick },
})

The first and third entries must be between 0.0 and 1.0. The second and fourth entries may be between -4.0 and 4.0. The array must contain exactly four finite numbers.

Named curves, strings, named table fields, and arrays with missing or extra entries are invalid. { 0.0, 0.0, 1.0, 1.0 } is linear.

Reload behavior

A valid reload changes later transitions. An active transition keeps the direction, distance, scale, curve, and duration with which it started. Changing its effect type settles the active presentation once before later transitions use the new type.

Disabling the master switch or an active family settles that family once and releases its resources. Setting its duration to zero has the same effect. An invalid reload keeps the last valid configuration.

Validate an edited file before reloading:

sweets --check-config ~/.config/sweets/sweets.lua

For performance counters and renderer fallback diagnostics, see Performance Diagnostics.

On this page