Skip to content

Commit

Permalink
fix(dragdrop): When drag source are nested, the top most drag operati…
Browse files Browse the repository at this point in the history
…on is cancelled in favor of the parent's one
  • Loading branch information
dr1rrb committed Oct 16, 2020
1 parent ceec30e commit d49a800
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions src/Uno.UI/UI/Xaml/UIElement.Pointers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ partial void PrepareManagedDragAndDropEventBubbling(RoutedEvent routedEvent, ref
var pt = ((global::Windows.UI.Xaml.DragEventArgs)args).SourceId;
var wasDragOver = IsDragOver(pt);

// As the IsDragOver is expected to reflect teh state of the current element **and the state of its children**,
// As the IsDragOver is expected to reflect the state of the current element **and the state of its children**,
// even if the AllowDrop flag has not been set, we have to update the IsDragOver state.
SetIsDragOver(pt, true);

Expand All @@ -506,7 +506,7 @@ partial void PrepareManagedDragAndDropEventBubbling(RoutedEvent routedEvent, ref
}

case RoutedEventFlag.DragOver:
// As the IsDragOver is expected to reflect teh state of the current element **and the state of its children**,
// As the IsDragOver is expected to reflect the state of the current element **and the state of its children**,
// even if the AllowDrop flag has not been set, we have to update the IsDragOver state.
SetIsDragOver(((global::Windows.UI.Xaml.DragEventArgs)args).SourceId, true);

Expand All @@ -522,7 +522,7 @@ partial void PrepareManagedDragAndDropEventBubbling(RoutedEvent routedEvent, ref
var pt = ((global::Windows.UI.Xaml.DragEventArgs)args).SourceId;
var wasDragOver = IsDragOver(pt);

// As the IsDragOver is expected to reflect teh state of the current element **and the state of its children**,
// As the IsDragOver is expected to reflect the state of the current element **and the state of its children**,
// even if the AllowDrop flag has not been set, we have to update the IsDragOver state.
SetIsDragOver(pt, false);

Expand All @@ -536,15 +536,27 @@ partial void PrepareManagedDragAndDropEventBubbling(RoutedEvent routedEvent, ref
}
}

[ThreadStatic]
private static uint _lastDragStartFrameId;

private void OnDragStarting(DraggingEventArgs args)
{
if (args.DraggingState != DraggingState.Started // This UIElement is actually interested only by the starting
|| !CanDrag // Sanity ... should never happen!
|| !args.Pointer.Properties.IsLeftButtonPressed)
|| !args.Pointer.Properties.IsLeftButtonPressed

// As the pointer args are always bubbling (for to properly update pressed/over state and manipulations),
// if a parent is CanDrag == true, its gesture recognizer might (should) also trigger the DragStarting.
// But: (1.) on UWP only the top-most draggable element starts the drag operation;
// (2.) as CoreDragDropManager.AreConcurrentOperationsEnabled is false by default, the parent would cancel the drag of its child
// So here we allow only one "starting" per "FrameId".
|| args.Pointer.FrameId <= _lastDragStartFrameId)
{
return;
}

_lastDragStartFrameId = args.Pointer.FrameId;

// Note: We do not provide the _pendingRaisedEvent.args since it has probably not been updated yet,
// but as we are in the handler of an event from the gesture recognizer,
// the LastPointerEvent from the CoreWindow will be up to date.
Expand Down

0 comments on commit d49a800

Please sign in to comment.