Animation-wide UI bounds (duration, stagger interval). More...
Go to the source code of this file.
Namespaces | |
| namespace | PhosphorAnimation |
| namespace | PhosphorAnimation::Limits |
Variables | |
| constexpr int | PhosphorAnimation::Limits::MinAnimationDurationMs = 50 |
| Minimum animation duration in milliseconds. | |
| constexpr int | PhosphorAnimation::Limits::MaxAnimationDurationMs = 2000 |
| Maximum animation duration in milliseconds. | |
| constexpr int | PhosphorAnimation::Limits::DefaultAnimationDurationMs = 150 |
| Default animation duration in milliseconds, used as the fallback at startup before settings are loaded from the daemon. | |
| constexpr int | PhosphorAnimation::Limits::MinAnimationStaggerIntervalMs = 10 |
| Minimum stagger interval between sequenced animations in milliseconds. | |
| constexpr int | PhosphorAnimation::Limits::MaxAnimationStaggerIntervalMs = 200 |
| Maximum stagger interval between sequenced animations in milliseconds. | |
| constexpr int | PhosphorAnimation::Limits::DefaultAnimationStaggerIntervalMs = 40 |
| Shipped stagger interval, the twin of DefaultAnimationDurationMs and there for the same reason: a consumer that caches the setting needs something to hold BEFORE the first reply lands, and an inline literal there drifts from the real default silently. | |
| constexpr int | PhosphorAnimation::Limits::SequenceModeAllAtOnce = 0 |
| Batch sequencing mode: 0 applies every window at once, 1 cascades them in zone order. | |
| constexpr int | PhosphorAnimation::Limits::SequenceModeCascade = 1 |
| constexpr int | PhosphorAnimation::Limits::DefaultAnimationSequenceMode = SequenceModeCascade |
| constexpr float | PhosphorAnimation::Limits::MaxShaderTimeDeltaSeconds = 0.1f |
| Hard ceiling on a per-frame time delta handed to a shader or to a physics integrator, in seconds. | |
| constexpr double | PhosphorAnimation::Limits::MinCurveProgress = -1.0 |
| Overshoot envelope for a curve's OUTPUT. | |
| constexpr double | PhosphorAnimation::Limits::MaxCurveProgress = 2.0 |
Animation-wide UI bounds (duration, stagger interval).
Source-of-truth min/max values surfaced by the settings UI's duration and stagger-interval sliders. They are animation-wide policy, so they MUST live in the animation library and not in any consumer-specific constants header. Previously homed under PhosphorTiles::AutotileDefaults for historical reasons; that placement was a layering mistake (the autotile library has no authority over generic animation policy) and has been corrected.
The duration bounds are ENFORCED clamps, not merely slider policy. They cap how long an animation may hold per-frame repaints — and, for the desktop switch, the fullscreen-effect claim — so a hand-edited per-event profile JSON cannot arm a multi-minute animation. Four call sites clamp against them (keep in sync when adding one):
daemon_settings.cpp),resolveAnimationMotionProfile (shader_resolve.cpp). The shader resolver deliberately does NOT read that slot: resolveEventMotionProfile owns it and feeds both the animator leg and the shader leg from one read and one clamp,PlasmaZonesEffect::resolveEventMotionProfile (shader_config_dbus.cpp), which bounds the motion cascade's resolved DURATION at the source,ShaderInternal::resolveTransitionLifetimeMs (kwin-effect/plasmazoneseffect/shader_internal.h), which bounds a shader transition's LIFETIME and folds in the spring settle-time rule. Both the per-window transition (shader_transitions.cpp) and the desktop switch (desktoptransitionmanager.cpp) route through it. Changing a bound changes runtime behaviour on those paths, not just the slider range.These bounds constrain a DURATION. They do NOT bound a STATEFUL (spring) curve, which derives its lifetime from its own physics and ignores the duration entirely — see AnimatedValue::advance. Absent anything else a spring is bounded only by Curve::settleTime(), itself capped at 30 s inside Spring. That is a PHYSICS bound, and it is the right one for a consumer deliberately outside this envelope (the daemon's SurfaceAnimator).
It is NOT enough for the compositor, whose two legs would otherwise disagree about the same curve: the shader leg cuts at MaxAnimationDurationMs via ShaderInternal::resolveTransitionLifetimeMs, while the geometry leg would run out to the raw settle time — and a SLIDER-reachable soft spring (zeta*omega < 2.649, e.g. "spring:10,0.15") settles in 3.5 s, leaving the window animating for seconds after its shader was torn down. So WindowAnimator resolves the lifetime through that same helper and passes it as MotionSpec::maxLifetimeMs, and AnimatedValue::advance folds it into the completion test. The geometry leg can therefore never OUTLIVE the shader leg — which is the failure that mattered. They are not identical at the fast end: a spring settling under MinAnimationDurationMs completes the geometry at its true settle time while the shader is floored to 50 ms and simply holds at iTime ≈ 1, which is harmless.
NOT universal: the daemon's SurfaceAnimator (OSD / popup / overlay surfaces) reads Profile::effectiveDuration() raw and is bounded only by Profile::MaxDurationMs, and the autotile library does not reference these constants at all. Do not assume a duration reaching you has been clamped — clamp at the site that arms the lifetime.