Repository: AvaloniaUI/Avalonia
File: src/Avalonia.Base/Input/Pointer.cs (C#)

Code before:

        internal void Capture(IInputElement? control, CaptureSource source)
        {
            var oldCapture = Captured;
            if (oldCapture == control)
                return;

            var oldVisual = oldCapture as Visual;

            IInputElement? commonParent = null;
            if (oldVisual != null)
            {
                commonParent = FindCommonParent(control, oldCapture);
                foreach (var notifyTarget in oldVisual.GetSelfAndVisualAncestors().OfType<IInputElement>())
                {
                    if (notifyTarget == commonParent)
                        break;
                    var args = new PointerCaptureChangingEventArgs(notifyTarget, this, control, source);
                    notifyTarget.RaiseEvent(args);
                    if (args.Handled)
                        return;
                }
            }

            if (source == CaptureSource.Explicit)
                PlatformCapture(control);

            if (oldVisual != null)
                oldVisual.DetachedFromVisualTree -= OnCaptureDetached;
            
            Captured = control;

            if (oldVisual != null)
                foreach (var notifyTarget in oldVisual.GetSelfAndVisualAncestors().OfType<IInputElement>())
                {
                    if (notifyTarget == commonParent)
                        break;
                    notifyTarget.RaiseEvent(new PointerCaptureLostEventArgs(notifyTarget, this));
                }

            if (Captured is Visual newVisual)
                newVisual.DetachedFromVisualTree += OnCaptureDetached;

            if (Captured != null)
                CaptureGestureRecognizer(null);

            if(Captured == null && CapturedGestureRecognizer == null)
            {
                IsGestureRecognitionSkipped = false;
            }
        }

Review comment (suggestion):
`PlatformCapture()` is now called before detaching from the event, is that intended? I think we should detach from the event as soon as possible (like it was before) to avoid side effects where `OnCaptureDetached` could be inadvertently called as a result of the platform capture.

Code after:

        internal void Capture(IInputElement? control, CaptureSource source)
        {
            var oldCapture = Captured;
            if (oldCapture == control)
                return;

            var oldVisual = oldCapture as Visual;

            IInputElement? commonParent = null;
            if (oldVisual != null)
            {
                commonParent = FindCommonParent(control, oldCapture);
                foreach (var notifyTarget in oldVisual.GetSelfAndVisualAncestors().OfType<IInputElement>())
                {
                    if (notifyTarget == commonParent)
                        break;
                    var args = new PointerCaptureChangingEventArgs(notifyTarget, this, control, source);
                    notifyTarget.RaiseEvent(args);
                    if (args.Handled)
                        return;
                }
            }

            if (oldVisual != null)
                oldVisual.DetachedFromVisualTree -= OnCaptureDetached;
            Captured = control;

            if (source != CaptureSource.Platform)
                PlatformCapture(control);

            if (oldVisual != null)
                foreach (var notifyTarget in oldVisual.GetSelfAndVisualAncestors().OfType<IInputElement>())
                {
                    if (notifyTarget == commonParent)
                        break;
                    notifyTarget.RaiseEvent(new PointerCaptureLostEventArgs(notifyTarget, this));
                }

            if (Captured is Visual newVisual)
                newVisual.DetachedFromVisualTree += OnCaptureDetached;

            if (Captured != null)
                CaptureGestureRecognizer(null);

            if(Captured == null && CapturedGestureRecognizer == null)
            {
                IsGestureRecognitionSkipped = false;
            }
        }