Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix visual transition support #6792

Merged
merged 7 commits into from
Aug 19, 2021
10 changes: 10 additions & 0 deletions src/Uno.UI/FeatureConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,16 @@ public static class UIElement
#endif
}

public static class VisualState
{
/// <summary>
/// When this is set, the <see cref="Windows.UI.Xaml.VisualState.Setters"/> will be applied synchronously when changing state,
/// unlike UWP which waits the for the end of the <see cref="VisualTransition.Storyboard"/> (if any) to apply them.
/// </summary>
/// <remarks>This flag is for backward compatibility with old versions of uno and should not be turned on.</remarks>
dr1rrb marked this conversation as resolved.
Show resolved Hide resolved
public static bool ApplySettersBeforeTransition { get; set; } = false;
}

public static class WebView
{
#if __ANDROID__
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,9 @@ private void Play()
_scheduledFrames.Add(
CoreDispatcher.Main.RunAsync(
CoreDispatcherPriority.Normal,
async () =>
async ct =>
{
await Task.Delay(dueTime);
await Task.Delay(dueTime, ct);
update();
}
)
Expand Down
1 change: 1 addition & 0 deletions src/Uno.UI/UI/Xaml/Media/Animation/Storyboard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ internal void TurnOverAnimationsTo(Storyboard storyboard)
((ITimeline)child).Stop();
}
}

State = TimelineState.Stopped;
}

Expand Down
4 changes: 2 additions & 2 deletions src/Uno.UI/UI/Xaml/Media/Animation/Timeline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public Timeline()
State = TimelineState.Stopped;
}

protected enum TimelineState
protected internal enum TimelineState
dr1rrb marked this conversation as resolved.
Show resolved Hide resolved
{
Active,
Filling,
Expand All @@ -46,7 +46,7 @@ protected string[] GetTraceProperties()
/// An internally-used property which is essentially equivalent to <see cref="Storyboard.GetCurrentState"/>, except that it
/// distinguishes <see cref="TimelineState.Active"/> from <see cref="TimelineState.Paused"/>.
/// </summary>
protected TimelineState State { get; set; }
protected internal TimelineState State { get; set; }

public TimeSpan? BeginTime
{
Expand Down
34 changes: 30 additions & 4 deletions src/Uno.UI/UI/Xaml/UIElement.Pointers.Managed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Text;
using Windows.Devices.Input;
using Microsoft.Extensions.Logging;
using Uno.Disposables;
using Uno.Extensions;
Expand Down Expand Up @@ -137,6 +138,12 @@ private void CoreWindow_PointerExited(CoreWindow sender, PointerEventArgs args)
var routedArgs = new PointerRoutedEventArgs(args, originalSource);

Raise(Leave, overBranchLeaf, routedArgs);
if (!args.CurrentPoint.IsInContact && args.CurrentPoint.Pointer.Type == PointerDeviceType.Touch)
{
// We release the captures on exit when pointer if not pressed
// Note: for a "Tap" with a finger the sequence is Up / Exited / Lost, so the lost cannot be raised on Up
ReleaseCaptures(routedArgs);
}
}

private void CoreWindow_PointerPressed(CoreWindow sender, PointerEventArgs args)
Expand Down Expand Up @@ -172,6 +179,7 @@ private void CoreWindow_PointerPressed(CoreWindow sender, PointerEventArgs args)
private void CoreWindow_PointerReleased(CoreWindow sender, PointerEventArgs args)
{
var (originalSource, _) = VisualTreeHelper.HitTest(args.CurrentPoint.Position);
var isOutOfWindow = originalSource is null;

// Even if impossible for the Release, we are fallbacking on the RootElement for safety
// This is how UWP behaves: when out of the bounds of the Window, the root element is use.
Expand All @@ -196,6 +204,12 @@ private void CoreWindow_PointerReleased(CoreWindow sender, PointerEventArgs args
var routedArgs = new PointerRoutedEventArgs(args, originalSource);

RaiseUsingCaptures(Released, originalSource, routedArgs);
if (isOutOfWindow || args.CurrentPoint.Pointer.Type != PointerDeviceType.Touch)
{
// We release the captures on up but only after the released event and processed the gesture
// Note: For a "Tap" with a finger the sequence is Up / Exited / Lost, so we let the Exit raise the capture lost
ReleaseCaptures(routedArgs);
}
ClearPressedState(routedArgs);
}

Expand Down Expand Up @@ -266,9 +280,21 @@ private void CoreWindow_PointerCancelled(CoreWindow sender, PointerEventArgs arg
var routedArgs = new PointerRoutedEventArgs(args, originalSource);

RaiseUsingCaptures(Cancelled, originalSource, routedArgs);
// Note: No ReleaseCaptures(routedArgs);, the cancel automatically raise it
ClearPressedState(routedArgs);
}

private void ReleaseCaptures(PointerRoutedEventArgs routedArgs)
{
if (PointerCapture.TryGet(routedArgs.Pointer, out var capture))
{
foreach (var target in capture.Targets)
{
target.Element.ReleasePointerCapture(capture.Pointer);
}
}
}

private void ClearPressedState(PointerRoutedEventArgs routedArgs)
{
if (_pressedElements.TryGetValue(routedArgs.Pointer, out var pressedLeaf))
Expand All @@ -285,7 +311,7 @@ private void ClearPressedState(PointerRoutedEventArgs routedArgs)
}
}

#region Helpers
#region Helpers
private delegate void RaisePointerEventArgs(UIElement element, PointerRoutedEventArgs args, BubblingContext ctx);

private static readonly RaisePointerEventArgs Wheel = (elt, args, ctx) => elt.OnPointerWheel(args, ctx);
Expand Down Expand Up @@ -351,7 +377,7 @@ private static void RaiseUsingCaptures(RaisePointerEventArgs raise, UIElement or
raise(originalSource, routedArgs, BubblingContext.Bubble);
}
}
#endregion
#endregion
}

// TODO Should be per CoreWindow
Expand All @@ -365,7 +391,7 @@ partial void InitializePointersPartial()
}
}

#region HitTestVisibility
#region HitTestVisibility
internal void UpdateHitTest()
{
this.CoerceValue(HitTestVisibilityProperty);
Expand Down Expand Up @@ -434,7 +460,7 @@ internal void ClearHitTestVisibilityForRoot()
this.ClearValue(HitTestVisibilityProperty);
}

#endregion
#endregion

partial void CapturePointerNative(Pointer pointer)
=> CoreWindow.GetForCurrentThread()!.SetPointerCapture();
Expand Down
27 changes: 15 additions & 12 deletions src/Uno.UI/UI/Xaml/UIElement.Pointers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,6 @@ private bool OnPointerUp(PointerRoutedEventArgs args, BubblingContext ctx = defa

handledInManaged |= SetPressed(args, false, muteEvent: ctx.IsLocalOnly || !isOverOrCaptured);


// Note: We process the UpEvent between Release and Exited as the gestures like "Tap"
// are fired between those events.
if (_gestures.IsValueCreated)
Expand All @@ -873,13 +872,15 @@ private bool OnPointerUp(PointerRoutedEventArgs args, BubblingContext ctx = defa
}
}

#if !UNO_HAS_MANAGED_POINTERS // Captures release are handled a root level
// We release the captures on up but only after the released event and processed the gesture
// Note: For a "Tap" with a finger the sequence is Up / Exited / Lost, so we let the Exit raise the capture lost
// Note: If '!isOver', that means that 'IsCaptured == true' otherwise 'isOverOrCaptured' would have been false.
if (!isOver || args.Pointer.PointerDeviceType != PointerDeviceType.Touch)
{
handledInManaged |= SetNotCaptured(args);
}
#endif

return handledInManaged;
}
Expand All @@ -898,12 +899,14 @@ private bool OnPointerExited(PointerRoutedEventArgs args, BubblingContext ctx =
global::Windows.UI.Xaml.Window.Current.DragDrop.ProcessMoved(args);
}

#if !UNO_HAS_MANAGED_POINTERS // Captures release are handled a root level
// We release the captures on exit when pointer if not pressed
// Note: for a "Tap" with a finger the sequence is Up / Exited / Lost, so the lost cannot be raised on Up
if (!IsPressed(args.Pointer))
{
handledInManaged |= SetNotCaptured(args);
}
#endif

return handledInManaged;
}
Expand Down Expand Up @@ -990,9 +993,9 @@ private bool RaisePointerEvent(RoutedEvent evt, PointerRoutedEventArgs args, Bub
_pendingRaisedEvent = (null, null, null);
}
}
#endregion
#endregion

#region Pointer over state (Updated by the partial API OnNative***, should not be updated externaly)
#region Pointer over state (Updated by the partial API OnNative***, should not be updated externaly)
/// <summary>
/// Indicates if a pointer (no matter the pointer) is currently over the element (i.e. OverState)
/// WARNING: This might not be maintained for all controls, cf. remarks.
Expand Down Expand Up @@ -1039,9 +1042,9 @@ private bool SetOver(PointerRoutedEventArgs args, bool isOver, bool muteEvent =
return RaisePointerEvent(PointerExitedEvent, args);
}
}
#endregion
#endregion

#region Pointer pressed state (Updated by the partial API OnNative***, should not be updated externaly)
#region Pointer pressed state (Updated by the partial API OnNative***, should not be updated externaly)
private readonly HashSet<uint> _pressedPointers = new HashSet<uint>();

/// <summary>
Expand Down Expand Up @@ -1113,9 +1116,9 @@ private bool SetPressed(PointerRoutedEventArgs args, bool isPressed, bool muteEv
}

private void ClearPressed() => _pressedPointers.Clear();
#endregion
#endregion

#region Pointer capture state (Updated by the partial API OnNative***, should not be updated externaly)
#region Pointer capture state (Updated by the partial API OnNative***, should not be updated externaly)
/*
* About pointer capture
*
Expand All @@ -1129,7 +1132,7 @@ private bool SetPressed(PointerRoutedEventArgs args, bool isPressed, bool muteEv

private List<Pointer> _localExplicitCaptures;

#region Capture public (and internal) API ==> This manages only Explicit captures
#region Capture public (and internal) API ==> This manages only Explicit captures
public static DependencyProperty PointerCapturesProperty { get; } = DependencyProperty.Register(
"PointerCaptures",
typeof(IReadOnlyList<Pointer>),
Expand Down Expand Up @@ -1196,7 +1199,7 @@ public void ReleasePointerCaptures()

Release(PointerCaptureKind.Explicit);
}
#endregion
#endregion

partial void CapturePointerNative(Pointer pointer);
partial void ReleasePointerNative(Pointer pointer);
Expand Down Expand Up @@ -1295,9 +1298,9 @@ private bool Release(PointerCapture capture, PointerCaptureKind kinds, PointerRo
relatedArgs.Handled = false;
return RaisePointerEvent(PointerCaptureLostEvent, relatedArgs);
}
#endregion
#endregion

#region Drag state (Updated by the RaiseDrag***, should not be updated externaly)
#region Drag state (Updated by the RaiseDrag***, should not be updated externaly)
private HashSet<long> _draggingOver;

/// <summary>
Expand Down Expand Up @@ -1329,6 +1332,6 @@ private void ClearDragOver()
{
_draggingOver?.Clear();
}
#endregion
#endregion
}
}
Loading