private static void EnsureValid(ref IInputElement element) { // We understand UIElements and ContentElements. // If we are over something else (like a raw visual) find the containing element. if ((element != null) && !InputElement.IsValid(element)) { element = InputElement.GetContainingInputElement(element as DependencyObject); } }
private IInputElement CriticalHitTest(Point point, bool isSynchronize) { IInputElement over = null; if (_activeSource != null) { switch (_captureMode) { case CaptureMode.None: // No capture, do a regular hit-test. if (_isDown) { if (isSynchronize) { // In a synchronize call, we need to hit-test the window in addition to the element over = GlobalHitTest(point, _activeSource); } else { // Just hit-test the element over = LocalHitTest(point, _activeSource); } EnsureValid(ref over); } break; case CaptureMode.Element: // Capture is to a specific element, so the device will always be over that element. over = _captured; break; case CaptureMode.SubTree: // Capture is set to an entire subtree. Hit-test to determine the element (and window) // the device is over. If the element is within the captured sub-tree (which can span // multiple windows), then the device is over that element. If the element is not within // the sub-tree, then the device is over the captured element. { IInputElement capture = InputElement.GetContainingInputElement(_captured as DependencyObject); if (capture != null) { // We need to re-hit-test to get the "real" UIElement we are over. // This allows us to have our capture-to-subtree span multiple windows. // GlobalHitTest always returns an IInputElement, so we are sure to have one. over = GlobalHitTest(point, _activeSource); } EnsureValid(ref over); // Make sure that the element we hit is acutally underneath // our captured element. Because we did a global hit test, we // could have hit an element in a completely different window. // // Note that we support the child being in a completely different window. // So we use the GetUIParent method instead of just looking at // visual/content parents. if (over != null) { IInputElement ieTest = over; while ((ieTest != null) && (ieTest != _captured)) { UIElement eTest = ieTest as UIElement; if (eTest != null) { ieTest = InputElement.GetContainingInputElement(eTest.GetUIParent(true)); } else { ContentElement ceTest = ieTest as ContentElement; if (ceTest != null) { ieTest = InputElement.GetContainingInputElement(ceTest.GetUIParent(true)); } else { UIElement3D e3DTest = (UIElement3D)ieTest; ieTest = InputElement.GetContainingInputElement(e3DTest.GetUIParent(true)); } } } if (ieTest != _captured) { // If we missed the capture point, consider the device over the capture point. over = _captured; } } else { // If we didn't hit anything, consider the device over the capture point. over = _captured; } } break; } } return(over); }