Browse Source

Fixed ToggleSwitch animation

pull/11557/head
Nikita Tsukanov 3 years ago
parent
commit
9debf63c71
  1. 13
      src/Avalonia.Base/Media/MediaContext.Compositor.cs
  2. 23
      src/Avalonia.Base/Media/MediaContext.cs

13
src/Avalonia.Base/Media/MediaContext.Compositor.cs

@ -40,10 +40,10 @@ partial class MediaContext
_animationsAreWaitingForComposition = false;
// Check if we have uncommited changes
if (_scheduleCommitOnLastCompositionBatchCompletion && _pendingCompositionBatches.Count > 0)
if (_scheduleCommitOnLastCompositionBatchCompletion)
{
CommitCompositorsWithThrottling();
_scheduleCommitOnLastCompositionBatchCompletion = false;
CommitCompositorsWithThrottling();
}
// Check if there are active animations and schedule the next render
else if(_clock.HasSubscriptions)
@ -52,16 +52,23 @@ partial class MediaContext
}
/// <summary>
/// Triggers a composition commit if any batches are waiting to be sent,
/// handles throttling
/// </summary>
/// <returns>true if there are pending commits in-flight and there will be a "all-done" callback later</returns>
private bool CommitCompositorsWithThrottling()
{
// Check if we are still waiting for previous composition batches
if (_pendingCompositionBatches.Count > 0)
{
_scheduleCommitOnLastCompositionBatchCompletion = true;
// Previous commit isn't handled yet
return true;
}
if (_requestedCommits.Count == 0)
// Nothing to do, and there are no pending commits
return false;
foreach (var c in _requestedCommits)

23
src/Avalonia.Base/Media/MediaContext.cs

@ -28,6 +28,14 @@ internal partial class MediaContext : ICompositorScheduler
private List<Action>? _invokeOnRenderCallbacks;
private readonly Stack<List<Action>> _invokeOnRenderCallbackListPool = new();
private DispatcherTimer _animationsTimer = new(DispatcherPriority.Render)
{
// Since this timer is used to drive animations that didn't contribute to the previous frame at all
// We can safely use 16ms interval until we fix our animation system to actually report the next expected
// frame
Interval = TimeSpan.FromMilliseconds(16)
};
private Dictionary<object, TopLevelInfo> _topLevels = new();
private MediaContext()
@ -35,6 +43,11 @@ internal partial class MediaContext : ICompositorScheduler
_render = Render;
_inputMarkerHandler = InputMarkerHandler;
_clock = new(this);
_animationsTimer.Tick += (_, _) =>
{
_animationsTimer.Stop();
ScheduleRender(false);
};
}
public static MediaContext Instance
@ -129,14 +142,12 @@ internal partial class MediaContext : ICompositorScheduler
break;
}
// We are currently using compositor commit callbacks to drive animations
// Later we should use WPF's approach that asks the animation system for the next tick time
// and use some timer if the next animation frame is not needed to be sent to the compositor immediately
if (_requestedCommits.Count > 0 || _clock.HasSubscriptions)
{
_animationsAreWaitingForComposition = true;
CommitCompositorsWithThrottling();
_animationsAreWaitingForComposition = CommitCompositorsWithThrottling();
if (!_animationsAreWaitingForComposition && _clock.HasSubscriptions)
_animationsTimer.Start();
}
}

Loading…
Cancel
Save