/// <summary> /// Validate if the provided routed event args are relevant for the given element according to the active captures /// </summary> /// <param name="element">The target element for which the args are validated</param> /// <param name="args">The pending pointer event args that is under test</param> /// <param name="autoRelease">A flag that allows to automatically release any pending out-dated capture (for PointerDown only)</param> /// <returns>A boolean which indicates if the args are valid or not for the given element</returns> public bool ValidateAndUpdate(UIElement element, PointerRoutedEventArgs args, bool autoRelease) { if ((autoRelease && MostRecentDispatchedEventFrameId < args.FrameId) || _nativeCaptureElement.GetHitTestVisibility() == HitTestability.Collapsed) { // If 'autoRelease' we want to release any previous capture that was not release properly no matter the reason. // BUT we don't want to release a capture that was made by a child control (so MostRecentDispatchedEventFrameId should already be equals to current FrameId). // We also do not allow a control that is not loaded to keep a capture (they should all have been release on unload). // ** This is an IMPORTANT safety catch to prevent the application to become unresponsive ** Clear(); return(true); } else if (_targets.TryGetValue(element, out var target)) { Update(target, args); return(true); } else if (IsImplicitOnly) { // If the capture is implicit, we should not filter out events for children elements. return(true); } else { // We should dispatch the event only if the control which has captured the pointer has already dispatched the event // (Which actually means that the current control is a parent of the control which has captured the pointer) // Remarks: This is not enough to determine parent-child relationship when we dispatch multiple events base on the same native event, // (as they will all have the same FrameId), however in that case we dispatch events layer per layer // instead of bubbling a single event before raising the next one, so we are safe. // The only limitation would be when mixing native vs. managed bubbling, but this check only prevents // the leaf of the tree to raise the event, so we cannot mix bubbling mode in that case. return(MostRecentDispatchedEventFrameId >= args.FrameId); } }