private void ReevaluateCapturedWithinAsync(DependencyObject element, DependencyObject oldParent, bool isCoreParent) { if (element != null) { if (_capturedWithinTreeState == null) { _capturedWithinTreeState = new DeferredElementTreeState(); } if (isCoreParent) { _capturedWithinTreeState.SetCoreParent(element, oldParent); } else { _capturedWithinTreeState.SetLogicalParent(element, oldParent); } } if (_reevaluateCapture == null) { _reevaluateCapture = Dispatcher.BeginInvoke(DispatcherPriority.Input, (DispatcherOperationCallback) delegate(object args) { TouchDevice thisRef = (TouchDevice)args; thisRef._reevaluateCapture = null; thisRef.OnReevaluateCapturedWithinAsync(); return(null); }, this); } }
private void ReevaluateDirectlyOverAsync(DependencyObject element, DependencyObject oldParent, bool isCoreParent) { if (element != null) { if (_directlyOverTreeState == null) { _directlyOverTreeState = new DeferredElementTreeState(); } if (isCoreParent) { _directlyOverTreeState.SetCoreParent(element, oldParent); } else { _directlyOverTreeState.SetLogicalParent(element, oldParent); } } if (_reevaluateOver == null) { _reevaluateOver = Dispatcher.BeginInvoke(DispatcherPriority.Input, (DispatcherOperationCallback) delegate(object args) { TouchDevice thisRef = (TouchDevice)args; thisRef._reevaluateOver = null; thisRef.OnHitTestInvalidatedAsync(this, EventArgs.Empty); return(null); }, this); } }
internal void OnOriginValueChanged(DependencyObject oldOrigin, DependencyObject newOrigin, IList <DependencyObject> otherOrigins, ref DeferredElementTreeState oldTreeState, Action <DependencyObject, bool> originChangedAction) { DeferredElementTreeState treeStateLocalCopy = oldTreeState; oldTreeState = null; // Determine if one needs to raise notifications of elements // affected by the origin change irrespective of other origins bool setOriginCacheFlag = ((originChangedAction != null) && (FlagOldOriginCache != CoreFlags.None) && (FlagNewOriginCache != CoreFlags.None)); // Step #1 // Update the cache flags for all elements in the ancestry // of the element that got turned off and record the changed nodes if (oldOrigin != null) { SetCacheFlagInAncestry(oldOrigin, false, treeStateLocalCopy, true, setOriginCacheFlag); } // Step #2 // Update the cache flags for all elements in the ancestry // of the element that got turned on and record the changed nodes if (newOrigin != null) { SetCacheFlagInAncestry(newOrigin, true, null, true, setOriginCacheFlag); } int otherCount = (otherOrigins != null) ? otherOrigins.Count : 0; for (int i = 0; i < otherCount; i++) { // setOriginCacheFlag is false, because these flags should not be affected by other origins SetCacheFlagInAncestry(otherOrigins[i], true, null, false, /*setOriginCacheFlag*/ false); } // Step #3 // Fire value changed on elements in the ancestry of the element that got turned off. if (oldOrigin != null) { FirePropertyChangeInAncestry(oldOrigin, true /* oldValue */, treeStateLocalCopy, originChangedAction); } // Step #4 // Fire value changed on elements in the ancestry of the element that got turned on. if (newOrigin != null) { FirePropertyChangeInAncestry(newOrigin, false /* oldValue */, null, originChangedAction); } if (oldTreeState == null && treeStateLocalCopy != null) { // Now that we have applied the old tree state, throw it away. treeStateLocalCopy.Clear(); oldTreeState = treeStateLocalCopy; } }
private void SetCacheFlagInAncestry(DependencyObject element, bool newValue, DeferredElementTreeState treeState, bool shortCircuit, bool setOriginCacheFlag) { UIElement uie; ContentElement ce; UIElement3D uie3D; CastElement(element, out uie, out ce, out uie3D); bool isFlagSet = IsFlagSet(uie, ce, uie3D, FlagCache); bool isFlagOriginCacheSet = (setOriginCacheFlag ? IsFlagSet(uie, ce, uie3D, (newValue ? FlagNewOriginCache : FlagOldOriginCache)) : false); // If the cache flag value is undergoing change, record it and // propagate the change to the ancestors. if ((newValue != isFlagSet) || (setOriginCacheFlag && !isFlagOriginCacheSet) || !shortCircuit) { if (newValue != isFlagSet) { SetFlag(uie, ce, uie3D, FlagCache, newValue); // NOTE: we toggle the changed flag instead of setting it so that that way common // ancestors show resultant unchanged and do not receive any change notification. SetFlag(uie, ce, uie3D, FlagChanged, !IsFlagSet(uie, ce, uie3D, FlagChanged)); } if (setOriginCacheFlag && !isFlagOriginCacheSet) { SetFlag(uie, ce, uie3D, (newValue ? FlagNewOriginCache : FlagOldOriginCache), true); } // Check for block reverse inheritance flag, elements like popup want to set this. if (BlockReverseInheritance(uie, ce, uie3D)) { return; } // Propagate the flag up the visual and logical trees. Note our // minimal optimization check to avoid walking both the core // and logical parents if they are the same. { DependencyObject coreParent = DeferredElementTreeState.GetInputElementParent(element, treeState); DependencyObject logicalParent = DeferredElementTreeState.GetLogicalParent(element, treeState); if (coreParent != null) { SetCacheFlagInAncestry(coreParent, newValue, treeState, shortCircuit, setOriginCacheFlag); } if (logicalParent != null && logicalParent != coreParent) { SetCacheFlagInAncestry(logicalParent, newValue, treeState, shortCircuit, setOriginCacheFlag); } } } }
private void UpdateReverseInheritedProperty(bool capture, IInputElement oldElement, IInputElement newElement) { // consdier caching the array List <DependencyObject> others = null; int count = (_activeDevices != null) ? _activeDevices.Count : 0; if (count > 0) { others = new List <DependencyObject>(count); } for (int i = 0; i < count; i++) { TouchDevice touchDevice = _activeDevices[i]; if (touchDevice != this) { DependencyObject other = capture ? (touchDevice._captured as DependencyObject) : (touchDevice._directlyOver as DependencyObject); if (other != null) { others.Add(other); } } } ReverseInheritProperty property = capture ? (ReverseInheritProperty)UIElement.TouchesCapturedWithinProperty : (ReverseInheritProperty)UIElement.TouchesOverProperty; DeferredElementTreeState treeState = capture ? _capturedWithinTreeState : _directlyOverTreeState; Action <DependencyObject, bool> originChangedAction = capture ? null : RaiseTouchEnterOrLeaveAction; property.OnOriginValueChanged(oldElement as DependencyObject, newElement as DependencyObject, others, ref treeState, originChangedAction); if (capture) { _capturedWithinTreeState = treeState; } else { _directlyOverTreeState = treeState; } }
/// <summary> /// Determines if we can remain focused on the element we think has focus /// </summary> /// <remarks> /// Invoked asynchronously by ReevaluateFocusAsync. /// Confirms that the element we think has focus is: /// - still enabled /// - still visible /// - still in the tree /// </remarks> private object ReevaluateFocusCallback(object arg) { _reevaluateFocusOperation = null; if (_focus == null) { return(null); } // // Reevaluate the eligability of the focused element to actually // have focus. If that element is no longer focusable, then search // for an ancestor that is. // DependencyObject element = _focus; while (element != null) { if (Keyboard.IsFocusable(element)) { break; } // Walk the current tree structure. element = DeferredElementTreeState.GetCoreParent(element, null); } // Get the PresentationSource that contains the element to be focused. PresentationSource presentationSource = null; DependencyObject visualContainer = InputElement.GetContainingVisual(element); if (visualContainer != null) { presentationSource = PresentationSource.CriticalFromVisual(visualContainer); } // The default action is to reset focus to the root element // of the active presentation source. bool moveFocus = true; DependencyObject moveFocusTo = null; if (presentationSource != null) { IKeyboardInputProvider keyboardProvider = presentationSource.GetInputProvider(typeof(KeyboardDevice)) as IKeyboardInputProvider; if (keyboardProvider != null) { // Confirm with the keyboard provider for this // presentation source that it has acquired focus. if (keyboardProvider.AcquireFocus(true)) { if (element == _focus) { // The focus element is still good. moveFocus = false; } else { // The focus element is no longer focusable, but we found // an ancestor that is, so move focus there. moveFocus = true; moveFocusTo = element; } } } } if (moveFocus) { if (moveFocusTo == null && _activeSource != null) { moveFocusTo = _activeSource.Value.RootVisual as DependencyObject; } Focus(moveFocusTo, /*askOld=*/ false, /*askNew=*/ true, /*forceToNullIfFailed=*/ true); } else { // Refresh FocusWithinProperty so that ReverseInherited Flags are updated. // // We only need to do this if there is any information about the old // tree structure. if (_focusTreeState != null && !_focusTreeState.IsEmpty) { UIElement.FocusWithinProperty.OnOriginValueChanged(_focus, _focus, ref _focusTreeState); } } return(null); }
internal void OnOriginValueChanged(DependencyObject oldOrigin, DependencyObject newOrigin, ref DeferredElementTreeState oldTreeState) { OnOriginValueChanged(oldOrigin, newOrigin, null, ref oldTreeState, null); }
private void FirePropertyChangeInAncestry(DependencyObject element, bool oldValue, DeferredElementTreeState treeState, Action <DependencyObject, bool> originChangedAction) { UIElement uie; ContentElement ce; UIElement3D uie3D; CastElement(element, out uie, out ce, out uie3D); bool flagChanged = IsFlagSet(uie, ce, uie3D, FlagChanged); bool isFlagOldOriginCacheSet = ((FlagOldOriginCache == CoreFlags.None) ? false : IsFlagSet(uie, ce, uie3D, FlagOldOriginCache)); bool isFlagNewOriginCacheSet = ((FlagNewOriginCache == CoreFlags.None) ? false : IsFlagSet(uie, ce, uie3D, FlagNewOriginCache)); if (flagChanged || isFlagOldOriginCacheSet || isFlagNewOriginCacheSet) { if (flagChanged) { // if FlagChanged bit is set, then the value has changed effectively // after considering all the origins. Hence change the property value // and fire notifications. SetFlag(uie, ce, uie3D, FlagChanged, false); if (oldValue) { element.ClearValue(FlagKey); } else { element.SetValue(FlagKey, true); } FireNotifications(uie, ce, uie3D, oldValue); } if (isFlagOldOriginCacheSet || isFlagNewOriginCacheSet) { SetFlag(uie, ce, uie3D, FlagOldOriginCache, false); SetFlag(uie, ce, uie3D, FlagNewOriginCache, false); if (isFlagOldOriginCacheSet != isFlagNewOriginCacheSet) { // if either FlagOldOriginCache or FlagNewOriginCache // are set, then the origin change has affected this node // and hence originChangedAction should be executed. Debug.Assert(originChangedAction != null); originChangedAction(element, oldValue); } } // Check for block reverse inheritance flag, elements like popup want to set this. if (BlockReverseInheritance(uie, ce, uie3D)) { return; } // Call FirePropertyChange up the visual and logical trees. // Note our minimal optimization check to avoid walking both // the core and logical parents if they are the same. { DependencyObject coreParent = DeferredElementTreeState.GetInputElementParent(element, treeState); DependencyObject logicalParent = DeferredElementTreeState.GetLogicalParent(element, treeState); if (coreParent != null) { FirePropertyChangeInAncestry(coreParent, oldValue, treeState, originChangedAction); } if (logicalParent != null && logicalParent != coreParent) { FirePropertyChangeInAncestry(logicalParent, oldValue, treeState, originChangedAction); } } } }