Skip to content

Commit

Permalink
fix(pointers): Cannot get PointerReleased in LVItem when selection is…
Browse files Browse the repository at this point in the history
… not None
  • Loading branch information
dr1rrb committed Feb 2, 2022
1 parent e23fbd1 commit 9377ad4
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 9 deletions.
26 changes: 18 additions & 8 deletions src/Uno.UI/UI/Xaml/Controls/Primitives/SelectorItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ private enum ManipulationUpdateKind
private string _currentState;
private uint _goToStateRequest;
private DateTime _pauseStateUpdateUntil;
private bool _isPressed;

public SelectorItem()
{
Expand Down Expand Up @@ -137,7 +138,7 @@ private void UpdateCommonStatesWithoutNeedsLayout(ManipulationUpdateKind manipul

private void UpdateCommonStates(ManipulationUpdateKind manipulationUpdate = ManipulationUpdateKind.None)
{
var state = GetState(IsEnabled, IsSelected, IsPointerOver, HasPointerCapture);
var state = GetState(IsEnabled, IsSelected, IsPointerOver, _isPressed);

// On Windows, the pressed state appears only after a few, and won't appear at all if you quickly start to scroll with the finger.
// So here we make sure to delay the beginning of a manipulation to match this behavior (and avoid flickering when scrolling)
Expand Down Expand Up @@ -283,11 +284,13 @@ protected override void OnPointerPressed(PointerRoutedEventArgs args)
if (ShouldHandlePressed
&& IsItemClickEnabled
&& args.GetCurrentPoint(this).Properties.IsLeftButtonPressed
&& CapturePointer(args.Pointer))
&& CapturePointer(args.Pointer, PointerCaptureKind.Implicit))
{
args.Handled = true;
_isPressed = true;
}

args.Handled = ShouldHandlePressed;

Focus(FocusState.Pointer);

base.OnPointerPressed(args);
Expand All @@ -298,22 +301,24 @@ protected override void OnPointerPressed(PointerRoutedEventArgs args)
protected override void OnPointerReleased(PointerRoutedEventArgs args)
{
ManipulationUpdateKind update;
if (IsCaptured(args.Pointer))
if (IsCaptured(args.Pointer, PointerCaptureKind.Implicit))
{
_isPressed = false;

update = ManipulationUpdateKind.Clicked;
Selector?.OnItemClicked(this);

// This should be automatically done by the pointers due to release, but if for any reason
// the state is invalid, this makes sure to not keep invalid capture longer than needed.
ReleasePointerCapture(args.Pointer);

args.Handled = true;
ReleasePointerCapture(args.Pointer.UniqueId, kinds: PointerCaptureKind.Implicit);
}
else
{
update = ManipulationUpdateKind.End;
}

args.Handled = ShouldHandlePressed;

base.OnPointerReleased(args);
UpdateCommonStatesWithoutNeedsLayout(update);
}
Expand All @@ -322,7 +327,8 @@ protected override void OnPointerReleased(PointerRoutedEventArgs args)
protected override void OnPointerExited(PointerRoutedEventArgs args)
{
// Not like a Button, if the pointer goes out of this item, we abort the ItemClick
ReleasePointerCapture(args.Pointer);
_isPressed = false;
ReleasePointerCapture(args.Pointer.UniqueId, kinds: PointerCaptureKind.Implicit);

base.OnPointerExited(args);
UpdateCommonStatesWithoutNeedsLayout(ManipulationUpdateKind.End);
Expand All @@ -331,13 +337,17 @@ protected override void OnPointerExited(PointerRoutedEventArgs args)
/// <inheritdoc />
protected override void OnPointerCanceled(PointerRoutedEventArgs args)
{
_isPressed = false;

base.OnPointerCanceled(args);
UpdateCommonStatesWithoutNeedsLayout(ManipulationUpdateKind.End);
}

/// <inheritdoc />
protected override void OnPointerCaptureLost(PointerRoutedEventArgs args)
{
_isPressed = false;

base.OnPointerCaptureLost(args);
UpdateCommonStatesWithoutNeedsLayout(ManipulationUpdateKind.End);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UI/UI/Xaml/UIElement.Pointers.Managed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ private class PointerManager
// TODO: Use pointer ID for the predicates
private static readonly Predicate<UIElement> _isOver = e => e.IsPointerOver;

private readonly Dictionary<Pointer, UIElement> _pressedElements = new Dictionary<Pointer, UIElement>();
private readonly Dictionary<Pointer, UIElement> _pressedElements = new();

public PointerManager()
{
Expand Down
11 changes: 11 additions & 0 deletions src/Uno.UI/UI/Xaml/UIElement.Pointers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,13 +1220,24 @@ internal bool IsCaptured(Pointer pointer)
&& PointerCapture.TryGet(pointer, out var capture)
&& capture.IsTarget(this, PointerCaptureKind.Explicit);

internal bool IsCaptured(Pointer pointer, PointerCaptureKind kinds)
=> PointerCapture.TryGet(pointer, out var capture)
&& capture.IsTarget(this, kinds);

public bool CapturePointer(Pointer value)
{
var pointer = value ?? throw new ArgumentNullException(nameof(value));

return Capture(pointer, PointerCaptureKind.Explicit, _pendingRaisedEvent.args);
}

private protected bool CapturePointer(Pointer value, PointerCaptureKind kind)
{
var pointer = value ?? throw new ArgumentNullException(nameof(value));

return Capture(pointer, kind, _pendingRaisedEvent.args);
}

public void ReleasePointerCapture(Pointer value)
=> ReleasePointerCapture((value ?? throw new ArgumentNullException(nameof(value))).UniqueId, muteEvent: false);

Expand Down

0 comments on commit 9377ad4

Please sign in to comment.