KeyboardNavigation.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / System / Windows / Input / KeyboardNavigation.cs / 1 / KeyboardNavigation.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System; 
using System.Collections; 
using System.Collections.Generic;
using System.Collections.ObjectModel; 
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Threading;
using System.Threading; 
using System.Windows;
using System.Windows.Documents; 
using System.Windows.Interop; 
using System.Windows.Controls;
using System.Windows.Media; 
using System.Windows.Media.Media3D;
using System.Security;
using System.Security.Permissions;
using MS.Utility; 
using MS.Internal.Controls;
using MS.Internal; 
using MS.Internal.PresentationFramework; 
using MS.Internal.KnownBoxes;
using Microsoft.Win32; 

namespace System.Windows.Input
{
    #region public enum types 
    /// 
    /// These options specify how the container will move the focus when tab and directional navigation occurs 
    ///  
    public enum KeyboardNavigationMode
    { 
        /// 
        /// The container does not handle the keyboard navigation;
        /// each element receives keyboard focus as long as it is a key navigation stop.
        ///  
        Continue,
 
        ///  
        /// The container and all of its child elements as a whole only receive focus once.
        /// Either the first tree child or the ActiveElement receive focus 
        /// 
        Once,

        ///  
        /// Depending on the direction of the navigation,
        /// the focus returns to the first or the last item when the end or 
        /// the beginning of the container is reached, respectively. 
        /// 
        Cycle, 

        /// 
        /// No keyboard navigation is allowed inside this container
        ///  
        None,
 
        ///  
        /// Like cycle but does not move past the beginning or end of the container.
        ///  
        Contained,

        /// 
        /// TabIndexes are considered on local subtree only inside this container 
        /// 
        Local, 
 
        // NOTE: if you add or remove any values in this enum, be sure to update KeyboardNavigation.IsValidKeyNavigationMode()
    } 
    #endregion public enum types

    ///
    /// KeyboardNavigation class provide methods for logical (Tab) and directional (arrow) navigation between focusable controls 
    ///
    public sealed class KeyboardNavigation 
    { 
        #region Constructors
 
        ///
        ///     Critical - this function elevates via a call to InputManager.Current
        ///     TreatAsSafe: This code simply attaches a call back which is private
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        internal KeyboardNavigation() 
        { 
            InputManager inputManager = InputManager.Current;
 
            inputManager.PostProcessInput += new ProcessInputEventHandler(PostProcessInput);
            inputManager.TranslateAccelerator += new KeyEventHandler(TranslateAccelerator);
        }
 
        #endregion Constructors
 
        #region public API 

        #region Properties 

        private static readonly DependencyProperty TabOnceActiveElementProperty
            = DependencyProperty.RegisterAttached("TabOnceActiveElement", typeof(WeakReference), typeof(KeyboardNavigation));
 
        internal static DependencyObject GetTabOnceActiveElement(DependencyObject d)
        { 
            WeakReference weakRef = (WeakReference)d.GetValue(TabOnceActiveElementProperty); 
            if (weakRef != null && weakRef.IsAlive)
            { 
                DependencyObject activeElement = weakRef.Target as DependencyObject;
                // Verify if the element is still in the same visual tree
                if (GetVisualRoot(activeElement) == GetVisualRoot(d))
                    return activeElement; 
                else
                    d.SetValue(TabOnceActiveElementProperty, null); 
            } 
            return null;
        } 

        internal static void SetTabOnceActiveElement(DependencyObject d, DependencyObject value)
        {
            d.SetValue(TabOnceActiveElementProperty, new WeakReference(value)); 
        }
 
        internal static readonly DependencyProperty ControlTabOnceActiveElementProperty 
            = DependencyProperty.RegisterAttached("ControlTabOnceActiveElement", typeof(WeakReference), typeof(KeyboardNavigation));
 
        private static DependencyObject GetControlTabOnceActiveElement(DependencyObject d)
        {
            WeakReference weakRef = (WeakReference)d.GetValue(ControlTabOnceActiveElementProperty);
            if (weakRef != null && weakRef.IsAlive) 
            {
                DependencyObject activeElement = weakRef.Target as DependencyObject; 
                // Verify if the element is still in the same visual tree 
                if (GetVisualRoot(activeElement) == GetVisualRoot(d))
                    return activeElement; 
                else
                    d.SetValue(ControlTabOnceActiveElementProperty, null);
            }
            return null; 
        }
 
        private static void SetControlTabOnceActiveElement(DependencyObject d, DependencyObject value) 
        {
            d.SetValue(ControlTabOnceActiveElementProperty, new WeakReference(value)); 
        }

        private DependencyObject GetActiveElement(DependencyObject d)
        { 
            return _navigationProperty == ControlTabNavigationProperty ? GetControlTabOnceActiveElement(d) : GetTabOnceActiveElement(d);
        } 
 
        private void SetActiveElement(DependencyObject d, DependencyObject value)
        { 
            if (_navigationProperty == TabNavigationProperty)
                SetTabOnceActiveElement(d, value);
            else
                SetControlTabOnceActiveElement(d, value); 
        }
 
        ///  
        ///     Critical: This code retrieves PresentationSource which is a protected resource
        ///     TreatAsSafe: It returns rootvisual which is ok and it does not expose the PresentationSource 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal static Visual GetVisualRoot(DependencyObject d)
        { 
            if (d is Visual || d is Visual3D)
            { 
                PresentationSource source = PresentationSource.CriticalFromVisual(d); 

                if (source != null) 
                    return source.RootVisual;
            }
            else
            { 
                FrameworkContentElement fce = d as FrameworkContentElement;
                if (fce != null) 
                    return GetVisualRoot(fce.Parent); 
            }
 
            return null;
        }

        // This internal property is used by GetRectagle method to deflate the bounding box of the element 
        // If we expose this in the future - make sure it works with ContentElements too
        internal static readonly DependencyProperty DirectionalNavigationMarginProperty = 
                DependencyProperty.RegisterAttached("DirectionalNavigationMargin", 
                        typeof(Thickness),
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(new Thickness()));


        ///  
        ///     The DependencyProperty for the TabIndex property.
        ///     Flags:              Can be used in style rules 
        ///     Default Value:      Int32.MaxValue 
        /// 
        public static readonly DependencyProperty TabIndexProperty = 
                DependencyProperty.RegisterAttached(
                        "TabIndex",
                        typeof(int),
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(Int32.MaxValue));
 
        ///  
        ///     The DependencyProperty for the IsTabStop property.
        ///     Flags:              Can be used in style rules 
        ///     Default Value:      true
        /// 
        public static readonly DependencyProperty IsTabStopProperty =
                DependencyProperty.RegisterAttached( 
                        "IsTabStop",
                        typeof(bool), 
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(BooleanBoxes.TrueBox));
 

        /// 
        /// Controls the behavior of logical navigation on the children of the element this property is set on.
        /// TabNavigation is invoked with the TAB key. 
        /// 
        [CustomCategory("Accessibility")] 
        [Localizability(LocalizationCategory.NeverLocalize)] 
        [CommonDependencyProperty]
        public static readonly DependencyProperty TabNavigationProperty = 
                DependencyProperty.RegisterAttached(
                        "TabNavigation",
                        typeof(KeyboardNavigationMode),
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(KeyboardNavigationMode.Continue),
                        new ValidateValueCallback(IsValidKeyNavigationMode)); 
 
        /// 
        /// Controls the behavior of logical navigation on the children of the element this property is set on. 
        /// ControlTabNavigation is invoked with the CTRL+TAB key.
        /// 
        [CustomCategory("Accessibility")]
        [Localizability(LocalizationCategory.NeverLocalize)] 
        [CommonDependencyProperty]
        public static readonly DependencyProperty ControlTabNavigationProperty = 
                DependencyProperty.RegisterAttached( 
                        "ControlTabNavigation",
                        typeof(KeyboardNavigationMode), 
                        typeof(KeyboardNavigation),
                        new FrameworkPropertyMetadata(KeyboardNavigationMode.Continue),
                        new ValidateValueCallback(IsValidKeyNavigationMode));
 
        /// 
        /// Controls the behavior of directional navigation on the children of the element this property is set on. 
        /// Directional navigation is invoked with the arrow keys. 
        /// 
        [CustomCategory("Accessibility")] 
        [Localizability(LocalizationCategory.NeverLocalize)]
        [CommonDependencyProperty]
        public static readonly DependencyProperty DirectionalNavigationProperty =
                DependencyProperty.RegisterAttached( 
                        "DirectionalNavigation",
                        typeof(KeyboardNavigationMode), 
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(KeyboardNavigationMode.Continue),
                        new ValidateValueCallback(IsValidKeyNavigationMode)); 

        /// 
        /// Attached property set on elements registered with AccessKeyManager when AccessKeyCues should be shown.
        ///  
        internal static readonly DependencyProperty ShowKeyboardCuesProperty =
                DependencyProperty.RegisterAttached( 
                        "ShowKeyboardCues", 
                        typeof(bool),
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(
                                BooleanBoxes.FalseBox,
                                FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.OverridesInheritanceBehavior,
                                null /* No PropertyChangedCallback */, 
                                new CoerceValueCallback(CoerceShowKeyboardCues)));
 
        // Coercion for ShowKeyboardCuesProperty 
        private static object CoerceShowKeyboardCues(DependencyObject d, object value)
        { 
            // Always return true if the user has requested that KeyboardCues always
            // be on (accessibility setting).
            return SystemParameters.KeyboardCues ? BooleanBoxes.TrueBox : value;
        } 

        ///  
        /// Indicates if VK_Return character is accepted by a control 
        ///
        /// Default: false. 
        /// 
        public static readonly DependencyProperty AcceptsReturnProperty =
                DependencyProperty.RegisterAttached(
                        "AcceptsReturn", 
                        typeof(bool),
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); 

        #region Workaround for Bug 908235 -- when focus change events go to PostProcessInput we don't need this glue. 
        internal event KeyboardFocusChangedEventHandler FocusChanged
        {
            add
            { 
                lock (_weakFocusChangedHandlers)
                { 
                    _weakFocusChangedHandlers.Add(new WeakReference(value)); 
                }
            } 
            remove
            {
                lock (_weakFocusChangedHandlers)
                { 
                    for (int i = 0; i < _weakFocusChangedHandlers.Count; i++)
                    { 
                        object handler = _weakFocusChangedHandlers[i].Target; 
                        if (handler == null || (KeyboardFocusChangedEventHandler)handler == value)
                        { 
                            _weakFocusChangedHandlers.RemoveAt(i);
                            i--;
                        }
                    } 
                }
            } 
        } 

        internal void NotifyFocusChanged(object sender, KeyboardFocusChangedEventArgs e) 
        {
            if (_weakFocusChangedHandlers != null)
            {
                for (int i = 0; i < _weakFocusChangedHandlers.Count; i++) 
                {
                    KeyboardFocusChangedEventHandler handler = _weakFocusChangedHandlers[i].Target as KeyboardFocusChangedEventHandler; 
                    if (handler != null) 
                    {
                        handler(sender, e); 
                    }
                    else
                    {
                        _weakFocusChangedHandlers.RemoveAt(i); 
                        i--;
                    } 
                } 
            }
        } 

        private List _weakFocusChangedHandlers = new List(1);
        #endregion
 
        #endregion Properties
 
        #region methods 

        ///  
        /// Writes the attached property TabIndex to the given element.
        /// 
        /// The element to which to write the attached property.
        /// The property value to set 
        /// 
        public static void SetTabIndex(DependencyObject element, int index) 
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            }
            element.SetValue(TabIndexProperty, index);
        } 

        ///  
        /// Reads the attached property TabIndex from the given element. 
        /// 
        /// The element from which to read the attached property. 
        /// The property's value.
        /// 
        [AttachedPropertyBrowsableForType(typeof(DependencyObject))]
        public static int GetTabIndex(DependencyObject element) 
        {
            if (element == null) 
            { 
                throw new ArgumentNullException("element");
            } 
            return GetTabIndexHelper(element);
        }

        ///  
        /// Writes the attached property IsTabStop to the given element.
        ///  
        /// The element to which to write the attached property. 
        /// The property value to set
        ///  
        public static void SetIsTabStop(DependencyObject element, bool isTabStop)
        {
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            } 
            element.SetValue(IsTabStopProperty, BooleanBoxes.Box(isTabStop)); 
        }
 
        /// 
        /// Reads the attached property IsTabStop from the given element.
        /// 
        /// The element from which to read the attached property. 
        /// The property's value.
        ///  
        [AttachedPropertyBrowsableForType(typeof(DependencyObject))] 
        public static bool GetIsTabStop(DependencyObject element)
        { 
            if (element == null)
            {
                throw new ArgumentNullException("element");
            } 
            return (bool)element.GetValue(IsTabStopProperty);
        } 
 
        /// 
        /// Writes the attached property TabNavigation to the given element. 
        /// 
        /// The element to which to write the attached property.
        /// The property value to set
        ///  
        public static void SetTabNavigation(DependencyObject element, KeyboardNavigationMode mode)
        { 
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            }
            element.SetValue(TabNavigationProperty, mode);
        }
 
        /// 
        /// Reads the attached property TabNavigation from the given element. 
        ///  
        /// The element from which to read the attached property.
        /// The property's value. 
        /// 
        [CustomCategory("Accessibility")]
        [AttachedPropertyBrowsableForType(typeof(DependencyObject))]
        public static KeyboardNavigationMode GetTabNavigation(DependencyObject element) 
        {
            if (element == null) 
            { 
                throw new ArgumentNullException("element");
            } 
            return (KeyboardNavigationMode)element.GetValue(TabNavigationProperty);
        }

        ///  
        /// Writes the attached property ControlTabNavigation to the given element.
        ///  
        /// The element to which to write the attached property. 
        /// The property value to set
        ///  
        public static void SetControlTabNavigation(DependencyObject element, KeyboardNavigationMode mode)
        {
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            } 
            element.SetValue(ControlTabNavigationProperty, mode); 
        }
 
        /// 
        /// Reads the attached property ControlTabNavigation from the given element.
        /// 
        /// The element from which to read the attached property. 
        /// The property's value.
        ///  
        [CustomCategory("Accessibility")] 
        [AttachedPropertyBrowsableForType(typeof(DependencyObject))]
        public static KeyboardNavigationMode GetControlTabNavigation(DependencyObject element) 
        {
            if (element == null)
            {
                throw new ArgumentNullException("element"); 
            }
            return (KeyboardNavigationMode)element.GetValue(ControlTabNavigationProperty); 
        } 

        ///  
        /// Writes the attached property DirectionalNavigation to the given element.
        /// 
        /// The element to which to write the attached property.
        /// The property value to set 
        /// 
        public static void SetDirectionalNavigation(DependencyObject element, KeyboardNavigationMode mode) 
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            }
            element.SetValue(DirectionalNavigationProperty, mode);
        } 

        ///  
        /// Reads the attached property DirectionalNavigation from the given element. 
        /// 
        /// The element from which to read the attached property. 
        /// The property's value.
        /// 
        [CustomCategory("Accessibility")]
        [AttachedPropertyBrowsableForType(typeof(DependencyObject))] 
        public static KeyboardNavigationMode GetDirectionalNavigation(DependencyObject element)
        { 
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            }
            return (KeyboardNavigationMode)element.GetValue(DirectionalNavigationProperty);
        }
 
        /// 
        /// Writes the attached property AcceptsReturn to the given element. 
        ///  
        /// The element to which to write the attached property.
        /// The property value to set 
        /// 
        public static void SetAcceptsReturn(DependencyObject element, bool enabled)
        {
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            } 
            element.SetValue(AcceptsReturnProperty, BooleanBoxes.Box(enabled));
        } 

        /// 
        /// Reads the attached property AcceptsReturn from the given element.
        ///  
        /// The element from which to read the attached property.
        /// The property's value. 
        ///  
        [AttachedPropertyBrowsableForType(typeof(DependencyObject))]
        public static bool GetAcceptsReturn(DependencyObject element) 
        {
            if (element == null)
            {
                throw new ArgumentNullException("element"); 
            }
            return (bool)element.GetValue(AcceptsReturnProperty); 
        } 

        private static bool IsValidKeyNavigationMode(object o) 
        {
            KeyboardNavigationMode value = (KeyboardNavigationMode)o;
            return value == KeyboardNavigationMode.Contained
                || value == KeyboardNavigationMode.Continue 
                || value == KeyboardNavigationMode.Cycle
                || value == KeyboardNavigationMode.None 
                || value == KeyboardNavigationMode.Once 
                || value == KeyboardNavigationMode.Local;
        } 

        #endregion methods

        #endregion public API 

        #region FocusVisualStyle API 
        // This class is used by AdornerLayer which adds it to its visual tree 
        // Once AdornerLayer and Adorner are UIElement we can remove this class and
        // apply FrameworkElement.FocusVisualStyle directly to AdornerLayer 
        // Note:- This class is sealed because it calls OnVisualChildrenChanged virtual in the
        //              constructor and it does not override it, but derived classes could.
        private sealed class FocusVisualAdorner: Adorner
        { 
            public FocusVisualAdorner(UIElement adornedElement, Style focusVisualStyle) : base(adornedElement)
            { 
                Debug.Assert(adornedElement != null, "adornedElement should not be null"); 
                Debug.Assert(focusVisualStyle != null, "focusVisual should not be null");
 
                Control control = new Control();
                control.Style = focusVisualStyle;
                _adorderChild = control;
                IsClipEnabled = true; 
                IsHitTestVisible = false;
                IsEnabled = false; 
                AddVisualChild(_adorderChild); 
            }
 
            public FocusVisualAdorner(ContentElement adornedElement, UIElement adornedElementParent, IContentHost contentHostParent, Style focusVisualStyle)
                : base(adornedElementParent)
            {
                Debug.Assert(adornedElement != null, "adornedElement should not be null"); 
                Debug.Assert(adornedElementParent != null, "adornedElementParent should not be null");
                Debug.Assert(contentHostParent != null, "contentHostParent should not be null"); 
                Debug.Assert(contentHostParent is Visual, "contentHostParent should be Visual"); 
                Debug.Assert(focusVisualStyle != null, "focusVisual should not be null");
 
                _contentHostParent = contentHostParent;
                _adornedContentElement = adornedElement;
                _focusVisualStyle = focusVisualStyle;
 
                Canvas canvas = new Canvas();
                _canvasChildren = canvas.Children; 
                _adorderChild = canvas; 
                AddVisualChild(_adorderChild);
 
                IsClipEnabled = true;
                IsHitTestVisible = false;
                IsEnabled = false;
            } 

            ///  
            /// Measure adorner. Default behavior is to size to match the adorned element. 
            /// 
            protected override Size MeasureOverride(Size constraint) 
            {
                Size desiredSize = new Size();

                // If the focus visual is adorning a content element, 
                // the child will be a canvas that doesn't need to be measured.
                if (_adornedContentElement == null) 
                { 
                    desiredSize = AdornedElement.RenderSize;
                    constraint = desiredSize; 
                }

                // Measure the child
                ((UIElement)GetVisualChild(0)).Measure(constraint); 

                return desiredSize; 
           } 

            ///  
            ///     Default control arrangement is to only arrange
            ///     the first visual child. No transforms will be applied.
            /// 
            protected override Size ArrangeOverride(Size size) 
            {
                Size finalSize = base.ArrangeOverride(size); 
 
                // In case we adorn ContentElement we have to update the rectangles
                if (_adornedContentElement != null) 
                {
                    if (_contentRects == null)
                    {
                        // Clear rects 
                        _canvasChildren.Clear();
                    } 
                    else 
                    {
                        IContentHost contentHost = ContentHost; 

                        if (!(contentHost is Visual) || !AdornedElement.IsAncestorOf((Visual)contentHost))
                        {
                            // Content elements is not in the tree, clear children and give up. 
                            _canvasChildren.Clear();
                            return new Size(); 
                        } 

                        Rect desiredRect = Rect.Empty; 

                        IEnumerator enumerator = _contentRects.GetEnumerator();

                        if (_canvasChildren.Count == _contentRects.Count) 
                        {
                            // Reuse the controls and update the controls position 
                            for (int i = 0; i < _canvasChildren.Count; i++) 
                            {
                                enumerator.MoveNext(); 
                                Rect rect = enumerator.Current;

                                rect = _hostToAdornedElement.TransformBounds(rect);
 
                                Control control = (Control)_canvasChildren[i];
                                control.Width = rect.Width; 
                                control.Height = rect.Height; 
                                Canvas.SetLeft(control, rect.X);
                                Canvas.SetTop(control, rect.Y); 
                            }
                            _adorderChild.InvalidateArrange();
                        }
                        else // Rebuild the visual tree to correspond to current bounding rectangles 
                        {
                            _canvasChildren.Clear(); 
                            while (enumerator.MoveNext()) 
                            {
                                Rect rect = enumerator.Current; 

                                rect = _hostToAdornedElement.TransformBounds(rect);

                                Control control = new Control(); 
                                control.Style = _focusVisualStyle;
                                control.Width = rect.Width; 
                                control.Height = rect.Height; 
                                Canvas.SetLeft(control, rect.X);
                                Canvas.SetTop(control, rect.Y); 
                                _canvasChildren.Add(control);
                            }
                        }
                    } 
                }
 
                ((UIElement)GetVisualChild(0)).Arrange(new Rect(new Point(), finalSize)); 

                return finalSize; 
            }

            /// 
            ///  Derived classes override this property to enable the Visual code to enumerate 
            ///  the Visual children. Derived classes need to return the number of children
            ///  from this method. 
            /// 
            ///    By default a Visual does not have any children.
            /// 
            ///  Remark:
            ///      During this virtual method the Visual tree must not be modified.
            /// 
            protected override int VisualChildrenCount 
            {
                get 
                { 
                    return 1; // _adorderChild created in ctor.
                } 
            }

            /// 
            ///   Derived class must implement to support Visual children. The method must return 
            ///    the child at the specified index. Index must be between 0 and GetVisualChildrenCount-1.
            /// 
            ///    By default a Visual does not have any children. 
            ///
            ///  Remark: 
            ///       During this virtual call it is not valid to modify the Visual tree.
            /// 
            protected override Visual GetVisualChild(int index)
            { 
                if (index == 0)
                { 
                    return _adorderChild; 
                }
                else 
                {
                    throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange));
                }
            } 

            private IContentHost ContentHost 
            { 
                get
                { 
                    // Re-query IContentHost if the old one was disposed
                    if (_adornedContentElement != null && (_contentHostParent==null || VisualTreeHelper.GetParent(_contentHostParent as Visual) == null))
                    {
                        _contentHostParent = MS.Internal.Documents.ContentHostHelper.FindContentHost(_adornedContentElement); 
                    }
 
                    return _contentHostParent; 
                }
            } 

            /// 
            /// Says if the Adorner needs update based on the
            /// previously cached size if the AdornedElement. 
            /// 
            internal override bool NeedsUpdate(Size oldSize) 
            { 
                if (_adornedContentElement != null)
                { 
                    ReadOnlyCollection oldRects = _contentRects;
                    _contentRects = null;

                    IContentHost contentHost = ContentHost; 
                    if (contentHost != null)
                    { 
                        _contentRects = contentHost.GetRectangles(_adornedContentElement); 
                    }
 
                    // The positions of the focus rects are dependent on the rects returned from
                    // host.GetRectangles and the transform from the host to the adorned element
                    GeneralTransform oldTransform = _hostToAdornedElement;
 
                    if (contentHost is Visual && AdornedElement.IsAncestorOf((Visual)contentHost))
                    { 
                        _hostToAdornedElement = ((Visual)contentHost).TransformToAncestor(AdornedElement); 
                    }
                    else 
                    {
                        _hostToAdornedElement = Transform.Identity;
                    }
 
                    // See if these are the same transform
                    if (oldTransform != _hostToAdornedElement) 
                    { 
                        // Allow two identical matrix transforms
                        if (!(oldTransform is MatrixTransform) || 
                            !(_hostToAdornedElement is MatrixTransform) ||
                            !Matrix.Equals(((MatrixTransform)oldTransform).Matrix, ((MatrixTransform)_hostToAdornedElement).Matrix))
                        {
                            // one is a general transform or the matrices are not equal, need to update 
                            return true;
                        } 
                    } 

                    if (_contentRects != null && oldRects != null && _contentRects.Count == oldRects.Count) 
                    {
                        for (int i=0; i _contentRects;
        }

        internal static UIElement GetParentUIElementFromContentElement(ContentElement ce) 
        {
            IContentHost ichParent = null; 
            return GetParentUIElementFromContentElement(ce, ref ichParent); 
        }
 
        private static UIElement GetParentUIElementFromContentElement(ContentElement ce, ref IContentHost ichParent)
        {
            if (ce == null)
                return null; 

            IContentHost ich = MS.Internal.Documents.ContentHostHelper.FindContentHost(ce); 
            if (ichParent == null) 
                ichParent = ich;
 
            DependencyObject parent =  ich as DependencyObject;
            if(parent != null)
            {
                // Case 1: UIElement 
                // return the element
                UIElement eParent = parent as UIElement; 
                if(eParent != null) 
                    return eParent;
 
                // Case 2: Visual
                // Walk up the visual tree until we find UIElement
                Visual visualParent = parent as Visual;
                while (visualParent != null) 
                {
                    visualParent = VisualTreeHelper.GetParent(visualParent) as Visual; 
                    UIElement uielement = visualParent as UIElement; 
                    if (uielement != null)
                        return uielement; 
                }

                // Case 3: ContentElement
                ContentElement ceParent = parent as ContentElement; 
                if(ceParent != null)
                    return GetParentUIElementFromContentElement(ceParent, ref ichParent); 
            } 

            return null; 
        }

        internal void HideFocusVisual()
        { 
            // Remove the existing focus visual
            if (_focusVisualAdornerCache != null) 
            { 
                AdornerLayer adornerlayer = VisualTreeHelper.GetParent(_focusVisualAdornerCache) as AdornerLayer;
                if (adornerlayer != null) 
                {
                    adornerlayer.Remove(_focusVisualAdornerCache);
                }
                _focusVisualAdornerCache = null; 
            }
        } 
        ///  
        ///   Critical: This code accesses link demanded input manager
        ///   TreatAsSafe: This code is ok to expose as it simply return boolean weather Keyboard is the last used device 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal static bool IsKeyboardMostRecentInputDevice()
        { 
            return InputManager.Current.MostRecentInputDevice is KeyboardDevice;
        } 
 
        internal static bool AlwaysShowFocusVisual
        { 
            get
            {
                return _alwaysShowFocusVisual;
            } 
            set
            { 
                _alwaysShowFocusVisual = value; 
            }
        } 
        private static bool _alwaysShowFocusVisual = SystemParameters.KeyboardCues;

        internal static void ShowFocusVisual()
        { 
            Current.ShowFocusVisual(Keyboard.FocusedElement as DependencyObject);
        } 
 
        private void ShowFocusVisual(DependencyObject element)
        { 
            // Always hide the existing focus visual
            HideFocusVisual();

            // Disable keyboard cues (accesskey underline) if keyboard device is not MostRecentInputDevice 
            if (!IsKeyboardMostRecentInputDevice())
            { 
                EnableKeyboardCues(element, false); 
            }
 
            // Show focus visual if system metric is true or keyboard is used last
            if (AlwaysShowFocusVisual || IsKeyboardMostRecentInputDevice())
            {
 
                FrameworkElement fe = element as FrameworkElement;
                if (fe != null) 
                { 
                    AdornerLayer adornerlayer = AdornerLayer.GetAdornerLayer(fe);
                    if (adornerlayer == null) 
                        return;

                    Style fvs = fe.FocusVisualStyle;
 
                    // WORKAROUND: (Bug 1016350) If FocusVisualStyle is the "default" value
                    // then we load the default FocusVisualStyle from ResourceDictionary. 
                    if (fvs == FrameworkElement.DefaultFocusVisualStyle) 
                    {
                        fvs = SystemResources.FindResourceInternal(SystemParameters.FocusVisualStyleKey) as Style; 
                    }

                    if (fvs != null)
                    { 
                        _focusVisualAdornerCache = new FocusVisualAdorner(fe, fvs);
                        adornerlayer.Add(_focusVisualAdornerCache); 
                    } 
                }
                else // If not FrameworkElement 
                {
                    FrameworkContentElement fce = element as FrameworkContentElement;
                    if (fce != null)
                    { 
                        IContentHost parentICH = null;
                        UIElement parentUIElement = GetParentUIElementFromContentElement(fce, ref parentICH); 
                        if (parentICH != null && parentUIElement != null) 
                        {
                            AdornerLayer adornerlayer = AdornerLayer.GetAdornerLayer(parentUIElement); 
                            if (adornerlayer != null)
                            {
                                Style fvs = fce.FocusVisualStyle;
 
                                // WORKAROUND: (Bug 1016350) If FocusVisualStyle is the "default" value
                                // then we load the default FocusVisualStyle from ResourceDictionary. 
                                if (fvs == FrameworkElement.DefaultFocusVisualStyle) 
                                {
                                    fvs = SystemResources.FindResourceInternal(SystemParameters.FocusVisualStyleKey) as Style; 
                                }

                                if (fvs != null)
                                { 
                                    _focusVisualAdornerCache = new FocusVisualAdorner(fce, parentUIElement, parentICH, fvs);
                                    adornerlayer.Add(_focusVisualAdornerCache); 
                                } 
                            }
                        } 
                    }
                }
            }
        } 

        private FocusVisualAdorner _focusVisualAdornerCache = null; 
 
        #endregion FocusVisualStyle API
 
        #region Navigate helpers

        internal static void UpdateFocusedElement(DependencyObject focusTarget)
        { 
            DependencyObject focusScope = FocusManager.GetFocusScope(focusTarget);
            if (focusScope != null && focusScope != focusTarget) 
            { 
                FocusManager.SetFocusedElement(focusScope, focusTarget as IInputElement);
 
                // Raise FocusEnterMainFocusScope event
                Visual visualRoot = GetVisualRoot(focusTarget);
                if (visualRoot != null && focusScope == visualRoot)
                { 
                    Current.NotifyFocusEnterMainFocusScope(visualRoot, EventArgs.Empty);
                } 
            } 
        }
 
        internal void UpdateActiveElement(DependencyObject activeElement)
        {
            // Update TabNavigation = Once groups
            UpdateActiveElement(activeElement, TabNavigationProperty); 

            // Update ControlTabNavigation = Once groups 
            UpdateActiveElement(activeElement, ControlTabNavigationProperty); 
        }
 
        private void UpdateActiveElement(DependencyObject activeElement, DependencyProperty dp)
        {
            _navigationProperty = dp;
            DependencyObject container = GetGroupParent(activeElement); 
            if (activeElement == container)
                return; 
 
            // Update ActiveElement only if container has TabNavigation = Once
            if (GetKeyNavigationMode(container) == KeyboardNavigationMode.Once) 
            {
                SetActiveElement(container, activeElement);
            }
        } 

        // Called from FrameworkElement.MoveFocus 
        internal bool Navigate(DependencyObject currentElement, TraversalRequest request) 
        {
            return Navigate(currentElement, request, Keyboard.Modifiers); 
        }

        private bool Navigate(DependencyObject currentElement, TraversalRequest request, ModifierKeys modifierKeys)
        { 
            return Navigate(currentElement, request, modifierKeys, null);
        } 
 
        private bool Navigate(DependencyObject currentElement, TraversalRequest request, ModifierKeys modifierKeys, DependencyObject firstElement)
        { 
            Debug.Assert(currentElement != null, "currentElement should not be null");
            DependencyObject nextTab = null;
            IKeyboardInputSink inputSink = null;
 
            switch (request.FocusNavigationDirection)
            { 
                case FocusNavigationDirection.Next: 
                    _navigationProperty = (modifierKeys & ModifierKeys.Control) == ModifierKeys.Control ? ControlTabNavigationProperty : TabNavigationProperty;
                    nextTab = GetNextTab(currentElement, GetGroupParent(currentElement, true /*includeCurrent*/), false); 
                    break;

                case FocusNavigationDirection.Previous:
                    _navigationProperty = (modifierKeys & ModifierKeys.Control) == ModifierKeys.Control ? ControlTabNavigationProperty : TabNavigationProperty; 
                    nextTab = GetPrevTab(currentElement, null, false);
                    break; 
 
                case FocusNavigationDirection.First:
                    _navigationProperty = (modifierKeys & ModifierKeys.Control) == ModifierKeys.Control ? ControlTabNavigationProperty : TabNavigationProperty; 
                    nextTab = GetNextTab(null, currentElement, true);
                    break;

                case FocusNavigationDirection.Last: 
                    _navigationProperty = (modifierKeys & ModifierKeys.Control) == ModifierKeys.Control ? ControlTabNavigationProperty : TabNavigationProperty;
                    nextTab = GetPrevTab(null, currentElement, true); 
                    break; 

                case FocusNavigationDirection.Left: 
                case FocusNavigationDirection.Right:
                case FocusNavigationDirection.Up:
                case FocusNavigationDirection.Down:
                    _navigationProperty = DirectionalNavigationProperty; 
                    nextTab = GetNextInDirection(currentElement, request.FocusNavigationDirection);
                    break; 
            } 

            // If there are no other tabstops, try to pass focus outside PresentationSource 
            if (nextTab == null)
            {
                // If Wrapped is true we should not searach outside this container
                if (request.Wrapped || request.FocusNavigationDirection == FocusNavigationDirection.First || request.FocusNavigationDirection == FocusNavigationDirection.Last) 
                    return false;
 
                // Try to navigate outside the PresentationSource 
                bool navigatedOutside = NavigateOutsidePresentationSource(currentElement, request);
                if (navigatedOutside) 
                {
                    return true;
                }
                else if (request.FocusNavigationDirection == FocusNavigationDirection.Next || request.FocusNavigationDirection == FocusNavigationDirection.Previous) 
                {
                    // In case focus cannot navigate outside - we should cycle 
                    Visual visualRoot = GetVisualRoot(currentElement); 
                    if (visualRoot != null)
                        return Navigate(visualRoot, new TraversalRequest(request.FocusNavigationDirection == FocusNavigationDirection.Next ? FocusNavigationDirection.First : FocusNavigationDirection.Last)); 
                }

                return false;
            } 

            inputSink = nextTab as IKeyboardInputSink; 
            if (inputSink == null) 
            {
                // If target element does not support IKeyboardInputSink then we try to set focus 
                // In TextBox scenario Focus() return false although the focus is set to TextBox content
                // So we need to verify IsKeyboardFocusWithin property (bugfix 954000)
                IInputElement iie = nextTab as IInputElement;
                iie.Focus(); 

                return iie.IsKeyboardFocusWithin; 
            } 
            else
            { 
                // If target element supports IKeyboardInputSink then we pass the focus there
                bool traversed = false;

                if (request.FocusNavigationDirection == FocusNavigationDirection.First || request.FocusNavigationDirection == FocusNavigationDirection.Next) 
                {
                    traversed = inputSink.TabInto(new TraversalRequest(FocusNavigationDirection.First)); 
                } 
                else if (request.FocusNavigationDirection == FocusNavigationDirection.Last || request.FocusNavigationDirection == FocusNavigationDirection.Previous)
                { 
                    traversed = inputSink.TabInto(new TraversalRequest(FocusNavigationDirection.Last));
                }
                else // FocusNavigationDirection
                { 
                    TraversalRequest tr = new TraversalRequest(request.FocusNavigationDirection);
                    tr.Wrapped = true; 
                    traversed = inputSink.TabInto(tr); 
                }
 
                // If we fail to navigate into IKeyboardInputSink then move to the next element
                if (!traversed && firstElement != nextTab)
                {
                    // Navigate to next element in the tree 
                    traversed = Navigate(nextTab, request, modifierKeys, firstElement == null ? nextTab : firstElement);
                } 
 
                return traversed;
            } 
        }

        /// 
        ///     Critical: This code accesses PresentationSource. 
        ///     TreatAsSafe: This code causes navigation to different elements within an app.
        ///     It does not expose the PresentationSource 
        ///     Critical: Asserting UnmanagedCode permission to obtain HwndSource.IKeyboardInputSink.KeyboardInputSite 
        ///     TreatAsSafe: Not leaking the InputKeyboardSite obtained under elevation.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private bool NavigateOutsidePresentationSource(DependencyObject currentElement, TraversalRequest request)
        {
            Visual visual = currentElement as Visual; 
            if (visual == null)
            { 
                visual = GetParentUIElementFromContentElement(currentElement as ContentElement); 
                if (visual == null)
                    return false; 
            }

            IKeyboardInputSink inputSink = PresentationSource.CriticalFromVisual(visual) as IKeyboardInputSink;
            if (inputSink != null) 
            {
                IKeyboardInputSite ikis = null; 
 
                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();  // BlessedAssert
                try 
                {
                    ikis = inputSink.KeyboardInputSite;
                }
                finally 
                {
                    CodeAccessPermission.RevertAssert(); 
                } 

                if (ikis != null) 
                    return ikis.OnNoMoreTabStops(request);
            }

            return false; 
        }
 
        internal static KeyboardNavigation Current 
        {
            get 
            {
                return FrameworkElement.KeyboardNavigation;
            }
        } 

        ///////////////////////////////////////////////////////////////////// 
        /// 
        /// Critical: accesses e.StagingItem.Input and asserts to retrieve HwndSource
        /// 
        [SecurityCritical]
        private void PostProcessInput(object sender, ProcessInputEventArgs e)
        {
            // Call Forwarded 
            ProcessInput(e.StagingItem.Input);
        } 
 
        /////////////////////////////////////////////////////////////////////
        /// 
        /// Critical: asserts to retrieve HwndSource
        ///
        [SecurityCritical]
        private void TranslateAccelerator(object sender, KeyEventArgs e) 
        {
            // Call Forwarded 
            ProcessInput(e); 
        }
 
        /////////////////////////////////////////////////////////////////////
        ///
        /// Critical: asserts to retrieve HwndSource
        /// 
        [SecurityCritical]
        private void ProcessInput(InputEventArgs inputEventArgs) 
        { 
            ProcessForMenuMode(inputEventArgs);
            ProcessForUIState(inputEventArgs); 

            // Process keyboard navigation for keydown event for Tab,Left,Right,Up,Down keys.
            if(inputEventArgs.RoutedEvent != Keyboard.KeyDownEvent)
                return; 

            KeyEventArgs keyEventArgs = (KeyEventArgs)inputEventArgs; 
            if (keyEventArgs.Handled) 
                return;
 
            DependencyObject sourceElement = keyEventArgs.OriginalSource as DependencyObject;

            // For Keyboard Interop with Avalon-inside-Avalon via HwndHost.
            // In Keyboard interop, the target (called OriginalSource here) is "forced" 
            // to point at the HwndHost containing the Hwnd with focus.  This allows
            // us to tunnel/bubble the keystroke across the outer HwndSource to the 
            // child hwnd that has focus.  (see HwndSource.TranslateAccelerator) 
            // But this "forced" target is wrong for Tab Navigation; eg. tabbing
            // across an inner avalon under the HwndHost.   For that we need the 
            // real original target element, which we happen to find in KeyboardDevice.Target.
            //
            // sourceElement and innerElement I don't expect will ever be different
            // except in this case.  And I added a check that the "forced" target 
            // is an HwndHost for good measure.
            DependencyObject innerElement = keyEventArgs.KeyboardDevice.Target as DependencyObject; 
            if( innerElement != null && sourceElement != innerElement ) 
            {
                if(sourceElement is HwndHost) 
                    sourceElement = innerElement;
            }

            // When nothing has focus - we should start from the root of the visual tree 
            if (sourceElement == null)
            { 
 
                HwndSource hwndSource = keyEventArgs.UnsafeInputSource as HwndSource;
                if (hwndSource == null) 
                    return;

                sourceElement = hwndSource.RootVisual;
                if (sourceElement == null) 
                    return;
            } 
 
            // Focus visual support
            switch (GetRealKey(keyEventArgs)) 
            {
                case Key.LeftAlt:
                case Key.RightAlt:
                    ShowFocusVisual(); 
                    EnableKeyboardCues(sourceElement, true);
                    break; 
                case Key.Tab: 
                case Key.Right:
                case Key.Left: 
                case Key.Up:
                case Key.Down:
                    ShowFocusVisual();
                    break; 
            }
 
            keyEventArgs.Handled = Navigate(sourceElement, keyEventArgs.Key, keyEventArgs.KeyboardDevice.Modifiers); 
        }
 
        internal static void EnableKeyboardCues(DependencyObject element, bool enable)
        {
            Visual visual = element as Visual;
            if (visual == null) 
            {
                visual = GetParentUIElementFromContentElement(element as ContentElement); 
                if (visual == null) 
                    return;
            } 

            Visual rootVisual = GetVisualRoot(visual);
            if (rootVisual != null)
            { 
                rootVisual.SetValue(ShowKeyboardCuesProperty, enable ? BooleanBoxes.TrueBox : BooleanBoxes.FalseBox);
            } 
        } 

        internal static FocusNavigationDirection KeyToTraversalDirection(Key key) 
        {
            switch (key)
            {
                case Key.Left: 
                    return FocusNavigationDirection.Left;
 
                case Key.Right: 
                    return FocusNavigationDirection.Right;
 
                case Key.Up:
                    return FocusNavigationDirection.Up;

                case Key.Down: 
                    return FocusNavigationDirection.Down;
            } 
 
            throw new NotSupportedException();
        } 

        internal DependencyObject PredictFocusedElement(DependencyObject sourceElement, FocusNavigationDirection direction)
        {
            if (sourceElement == null) 
            {
                return null; 
            } 

            _navigationProperty = DirectionalNavigationProperty; 
            _verticalBaseline = BASELINE_DEFAULT;
            _horizontalBaseline = BASELINE_DEFAULT;
            return GetNextInDirection(sourceElement, direction);
        } 

        internal bool Navigate(DependencyObject sourceElement, Key key, ModifierKeys modifiers) 
        { 
            bool success = false;
 
            switch (key)
            {
                // Logical (Tab) navigation
                case Key.Tab: 
                    success = Navigate(sourceElement,
                        new TraversalRequest(((modifiers & ModifierKeys.Shift) == ModifierKeys.Shift) ? 
                        FocusNavigationDirection.Previous : FocusNavigationDirection.Next), modifiers); 
                    break;
 
                case Key.Right:
                    success = Navigate(sourceElement, new TraversalRequest(FocusNavigationDirection.Right), modifiers);
                    break;
 
                case Key.Left:
                    success = Navigate(sourceElement, new TraversalRequest(FocusNavigationDirection.Left), modifiers); 
                    break; 

                case Key.Up: 
                    success = Navigate(sourceElement, new TraversalRequest(FocusNavigationDirection.Up), modifiers);
                    break;

                case Key.Down: 
                    success = Navigate(sourceElement, new TraversalRequest(FocusNavigationDirection.Down), modifiers);
                    break; 
 
            }
            return success; 
        }

        #endregion Navigate helpers
 
        #region Tree navigation
 
        // Filter the visual tree and return true if: 
        // 1. visual is visible UIElement
        // 2. visual is visible UIElement3D 
        // 3. visual is IContentHost but not UIElementIsland
        // Note: UIElementIsland is a special element that has only one child and should be excluded
        private bool IsInNavigationTree(DependencyObject visual)
        { 
            UIElement uiElement = visual as UIElement;
            if (uiElement != null && uiElement.IsVisible) 
                return true; 

            if (visual is IContentHost && !(visual is MS.Internal.Documents.UIElementIsland)) 
                return true;

            UIElement3D uiElement3D = visual as UIElement3D;
            if (uiElement3D != null && uiElement3D.IsVisible) 
                return true;
 
            return false; 
        }
 
        private DependencyObject GetPreviousSibling(DependencyObject e)
        {
            DependencyObject parent = GetParent(e);
 
            // If parent is IContentHost - get next from the enumerator
            IContentHost ich = parent as IContentHost; 
            if (ich != null) 
            {
                IInputElement previousElement = null; 
                IEnumerator enumerator = ich.HostedElements;
                while (enumerator.MoveNext())
                {
                    IInputElement current = enumerator.Current; 
                    if (current == e)
                        return previousElement as DependencyObject; 
 
                    if (current is UIElement || current is UIElement3D)
                        previousElement = current; 
                    else
                    {
                        ContentElement ce = current as ContentElement;
                        if (ce != null && IsTabStop(ce)) 
                            previousElement = current;
                    } 
                } 
                return null;
            } 
            else
            {
                // If parent is UIElement(3D) - return visual sibling
                DependencyObject parentAsUIElement = parent as UIElement; 
                if (parentAsUIElement == null)
                { 
                    parentAsUIElement = parent as UIElement3D; 
                }
                DependencyObject elementAsVisual = e as Visual; 
                if (elementAsVisual == null)
                {
                    elementAsVisual = e as Visual3D;
                } 

                if (parentAsUIElement != null && elementAsVisual != null) 
                { 
                    int count = VisualTreeHelper.GetChildrenCount(parentAsUIElement);
                    DependencyObject prev = null; 
                    for(int i = 0; i < count; i++)
                    {
                        DependencyObject vchild = VisualTreeHelper.GetChild(parentAsUIElement, i);
                        if(vchild == elementAsVisual) break; 
                        if (IsInNavigationTree(vchild))
                            prev = vchild; 
                    } 
                    return prev;
                } 
            }
            return null;
        }
 
        private DependencyObject GetNextSibling(DependencyObject e)
        { 
            DependencyObject parent = GetParent(e); 

            // If parent is IContentHost - get next from the enumerator 
            IContentHost ich = parent as IContentHost;
            if (ich != null)
            {
                IEnumerator enumerator = ich.HostedElements; 
                bool found = false;
                while (enumerator.MoveNext()) 
                { 
                    IInputElement current = enumerator.Current;
                    if (found) 
                    {
                        if (current is UIElement || current is UIElement3D)
                            return current as DependencyObject;
                        else 
                        {
                            ContentElement ce = current as ContentElement; 
                            if (ce != null && IsTabStop(ce)) 
                                return ce;
                        } 
                    }
                    else if (current == e)
                    {
                        found = true; 
                    }
                } 
            } 
            else
            { 
                // If parent is UIElement(3D) - return visual sibling
                DependencyObject parentAsUIElement = parent as UIElement;
                if (parentAsUIElement == null)
                { 
                    parentAsUIElement = parent as UIElement3D;
                } 
                DependencyObject elementAsVisual = e as Visual; 
                if (elementAsVisual == null)
                { 
                    elementAsVisual = e as Visual3D;
                }

                if (parentAsUIElement != null && elementAsVisual != null) 
                {
                    int count = VisualTreeHelper.GetChildrenCount(parentAsUIElement); 
                    int i = 0; 
                    //go till itself
                    for(; i < count; i++) 
                    {
                        DependencyObject vchild = VisualTreeHelper.GetChild(parentAsUIElement, i);
                        if(vchild == elementAsVisual) break;
                    } 
                    i++;
                    //search ahead 
                    for(; i < count; i++) 
                    {
                        DependencyObject visual = VisualTreeHelper.GetChild(parentAsUIElement, i); 
                        if (IsInNavigationTree(visual))
                            return visual;
                    }
                } 
            }
 
            return null; 
        }
 
        // For Control+Tab navigation or TabNavigation when fe is not a FocusScope:
        // Scenarios:
        // 1. UserControl can set its FocusedElement to delegate focus when Tab navigation happens
        // 2. ToolBar or Menu (which have IsFocusScope=true) both have FocusedElement but included only in Control+Tab navigation 
        private DependencyObject FocusedElement(DependencyObject e)
        { 
            IInputElement iie = e as IInputElement; 
            // Focus delegation is enabled only if keyboard focus is outside the container
            if (iie != null && !iie.IsKeyboardFocusWithin) 
            {
                DependencyObject focusedElement = FocusManager.GetFocusedElement(e) as DependencyObject;
                if (focusedElement != null)
                { 
                    if (_navigationProperty == ControlTabNavigationProperty || !IsFocusScope(e))
                    { 
                        // Verify if focusedElement is a visual descendant of e 
                        Visual visualFocusedElement = focusedElement as Visual;
                        if (visualFocusedElement == null) 
                        {
                            Visual3D visual3DFocusedElement = focusedElement as Visual3D;
                            if (visual3DFocusedElement == null)
                            { 
                                visualFocusedElement = GetParentUIElementFromContentElement(focusedElement as ContentElement);
                            } 
                            else 
                            {
                                if (visual3DFocusedElement.IsDescendantOf(e)) 
                                {
                                    return focusedElement;
                                }
                            } 
                        }
                        if (visualFocusedElement.IsDescendantOf(e)) 
                        { 
                            return focusedElement;
                        } 
                    }
                }
            }
 
            return null;
        } 
 
        // We traverse only UIElement(3D) or ContentElement
        private DependencyObject GetFirstChild(DependencyObject e) 
        {
            // If the element has a FocusedElement it should be its first child
            DependencyObject focusedElement = FocusedElement(e);
            if (focusedElement != null) 
                return focusedElement;
 
            // If the element is IContentHost - return the first child 
            IContentHost ich = e as IContentHost;
            if (ich != null) 
            {
                IEnumerator enumerator = ich.HostedElements;
                while (enumerator.MoveNext())
                { 
                    IInputElement current = enumerator.Current;
                    if (current is UIElement || current is UIElement3D) 
                    { 
                        return current as DependencyObject;
                    } 
                    else
                    {
                        ContentElement ce = current as ContentElement;
                        if (ce != null && IsTabStop(ce)) 
                            return ce;
                    } 
                } 
                return null;
            } 

            // Return the first visible UIElement(3D) or IContentHost
            DependencyObject uiElement = e as UIElement;
            if (uiElement == null) 
            {
                uiElement = e as UIElement3D; 
            } 

            if (uiElement == null || 
                UIElementHelper.IsVisible(uiElement))
            {
                DependencyObject elementAsVisual = e as Visual;
                if (elementAsVisual == null) 
                {
                    elementAsVisual = e as Visual3D; 
                } 

                if (elementAsVisual != null) 
                {
                    int count = VisualTreeHelper.GetChildrenCount(elementAsVisual);
                    for (int i = 0; i < count; i++)
                    { 
                        DependencyObject visual = VisualTreeHelper.GetChild(elementAsVisual, i);
                        if (IsInNavigationTree(visual)) 
                            return visual; 
                        else
                        { 
                            DependencyObject firstChild = GetFirstChild(visual);
                            if (firstChild != null)
                                return firstChild;
                        } 
                    }
                } 
            } 

            // If element is ContentElement for example 
            return null;
        }

        private DependencyObject GetLastChild(DependencyObject e) 
        {
            // If the element has a FocusedElement it should be its last child 
            DependencyObject focusedElement = FocusedElement(e); 
            if (focusedElement != null)
                return focusedElement; 

            // If the element is IContentHost - return the last child
            IContentHost ich = e as IContentHost;
            if (ich != null) 
            {
                IEnumerator enumerator = ich.HostedElements; 
                IInputElement last = null; 
                while (enumerator.MoveNext())
                { 
                    IInputElement current = enumerator.Current;
                    if (current is UIElement || current is UIElement3D)
                        last = current;
                    else 
                    {
                        ContentElement ce = current as ContentElement; 
                        if (ce != null && IsTabStop(ce)) 
                            last = current;
                    } 
                }
                return last as DependencyObject;
            }
 
            // Return the last visible UIElement(3D) or IContentHost
            DependencyObject uiElement = e as UIElement; 
            if (uiElement == null) 
            {
                uiElement = e as UIElement3D; 
            }

            if (uiElement == null || UIElementHelper.IsVisible(uiElement))
            { 
                DependencyObject elementAsVisual = e as Visual;
                if (elementAsVisual == null) 
                { 
                    elementAsVisual = e as Visual3D;
                } 

                if (elementAsVisual != null)
                {
                    int count = VisualTreeHelper.GetChildrenCount(elementAsVisual); 
                    for (int i = count - 1; i >= 0; i--)
                    { 
                        DependencyObject visual = VisualTreeHelper.GetChild(elementAsVisual, i); 
                        if (IsInNavigationTree(visual))
                            return visual; 
                        else
                        {
                            DependencyObject lastChild = GetLastChild(visual);
                            if (lastChild != null) 
                                return lastChild;
                        } 
                    } 
                }
            } 

            return null;
        }
 
        private DependencyObject GetParent(DependencyObject e)
        { 
            // For Visual - go up the visual parent chain until we find Visual, Visual3D or IContentHost 
            if (e is Visual || e is Visual3D)
            { 
                DependencyObject visual = e;

                while ((visual = VisualTreeHelper.GetParent(visual)) != null)
                { 
                    //
 
 
                    if (IsInNavigationTree(visual))
                        return visual; 
                }
            }
            else
            { 
                // For ContentElement - return the host element (which is IContentHost)
                ContentElement contentElement = e as ContentElement; 
                if (contentElement != null) 
                {
                    return MS.Internal.Documents.ContentHostHelper.FindContentHost(contentElement) as DependencyObject; 
                }
            }

            return null; 
        }
 
        /***************************************************************************\ 
        *
        * GetNextInTree(DependencyObject e, DependencyObject container) 
        * Search the subtree with container root; Don't go inside TabGroups
        *
        * Return the next Element in tree in depth order (self-child-sibling).
        *            1 
        *           / \
        *          2   5 
        *         / \ 
        *        3   4
        * 
        \***************************************************************************/
        private DependencyObject GetNextInTree(DependencyObject e, DependencyObject container)
        {
            Debug.Assert(e != null, "e should not be null"); 
            Debug.Assert(container != null, "container should not be null");
 
            DependencyObject result = null; 

            if (e == container || !IsGroup(e)) 
                result = GetFirstChild(e);

            if (result != null || e == container)
                return result; 

            DependencyObject parent = e; 
            do 
            {
                DependencyObject sibling = GetNextSibling(parent); 
                if (sibling != null)
                    return sibling;

                parent = GetParent(parent); 
            } while (parent != null && parent != container);
 
            return null; 
        }
 

        /***************************************************************************\
        *
        * GetPreviousInTree(DependencyObject e, DependencyObject container) 
        * Don't go inside TabGroups
        * Return the previous Element in tree in depth order (self-child-sibling). 
        *            5 
        *           / \
        *          4   1 
        *         / \
        *        3   2
        \***************************************************************************/
        private DependencyObject GetPreviousInTree(DependencyObject e, DependencyObject container) 
        {
            if (e == container) 
                return null; 

            DependencyObject result = GetPreviousSibling(e); 

            if (result != null)
            {
                if (IsGroup(result)) 
                    return result;
                else 
                    return GetLastInTree(result); 
            }
            else 
                return GetParent(e);
        }

        // Find the last element in the subtree 
        private DependencyObject GetLastInTree(DependencyObject container)
        { 
            DependencyObject result; 
            do
            { 
                result = container;
                container = GetLastChild(container);
            } while (container != null && !IsGroup(container));
 
            if (container != null)
                return container; 
 
            return result;
        } 

        private DependencyObject GetGroupParent(DependencyObject e)
        {
            return GetGroupParent(e, false /*includeCurrent*/); 
        }
 
        // Go up thru the parent chain until we find TabNavigation != Continue 
        // In case all parents are Continue then return the root
        private DependencyObject GetGroupParent(DependencyObject e, bool includeCurrent) 
        {
            Debug.Assert(e != null, "e cannot be null");

            DependencyObject result = e; // Keep the last non null element 

            // If we don't want to include the current element, 
            // start at the parent of the element.  If the element 
            // is the root, then just return it as the group parent.
            if (!includeCurrent) 
            {
                result = e;
                e = GetParent(e);
                if (e == null) 
                {
                    return result; 
                } 
            }
 
            while (e != null)
            {
                if (IsGroup(e))
                    return e; 

                result = e; 
                e = GetParent(e); 
            }
 
            return result;
        }

        #endregion Tree navigation 

        #region Logical Navigation 
 
        private bool IsTabStop(DependencyObject e)
        { 
            FrameworkElement fe = e as FrameworkElement;
            if (fe != null)
                return
                    (fe.Focusable 
                    && (bool)fe.GetValue(IsTabStopProperty))
                    && fe.IsEnabled 
                    && fe.IsVisible; 

            FrameworkContentElement fce = e as FrameworkContentElement; 
            return fce != null && fce.Focusable && (bool)fce.GetValue(IsTabStopProperty) && fce.IsEnabled;
        }

        private bool IsGroup(DependencyObject e) 
        {
            return GetKeyNavigationMode(e) != KeyboardNavigationMode.Continue; 
        } 

        private KeyboardNavigationMode GetKeyNavigationMode(DependencyObject e) 
        {
            return (KeyboardNavigationMode)e.GetValue(_navigationProperty);
        }
 
        private bool IsTabStopOrGroup(DependencyObject e)
        { 
            return IsTabStop(e) || IsGroup(e); 
        }
 
        private static int GetTabIndexHelper(DependencyObject d)
        {
            return (int)d.GetValue(TabIndexProperty);
        } 

        #region Tab Navigation 
 
        // Find the element with highest priority (lowest index) inside the group
        private DependencyObject GetFirstTabInGroup(DependencyObject container) 
        {
            DependencyObject firstTabElement = null;
            int minIndexFirstTab = Int32.MinValue;
 
            DependencyObject currElement = container;
            while ((currElement = GetNextInTree(currElement, container)) != null) 
            { 
                if (IsTabStopOrGroup(currElement))
                { 
                    int currPriority = GetTabIndexHelper(currElement);

                    if (currPriority < minIndexFirstTab || firstTabElement == null)
                    { 
                        minIndexFirstTab = currPriority;
                        firstTabElement = currElement; 
                    } 
                }
            } 
            return firstTabElement;
        }

        // Find the element with the same TabIndex after the current element 
        private DependencyObject GetNextTabWithSameIndex(DependencyObject e, DependencyObject container)
        { 
            int elementTabPriority = GetTabIndexHelper(e); 
            DependencyObject currElement = e;
            while ((currElement = GetNextInTree(currElement, container)) != null) 
            {
                if (IsTabStopOrGroup(currElement) && GetTabIndexHelper(currElement) == elementTabPriority)
                {
                    return currElement; 
                }
            } 
 
            return null;
        } 

        // Find the element with the next TabIndex after the current element
        private DependencyObject GetNextTabWithNextIndex(DependencyObject e, DependencyObject container, KeyboardNavigationMode tabbingType)
        { 
            // Find the next min index in the tree
            // min (index>currentTabIndex) 
            DependencyObject nextTabElement = null; 
            DependencyObject firstTabElement = null;
            int minIndexFirstTab = Int32.MinValue; 
            int minIndex = Int32.MinValue;
            int elementTabPriority = GetTabIndexHelper(e);

            DependencyObject currElement = container; 
            while ((currElement = GetNextInTree(currElement, container)) != null)
            { 
 
                if (IsTabStopOrGroup(currElement))
                { 
                    int currPriority = GetTabIndexHelper(currElement);
                    if (currPriority > elementTabPriority)
                    {
                        if (currPriority < minIndex || nextTabElement == null) 
                        {
                            minIndex = currPriority; 
                            nextTabElement = currElement; 
                        }
                    } 

                    if (currPriority < minIndexFirstTab || firstTabElement == null)
                    {
                        minIndexFirstTab = currPriority; 
                        firstTabElement = currElement;
                    } 
                } 
            }
 
            // Cycle groups: if not found - return first element
            if (tabbingType == KeyboardNavigationMode.Cycle && nextTabElement == null)
                nextTabElement = firstTabElement;
 
            return nextTabElement;
        } 
 
        private DependencyObject GetNextTabInGroup(DependencyObject e, DependencyObject container, KeyboardNavigationMode tabbingType)
        { 
            // None groups: Tab navigation is not supported
            if (tabbingType == KeyboardNavigationMode.None)
                return null;
 
            // e == null or e == container -> return the first TabStopOrGroup
            if (e == null || e == container) 
            { 
                return GetFirstTabInGroup(container);
            } 

            if (tabbingType == KeyboardNavigationMode.Once)
                return null;
 
            DependencyObject nextTabElement = GetNextTabWithSameIndex(e, container);
            if (nextTabElement != null) 
                return nextTabElement; 

            return GetNextTabWithNextIndex(e, container, tabbingType); 
        }

        private DependencyObject GetNextTab(DependencyObject e, DependencyObject container, bool goDownOnly)
        { 
            Debug.Assert(container != null, "container should not be null");
 
            KeyboardNavigationMode tabbingType = GetKeyNavigationMode(container); 

            if (e == null) 
            {
                if (IsTabStop(container))
                    return container;
 
                // Using ActiveElement if set
                DependencyObject activeElement = GetActiveElement(container); 
                if (activeElement != null) 
                    return GetNextTab(null, activeElement, true);
            } 
            else
            {
                if (tabbingType == KeyboardNavigationMode.Once || tabbingType == KeyboardNavigationMode.None)
                { 
                    if (container != e)
                    { 
                        if (goDownOnly) 
                            return null;
                        DependencyObject parentContainer = GetGroupParent(container); 
                        return GetNextTab(container, parentContainer, goDownOnly);
                    }
                }
            } 

            // All groups 
            DependencyObject loopStartElement = null; 
            DependencyObject nextTabElement = e;
            KeyboardNavigationMode currentTabbingType = tabbingType; 

            // Search down inside the container
            while ((nextTabElement = GetNextTabInGroup(nextTabElement, container, currentTabbingType)) != null)
            { 
                Debug.Assert(IsTabStopOrGroup(nextTabElement), "nextTabElement should be IsTabStop or group");
 
                // Avoid the endless loop here for Cycle groups 
                if (loopStartElement == nextTabElement)
                    break; 
                if (loopStartElement == null)
                    loopStartElement = nextTabElement;

                DependencyObject firstTabElementInside = GetNextTab(null, nextTabElement, true); 
                if (firstTabElementInside != null)
                    return firstTabElementInside; 
 
                // If we want to continue searching inside the Once groups, we should change the navigation mode
                if (currentTabbingType == KeyboardNavigationMode.Once) 
                    currentTabbingType = KeyboardNavigationMode.Contained;
            }

            // If there is no next element in the group (nextTabElement == null) 

            // Search up in the tree if allowed 
            // 
            if (!goDownOnly && currentTabbingType != KeyboardNavigationMode.Contained && GetParent(container) != null)
            { 
                return GetNextTab(container, GetGroupParent(container), false);
            }

            return null; 
        }
 
        #endregion Tab Navigation 

        #region Shift+Tab Navigation 

        private DependencyObject GetLastTabInGroup(DependencyObject container)
        {
            DependencyObject lastTabElement = null; 
            int maxIndexFirstTab = Int32.MaxValue;
            DependencyObject currElement = GetLastInTree(container); 
            while (currElement != null && currElement != container) 
            {
                if (IsTabStopOrGroup(currElement)) 
                {
                    int currPriority = GetTabIndexHelper(currElement);

                    if (currPriority > maxIndexFirstTab || lastTabElement == null) 
                    {
                        maxIndexFirstTab = currPriority; 
                        lastTabElement = currElement; 
                    }
                } 
                currElement = GetPreviousInTree(currElement, container);
            }
            return lastTabElement;
        } 

        // Look for element with the same TabIndex before the current element 
        private DependencyObject GetPrevTabWithSameIndex(DependencyObject e, DependencyObject container) 
        {
            int elementTabPriority = GetTabIndexHelper(e); 
            DependencyObject currElement = GetPreviousInTree(e, container);
            while (currElement != null)
            {
                if (IsTabStopOrGroup(currElement) && GetTabIndexHelper(currElement) == elementTabPriority && currElement != container) 
                {
                    return currElement; 
                } 
                currElement = GetPreviousInTree(currElement, container);
            } 
            return null;
        }

        private DependencyObject GetPrevTabWithPrevIndex(DependencyObject e, DependencyObject container, KeyboardNavigationMode tabbingType) 
        {
            // Find the next max index in the tree 
            // max (index maxIndex || nextTabElement == null)
                        { 
                            maxIndex = currPriority;
                            nextTabElement = currElement; 
                        } 
                    }
 
                    if (currPriority > maxIndexFirstTab || lastTabElement == null)
                    {
                        maxIndexFirstTab = currPriority;
                        lastTabElement = currElement; 
                    }
                } 
 
                currElement = GetPreviousInTree(currElement, container);
            } 

            // Cycle groups: if not found - return first element
            if (tabbingType == KeyboardNavigationMode.Cycle && nextTabElement == null)
                nextTabElement = lastTabElement; 

            return nextTabElement; 
        } 

        private DependencyObject GetPrevTabInGroup(DependencyObject e, DependencyObject container, KeyboardNavigationMode tabbingType) 
        {
            // None groups: Tab navigation is not supported
            if (tabbingType == KeyboardNavigationMode.None)
                return null; 

            // Search the last index inside the group 
            if (e==null) 
            {
                return GetLastTabInGroup(container); 
            }

            if (tabbingType == KeyboardNavigationMode.Once)
                return null; 

            if (e == container) 
                return null; 

            DependencyObject nextTabElement = GetPrevTabWithSameIndex(e, container); 
            if (nextTabElement != null)
                return nextTabElement;

            return GetPrevTabWithPrevIndex(e, container, tabbingType); 
        }
 
        private DependencyObject GetPrevTab(DependencyObject e, DependencyObject container, bool goDownOnly) 
        {
            Debug.Assert(e != null || container != null, "e or container should not be null"); 

            if (container == null)
                container = GetGroupParent(e);
 
            KeyboardNavigationMode tabbingType = GetKeyNavigationMode(container);
 
            if (e == null) 
            {
                // Using ActiveElement if set 
                DependencyObject activeElement = GetActiveElement(container);
                if (activeElement != null)
                    return GetPrevTab(null, activeElement, true);
                else 
                {
                    // If we Shift+Tab on a container with KeyboardNavigationMode=Once, and ActiveElement is null 
                    // then we want to go to the fist item (not last) within the container 
                    if (tabbingType == KeyboardNavigationMode.Once)
                    { 
                        DependencyObject firstTabElement = GetNextTabInGroup(null, container, tabbingType);
                        if (firstTabElement == null)
                        {
                            if (IsTabStop(container)) 
                                return container;
                            if (goDownOnly) 
                                return null; 

                            return GetPrevTab(container, null, false); 
                        }
                        else
                        {
                            return GetPrevTab(null, firstTabElement, true); 
                        }
                    } 
                } 
            }
            else 
            {
                if (tabbingType == KeyboardNavigationMode.Once || tabbingType == KeyboardNavigationMode.None)
                {
                    if (goDownOnly || container==e) 
                        return null;
 
                    // FocusedElement should not be e otherwise we will delegate focus to the same element 
                    if (IsTabStop(container))
                        return container; 

                    return GetPrevTab(container, null, false);
                }
            } 

            // All groups (except Once) - continue 
            DependencyObject loopStartElement = null; 
            DependencyObject nextTabElement = e;
 
            // Look for element with the same TabIndex before the current element
            while ((nextTabElement = GetPrevTabInGroup(nextTabElement, container, tabbingType)) != null)
            {
                if (nextTabElement == container && tabbingType == KeyboardNavigationMode.Local) 
                    break;
 
                // At this point nextTabElement is TabStop or TabGroup 
                // In case it is a TabStop only return the element
                if (IsTabStop(nextTabElement) && !IsGroup(nextTabElement)) 
                    return nextTabElement;

                // Avoid the endless loop here
                if (loopStartElement == nextTabElement) 
                    break;
                if (loopStartElement == null) 
                    loopStartElement = nextTabElement; 

                // At this point nextTabElement is TabGroup 
                DependencyObject lastTabElementInside = GetPrevTab(null, nextTabElement, true);
                if (lastTabElementInside != null)
                    return lastTabElementInside;
            } 

            if (tabbingType == KeyboardNavigationMode.Contained) 
                return null; 

            if (e != container && IsTabStop(container)) 
                return container;

            // If end of the subtree is reached or there no other elements above
            if (!goDownOnly && GetParent(container) != null) 
            {
                return GetPrevTab(container, null, false); 
            } 

            return null; 
        }

        #endregion Shift+Tab Navigation
 
        #endregion Logical Navigation
 
        #region Directional Navigation 

        // return the element rectange relative to the root 
        internal static Rect GetRectangle(DependencyObject element)
        {
            UIElement uiElement = element as UIElement;
            if (uiElement != null && uiElement.IsArrangeValid) 
            {
                Visual rootVisual = GetVisualRoot(uiElement); 
 
                if (rootVisual != null)
                { 
                    GeneralTransform transform = uiElement.TransformToAncestor(rootVisual);
                    Thickness deflateThickness = (Thickness)uiElement.GetValue(DirectionalNavigationMarginProperty);
                    double x = -deflateThickness.Left;
                    double y = -deflateThickness.Top; 
                    double width = uiElement.RenderSize.Width + deflateThickness.Left + deflateThickness.Right;
                    double height = uiElement.RenderSize.Height + deflateThickness.Top + deflateThickness.Bottom; 
                    if (width < 0) 
                    {
                        x = uiElement.RenderSize.Width * 0.5; 
                        width = 0d;
                    }
                    if (height < 0)
                    { 
                        y = uiElement.RenderSize.Height * 0.5;
                        height = 0d; 
                    } 
                    return transform.TransformBounds(new Rect(x, y, width, height));
                } 
            }
            else
            {
                ContentElement ce = element as ContentElement; 
                if (ce != null)
                { 
                    IContentHost parentICH = null; 
                    UIElement parentUIElement = GetParentUIElementFromContentElement(ce, ref parentICH);
                    Visual parent = parentICH as Visual; 
                    if (parentICH != null && parent != null && parentUIElement != null)
                    {
                        Visual rootVisual = GetVisualRoot(parent);
                        if (rootVisual != null && parentUIElement.IsMeasureValid) 
                        {
                            // Note: Here we consider only the fist rectangle 
                            // Do we need to consider all of them as one combined rectangle? 
                            ReadOnlyCollection rects = parentICH.GetRectangles(ce);
                            IEnumerator enumerator = rects.GetEnumerator(); 
                            if (enumerator.MoveNext())
                            {
                                GeneralTransform transform = parent.TransformToAncestor(rootVisual);
                                Rect rect = enumerator.Current; 
                                return transform.TransformBounds(rect);
                            } 
                        } 
                    }
                } 
                else
                {
                    UIElement3D uiElement3D = element as UIElement3D;
                    if (uiElement3D != null) 
                    {
                        Visual rootVisual = GetVisualRoot(uiElement3D); 
                        Visual containingVisual2D = VisualTreeHelper.GetContainingVisual2D(uiElement3D); 

                        if (rootVisual != null && containingVisual2D != null) 
                        {
                            Rect rectElement = uiElement3D.Visual2DContentBounds;
                            GeneralTransform transform = containingVisual2D.TransformToAncestor(rootVisual);
 
                            return transform.TransformBounds(rectElement);
                        } 
                    } 
                }
            } 

            return Rect.Empty;
        }
 
        // distance between two points
        private double GetDistance(Point p1, Point p2) 
        { 
            double deltaX = p1.X - p2.X;
            double deltaY = p1.Y - p2.Y; 
            return Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
        }

        private double GetPerpDistance(Rect sourceRect, Rect targetRect, FocusNavigationDirection direction) 
        {
            switch (direction) 
            { 
                case FocusNavigationDirection.Right :
                    return targetRect.Left - sourceRect.Left; 

                case FocusNavigationDirection.Left :
                    return sourceRect.Right - targetRect.Right;
 
                case FocusNavigationDirection.Up :
                    return sourceRect.Bottom - targetRect.Bottom; 
 
                case FocusNavigationDirection.Down :
                    return targetRect.Top - sourceRect.Top; 

                default :
                    throw new System.ComponentModel.InvalidEnumArgumentException("direction", (int)direction, typeof(FocusNavigationDirection));
            } 
        }
 
        // Example when moving down: 
        // distance between sourceRect.TopLeft (or Y=vertical baseline)
        // and targetRect.TopLeft 
        private double GetDistance(Rect sourceRect, Rect targetRect, FocusNavigationDirection direction)
        {
            Point startPoint;
            Point endPoint; 
            switch (direction)
            { 
                case FocusNavigationDirection.Right : 
                    startPoint = sourceRect.TopLeft;
                    if (_horizontalBaseline != BASELINE_DEFAULT) 
                        startPoint.Y = _horizontalBaseline;
                    endPoint = targetRect.TopLeft;
                    break;
 
                case FocusNavigationDirection.Left :
                    startPoint = sourceRect.TopRight; 
                    if (_horizontalBaseline != BASELINE_DEFAULT) 
                        startPoint.Y = _horizontalBaseline;
                    endPoint = targetRect.TopRight; 
                    break;

                case FocusNavigationDirection.Up :
                    startPoint = sourceRect.BottomLeft; 
                    if (_verticalBaseline != BASELINE_DEFAULT)
                        startPoint.X = _verticalBaseline; 
                    endPoint = targetRect.BottomLeft; 
                    break;
 
                case FocusNavigationDirection.Down :
                    startPoint = sourceRect.TopLeft;
                    if (_verticalBaseline != BASELINE_DEFAULT)
                        startPoint.X = _verticalBaseline; 
                    endPoint = targetRect.TopLeft;
                    break; 
 
                default :
                    throw new System.ComponentModel.InvalidEnumArgumentException("direction", (int)direction, typeof(FocusNavigationDirection)); 
            }
            return GetDistance(startPoint, endPoint);
        }
 
        // Example when moving down:
        // true if the top of the toRect is below the bottom of fromRect 
        private bool IsInDirection(Rect fromRect, Rect toRect, FocusNavigationDirection direction) 
        {
            switch (direction) 
            {
                case FocusNavigationDirection.Right:
                    return DoubleUtil.LessThanOrClose(fromRect.Right, toRect.Left);
                case FocusNavigationDirection.Left: 
                    return DoubleUtil.GreaterThanOrClose(fromRect.Left, toRect.Right);
                case FocusNavigationDirection.Up : 
                    return DoubleUtil.GreaterThanOrClose(fromRect.Top, toRect.Bottom); 
                case FocusNavigationDirection.Down :
                    return DoubleUtil.LessThanOrClose(fromRect.Bottom, toRect.Top); 
                default:
                    throw new System.ComponentModel.InvalidEnumArgumentException("direction", (int)direction, typeof(FocusNavigationDirection));
            }
        } 

        // The element is focus scope if IsFocusScope is true or it is the visual tree root 
        private bool IsFocusScope(DependencyObject e) 
        {
            return FocusManager.GetIsFocusScope(e) || GetParent(e) == null; 
        }

        private bool IsAncestorOf(DependencyObject sourceElement, DependencyObject targetElement)
        { 
            Visual sourceVisual = sourceElement as Visual;
            Visual targetVisual = targetElement as Visual; 
            if (sourceVisual == null || targetVisual == null) 
                return false;
 
            return sourceVisual.IsAncestorOf(targetVisual);
        }

        // Example: When moving down: 
        // Range is the sourceRect width extended to the vertical baseline
        // targetRect.Top > sourceRect.Top (target is below the source) 
        // targetRect.Right > sourceRect.Left || targetRect.Left < sourceRect.Right 
        private bool IsInRange(DependencyObject sourceElement, DependencyObject targetElement, Rect sourceRect, Rect targetRect, FocusNavigationDirection direction, double startRange, double endRange)
        { 
            switch (direction)
            {
                case FocusNavigationDirection.Right :
                case FocusNavigationDirection.Left : 
                    if (_horizontalBaseline != BASELINE_DEFAULT)
                    { 
                        startRange = Math.Min(startRange, _horizontalBaseline); 
                        endRange = Math.Max(endRange, _horizontalBaseline);
                    } 

                    if (DoubleUtil.GreaterThan(targetRect.Bottom, startRange) && DoubleUtil.LessThan(targetRect.Top, endRange))
                    {
                        // If there is no sourceElement - checking the range is enough 
                        if (sourceElement == null)
                            return true; 
 
                        if (direction == FocusNavigationDirection.Right)
                            return DoubleUtil.GreaterThan(targetRect.Left, sourceRect.Left) || (DoubleUtil.AreClose(targetRect.Left, sourceRect.Left) && IsAncestorOf(sourceElement, targetElement)); 
                        else
                            return DoubleUtil.LessThan(targetRect.Right, sourceRect.Right) || (DoubleUtil.AreClose(targetRect.Right, sourceRect.Right) && IsAncestorOf(sourceElement, targetElement));

                    } 
                    break;
 
                case FocusNavigationDirection.Up : 
                case FocusNavigationDirection.Down :
                    if (_verticalBaseline != BASELINE_DEFAULT) 
                    {
                        startRange = Math.Min(startRange, _verticalBaseline);
                        endRange = Math.Max(endRange, _verticalBaseline);
                    } 

                    if (DoubleUtil.GreaterThan(targetRect.Right, startRange) && DoubleUtil.LessThan(targetRect.Left, endRange)) 
                    { 
                        // If there is no sourceElement - checking the range is enough
                        if (sourceElement == null) 
                            return true;

                        if (direction == FocusNavigationDirection.Down)
                            return DoubleUtil.GreaterThan(targetRect.Top, sourceRect.Top) || (DoubleUtil.AreClose (targetRect.Top, sourceRect.Top) && IsAncestorOf(sourceElement, targetElement)); 
                        else
                            return DoubleUtil.LessThan(targetRect.Bottom, sourceRect.Bottom) || (DoubleUtil.AreClose(targetRect.Bottom, sourceRect.Bottom) && IsAncestorOf(sourceElement, targetElement)); 
                    } 
                    break;
 
                default :
                    throw new System.ComponentModel.InvalidEnumArgumentException("direction", (int)direction, typeof(FocusNavigationDirection));
            }
 
            return false;
        } 
 
        private DependencyObject GetNextInDirection(DependencyObject sourceElement, FocusNavigationDirection direction)
        { 
            _containerHashtable.Clear();
            DependencyObject targetElement = MoveNext(sourceElement, null, direction, BASELINE_DEFAULT, BASELINE_DEFAULT);

            if (targetElement != null) 
            {
                UIElement sourceUIElement = sourceElement as UIElement; 
                if (sourceUIElement != null) 
                    sourceUIElement.RemoveHandler(Keyboard.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(_LostFocus));
                else 
                {
                    ContentElement sourceContentElement = sourceElement as ContentElement;
                    if (sourceContentElement != null)
                        sourceContentElement.RemoveHandler(Keyboard.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(_LostFocus)); 
                }
 
                UIElement targetUIElement = targetElement as UIElement; 
                if (targetUIElement == null)
                    targetUIElement = GetParentUIElementFromContentElement(targetElement as ContentElement); 
                else
                {
                    ContentElement targetContentElement = targetElement as ContentElement;
                    if (targetContentElement != null) 
                    {
                        // When Focus is changed we need to reset the base line 
                        targetContentElement.AddHandler(Keyboard.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(_LostFocus), true); 
                    }
                } 

                if (targetUIElement != null)
                {
                    // When layout is changed we need to reset the base line 
                    // Set up a layout invalidation listener.
                    targetUIElement.LayoutUpdated += new EventHandler(OnLayoutUpdated); 
 
                    // When Focus is changed we need to reset the base line
                    if (targetElement == targetUIElement) 
                        targetUIElement.AddHandler(Keyboard.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(_LostFocus), true);
                }

            } 

            _containerHashtable.Clear(); 
            return targetElement; 
        }
 
        // LayoutUpdated handler.
        private void OnLayoutUpdated(object sender, EventArgs e)
        {
            UIElement uiElement = sender as UIElement; 
            // Disconnect the layout listener.
            if (uiElement != null) 
            { 
                uiElement.LayoutUpdated -= new EventHandler(OnLayoutUpdated);
            } 

            _verticalBaseline = BASELINE_DEFAULT;
            _horizontalBaseline = BASELINE_DEFAULT;
        } 

        private void _LostFocus(object sender, KeyboardFocusChangedEventArgs e) 
        { 
            _verticalBaseline = BASELINE_DEFAULT;
            _horizontalBaseline = BASELINE_DEFAULT; 

            if (sender is UIElement)
                ((UIElement)sender).RemoveHandler(Keyboard.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(_LostFocus));
            else if (sender is ContentElement) 
                ((ContentElement)sender).RemoveHandler(Keyboard.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(_LostFocus));
        } 
 
        private bool IsEndlessLoop(DependencyObject element, DependencyObject container)
        { 
            object elementObject = element != null ? (object)element : _fakeNull;

            // If entry exists then we have endless loop
            Hashtable elementTable = _containerHashtable[container] as Hashtable; 
            if (elementTable != null)
            { 
                if (elementTable[elementObject] != null) 
                    return true;
            } 
            else
            {
                // Adding the entry to the collection
                elementTable = new Hashtable(10); 
                _containerHashtable[container] = elementTable;
            } 
 
            elementTable[elementObject] = BooleanBoxes.TrueBox;
            return false; 
        }

        private void ResetBaseLines(double value, bool horizontalDirection)
        { 
            if (horizontalDirection)
            { 
                _verticalBaseline = BASELINE_DEFAULT; 
                if (_horizontalBaseline == BASELINE_DEFAULT)
                    _horizontalBaseline = value; 
            }
            else // vertical direction
            {
                _horizontalBaseline = BASELINE_DEFAULT; 
                if (_verticalBaseline == BASELINE_DEFAULT)
                    _verticalBaseline = value; 
            } 
        }
        private DependencyObject FindNextInDirection(DependencyObject sourceElement, Rect sourceRect, DependencyObject container, FocusNavigationDirection direction, double startRange, double endRange) 
        {
            DependencyObject result = null;
            Rect resultRect = Rect.Empty;
            double resultScore = 0d; 
            bool searchInsideContainer = sourceElement == null;
            DependencyObject currElement = container; 
            while ((currElement = GetNextInTree(currElement, container)) != null) 
            {
                if (currElement != sourceElement && IsTabStopOrGroup(currElement)) 
                {
                    Rect currentRect = GetRectangle(currElement);
                    bool isInDirection = IsInDirection(sourceRect, currentRect, direction);
                    bool isInRange = IsInRange(sourceElement, currElement, sourceRect, currentRect, direction, startRange, endRange); 
                    if (searchInsideContainer || isInDirection || isInRange)
                    { 
                        double score = isInRange ? GetPerpDistance(sourceRect, currentRect, direction) : GetDistance(sourceRect, currentRect, direction); 

                        // Keep the first element in the result 
                        if (result == null)
                        {
                            result = currElement;
                            resultRect = currentRect; 
                            resultScore = score;
                        } 
                        else if (DoubleUtil.LessThan(score, resultScore) || (DoubleUtil.AreClose(score, resultScore) && GetDistance(sourceRect, resultRect, direction) > GetDistance(sourceRect, currentRect, direction))) 
                        {
                            result = currElement; 
                            resultRect = currentRect;
                            resultScore = score;
                        }
                    } 
                }
            } 
 
            return result;
        } 

        private DependencyObject MoveNext(DependencyObject sourceElement, DependencyObject container, FocusNavigationDirection direction, double startRange, double endRange)
        {
            Debug.Assert(!(sourceElement == null && container == null), "Both sourceElement and container cannot be null"); 

            if (container == null) 
            { 
                container = GetGroupParent(sourceElement);
                Debug.Assert(container != null, "container cannot be null"); 
            }

            // If we get to the tree root, return null
            if (container == sourceElement) 
                return null;
 
            if (IsEndlessLoop(sourceElement, container)) 
                return null;
 
            KeyboardNavigationMode mode = GetKeyNavigationMode(container);
            bool searchInsideContainer = (sourceElement == null);

            // Don't navigate inside None containers 
            if (mode == KeyboardNavigationMode.None && searchInsideContainer)
                return null; 
 
            Rect sourceRect = GetRectangle(searchInsideContainer ? container : sourceElement );
            bool horizontalDirection = direction == FocusNavigationDirection.Right || direction == FocusNavigationDirection.Left; 

            // Reset the baseline when we change the direction
            ResetBaseLines(horizontalDirection ? sourceRect.Top : sourceRect.Left, horizontalDirection);
 
            // If range is not set - use source rect
            if (startRange == BASELINE_DEFAULT || endRange == BASELINE_DEFAULT) 
            { 
                startRange = horizontalDirection ? sourceRect.Top : sourceRect.Left;
                endRange = horizontalDirection ? sourceRect.Bottom : sourceRect.Right; 
            }

            // Navigate outside the container
            if (mode == KeyboardNavigationMode.Once && !searchInsideContainer) 
                return MoveNext(container, null, direction, startRange, endRange);
 
            DependencyObject result = FindNextInDirection(sourceElement, sourceRect, container, direction, startRange, endRange); 

            // If there is no next element in current container 
            if (result == null)
            {
                switch (mode)
                { 
                    case KeyboardNavigationMode.Cycle:
                        return MoveNext(null, container, direction, startRange, endRange); 
 
                    case KeyboardNavigationMode.Contained:
                        return null; 

                    default: // Continue, Once, None, Local - search outside the container
                        return MoveNext(container, null, direction, startRange, endRange);
                } 
            }
 
            // If the element is focusable and IsTabStop is true 
            if (IsTabStop(result))
                return result; 

            // Using ActiveElement if set
            DependencyObject activeElement = GetActiveElementChain(result);
            if (activeElement != null) 
                return activeElement;
 
            // Try to find focus inside the element 
            // result is not TabStop, which means it is a group
            DependencyObject insideElement = MoveNext(null, result, direction, startRange, endRange); 
            if (insideElement != null)
                return insideElement;

            return MoveNext(result, null, direction, startRange, endRange); 
        }
 
        private DependencyObject GetActiveElementChain(DependencyObject element) 
        {
            DependencyObject validActiveElement = null; 
            DependencyObject activeElement = element;
            while ((activeElement = GetActiveElement(activeElement)) != null)
            {
                if (IsTabStop(activeElement)) 
                    validActiveElement = activeElement;
            } 
 
            return validActiveElement;
        } 

        #endregion Directional Navigation

        #region Global tracking for entering MenuMode 

        // ISSUE: how do we deal with deactivate? 
 
        /////////////////////////////////////////////////////////////////////
        /// 
        /// Critical: accesses e.StagingItem.Input
        ///
        [SecurityCritical]
        private void ProcessForMenuMode(InputEventArgs inputEventArgs) 
        {
            // When ALT or F10 key up happens we should fire the EnterMenuMode event. 
            // We should not fire if: 
            // * there were any handled input events in between the key down and corresponding key up.
            // * another unmatched keydown or keyup happened 
            // * an unhandled mouse down/up happens

            if (inputEventArgs.RoutedEvent == Keyboard.LostKeyboardFocusEvent)
            { 
                KeyboardFocusChangedEventArgs args = inputEventArgs as KeyboardFocusChangedEventArgs;
                if (((args != null) && (args.NewFocus == null)) || inputEventArgs.Handled) 
                { 
                    // Focus went to null, stop tracking the last key down
                    _lastKeyPressed = Key.None; 
                }
            }
            // If a key is pressed down, remember it until the corresponding
            // key up.  Ignore repeated keydowns. 
            else if (inputEventArgs.RoutedEvent == Keyboard.KeyDownEvent)
            { 
                if (inputEventArgs.Handled) 
                    _lastKeyPressed = Key.None;
                else 
                {
                    KeyEventArgs keyEventArgs = inputEventArgs as KeyEventArgs;

                    if (!keyEventArgs.IsRepeat) 
                    {
                        if (_lastKeyPressed == Key.None) 
                        { 
                            if ((Keyboard.Modifiers & (ModifierKeys.Control | ModifierKeys.Shift | ModifierKeys.Windows)) == ModifierKeys.None)
                            { 
                                _lastKeyPressed = GetRealKey(keyEventArgs);
                            }
                        }
                        else 
                        {
                            // Another key was pressed down in between the one that we're tracking, so reset. 
                            _lastKeyPressed = Key.None; 
                        }
 
                        // Clear this bit, Win32 will see message and clear QF_FMENUSTATUS.
                        _win32MenuModeWorkAround = false;
                    }
                } 
            }
            // If a key up is received and matches the last key down 
            // and is a key that would cause us to enter menumode, 
            // raise the (internal) EnterMenuMode event.
            else if (inputEventArgs.RoutedEvent == Keyboard.KeyUpEvent) 
            {
                if (!inputEventArgs.Handled)
                {
                    KeyEventArgs keyEventArgs = inputEventArgs as KeyEventArgs; 
                    Key realKey = GetRealKey(keyEventArgs);
 
                    if (realKey == _lastKeyPressed && IsMenuKey(realKey)) 
                    {
                        EnableKeyboardCues(keyEventArgs.Source as DependencyObject, true); 
                        keyEventArgs.Handled = OnEnterMenuMode(keyEventArgs.Source);
                    }

                    if (_win32MenuModeWorkAround) 
                    {
                        if (IsMenuKey(realKey)) 
                        { 
                            _win32MenuModeWorkAround = false;
 
                            // Mark the event args as handled so that Win32 never
                            // sees this key up and doesn't enter menu-mode.
                            keyEventArgs.Handled = true;
                        } 
                    }
                    // If someone was listening for MenuMode and did something, 
                    // we need to make sure we don't let Win32 enter menu mode. 
                    else if (keyEventArgs.Handled)
                    { 
                        // Set this bit to true, this means that we will handle
                        // the next ALT-up if no one else does.
                        _win32MenuModeWorkAround = true;
                    } 
                }
                // No matter what we should reset and not track the last key anymore. 
                _lastKeyPressed = Key.None; 
            }
            // The following input events act to "cancel" the EnterMenuMode event 
            else if (inputEventArgs.RoutedEvent == Mouse.MouseDownEvent
                  || inputEventArgs.RoutedEvent == Mouse.MouseUpEvent)
            {
                _lastKeyPressed = Key.None; 

                // Win32 will see this message and will set QF_FMENUSTATUS to false. 
                _win32MenuModeWorkAround = false; 
            }
        } 

        private bool IsMenuKey(Key key)
        {
            return (key == Key.LeftAlt || key == Key.RightAlt || key == Key.F10); 
        }
 
        private Key GetRealKey(KeyEventArgs e) 
        {
            return (e.Key == Key.System) ? e.SystemKey : e.Key; 
        }

        /// 
        ///   SecurityCritical:This code gets  PresentationSource and passes it to event handlers 
        ///   TreatAsSafe: This code is safe inspite of passing the object because of 3 reasons
        ///                        1. We have a demand on adding the event handler so that no one external can attach 
        ///                        2. The one event handler that we are aware of does not expose the object 
        ///                        3. This code in the worst case will cause your app to go to menu mode
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private bool OnEnterMenuMode(object eventSource)
        {
            if (_weakEnterMenuModeHandlers == null) 
                return false;
 
            lock (_weakEnterMenuModeHandlers) 
            {
                if (_weakEnterMenuModeHandlers.Count == 0) 
                {
                    return false;
                }
 
                // Bug 940610: no way to get PresentationSource of event in PostProcessInput
                // WORKAROUND: For now I will try to get the source of the event with 
                //             PresentationSource.FromVisual.  If that fails, try to get the 
                //             source of the active window.
                PresentationSource source = null; 

                if (eventSource != null)
                {
                    Visual eventSourceVisual = eventSource as Visual; 
                    source = (eventSourceVisual != null) ? PresentationSource.CriticalFromVisual(eventSourceVisual) : null;
                } 
                else 
                {
                    // If Keyboard.FocusedElement is null we'll have to fall back here. 
                    IntPtr activeWindow = MS.Win32.UnsafeNativeMethods.GetActiveWindow();

                    if (activeWindow != IntPtr.Zero)
                    { 
                        source = HwndSource.CriticalFromHwnd(activeWindow);
                    } 
                } 

                // Can't fire the event if the event didn't happen in any source 
                if (source == null)
                {
                    return false;
                } 

                EventArgs e = EventArgs.Empty; 
                bool handled = false; 

                for (int i = 0; i < _weakEnterMenuModeHandlers.Count; i++) 
                {
                    EnterMenuModeEventHandler currentHandler = _weakEnterMenuModeHandlers[i].Target as EnterMenuModeEventHandler;

                    if (currentHandler != null) 
                    {
                        if (currentHandler(source, e)) 
                        { 
                            handled = true;
                            break; 
                        }
                    }
                    else
                    { 
                        _weakEnterMenuModeHandlers.RemoveAt(i);
                        i--; 
                    } 
                }
 
                return handled;
            }
        }
 
        /// 
        ///     Called when ALT or F10 is pressed anywhere in the global scope 
        ///  
        /// 
        ///     Critical: This code causes the handler attached to get an object of type presentationsource 
        ///                  The add is critical, the remove is ok
        ///     TreatAsSafe: There is a demand on this
        /// 
        internal event EnterMenuModeEventHandler EnterMenuMode 
        {
            [SecurityCritical,SecurityTreatAsSafe] 
            add 
            {
                SecurityHelper.DemandUIWindowPermission(); 

                if (_weakEnterMenuModeHandlers == null)
                    _weakEnterMenuModeHandlers = new List(1);
 
                lock (_weakEnterMenuModeHandlers)
                { 
                    // Cleanup the list in case some of the weakEnterMenuModeHandlers is disposed 
                    for (int i = 0; i < _weakEnterMenuModeHandlers.Count; i++)
                    { 
                        if (!(_weakEnterMenuModeHandlers[i].Target is EnterMenuModeEventHandler))
                        {
                            _weakEnterMenuModeHandlers.RemoveAt(i);
                            i--; 
                        }
                    } 
                    _weakEnterMenuModeHandlers.Add(new WeakReference(value)); 
                }
            } 
            remove
            {
                if (_weakEnterMenuModeHandlers != null)
                { 
                    lock (_weakEnterMenuModeHandlers)
                    { 
                        for (int i = 0; i < _weakEnterMenuModeHandlers.Count; i++) 
                        {
                            EnterMenuModeEventHandler current = _weakEnterMenuModeHandlers[i].Target as EnterMenuModeEventHandler; 

                            if (current == null || current == value)
                            {
                                _weakEnterMenuModeHandlers.RemoveAt(i); 
                                i--;
                            } 
                        } 
                    }
                } 
            }
        }

        internal delegate bool EnterMenuModeEventHandler(object sender, EventArgs e); 

        // Used to track what the last key was pressed so that 
        // we can fire the EnterMenuMode event. 
        // Will be reset to Key.None when an unmatched KeyUp or other input event happens
        private Key _lastKeyPressed = Key.None; 

        // List of WeakReferences to delegates to be invoked when EnterMenuMode happens
        private List _weakEnterMenuModeHandlers;
 
        // Fix for bug 936302: (JevanSa)
        //     The DefaultWindowProcWorker (windows/core/ntuser/kernel/dwp.c) 
        //     listens for ALT down followed by ALT up with nothing in between. 
        //     When ALT goes down they set QF_FMENUSTATUS.  When ALT up happens,
        //     if QF_FMENUSTATUS is still set, they open the system menu (or 
        //     menu for the window if there is one).  If any keystrokes happen
        //     in between, they clear QF_FMENUSTATUS.
        //
        //     Consider the following sequence: 
        //       1) KeyDown(Alt) - neither Win32 nor Avalon respond
        //       2) KeyUp(Alt) - Avalon handles the event, Win32 is skipped 
        //       3) KeyDown(Alt) - Avalon handles the event, Win32 is skipped 
        //       4) KeyUp(Alt) - Avalon does not respond, Win32 handles the message
        //                       (and enters "Invisible" MenuMode) 
        //
        //     Here, from the point of view of the DWP, there was just ALT down
        //     followed by ALT up.  We must fool the DWP somehow so that they
        //     clear clear the QF_FMENUSTATUS bit before #4. 
        //
        //     Currently the best way DwayneN and I have come up with is to 
        //     mark the event has handled in case #4 so that the DWP 
        //     never sees the ALT up in #4.  We set this bit when #2 happens.
        //     If we see an unhandled ALT-up and this bit is set, we mark the 
        //     event as handled.  If we see any unhandled key down or mouse up/down
        //     we can clear this bit.
        private bool _win32MenuModeWorkAround;
 
        #endregion
 
        #region UIState 

        ///  
        ///     Critical: accesses the RawUIStateInputReport
        /// 
        [SecurityCritical]
        private void ProcessForUIState(InputEventArgs inputEventArgs) 
        {
            PresentationSource source; 
            RawUIStateInputReport report = ExtractRawUIStateInputReport(inputEventArgs, InputManager.InputReportEvent); 

            if (report != null && (source = report.InputSource) != null) 
            {
                // handle accelerator cue display
                if ((report.Targets & RawUIStateTargets.HideAccelerators) != 0)
                { 
                    Visual root = source.RootVisual;
                    bool enable = (report.Action == RawUIStateActions.Clear); 
 
                    EnableKeyboardCues(root, enable);
                } 
            }
        }

        ///  
        ///     Critical: accesses the RawUIStateInputReport
        ///  
        [SecurityCritical] 
        private RawUIStateInputReport ExtractRawUIStateInputReport(InputEventArgs e, RoutedEvent Event)
        { 
            RawUIStateInputReport uiStateInputReport = null;
            InputReportEventArgs input = e as InputReportEventArgs;

            if (input != null) 
            {
                if (input.Report.Type == InputType.Keyboard && input.RoutedEvent == Event) 
                { 
                    uiStateInputReport = input.Report as RawUIStateInputReport;
                } 
            }

            return uiStateInputReport;
        } 

        #endregion UIState 
 
        #region FocusEnterMainFocusScope weak event
 
        // The event is raised when KeyboardFocus enters the main focus scope (visual tree root)
        // Selector and TreeView listen for this event to update their ActiveSelection property
        internal event EventHandler FocusEnterMainFocusScope
        { 
            add
            { 
                lock (_weakFocusEnterMainFocusScopeHandlers) 
                {
                    _weakFocusEnterMainFocusScopeHandlers.Add(new WeakReference(value)); 
                }
            }
            remove
            { 
                lock (_weakFocusEnterMainFocusScopeHandlers)
                { 
                    for (int i = 0; i < _weakFocusEnterMainFocusScopeHandlers.Count; i++) 
                    {
                        object handler = _weakFocusEnterMainFocusScopeHandlers[i].Target; 
                        if (handler == null || (EventHandler)handler == value)
                        {
                            _weakFocusEnterMainFocusScopeHandlers.RemoveAt(i);
                            i--; 
                        }
                    } 
                } 
            }
        } 

        private void NotifyFocusEnterMainFocusScope(object sender, EventArgs e)
        {
            if (_weakFocusEnterMainFocusScopeHandlers != null) 
            {
                for (int i = 0; i < _weakFocusEnterMainFocusScopeHandlers.Count; i++) 
                { 
                    EventHandler handler = _weakFocusEnterMainFocusScopeHandlers[i].Target as EventHandler;
                    if (handler != null) 
                    {
                        handler(sender, e);
                    }
                    else 
                    {
                        _weakFocusEnterMainFocusScopeHandlers.RemoveAt(i); 
                        i--; 
                    }
                } 
            }
        }

        private List _weakFocusEnterMainFocusScopeHandlers = new List(1); 
        #endregion
 
        #region Data 

        private const double BASELINE_DEFAULT = Double.MinValue; 
        private double _verticalBaseline = BASELINE_DEFAULT;
        private double _horizontalBaseline = BASELINE_DEFAULT;
        private DependencyProperty _navigationProperty = null;
        private Hashtable _containerHashtable = new Hashtable(10); 
        private static object _fakeNull = new object();
 
        #endregion Data 
    }
} 



 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System; 
using System.Collections; 
using System.Collections.Generic;
using System.Collections.ObjectModel; 
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Threading;
using System.Threading; 
using System.Windows;
using System.Windows.Documents; 
using System.Windows.Interop; 
using System.Windows.Controls;
using System.Windows.Media; 
using System.Windows.Media.Media3D;
using System.Security;
using System.Security.Permissions;
using MS.Utility; 
using MS.Internal.Controls;
using MS.Internal; 
using MS.Internal.PresentationFramework; 
using MS.Internal.KnownBoxes;
using Microsoft.Win32; 

namespace System.Windows.Input
{
    #region public enum types 
    /// 
    /// These options specify how the container will move the focus when tab and directional navigation occurs 
    ///  
    public enum KeyboardNavigationMode
    { 
        /// 
        /// The container does not handle the keyboard navigation;
        /// each element receives keyboard focus as long as it is a key navigation stop.
        ///  
        Continue,
 
        ///  
        /// The container and all of its child elements as a whole only receive focus once.
        /// Either the first tree child or the ActiveElement receive focus 
        /// 
        Once,

        ///  
        /// Depending on the direction of the navigation,
        /// the focus returns to the first or the last item when the end or 
        /// the beginning of the container is reached, respectively. 
        /// 
        Cycle, 

        /// 
        /// No keyboard navigation is allowed inside this container
        ///  
        None,
 
        ///  
        /// Like cycle but does not move past the beginning or end of the container.
        ///  
        Contained,

        /// 
        /// TabIndexes are considered on local subtree only inside this container 
        /// 
        Local, 
 
        // NOTE: if you add or remove any values in this enum, be sure to update KeyboardNavigation.IsValidKeyNavigationMode()
    } 
    #endregion public enum types

    ///
    /// KeyboardNavigation class provide methods for logical (Tab) and directional (arrow) navigation between focusable controls 
    ///
    public sealed class KeyboardNavigation 
    { 
        #region Constructors
 
        ///
        ///     Critical - this function elevates via a call to InputManager.Current
        ///     TreatAsSafe: This code simply attaches a call back which is private
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        internal KeyboardNavigation() 
        { 
            InputManager inputManager = InputManager.Current;
 
            inputManager.PostProcessInput += new ProcessInputEventHandler(PostProcessInput);
            inputManager.TranslateAccelerator += new KeyEventHandler(TranslateAccelerator);
        }
 
        #endregion Constructors
 
        #region public API 

        #region Properties 

        private static readonly DependencyProperty TabOnceActiveElementProperty
            = DependencyProperty.RegisterAttached("TabOnceActiveElement", typeof(WeakReference), typeof(KeyboardNavigation));
 
        internal static DependencyObject GetTabOnceActiveElement(DependencyObject d)
        { 
            WeakReference weakRef = (WeakReference)d.GetValue(TabOnceActiveElementProperty); 
            if (weakRef != null && weakRef.IsAlive)
            { 
                DependencyObject activeElement = weakRef.Target as DependencyObject;
                // Verify if the element is still in the same visual tree
                if (GetVisualRoot(activeElement) == GetVisualRoot(d))
                    return activeElement; 
                else
                    d.SetValue(TabOnceActiveElementProperty, null); 
            } 
            return null;
        } 

        internal static void SetTabOnceActiveElement(DependencyObject d, DependencyObject value)
        {
            d.SetValue(TabOnceActiveElementProperty, new WeakReference(value)); 
        }
 
        internal static readonly DependencyProperty ControlTabOnceActiveElementProperty 
            = DependencyProperty.RegisterAttached("ControlTabOnceActiveElement", typeof(WeakReference), typeof(KeyboardNavigation));
 
        private static DependencyObject GetControlTabOnceActiveElement(DependencyObject d)
        {
            WeakReference weakRef = (WeakReference)d.GetValue(ControlTabOnceActiveElementProperty);
            if (weakRef != null && weakRef.IsAlive) 
            {
                DependencyObject activeElement = weakRef.Target as DependencyObject; 
                // Verify if the element is still in the same visual tree 
                if (GetVisualRoot(activeElement) == GetVisualRoot(d))
                    return activeElement; 
                else
                    d.SetValue(ControlTabOnceActiveElementProperty, null);
            }
            return null; 
        }
 
        private static void SetControlTabOnceActiveElement(DependencyObject d, DependencyObject value) 
        {
            d.SetValue(ControlTabOnceActiveElementProperty, new WeakReference(value)); 
        }

        private DependencyObject GetActiveElement(DependencyObject d)
        { 
            return _navigationProperty == ControlTabNavigationProperty ? GetControlTabOnceActiveElement(d) : GetTabOnceActiveElement(d);
        } 
 
        private void SetActiveElement(DependencyObject d, DependencyObject value)
        { 
            if (_navigationProperty == TabNavigationProperty)
                SetTabOnceActiveElement(d, value);
            else
                SetControlTabOnceActiveElement(d, value); 
        }
 
        ///  
        ///     Critical: This code retrieves PresentationSource which is a protected resource
        ///     TreatAsSafe: It returns rootvisual which is ok and it does not expose the PresentationSource 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal static Visual GetVisualRoot(DependencyObject d)
        { 
            if (d is Visual || d is Visual3D)
            { 
                PresentationSource source = PresentationSource.CriticalFromVisual(d); 

                if (source != null) 
                    return source.RootVisual;
            }
            else
            { 
                FrameworkContentElement fce = d as FrameworkContentElement;
                if (fce != null) 
                    return GetVisualRoot(fce.Parent); 
            }
 
            return null;
        }

        // This internal property is used by GetRectagle method to deflate the bounding box of the element 
        // If we expose this in the future - make sure it works with ContentElements too
        internal static readonly DependencyProperty DirectionalNavigationMarginProperty = 
                DependencyProperty.RegisterAttached("DirectionalNavigationMargin", 
                        typeof(Thickness),
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(new Thickness()));


        ///  
        ///     The DependencyProperty for the TabIndex property.
        ///     Flags:              Can be used in style rules 
        ///     Default Value:      Int32.MaxValue 
        /// 
        public static readonly DependencyProperty TabIndexProperty = 
                DependencyProperty.RegisterAttached(
                        "TabIndex",
                        typeof(int),
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(Int32.MaxValue));
 
        ///  
        ///     The DependencyProperty for the IsTabStop property.
        ///     Flags:              Can be used in style rules 
        ///     Default Value:      true
        /// 
        public static readonly DependencyProperty IsTabStopProperty =
                DependencyProperty.RegisterAttached( 
                        "IsTabStop",
                        typeof(bool), 
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(BooleanBoxes.TrueBox));
 

        /// 
        /// Controls the behavior of logical navigation on the children of the element this property is set on.
        /// TabNavigation is invoked with the TAB key. 
        /// 
        [CustomCategory("Accessibility")] 
        [Localizability(LocalizationCategory.NeverLocalize)] 
        [CommonDependencyProperty]
        public static readonly DependencyProperty TabNavigationProperty = 
                DependencyProperty.RegisterAttached(
                        "TabNavigation",
                        typeof(KeyboardNavigationMode),
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(KeyboardNavigationMode.Continue),
                        new ValidateValueCallback(IsValidKeyNavigationMode)); 
 
        /// 
        /// Controls the behavior of logical navigation on the children of the element this property is set on. 
        /// ControlTabNavigation is invoked with the CTRL+TAB key.
        /// 
        [CustomCategory("Accessibility")]
        [Localizability(LocalizationCategory.NeverLocalize)] 
        [CommonDependencyProperty]
        public static readonly DependencyProperty ControlTabNavigationProperty = 
                DependencyProperty.RegisterAttached( 
                        "ControlTabNavigation",
                        typeof(KeyboardNavigationMode), 
                        typeof(KeyboardNavigation),
                        new FrameworkPropertyMetadata(KeyboardNavigationMode.Continue),
                        new ValidateValueCallback(IsValidKeyNavigationMode));
 
        /// 
        /// Controls the behavior of directional navigation on the children of the element this property is set on. 
        /// Directional navigation is invoked with the arrow keys. 
        /// 
        [CustomCategory("Accessibility")] 
        [Localizability(LocalizationCategory.NeverLocalize)]
        [CommonDependencyProperty]
        public static readonly DependencyProperty DirectionalNavigationProperty =
                DependencyProperty.RegisterAttached( 
                        "DirectionalNavigation",
                        typeof(KeyboardNavigationMode), 
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(KeyboardNavigationMode.Continue),
                        new ValidateValueCallback(IsValidKeyNavigationMode)); 

        /// 
        /// Attached property set on elements registered with AccessKeyManager when AccessKeyCues should be shown.
        ///  
        internal static readonly DependencyProperty ShowKeyboardCuesProperty =
                DependencyProperty.RegisterAttached( 
                        "ShowKeyboardCues", 
                        typeof(bool),
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(
                                BooleanBoxes.FalseBox,
                                FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.OverridesInheritanceBehavior,
                                null /* No PropertyChangedCallback */, 
                                new CoerceValueCallback(CoerceShowKeyboardCues)));
 
        // Coercion for ShowKeyboardCuesProperty 
        private static object CoerceShowKeyboardCues(DependencyObject d, object value)
        { 
            // Always return true if the user has requested that KeyboardCues always
            // be on (accessibility setting).
            return SystemParameters.KeyboardCues ? BooleanBoxes.TrueBox : value;
        } 

        ///  
        /// Indicates if VK_Return character is accepted by a control 
        ///
        /// Default: false. 
        /// 
        public static readonly DependencyProperty AcceptsReturnProperty =
                DependencyProperty.RegisterAttached(
                        "AcceptsReturn", 
                        typeof(bool),
                        typeof(KeyboardNavigation), 
                        new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); 

        #region Workaround for Bug 908235 -- when focus change events go to PostProcessInput we don't need this glue. 
        internal event KeyboardFocusChangedEventHandler FocusChanged
        {
            add
            { 
                lock (_weakFocusChangedHandlers)
                { 
                    _weakFocusChangedHandlers.Add(new WeakReference(value)); 
                }
            } 
            remove
            {
                lock (_weakFocusChangedHandlers)
                { 
                    for (int i = 0; i < _weakFocusChangedHandlers.Count; i++)
                    { 
                        object handler = _weakFocusChangedHandlers[i].Target; 
                        if (handler == null || (KeyboardFocusChangedEventHandler)handler == value)
                        { 
                            _weakFocusChangedHandlers.RemoveAt(i);
                            i--;
                        }
                    } 
                }
            } 
        } 

        internal void NotifyFocusChanged(object sender, KeyboardFocusChangedEventArgs e) 
        {
            if (_weakFocusChangedHandlers != null)
            {
                for (int i = 0; i < _weakFocusChangedHandlers.Count; i++) 
                {
                    KeyboardFocusChangedEventHandler handler = _weakFocusChangedHandlers[i].Target as KeyboardFocusChangedEventHandler; 
                    if (handler != null) 
                    {
                        handler(sender, e); 
                    }
                    else
                    {
                        _weakFocusChangedHandlers.RemoveAt(i); 
                        i--;
                    } 
                } 
            }
        } 

        private List _weakFocusChangedHandlers = new List(1);
        #endregion
 
        #endregion Properties
 
        #region methods 

        ///  
        /// Writes the attached property TabIndex to the given element.
        /// 
        /// The element to which to write the attached property.
        /// The property value to set 
        /// 
        public static void SetTabIndex(DependencyObject element, int index) 
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            }
            element.SetValue(TabIndexProperty, index);
        } 

        ///  
        /// Reads the attached property TabIndex from the given element. 
        /// 
        /// The element from which to read the attached property. 
        /// The property's value.
        /// 
        [AttachedPropertyBrowsableForType(typeof(DependencyObject))]
        public static int GetTabIndex(DependencyObject element) 
        {
            if (element == null) 
            { 
                throw new ArgumentNullException("element");
            } 
            return GetTabIndexHelper(element);
        }

        ///  
        /// Writes the attached property IsTabStop to the given element.
        ///  
        /// The element to which to write the attached property. 
        /// The property value to set
        ///  
        public static void SetIsTabStop(DependencyObject element, bool isTabStop)
        {
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            } 
            element.SetValue(IsTabStopProperty, BooleanBoxes.Box(isTabStop)); 
        }
 
        /// 
        /// Reads the attached property IsTabStop from the given element.
        /// 
        /// The element from which to read the attached property. 
        /// The property's value.
        ///  
        [AttachedPropertyBrowsableForType(typeof(DependencyObject))] 
        public static bool GetIsTabStop(DependencyObject element)
        { 
            if (element == null)
            {
                throw new ArgumentNullException("element");
            } 
            return (bool)element.GetValue(IsTabStopProperty);
        } 
 
        /// 
        /// Writes the attached property TabNavigation to the given element. 
        /// 
        /// The element to which to write the attached property.
        /// The property value to set
        ///  
        public static void SetTabNavigation(DependencyObject element, KeyboardNavigationMode mode)
        { 
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            }
            element.SetValue(TabNavigationProperty, mode);
        }
 
        /// 
        /// Reads the attached property TabNavigation from the given element. 
        ///  
        /// The element from which to read the attached property.
        /// The property's value. 
        /// 
        [CustomCategory("Accessibility")]
        [AttachedPropertyBrowsableForType(typeof(DependencyObject))]
        public static KeyboardNavigationMode GetTabNavigation(DependencyObject element) 
        {
            if (element == null) 
            { 
                throw new ArgumentNullException("element");
            } 
            return (KeyboardNavigationMode)element.GetValue(TabNavigationProperty);
        }

        ///  
        /// Writes the attached property ControlTabNavigation to the given element.
        ///  
        /// The element to which to write the attached property. 
        /// The property value to set
        ///  
        public static void SetControlTabNavigation(DependencyObject element, KeyboardNavigationMode mode)
        {
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            } 
            element.SetValue(ControlTabNavigationProperty, mode); 
        }
 
        /// 
        /// Reads the attached property ControlTabNavigation from the given element.
        /// 
        /// The element from which to read the attached property. 
        /// The property's value.
        ///  
        [CustomCategory("Accessibility")] 
        [AttachedPropertyBrowsableForType(typeof(DependencyObject))]
        public static KeyboardNavigationMode GetControlTabNavigation(DependencyObject element) 
        {
            if (element == null)
            {
                throw new ArgumentNullException("element"); 
            }
            return (KeyboardNavigationMode)element.GetValue(ControlTabNavigationProperty); 
        } 

        ///  
        /// Writes the attached property DirectionalNavigation to the given element.
        /// 
        /// The element to which to write the attached property.
        /// The property value to set 
        /// 
        public static void SetDirectionalNavigation(DependencyObject element, KeyboardNavigationMode mode) 
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            }
            element.SetValue(DirectionalNavigationProperty, mode);
        } 

        ///  
        /// Reads the attached property DirectionalNavigation from the given element. 
        /// 
        /// The element from which to read the attached property. 
        /// The property's value.
        /// 
        [CustomCategory("Accessibility")]
        [AttachedPropertyBrowsableForType(typeof(DependencyObject))] 
        public static KeyboardNavigationMode GetDirectionalNavigation(DependencyObject element)
        { 
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            }
            return (KeyboardNavigationMode)element.GetValue(DirectionalNavigationProperty);
        }
 
        /// 
        /// Writes the attached property AcceptsReturn to the given element. 
        ///  
        /// The element to which to write the attached property.
        /// The property value to set 
        /// 
        public static void SetAcceptsReturn(DependencyObject element, bool enabled)
        {
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            } 
            element.SetValue(AcceptsReturnProperty, BooleanBoxes.Box(enabled));
        } 

        /// 
        /// Reads the attached property AcceptsReturn from the given element.
        ///  
        /// The element from which to read the attached property.
        /// The property's value. 
        ///  
        [AttachedPropertyBrowsableForType(typeof(DependencyObject))]
        public static bool GetAcceptsReturn(DependencyObject element) 
        {
            if (element == null)
            {
                throw new ArgumentNullException("element"); 
            }
            return (bool)element.GetValue(AcceptsReturnProperty); 
        } 

        private static bool IsValidKeyNavigationMode(object o) 
        {
            KeyboardNavigationMode value = (KeyboardNavigationMode)o;
            return value == KeyboardNavigationMode.Contained
                || value == KeyboardNavigationMode.Continue 
                || value == KeyboardNavigationMode.Cycle
                || value == KeyboardNavigationMode.None 
                || value == KeyboardNavigationMode.Once 
                || value == KeyboardNavigationMode.Local;
        } 

        #endregion methods

        #endregion public API 

        #region FocusVisualStyle API 
        // This class is used by AdornerLayer which adds it to its visual tree 
        // Once AdornerLayer and Adorner are UIElement we can remove this class and
        // apply FrameworkElement.FocusVisualStyle directly to AdornerLayer 
        // Note:- This class is sealed because it calls OnVisualChildrenChanged virtual in the
        //              constructor and it does not override it, but derived classes could.
        private sealed class FocusVisualAdorner: Adorner
        { 
            public FocusVisualAdorner(UIElement adornedElement, Style focusVisualStyle) : base(adornedElement)
            { 
                Debug.Assert(adornedElement != null, "adornedElement should not be null"); 
                Debug.Assert(focusVisualStyle != null, "focusVisual should not be null");
 
                Control control = new Control();
                control.Style = focusVisualStyle;
                _adorderChild = control;
                IsClipEnabled = true; 
                IsHitTestVisible = false;
                IsEnabled = false; 
                AddVisualChild(_adorderChild); 
            }
 
            public FocusVisualAdorner(ContentElement adornedElement, UIElement adornedElementParent, IContentHost contentHostParent, Style focusVisualStyle)
                : base(adornedElementParent)
            {
                Debug.Assert(adornedElement != null, "adornedElement should not be null"); 
                Debug.Assert(adornedElementParent != null, "adornedElementParent should not be null");
                Debug.Assert(contentHostParent != null, "contentHostParent should not be null"); 
                Debug.Assert(contentHostParent is Visual, "contentHostParent should be Visual"); 
                Debug.Assert(focusVisualStyle != null, "focusVisual should not be null");
 
                _contentHostParent = contentHostParent;
                _adornedContentElement = adornedElement;
                _focusVisualStyle = focusVisualStyle;
 
                Canvas canvas = new Canvas();
                _canvasChildren = canvas.Children; 
                _adorderChild = canvas; 
                AddVisualChild(_adorderChild);
 
                IsClipEnabled = true;
                IsHitTestVisible = false;
                IsEnabled = false;
            } 

            ///  
            /// Measure adorner. Default behavior is to size to match the adorned element. 
            /// 
            protected override Size MeasureOverride(Size constraint) 
            {
                Size desiredSize = new Size();

                // If the focus visual is adorning a content element, 
                // the child will be a canvas that doesn't need to be measured.
                if (_adornedContentElement == null) 
                { 
                    desiredSize = AdornedElement.RenderSize;
                    constraint = desiredSize; 
                }

                // Measure the child
                ((UIElement)GetVisualChild(0)).Measure(constraint); 

                return desiredSize; 
           } 

            ///  
            ///     Default control arrangement is to only arrange
            ///     the first visual child. No transforms will be applied.
            /// 
            protected override Size ArrangeOverride(Size size) 
            {
                Size finalSize = base.ArrangeOverride(size); 
 
                // In case we adorn ContentElement we have to update the rectangles
                if (_adornedContentElement != null) 
                {
                    if (_contentRects == null)
                    {
                        // Clear rects 
                        _canvasChildren.Clear();
                    } 
                    else 
                    {
                        IContentHost contentHost = ContentHost; 

                        if (!(contentHost is Visual) || !AdornedElement.IsAncestorOf((Visual)contentHost))
                        {
                            // Content elements is not in the tree, clear children and give up. 
                            _canvasChildren.Clear();
                            return new Size(); 
                        } 

                        Rect desiredRect = Rect.Empty; 

                        IEnumerator enumerator = _contentRects.GetEnumerator();

                        if (_canvasChildren.Count == _contentRects.Count) 
                        {
                            // Reuse the controls and update the controls position 
                            for (int i = 0; i < _canvasChildren.Count; i++) 
                            {
                                enumerator.MoveNext(); 
                                Rect rect = enumerator.Current;

                                rect = _hostToAdornedElement.TransformBounds(rect);
 
                                Control control = (Control)_canvasChildren[i];
                                control.Width = rect.Width; 
                                control.Height = rect.Height; 
                                Canvas.SetLeft(control, rect.X);
                                Canvas.SetTop(control, rect.Y); 
                            }
                            _adorderChild.InvalidateArrange();
                        }
                        else // Rebuild the visual tree to correspond to current bounding rectangles 
                        {
                            _canvasChildren.Clear(); 
                            while (enumerator.MoveNext()) 
                            {
                                Rect rect = enumerator.Current; 

                                rect = _hostToAdornedElement.TransformBounds(rect);

                                Control control = new Control(); 
                                control.Style = _focusVisualStyle;
                                control.Width = rect.Width; 
                                control.Height = rect.Height; 
                                Canvas.SetLeft(control, rect.X);
                                Canvas.SetTop(control, rect.Y); 
                                _canvasChildren.Add(control);
                            }
                        }
                    } 
                }
 
                ((UIElement)GetVisualChild(0)).Arrange(new Rect(new Point(), finalSize)); 

                return finalSize; 
            }

            /// 
            ///  Derived classes override this property to enable the Visual code to enumerate 
            ///  the Visual children. Derived classes need to return the number of children
            ///  from this method. 
            /// 
            ///    By default a Visual does not have any children.
            /// 
            ///  Remark:
            ///      During this virtual method the Visual tree must not be modified.
            /// 
            protected override int VisualChildrenCount 
            {
                get 
                { 
                    return 1; // _adorderChild created in ctor.
                } 
            }

            /// 
            ///   Derived class must implement to support Visual children. The method must return 
            ///    the child at the specified index. Index must be between 0 and GetVisualChildrenCount-1.
            /// 
            ///    By default a Visual does not have any children. 
            ///
            ///  Remark: 
            ///       During this virtual call it is not valid to modify the Visual tree.
            /// 
            protected override Visual GetVisualChild(int index)
            { 
                if (index == 0)
                { 
                    return _adorderChild; 
                }
                else 
                {
                    throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange));
                }
            } 

            private IContentHost ContentHost 
            { 
                get
                { 
                    // Re-query IContentHost if the old one was disposed
                    if (_adornedContentElement != null && (_contentHostParent==null || VisualTreeHelper.GetParent(_contentHostParent as Visual) == null))
                    {
                        _contentHostParent = MS.Internal.Documents.ContentHostHelper.FindContentHost(_adornedContentElement); 
                    }
 
                    return _contentHostParent; 
                }
            } 

            /// 
            /// Says if the Adorner needs update based on the
            /// previously cached size if the AdornedElement. 
            /// 
            internal override bool NeedsUpdate(Size oldSize) 
            { 
                if (_adornedContentElement != null)
                { 
                    ReadOnlyCollection oldRects = _contentRects;
                    _contentRects = null;

                    IContentHost contentHost = ContentHost; 
                    if (contentHost != null)
                    { 
                        _contentRects = contentHost.GetRectangles(_adornedContentElement); 
                    }
 
                    // The positions of the focus rects are dependent on the rects returned from
                    // host.GetRectangles and the transform from the host to the adorned element
                    GeneralTransform oldTransform = _hostToAdornedElement;
 
                    if (contentHost is Visual && AdornedElement.IsAncestorOf((Visual)contentHost))
                    { 
                        _hostToAdornedElement = ((Visual)contentHost).TransformToAncestor(AdornedElement); 
                    }
                    else 
                    {
                        _hostToAdornedElement = Transform.Identity;
                    }
 
                    // See if these are the same transform
                    if (oldTransform != _hostToAdornedElement) 
                    { 
                        // Allow two identical matrix transforms
                        if (!(oldTransform is MatrixTransform) || 
                            !(_hostToAdornedElement is MatrixTransform) ||
                            !Matrix.Equals(((MatrixTransform)oldTransform).Matrix, ((MatrixTransform)_hostToAdornedElement).Matrix))
                        {
                            // one is a general transform or the matrices are not equal, need to update 
                            return true;
                        } 
                    } 

                    if (_contentRects != null && oldRects != null && _contentRects.Count == oldRects.Count) 
                    {
                        for (int i=0; i _contentRects;
        }

        internal static UIElement GetParentUIElementFromContentElement(ContentElement ce) 
        {
            IContentHost ichParent = null; 
            return GetParentUIElementFromContentElement(ce, ref ichParent); 
        }
 
        private static UIElement GetParentUIElementFromContentElement(ContentElement ce, ref IContentHost ichParent)
        {
            if (ce == null)
                return null; 

            IContentHost ich = MS.Internal.Documents.ContentHostHelper.FindContentHost(ce); 
            if (ichParent == null) 
                ichParent = ich;
 
            DependencyObject parent =  ich as DependencyObject;
            if(parent != null)
            {
                // Case 1: UIElement 
                // return the element
                UIElement eParent = parent as UIElement; 
                if(eParent != null) 
                    return eParent;
 
                // Case 2: Visual
                // Walk up the visual tree until we find UIElement
                Visual visualParent = parent as Visual;
                while (visualParent != null) 
                {
                    visualParent = VisualTreeHelper.GetParent(visualParent) as Visual; 
                    UIElement uielement = visualParent as UIElement; 
                    if (uielement != null)
                        return uielement; 
                }

                // Case 3: ContentElement
                ContentElement ceParent = parent as ContentElement; 
                if(ceParent != null)
                    return GetParentUIElementFromContentElement(ceParent, ref ichParent); 
            } 

            return null; 
        }

        internal void HideFocusVisual()
        { 
            // Remove the existing focus visual
            if (_focusVisualAdornerCache != null) 
            { 
                AdornerLayer adornerlayer = VisualTreeHelper.GetParent(_focusVisualAdornerCache) as AdornerLayer;
                if (adornerlayer != null) 
                {
                    adornerlayer.Remove(_focusVisualAdornerCache);
                }
                _focusVisualAdornerCache = null; 
            }
        } 
        ///  
        ///   Critical: This code accesses link demanded input manager
        ///   TreatAsSafe: This code is ok to expose as it simply return boolean weather Keyboard is the last used device 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal static bool IsKeyboardMostRecentInputDevice()
        { 
            return InputManager.Current.MostRecentInputDevice is KeyboardDevice;
        } 
 
        internal static bool AlwaysShowFocusVisual
        { 
            get
            {
                return _alwaysShowFocusVisual;
            } 
            set
            { 
                _alwaysShowFocusVisual = value; 
            }
        } 
        private static bool _alwaysShowFocusVisual = SystemParameters.KeyboardCues;

        internal static void ShowFocusVisual()
        { 
            Current.ShowFocusVisual(Keyboard.FocusedElement as DependencyObject);
        } 
 
        private void ShowFocusVisual(DependencyObject element)
        { 
            // Always hide the existing focus visual
            HideFocusVisual();

            // Disable keyboard cues (accesskey underline) if keyboard device is not MostRecentInputDevice 
            if (!IsKeyboardMostRecentInputDevice())
            { 
                EnableKeyboardCues(element, false); 
            }
 
            // Show focus visual if system metric is true or keyboard is used last
            if (AlwaysShowFocusVisual || IsKeyboardMostRecentInputDevice())
            {
 
                FrameworkElement fe = element as FrameworkElement;
                if (fe != null) 
                { 
                    AdornerLayer adornerlayer = AdornerLayer.GetAdornerLayer(fe);
                    if (adornerlayer == null) 
                        return;

                    Style fvs = fe.FocusVisualStyle;
 
                    // WORKAROUND: (Bug 1016350) If FocusVisualStyle is the "default" value
                    // then we load the default FocusVisualStyle from ResourceDictionary. 
                    if (fvs == FrameworkElement.DefaultFocusVisualStyle) 
                    {
                        fvs = SystemResources.FindResourceInternal(SystemParameters.FocusVisualStyleKey) as Style; 
                    }

                    if (fvs != null)
                    { 
                        _focusVisualAdornerCache = new FocusVisualAdorner(fe, fvs);
                        adornerlayer.Add(_focusVisualAdornerCache); 
                    } 
                }
                else // If not FrameworkElement 
                {
                    FrameworkContentElement fce = element as FrameworkContentElement;
                    if (fce != null)
                    { 
                        IContentHost parentICH = null;
                        UIElement parentUIElement = GetParentUIElementFromContentElement(fce, ref parentICH); 
                        if (parentICH != null && parentUIElement != null) 
                        {
                            AdornerLayer adornerlayer = AdornerLayer.GetAdornerLayer(parentUIElement); 
                            if (adornerlayer != null)
                            {
                                Style fvs = fce.FocusVisualStyle;
 
                                // WORKAROUND: (Bug 1016350) If FocusVisualStyle is the "default" value
                                // then we load the default FocusVisualStyle from ResourceDictionary. 
                                if (fvs == FrameworkElement.DefaultFocusVisualStyle) 
                                {
                                    fvs = SystemResources.FindResourceInternal(SystemParameters.FocusVisualStyleKey) as Style; 
                                }

                                if (fvs != null)
                                { 
                                    _focusVisualAdornerCache = new FocusVisualAdorner(fce, parentUIElement, parentICH, fvs);
                                    adornerlayer.Add(_focusVisualAdornerCache); 
                                } 
                            }
                        } 
                    }
                }
            }
        } 

        private FocusVisualAdorner _focusVisualAdornerCache = null; 
 
        #endregion FocusVisualStyle API
 
        #region Navigate helpers

        internal static void UpdateFocusedElement(DependencyObject focusTarget)
        { 
            DependencyObject focusScope = FocusManager.GetFocusScope(focusTarget);
            if (focusScope != null && focusScope != focusTarget) 
            { 
                FocusManager.SetFocusedElement(focusScope, focusTarget as IInputElement);
 
                // Raise FocusEnterMainFocusScope event
                Visual visualRoot = GetVisualRoot(focusTarget);
                if (visualRoot != null && focusScope == visualRoot)
                { 
                    Current.NotifyFocusEnterMainFocusScope(visualRoot, EventArgs.Empty);
                } 
            } 
        }
 
        internal void UpdateActiveElement(DependencyObject activeElement)
        {
            // Update TabNavigation = Once groups
            UpdateActiveElement(activeElement, TabNavigationProperty); 

            // Update ControlTabNavigation = Once groups 
            UpdateActiveElement(activeElement, ControlTabNavigationProperty); 
        }
 
        private void UpdateActiveElement(DependencyObject activeElement, DependencyProperty dp)
        {
            _navigationProperty = dp;
            DependencyObject container = GetGroupParent(activeElement); 
            if (activeElement == container)
                return; 
 
            // Update ActiveElement only if container has TabNavigation = Once
            if (GetKeyNavigationMode(container) == KeyboardNavigationMode.Once) 
            {
                SetActiveElement(container, activeElement);
            }
        } 

        // Called from FrameworkElement.MoveFocus 
        internal bool Navigate(DependencyObject currentElement, TraversalRequest request) 
        {
            return Navigate(currentElement, request, Keyboard.Modifiers); 
        }

        private bool Navigate(DependencyObject currentElement, TraversalRequest request, ModifierKeys modifierKeys)
        { 
            return Navigate(currentElement, request, modifierKeys, null);
        } 
 
        private bool Navigate(DependencyObject currentElement, TraversalRequest request, ModifierKeys modifierKeys, DependencyObject firstElement)
        { 
            Debug.Assert(currentElement != null, "currentElement should not be null");
            DependencyObject nextTab = null;
            IKeyboardInputSink inputSink = null;
 
            switch (request.FocusNavigationDirection)
            { 
                case FocusNavigationDirection.Next: 
                    _navigationProperty = (modifierKeys & ModifierKeys.Control) == ModifierKeys.Control ? ControlTabNavigationProperty : TabNavigationProperty;
                    nextTab = GetNextTab(currentElement, GetGroupParent(currentElement, true /*includeCurrent*/), false); 
                    break;

                case FocusNavigationDirection.Previous:
                    _navigationProperty = (modifierKeys & ModifierKeys.Control) == ModifierKeys.Control ? ControlTabNavigationProperty : TabNavigationProperty; 
                    nextTab = GetPrevTab(currentElement, null, false);
                    break; 
 
                case FocusNavigationDirection.First:
                    _navigationProperty = (modifierKeys & ModifierKeys.Control) == ModifierKeys.Control ? ControlTabNavigationProperty : TabNavigationProperty; 
                    nextTab = GetNextTab(null, currentElement, true);
                    break;

                case FocusNavigationDirection.Last: 
                    _navigationProperty = (modifierKeys & ModifierKeys.Control) == ModifierKeys.Control ? ControlTabNavigationProperty : TabNavigationProperty;
                    nextTab = GetPrevTab(null, currentElement, true); 
                    break; 

                case FocusNavigationDirection.Left: 
                case FocusNavigationDirection.Right:
                case FocusNavigationDirection.Up:
                case FocusNavigationDirection.Down:
                    _navigationProperty = DirectionalNavigationProperty; 
                    nextTab = GetNextInDirection(currentElement, request.FocusNavigationDirection);
                    break; 
            } 

            // If there are no other tabstops, try to pass focus outside PresentationSource 
            if (nextTab == null)
            {
                // If Wrapped is true we should not searach outside this container
                if (request.Wrapped || request.FocusNavigationDirection == FocusNavigationDirection.First || request.FocusNavigationDirection == FocusNavigationDirection.Last) 
                    return false;
 
                // Try to navigate outside the PresentationSource 
                bool navigatedOutside = NavigateOutsidePresentationSource(currentElement, request);
                if (navigatedOutside) 
                {
                    return true;
                }
                else if (request.FocusNavigationDirection == FocusNavigationDirection.Next || request.FocusNavigationDirection == FocusNavigationDirection.Previous) 
                {
                    // In case focus cannot navigate outside - we should cycle 
                    Visual visualRoot = GetVisualRoot(currentElement); 
                    if (visualRoot != null)
                        return Navigate(visualRoot, new TraversalRequest(request.FocusNavigationDirection == FocusNavigationDirection.Next ? FocusNavigationDirection.First : FocusNavigationDirection.Last)); 
                }

                return false;
            } 

            inputSink = nextTab as IKeyboardInputSink; 
            if (inputSink == null) 
            {
                // If target element does not support IKeyboardInputSink then we try to set focus 
                // In TextBox scenario Focus() return false although the focus is set to TextBox content
                // So we need to verify IsKeyboardFocusWithin property (bugfix 954000)
                IInputElement iie = nextTab as IInputElement;
                iie.Focus(); 

                return iie.IsKeyboardFocusWithin; 
            } 
            else
            { 
                // If target element supports IKeyboardInputSink then we pass the focus there
                bool traversed = false;

                if (request.FocusNavigationDirection == FocusNavigationDirection.First || request.FocusNavigationDirection == FocusNavigationDirection.Next) 
                {
                    traversed = inputSink.TabInto(new TraversalRequest(FocusNavigationDirection.First)); 
                } 
                else if (request.FocusNavigationDirection == FocusNavigationDirection.Last || request.FocusNavigationDirection == FocusNavigationDirection.Previous)
                { 
                    traversed = inputSink.TabInto(new TraversalRequest(FocusNavigationDirection.Last));
                }
                else // FocusNavigationDirection
                { 
                    TraversalRequest tr = new TraversalRequest(request.FocusNavigationDirection);
                    tr.Wrapped = true; 
                    traversed = inputSink.TabInto(tr); 
                }
 
                // If we fail to navigate into IKeyboardInputSink then move to the next element
                if (!traversed && firstElement != nextTab)
                {
                    // Navigate to next element in the tree 
                    traversed = Navigate(nextTab, request, modifierKeys, firstElement == null ? nextTab : firstElement);
                } 
 
                return traversed;
            } 
        }

        /// 
        ///     Critical: This code accesses PresentationSource. 
        ///     TreatAsSafe: This code causes navigation to different elements within an app.
        ///     It does not expose the PresentationSource 
        ///     Critical: Asserting UnmanagedCode permission to obtain HwndSource.IKeyboardInputSink.KeyboardInputSite 
        ///     TreatAsSafe: Not leaking the InputKeyboardSite obtained under elevation.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private bool NavigateOutsidePresentationSource(DependencyObject currentElement, TraversalRequest request)
        {
            Visual visual = currentElement as Visual; 
            if (visual == null)
            { 
                visual = GetParentUIElementFromContentElement(currentElement as ContentElement); 
                if (visual == null)
                    return false; 
            }

            IKeyboardInputSink inputSink = PresentationSource.CriticalFromVisual(visual) as IKeyboardInputSink;
            if (inputSink != null) 
            {
                IKeyboardInputSite ikis = null; 
 
                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();  // BlessedAssert
                try 
                {
                    ikis = inputSink.KeyboardInputSite;
                }
                finally 
                {
                    CodeAccessPermission.RevertAssert(); 
                } 

                if (ikis != null) 
                    return ikis.OnNoMoreTabStops(request);
            }

            return false; 
        }
 
        internal static KeyboardNavigation Current 
        {
            get 
            {
                return FrameworkElement.KeyboardNavigation;
            }
        } 

        ///////////////////////////////////////////////////////////////////// 
        /// 
        /// Critical: accesses e.StagingItem.Input and asserts to retrieve HwndSource
        /// 
        [SecurityCritical]
        private void PostProcessInput(object sender, ProcessInputEventArgs e)
        {
            // Call Forwarded 
            ProcessInput(e.StagingItem.Input);
        } 
 
        /////////////////////////////////////////////////////////////////////
        /// 
        /// Critical: asserts to retrieve HwndSource
        ///
        [SecurityCritical]
        private void TranslateAccelerator(object sender, KeyEventArgs e) 
        {
            // Call Forwarded 
            ProcessInput(e); 
        }
 
        /////////////////////////////////////////////////////////////////////
        ///
        /// Critical: asserts to retrieve HwndSource
        /// 
        [SecurityCritical]
        private void ProcessInput(InputEventArgs inputEventArgs) 
        { 
            ProcessForMenuMode(inputEventArgs);
            ProcessForUIState(inputEventArgs); 

            // Process keyboard navigation for keydown event for Tab,Left,Right,Up,Down keys.
            if(inputEventArgs.RoutedEvent != Keyboard.KeyDownEvent)
                return; 

            KeyEventArgs keyEventArgs = (KeyEventArgs)inputEventArgs; 
            if (keyEventArgs.Handled) 
                return;
 
            DependencyObject sourceElement = keyEventArgs.OriginalSource as DependencyObject;

            // For Keyboard Interop with Avalon-inside-Avalon via HwndHost.
            // In Keyboard interop, the target (called OriginalSource here) is "forced" 
            // to point at the HwndHost containing the Hwnd with focus.  This allows
            // us to tunnel/bubble the keystroke across the outer HwndSource to the 
            // child hwnd that has focus.  (see HwndSource.TranslateAccelerator) 
            // But this "forced" target is wrong for Tab Navigation; eg. tabbing
            // across an inner avalon under the HwndHost.   For that we need the 
            // real original target element, which we happen to find in KeyboardDevice.Target.
            //
            // sourceElement and innerElement I don't expect will ever be different
            // except in this case.  And I added a check that the "forced" target 
            // is an HwndHost for good measure.
            DependencyObject innerElement = keyEventArgs.KeyboardDevice.Target as DependencyObject; 
            if( innerElement != null && sourceElement != innerElement ) 
            {
                if(sourceElement is HwndHost) 
                    sourceElement = innerElement;
            }

            // When nothing has focus - we should start from the root of the visual tree 
            if (sourceElement == null)
            { 
 
                HwndSource hwndSource = keyEventArgs.UnsafeInputSource as HwndSource;
                if (hwndSource == null) 
                    return;

                sourceElement = hwndSource.RootVisual;
                if (sourceElement == null) 
                    return;
            } 
 
            // Focus visual support
            switch (GetRealKey(keyEventArgs)) 
            {
                case Key.LeftAlt:
                case Key.RightAlt:
                    ShowFocusVisual(); 
                    EnableKeyboardCues(sourceElement, true);
                    break; 
                case Key.Tab: 
                case Key.Right:
                case Key.Left: 
                case Key.Up:
                case Key.Down:
                    ShowFocusVisual();
                    break; 
            }
 
            keyEventArgs.Handled = Navigate(sourceElement, keyEventArgs.Key, keyEventArgs.KeyboardDevice.Modifiers); 
        }
 
        internal static void EnableKeyboardCues(DependencyObject element, bool enable)
        {
            Visual visual = element as Visual;
            if (visual == null) 
            {
                visual = GetParentUIElementFromContentElement(element as ContentElement); 
                if (visual == null) 
                    return;
            } 

            Visual rootVisual = GetVisualRoot(visual);
            if (rootVisual != null)
            { 
                rootVisual.SetValue(ShowKeyboardCuesProperty, enable ? BooleanBoxes.TrueBox : BooleanBoxes.FalseBox);
            } 
        } 

        internal static FocusNavigationDirection KeyToTraversalDirection(Key key) 
        {
            switch (key)
            {
                case Key.Left: 
                    return FocusNavigationDirection.Left;
 
                case Key.Right: 
                    return FocusNavigationDirection.Right;
 
                case Key.Up:
                    return FocusNavigationDirection.Up;

                case Key.Down: 
                    return FocusNavigationDirection.Down;
            } 
 
            throw new NotSupportedException();
        } 

        internal DependencyObject PredictFocusedElement(DependencyObject sourceElement, FocusNavigationDirection direction)
        {
            if (sourceElement == null) 
            {
                return null; 
            } 

            _navigationProperty = DirectionalNavigationProperty; 
            _verticalBaseline = BASELINE_DEFAULT;
            _horizontalBaseline = BASELINE_DEFAULT;
            return GetNextInDirection(sourceElement, direction);
        } 

        internal bool Navigate(DependencyObject sourceElement, Key key, ModifierKeys modifiers) 
        { 
            bool success = false;
 
            switch (key)
            {
                // Logical (Tab) navigation
                case Key.Tab: 
                    success = Navigate(sourceElement,
                        new TraversalRequest(((modifiers & ModifierKeys.Shift) == ModifierKeys.Shift) ? 
                        FocusNavigationDirection.Previous : FocusNavigationDirection.Next), modifiers); 
                    break;
 
                case Key.Right:
                    success = Navigate(sourceElement, new TraversalRequest(FocusNavigationDirection.Right), modifiers);
                    break;
 
                case Key.Left:
                    success = Navigate(sourceElement, new TraversalRequest(FocusNavigationDirection.Left), modifiers); 
                    break; 

                case Key.Up: 
                    success = Navigate(sourceElement, new TraversalRequest(FocusNavigationDirection.Up), modifiers);
                    break;

                case Key.Down: 
                    success = Navigate(sourceElement, new TraversalRequest(FocusNavigationDirection.Down), modifiers);
                    break; 
 
            }
            return success; 
        }

        #endregion Navigate helpers
 
        #region Tree navigation
 
        // Filter the visual tree and return true if: 
        // 1. visual is visible UIElement
        // 2. visual is visible UIElement3D 
        // 3. visual is IContentHost but not UIElementIsland
        // Note: UIElementIsland is a special element that has only one child and should be excluded
        private bool IsInNavigationTree(DependencyObject visual)
        { 
            UIElement uiElement = visual as UIElement;
            if (uiElement != null && uiElement.IsVisible) 
                return true; 

            if (visual is IContentHost && !(visual is MS.Internal.Documents.UIElementIsland)) 
                return true;

            UIElement3D uiElement3D = visual as UIElement3D;
            if (uiElement3D != null && uiElement3D.IsVisible) 
                return true;
 
            return false; 
        }
 
        private DependencyObject GetPreviousSibling(DependencyObject e)
        {
            DependencyObject parent = GetParent(e);
 
            // If parent is IContentHost - get next from the enumerator
            IContentHost ich = parent as IContentHost; 
            if (ich != null) 
            {
                IInputElement previousElement = null; 
                IEnumerator enumerator = ich.HostedElements;
                while (enumerator.MoveNext())
                {
                    IInputElement current = enumerator.Current; 
                    if (current == e)
                        return previousElement as DependencyObject; 
 
                    if (current is UIElement || current is UIElement3D)
                        previousElement = current; 
                    else
                    {
                        ContentElement ce = current as ContentElement;
                        if (ce != null && IsTabStop(ce)) 
                            previousElement = current;
                    } 
                } 
                return null;
            } 
            else
            {
                // If parent is UIElement(3D) - return visual sibling
                DependencyObject parentAsUIElement = parent as UIElement; 
                if (parentAsUIElement == null)
                { 
                    parentAsUIElement = parent as UIElement3D; 
                }
                DependencyObject elementAsVisual = e as Visual; 
                if (elementAsVisual == null)
                {
                    elementAsVisual = e as Visual3D;
                } 

                if (parentAsUIElement != null && elementAsVisual != null) 
                { 
                    int count = VisualTreeHelper.GetChildrenCount(parentAsUIElement);
                    DependencyObject prev = null; 
                    for(int i = 0; i < count; i++)
                    {
                        DependencyObject vchild = VisualTreeHelper.GetChild(parentAsUIElement, i);
                        if(vchild == elementAsVisual) break; 
                        if (IsInNavigationTree(vchild))
                            prev = vchild; 
                    } 
                    return prev;
                } 
            }
            return null;
        }
 
        private DependencyObject GetNextSibling(DependencyObject e)
        { 
            DependencyObject parent = GetParent(e); 

            // If parent is IContentHost - get next from the enumerator 
            IContentHost ich = parent as IContentHost;
            if (ich != null)
            {
                IEnumerator enumerator = ich.HostedElements; 
                bool found = false;
                while (enumerator.MoveNext()) 
                { 
                    IInputElement current = enumerator.Current;
                    if (found) 
                    {
                        if (current is UIElement || current is UIElement3D)
                            return current as DependencyObject;
                        else 
                        {
                            ContentElement ce = current as ContentElement; 
                            if (ce != null && IsTabStop(ce)) 
                                return ce;
                        } 
                    }
                    else if (current == e)
                    {
                        found = true; 
                    }
                } 
            } 
            else
            { 
                // If parent is UIElement(3D) - return visual sibling
                DependencyObject parentAsUIElement = parent as UIElement;
                if (parentAsUIElement == null)
                { 
                    parentAsUIElement = parent as UIElement3D;
                } 
                DependencyObject elementAsVisual = e as Visual; 
                if (elementAsVisual == null)
                { 
                    elementAsVisual = e as Visual3D;
                }

                if (parentAsUIElement != null && elementAsVisual != null) 
                {
                    int count = VisualTreeHelper.GetChildrenCount(parentAsUIElement); 
                    int i = 0; 
                    //go till itself
                    for(; i < count; i++) 
                    {
                        DependencyObject vchild = VisualTreeHelper.GetChild(parentAsUIElement, i);
                        if(vchild == elementAsVisual) break;
                    } 
                    i++;
                    //search ahead 
                    for(; i < count; i++) 
                    {
                        DependencyObject visual = VisualTreeHelper.GetChild(parentAsUIElement, i); 
                        if (IsInNavigationTree(visual))
                            return visual;
                    }
                } 
            }
 
            return null; 
        }
 
        // For Control+Tab navigation or TabNavigation when fe is not a FocusScope:
        // Scenarios:
        // 1. UserControl can set its FocusedElement to delegate focus when Tab navigation happens
        // 2. ToolBar or Menu (which have IsFocusScope=true) both have FocusedElement but included only in Control+Tab navigation 
        private DependencyObject FocusedElement(DependencyObject e)
        { 
            IInputElement iie = e as IInputElement; 
            // Focus delegation is enabled only if keyboard focus is outside the container
            if (iie != null && !iie.IsKeyboardFocusWithin) 
            {
                DependencyObject focusedElement = FocusManager.GetFocusedElement(e) as DependencyObject;
                if (focusedElement != null)
                { 
                    if (_navigationProperty == ControlTabNavigationProperty || !IsFocusScope(e))
                    { 
                        // Verify if focusedElement is a visual descendant of e 
                        Visual visualFocusedElement = focusedElement as Visual;
                        if (visualFocusedElement == null) 
                        {
                            Visual3D visual3DFocusedElement = focusedElement as Visual3D;
                            if (visual3DFocusedElement == null)
                            { 
                                visualFocusedElement = GetParentUIElementFromContentElement(focusedElement as ContentElement);
                            } 
                            else 
                            {
                                if (visual3DFocusedElement.IsDescendantOf(e)) 
                                {
                                    return focusedElement;
                                }
                            } 
                        }
                        if (visualFocusedElement.IsDescendantOf(e)) 
                        { 
                            return focusedElement;
                        } 
                    }
                }
            }
 
            return null;
        } 
 
        // We traverse only UIElement(3D) or ContentElement
        private DependencyObject GetFirstChild(DependencyObject e) 
        {
            // If the element has a FocusedElement it should be its first child
            DependencyObject focusedElement = FocusedElement(e);
            if (focusedElement != null) 
                return focusedElement;
 
            // If the element is IContentHost - return the first child 
            IContentHost ich = e as IContentHost;
            if (ich != null) 
            {
                IEnumerator enumerator = ich.HostedElements;
                while (enumerator.MoveNext())
                { 
                    IInputElement current = enumerator.Current;
                    if (current is UIElement || current is UIElement3D) 
                    { 
                        return current as DependencyObject;
                    } 
                    else
                    {
                        ContentElement ce = current as ContentElement;
                        if (ce != null && IsTabStop(ce)) 
                            return ce;
                    } 
                } 
                return null;
            } 

            // Return the first visible UIElement(3D) or IContentHost
            DependencyObject uiElement = e as UIElement;
            if (uiElement == null) 
            {
                uiElement = e as UIElement3D; 
            } 

            if (uiElement == null || 
                UIElementHelper.IsVisible(uiElement))
            {
                DependencyObject elementAsVisual = e as Visual;
                if (elementAsVisual == null) 
                {
                    elementAsVisual = e as Visual3D; 
                } 

                if (elementAsVisual != null) 
                {
                    int count = VisualTreeHelper.GetChildrenCount(elementAsVisual);
                    for (int i = 0; i < count; i++)
                    { 
                        DependencyObject visual = VisualTreeHelper.GetChild(elementAsVisual, i);
                        if (IsInNavigationTree(visual)) 
                            return visual; 
                        else
                        { 
                            DependencyObject firstChild = GetFirstChild(visual);
                            if (firstChild != null)
                                return firstChild;
                        } 
                    }
                } 
            } 

            // If element is ContentElement for example 
            return null;
        }

        private DependencyObject GetLastChild(DependencyObject e) 
        {
            // If the element has a FocusedElement it should be its last child 
            DependencyObject focusedElement = FocusedElement(e); 
            if (focusedElement != null)
                return focusedElement; 

            // If the element is IContentHost - return the last child
            IContentHost ich = e as IContentHost;
            if (ich != null) 
            {
                IEnumerator enumerator = ich.HostedElements; 
                IInputElement last = null; 
                while (enumerator.MoveNext())
                { 
                    IInputElement current = enumerator.Current;
                    if (current is UIElement || current is UIElement3D)
                        last = current;
                    else 
                    {
                        ContentElement ce = current as ContentElement; 
                        if (ce != null && IsTabStop(ce)) 
                            last = current;
                    } 
                }
                return last as DependencyObject;
            }
 
            // Return the last visible UIElement(3D) or IContentHost
            DependencyObject uiElement = e as UIElement; 
            if (uiElement == null) 
            {
                uiElement = e as UIElement3D; 
            }

            if (uiElement == null || UIElementHelper.IsVisible(uiElement))
            { 
                DependencyObject elementAsVisual = e as Visual;
                if (elementAsVisual == null) 
                { 
                    elementAsVisual = e as Visual3D;
                } 

                if (elementAsVisual != null)
                {
                    int count = VisualTreeHelper.GetChildrenCount(elementAsVisual); 
                    for (int i = count - 1; i >= 0; i--)
                    { 
                        DependencyObject visual = VisualTreeHelper.GetChild(elementAsVisual, i); 
                        if (IsInNavigationTree(visual))
                            return visual; 
                        else
                        {
                            DependencyObject lastChild = GetLastChild(visual);
                            if (lastChild != null) 
                                return lastChild;
                        } 
                    } 
                }
            } 

            return null;
        }
 
        private DependencyObject GetParent(DependencyObject e)
        { 
            // For Visual - go up the visual parent chain until we find Visual, Visual3D or IContentHost 
            if (e is Visual || e is Visual3D)
            { 
                DependencyObject visual = e;

                while ((visual = VisualTreeHelper.GetParent(visual)) != null)
                { 
                    //
 
 
                    if (IsInNavigationTree(visual))
                        return visual; 
                }
            }
            else
            { 
                // For ContentElement - return the host element (which is IContentHost)
                ContentElement contentElement = e as ContentElement; 
                if (contentElement != null) 
                {
                    return MS.Internal.Documents.ContentHostHelper.FindContentHost(contentElement) as DependencyObject; 
                }
            }

            return null; 
        }
 
        /***************************************************************************\ 
        *
        * GetNextInTree(DependencyObject e, DependencyObject container) 
        * Search the subtree with container root; Don't go inside TabGroups
        *
        * Return the next Element in tree in depth order (self-child-sibling).
        *            1 
        *           / \
        *          2   5 
        *         / \ 
        *        3   4
        * 
        \***************************************************************************/
        private DependencyObject GetNextInTree(DependencyObject e, DependencyObject container)
        {
            Debug.Assert(e != null, "e should not be null"); 
            Debug.Assert(container != null, "container should not be null");
 
            DependencyObject result = null; 

            if (e == container || !IsGroup(e)) 
                result = GetFirstChild(e);

            if (result != null || e == container)
                return result; 

            DependencyObject parent = e; 
            do 
            {
                DependencyObject sibling = GetNextSibling(parent); 
                if (sibling != null)
                    return sibling;

                parent = GetParent(parent); 
            } while (parent != null && parent != container);
 
            return null; 
        }
 

        /***************************************************************************\
        *
        * GetPreviousInTree(DependencyObject e, DependencyObject container) 
        * Don't go inside TabGroups
        * Return the previous Element in tree in depth order (self-child-sibling). 
        *            5 
        *           / \
        *          4   1 
        *         / \
        *        3   2
        \***************************************************************************/
        private DependencyObject GetPreviousInTree(DependencyObject e, DependencyObject container) 
        {
            if (e == container) 
                return null; 

            DependencyObject result = GetPreviousSibling(e); 

            if (result != null)
            {
                if (IsGroup(result)) 
                    return result;
                else 
                    return GetLastInTree(result); 
            }
            else 
                return GetParent(e);
        }

        // Find the last element in the subtree 
        private DependencyObject GetLastInTree(DependencyObject container)
        { 
            DependencyObject result; 
            do
            { 
                result = container;
                container = GetLastChild(container);
            } while (container != null && !IsGroup(container));
 
            if (container != null)
                return container; 
 
            return result;
        } 

        private DependencyObject GetGroupParent(DependencyObject e)
        {
            return GetGroupParent(e, false /*includeCurrent*/); 
        }
 
        // Go up thru the parent chain until we find TabNavigation != Continue 
        // In case all parents are Continue then return the root
        private DependencyObject GetGroupParent(DependencyObject e, bool includeCurrent) 
        {
            Debug.Assert(e != null, "e cannot be null");

            DependencyObject result = e; // Keep the last non null element 

            // If we don't want to include the current element, 
            // start at the parent of the element.  If the element 
            // is the root, then just return it as the group parent.
            if (!includeCurrent) 
            {
                result = e;
                e = GetParent(e);
                if (e == null) 
                {
                    return result; 
                } 
            }
 
            while (e != null)
            {
                if (IsGroup(e))
                    return e; 

                result = e; 
                e = GetParent(e); 
            }
 
            return result;
        }

        #endregion Tree navigation 

        #region Logical Navigation 
 
        private bool IsTabStop(DependencyObject e)
        { 
            FrameworkElement fe = e as FrameworkElement;
            if (fe != null)
                return
                    (fe.Focusable 
                    && (bool)fe.GetValue(IsTabStopProperty))
                    && fe.IsEnabled 
                    && fe.IsVisible; 

            FrameworkContentElement fce = e as FrameworkContentElement; 
            return fce != null && fce.Focusable && (bool)fce.GetValue(IsTabStopProperty) && fce.IsEnabled;
        }

        private bool IsGroup(DependencyObject e) 
        {
            return GetKeyNavigationMode(e) != KeyboardNavigationMode.Continue; 
        } 

        private KeyboardNavigationMode GetKeyNavigationMode(DependencyObject e) 
        {
            return (KeyboardNavigationMode)e.GetValue(_navigationProperty);
        }
 
        private bool IsTabStopOrGroup(DependencyObject e)
        { 
            return IsTabStop(e) || IsGroup(e); 
        }
 
        private static int GetTabIndexHelper(DependencyObject d)
        {
            return (int)d.GetValue(TabIndexProperty);
        } 

        #region Tab Navigation 
 
        // Find the element with highest priority (lowest index) inside the group
        private DependencyObject GetFirstTabInGroup(DependencyObject container) 
        {
            DependencyObject firstTabElement = null;
            int minIndexFirstTab = Int32.MinValue;
 
            DependencyObject currElement = container;
            while ((currElement = GetNextInTree(currElement, container)) != null) 
            { 
                if (IsTabStopOrGroup(currElement))
                { 
                    int currPriority = GetTabIndexHelper(currElement);

                    if (currPriority < minIndexFirstTab || firstTabElement == null)
                    { 
                        minIndexFirstTab = currPriority;
                        firstTabElement = currElement; 
                    } 
                }
            } 
            return firstTabElement;
        }

        // Find the element with the same TabIndex after the current element 
        private DependencyObject GetNextTabWithSameIndex(DependencyObject e, DependencyObject container)
        { 
            int elementTabPriority = GetTabIndexHelper(e); 
            DependencyObject currElement = e;
            while ((currElement = GetNextInTree(currElement, container)) != null) 
            {
                if (IsTabStopOrGroup(currElement) && GetTabIndexHelper(currElement) == elementTabPriority)
                {
                    return currElement; 
                }
            } 
 
            return null;
        } 

        // Find the element with the next TabIndex after the current element
        private DependencyObject GetNextTabWithNextIndex(DependencyObject e, DependencyObject container, KeyboardNavigationMode tabbingType)
        { 
            // Find the next min index in the tree
            // min (index>currentTabIndex) 
            DependencyObject nextTabElement = null; 
            DependencyObject firstTabElement = null;
            int minIndexFirstTab = Int32.MinValue; 
            int minIndex = Int32.MinValue;
            int elementTabPriority = GetTabIndexHelper(e);

            DependencyObject currElement = container; 
            while ((currElement = GetNextInTree(currElement, container)) != null)
            { 
 
                if (IsTabStopOrGroup(currElement))
                { 
                    int currPriority = GetTabIndexHelper(currElement);
                    if (currPriority > elementTabPriority)
                    {
                        if (currPriority < minIndex || nextTabElement == null) 
                        {
                            minIndex = currPriority; 
                            nextTabElement = currElement; 
                        }
                    } 

                    if (currPriority < minIndexFirstTab || firstTabElement == null)
                    {
                        minIndexFirstTab = currPriority; 
                        firstTabElement = currElement;
                    } 
                } 
            }
 
            // Cycle groups: if not found - return first element
            if (tabbingType == KeyboardNavigationMode.Cycle && nextTabElement == null)
                nextTabElement = firstTabElement;
 
            return nextTabElement;
        } 
 
        private DependencyObject GetNextTabInGroup(DependencyObject e, DependencyObject container, KeyboardNavigationMode tabbingType)
        { 
            // None groups: Tab navigation is not supported
            if (tabbingType == KeyboardNavigationMode.None)
                return null;
 
            // e == null or e == container -> return the first TabStopOrGroup
            if (e == null || e == container) 
            { 
                return GetFirstTabInGroup(container);
            } 

            if (tabbingType == KeyboardNavigationMode.Once)
                return null;
 
            DependencyObject nextTabElement = GetNextTabWithSameIndex(e, container);
            if (nextTabElement != null) 
                return nextTabElement; 

            return GetNextTabWithNextIndex(e, container, tabbingType); 
        }

        private DependencyObject GetNextTab(DependencyObject e, DependencyObject container, bool goDownOnly)
        { 
            Debug.Assert(container != null, "container should not be null");
 
            KeyboardNavigationMode tabbingType = GetKeyNavigationMode(container); 

            if (e == null) 
            {
                if (IsTabStop(container))
                    return container;
 
                // Using ActiveElement if set
                DependencyObject activeElement = GetActiveElement(container); 
                if (activeElement != null) 
                    return GetNextTab(null, activeElement, true);
            } 
            else
            {
                if (tabbingType == KeyboardNavigationMode.Once || tabbingType == KeyboardNavigationMode.None)
                { 
                    if (container != e)
                    { 
                        if (goDownOnly) 
                            return null;
                        DependencyObject parentContainer = GetGroupParent(container); 
                        return GetNextTab(container, parentContainer, goDownOnly);
                    }
                }
            } 

            // All groups 
            DependencyObject loopStartElement = null; 
            DependencyObject nextTabElement = e;
            KeyboardNavigationMode currentTabbingType = tabbingType; 

            // Search down inside the container
            while ((nextTabElement = GetNextTabInGroup(nextTabElement, container, currentTabbingType)) != null)
            { 
                Debug.Assert(IsTabStopOrGroup(nextTabElement), "nextTabElement should be IsTabStop or group");
 
                // Avoid the endless loop here for Cycle groups 
                if (loopStartElement == nextTabElement)
                    break; 
                if (loopStartElement == null)
                    loopStartElement = nextTabElement;

                DependencyObject firstTabElementInside = GetNextTab(null, nextTabElement, true); 
                if (firstTabElementInside != null)
                    return firstTabElementInside; 
 
                // If we want to continue searching inside the Once groups, we should change the navigation mode
                if (currentTabbingType == KeyboardNavigationMode.Once) 
                    currentTabbingType = KeyboardNavigationMode.Contained;
            }

            // If there is no next element in the group (nextTabElement == null) 

            // Search up in the tree if allowed 
            // 
            if (!goDownOnly && currentTabbingType != KeyboardNavigationMode.Contained && GetParent(container) != null)
            { 
                return GetNextTab(container, GetGroupParent(container), false);
            }

            return null; 
        }
 
        #endregion Tab Navigation 

        #region Shift+Tab Navigation 

        private DependencyObject GetLastTabInGroup(DependencyObject container)
        {
            DependencyObject lastTabElement = null; 
            int maxIndexFirstTab = Int32.MaxValue;
            DependencyObject currElement = GetLastInTree(container); 
            while (currElement != null && currElement != container) 
            {
                if (IsTabStopOrGroup(currElement)) 
                {
                    int currPriority = GetTabIndexHelper(currElement);

                    if (currPriority > maxIndexFirstTab || lastTabElement == null) 
                    {
                        maxIndexFirstTab = currPriority; 
                        lastTabElement = currElement; 
                    }
                } 
                currElement = GetPreviousInTree(currElement, container);
            }
            return lastTabElement;
        } 

        // Look for element with the same TabIndex before the current element 
        private DependencyObject GetPrevTabWithSameIndex(DependencyObject e, DependencyObject container) 
        {
            int elementTabPriority = GetTabIndexHelper(e); 
            DependencyObject currElement = GetPreviousInTree(e, container);
            while (currElement != null)
            {
                if (IsTabStopOrGroup(currElement) && GetTabIndexHelper(currElement) == elementTabPriority && currElement != container) 
                {
                    return currElement; 
                } 
                currElement = GetPreviousInTree(currElement, container);
            } 
            return null;
        }

        private DependencyObject GetPrevTabWithPrevIndex(DependencyObject e, DependencyObject container, KeyboardNavigationMode tabbingType) 
        {
            // Find the next max index in the tree 
            // max (index maxIndex || nextTabElement == null)
                        { 
                            maxIndex = currPriority;
                            nextTabElement = currElement; 
                        } 
                    }
 
                    if (currPriority > maxIndexFirstTab || lastTabElement == null)
                    {
                        maxIndexFirstTab = currPriority;
                        lastTabElement = currElement; 
                    }
                } 
 
                currElement = GetPreviousInTree(currElement, container);
            } 

            // Cycle groups: if not found - return first element
            if (tabbingType == KeyboardNavigationMode.Cycle && nextTabElement == null)
                nextTabElement = lastTabElement; 

            return nextTabElement; 
        } 

        private DependencyObject GetPrevTabInGroup(DependencyObject e, DependencyObject container, KeyboardNavigationMode tabbingType) 
        {
            // None groups: Tab navigation is not supported
            if (tabbingType == KeyboardNavigationMode.None)
                return null; 

            // Search the last index inside the group 
            if (e==null) 
            {
                return GetLastTabInGroup(container); 
            }

            if (tabbingType == KeyboardNavigationMode.Once)
                return null; 

            if (e == container) 
                return null; 

            DependencyObject nextTabElement = GetPrevTabWithSameIndex(e, container); 
            if (nextTabElement != null)
                return nextTabElement;

            return GetPrevTabWithPrevIndex(e, container, tabbingType); 
        }
 
        private DependencyObject GetPrevTab(DependencyObject e, DependencyObject container, bool goDownOnly) 
        {
            Debug.Assert(e != null || container != null, "e or container should not be null"); 

            if (container == null)
                container = GetGroupParent(e);
 
            KeyboardNavigationMode tabbingType = GetKeyNavigationMode(container);
 
            if (e == null) 
            {
                // Using ActiveElement if set 
                DependencyObject activeElement = GetActiveElement(container);
                if (activeElement != null)
                    return GetPrevTab(null, activeElement, true);
                else 
                {
                    // If we Shift+Tab on a container with KeyboardNavigationMode=Once, and ActiveElement is null 
                    // then we want to go to the fist item (not last) within the container 
                    if (tabbingType == KeyboardNavigationMode.Once)
                    { 
                        DependencyObject firstTabElement = GetNextTabInGroup(null, container, tabbingType);
                        if (firstTabElement == null)
                        {
                            if (IsTabStop(container)) 
                                return container;
                            if (goDownOnly) 
                                return null; 

                            return GetPrevTab(container, null, false); 
                        }
                        else
                        {
                            return GetPrevTab(null, firstTabElement, true); 
                        }
                    } 
                } 
            }
            else 
            {
                if (tabbingType == KeyboardNavigationMode.Once || tabbingType == KeyboardNavigationMode.None)
                {
                    if (goDownOnly || container==e) 
                        return null;
 
                    // FocusedElement should not be e otherwise we will delegate focus to the same element 
                    if (IsTabStop(container))
                        return container; 

                    return GetPrevTab(container, null, false);
                }
            } 

            // All groups (except Once) - continue 
            DependencyObject loopStartElement = null; 
            DependencyObject nextTabElement = e;
 
            // Look for element with the same TabIndex before the current element
            while ((nextTabElement = GetPrevTabInGroup(nextTabElement, container, tabbingType)) != null)
            {
                if (nextTabElement == container && tabbingType == KeyboardNavigationMode.Local) 
                    break;
 
                // At this point nextTabElement is TabStop or TabGroup 
                // In case it is a TabStop only return the element
                if (IsTabStop(nextTabElement) && !IsGroup(nextTabElement)) 
                    return nextTabElement;

                // Avoid the endless loop here
                if (loopStartElement == nextTabElement) 
                    break;
                if (loopStartElement == null) 
                    loopStartElement = nextTabElement; 

                // At this point nextTabElement is TabGroup 
                DependencyObject lastTabElementInside = GetPrevTab(null, nextTabElement, true);
                if (lastTabElementInside != null)
                    return lastTabElementInside;
            } 

            if (tabbingType == KeyboardNavigationMode.Contained) 
                return null; 

            if (e != container && IsTabStop(container)) 
                return container;

            // If end of the subtree is reached or there no other elements above
            if (!goDownOnly && GetParent(container) != null) 
            {
                return GetPrevTab(container, null, false); 
            } 

            return null; 
        }

        #endregion Shift+Tab Navigation
 
        #endregion Logical Navigation
 
        #region Directional Navigation 

        // return the element rectange relative to the root 
        internal static Rect GetRectangle(DependencyObject element)
        {
            UIElement uiElement = element as UIElement;
            if (uiElement != null && uiElement.IsArrangeValid) 
            {
                Visual rootVisual = GetVisualRoot(uiElement); 
 
                if (rootVisual != null)
                { 
                    GeneralTransform transform = uiElement.TransformToAncestor(rootVisual);
                    Thickness deflateThickness = (Thickness)uiElement.GetValue(DirectionalNavigationMarginProperty);
                    double x = -deflateThickness.Left;
                    double y = -deflateThickness.Top; 
                    double width = uiElement.RenderSize.Width + deflateThickness.Left + deflateThickness.Right;
                    double height = uiElement.RenderSize.Height + deflateThickness.Top + deflateThickness.Bottom; 
                    if (width < 0) 
                    {
                        x = uiElement.RenderSize.Width * 0.5; 
                        width = 0d;
                    }
                    if (height < 0)
                    { 
                        y = uiElement.RenderSize.Height * 0.5;
                        height = 0d; 
                    } 
                    return transform.TransformBounds(new Rect(x, y, width, height));
                } 
            }
            else
            {
                ContentElement ce = element as ContentElement; 
                if (ce != null)
                { 
                    IContentHost parentICH = null; 
                    UIElement parentUIElement = GetParentUIElementFromContentElement(ce, ref parentICH);
                    Visual parent = parentICH as Visual; 
                    if (parentICH != null && parent != null && parentUIElement != null)
                    {
                        Visual rootVisual = GetVisualRoot(parent);
                        if (rootVisual != null && parentUIElement.IsMeasureValid) 
                        {
                            // Note: Here we consider only the fist rectangle 
                            // Do we need to consider all of them as one combined rectangle? 
                            ReadOnlyCollection rects = parentICH.GetRectangles(ce);
                            IEnumerator enumerator = rects.GetEnumerator(); 
                            if (enumerator.MoveNext())
                            {
                                GeneralTransform transform = parent.TransformToAncestor(rootVisual);
                                Rect rect = enumerator.Current; 
                                return transform.TransformBounds(rect);
                            } 
                        } 
                    }
                } 
                else
                {
                    UIElement3D uiElement3D = element as UIElement3D;
                    if (uiElement3D != null) 
                    {
                        Visual rootVisual = GetVisualRoot(uiElement3D); 
                        Visual containingVisual2D = VisualTreeHelper.GetContainingVisual2D(uiElement3D); 

                        if (rootVisual != null && containingVisual2D != null) 
                        {
                            Rect rectElement = uiElement3D.Visual2DContentBounds;
                            GeneralTransform transform = containingVisual2D.TransformToAncestor(rootVisual);
 
                            return transform.TransformBounds(rectElement);
                        } 
                    } 
                }
            } 

            return Rect.Empty;
        }
 
        // distance between two points
        private double GetDistance(Point p1, Point p2) 
        { 
            double deltaX = p1.X - p2.X;
            double deltaY = p1.Y - p2.Y; 
            return Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
        }

        private double GetPerpDistance(Rect sourceRect, Rect targetRect, FocusNavigationDirection direction) 
        {
            switch (direction) 
            { 
                case FocusNavigationDirection.Right :
                    return targetRect.Left - sourceRect.Left; 

                case FocusNavigationDirection.Left :
                    return sourceRect.Right - targetRect.Right;
 
                case FocusNavigationDirection.Up :
                    return sourceRect.Bottom - targetRect.Bottom; 
 
                case FocusNavigationDirection.Down :
                    return targetRect.Top - sourceRect.Top; 

                default :
                    throw new System.ComponentModel.InvalidEnumArgumentException("direction", (int)direction, typeof(FocusNavigationDirection));
            } 
        }
 
        // Example when moving down: 
        // distance between sourceRect.TopLeft (or Y=vertical baseline)
        // and targetRect.TopLeft 
        private double GetDistance(Rect sourceRect, Rect targetRect, FocusNavigationDirection direction)
        {
            Point startPoint;
            Point endPoint; 
            switch (direction)
            { 
                case FocusNavigationDirection.Right : 
                    startPoint = sourceRect.TopLeft;
                    if (_horizontalBaseline != BASELINE_DEFAULT) 
                        startPoint.Y = _horizontalBaseline;
                    endPoint = targetRect.TopLeft;
                    break;
 
                case FocusNavigationDirection.Left :
                    startPoint = sourceRect.TopRight; 
                    if (_horizontalBaseline != BASELINE_DEFAULT) 
                        startPoint.Y = _horizontalBaseline;
                    endPoint = targetRect.TopRight; 
                    break;

                case FocusNavigationDirection.Up :
                    startPoint = sourceRect.BottomLeft; 
                    if (_verticalBaseline != BASELINE_DEFAULT)
                        startPoint.X = _verticalBaseline; 
                    endPoint = targetRect.BottomLeft; 
                    break;
 
                case FocusNavigationDirection.Down :
                    startPoint = sourceRect.TopLeft;
                    if (_verticalBaseline != BASELINE_DEFAULT)
                        startPoint.X = _verticalBaseline; 
                    endPoint = targetRect.TopLeft;
                    break; 
 
                default :
                    throw new System.ComponentModel.InvalidEnumArgumentException("direction", (int)direction, typeof(FocusNavigationDirection)); 
            }
            return GetDistance(startPoint, endPoint);
        }
 
        // Example when moving down:
        // true if the top of the toRect is below the bottom of fromRect 
        private bool IsInDirection(Rect fromRect, Rect toRect, FocusNavigationDirection direction) 
        {
            switch (direction) 
            {
                case FocusNavigationDirection.Right:
                    return DoubleUtil.LessThanOrClose(fromRect.Right, toRect.Left);
                case FocusNavigationDirection.Left: 
                    return DoubleUtil.GreaterThanOrClose(fromRect.Left, toRect.Right);
                case FocusNavigationDirection.Up : 
                    return DoubleUtil.GreaterThanOrClose(fromRect.Top, toRect.Bottom); 
                case FocusNavigationDirection.Down :
                    return DoubleUtil.LessThanOrClose(fromRect.Bottom, toRect.Top); 
                default:
                    throw new System.ComponentModel.InvalidEnumArgumentException("direction", (int)direction, typeof(FocusNavigationDirection));
            }
        } 

        // The element is focus scope if IsFocusScope is true or it is the visual tree root 
        private bool IsFocusScope(DependencyObject e) 
        {
            return FocusManager.GetIsFocusScope(e) || GetParent(e) == null; 
        }

        private bool IsAncestorOf(DependencyObject sourceElement, DependencyObject targetElement)
        { 
            Visual sourceVisual = sourceElement as Visual;
            Visual targetVisual = targetElement as Visual; 
            if (sourceVisual == null || targetVisual == null) 
                return false;
 
            return sourceVisual.IsAncestorOf(targetVisual);
        }

        // Example: When moving down: 
        // Range is the sourceRect width extended to the vertical baseline
        // targetRect.Top > sourceRect.Top (target is below the source) 
        // targetRect.Right > sourceRect.Left || targetRect.Left < sourceRect.Right 
        private bool IsInRange(DependencyObject sourceElement, DependencyObject targetElement, Rect sourceRect, Rect targetRect, FocusNavigationDirection direction, double startRange, double endRange)
        { 
            switch (direction)
            {
                case FocusNavigationDirection.Right :
                case FocusNavigationDirection.Left : 
                    if (_horizontalBaseline != BASELINE_DEFAULT)
                    { 
                        startRange = Math.Min(startRange, _horizontalBaseline); 
                        endRange = Math.Max(endRange, _horizontalBaseline);
                    } 

                    if (DoubleUtil.GreaterThan(targetRect.Bottom, startRange) && DoubleUtil.LessThan(targetRect.Top, endRange))
                    {
                        // If there is no sourceElement - checking the range is enough 
                        if (sourceElement == null)
                            return true; 
 
                        if (direction == FocusNavigationDirection.Right)
                            return DoubleUtil.GreaterThan(targetRect.Left, sourceRect.Left) || (DoubleUtil.AreClose(targetRect.Left, sourceRect.Left) && IsAncestorOf(sourceElement, targetElement)); 
                        else
                            return DoubleUtil.LessThan(targetRect.Right, sourceRect.Right) || (DoubleUtil.AreClose(targetRect.Right, sourceRect.Right) && IsAncestorOf(sourceElement, targetElement));

                    } 
                    break;
 
                case FocusNavigationDirection.Up : 
                case FocusNavigationDirection.Down :
                    if (_verticalBaseline != BASELINE_DEFAULT) 
                    {
                        startRange = Math.Min(startRange, _verticalBaseline);
                        endRange = Math.Max(endRange, _verticalBaseline);
                    } 

                    if (DoubleUtil.GreaterThan(targetRect.Right, startRange) && DoubleUtil.LessThan(targetRect.Left, endRange)) 
                    { 
                        // If there is no sourceElement - checking the range is enough
                        if (sourceElement == null) 
                            return true;

                        if (direction == FocusNavigationDirection.Down)
                            return DoubleUtil.GreaterThan(targetRect.Top, sourceRect.Top) || (DoubleUtil.AreClose (targetRect.Top, sourceRect.Top) && IsAncestorOf(sourceElement, targetElement)); 
                        else
                            return DoubleUtil.LessThan(targetRect.Bottom, sourceRect.Bottom) || (DoubleUtil.AreClose(targetRect.Bottom, sourceRect.Bottom) && IsAncestorOf(sourceElement, targetElement)); 
                    } 
                    break;
 
                default :
                    throw new System.ComponentModel.InvalidEnumArgumentException("direction", (int)direction, typeof(FocusNavigationDirection));
            }
 
            return false;
        } 
 
        private DependencyObject GetNextInDirection(DependencyObject sourceElement, FocusNavigationDirection direction)
        { 
            _containerHashtable.Clear();
            DependencyObject targetElement = MoveNext(sourceElement, null, direction, BASELINE_DEFAULT, BASELINE_DEFAULT);

            if (targetElement != null) 
            {
                UIElement sourceUIElement = sourceElement as UIElement; 
                if (sourceUIElement != null) 
                    sourceUIElement.RemoveHandler(Keyboard.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(_LostFocus));
                else 
                {
                    ContentElement sourceContentElement = sourceElement as ContentElement;
                    if (sourceContentElement != null)
                        sourceContentElement.RemoveHandler(Keyboard.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(_LostFocus)); 
                }
 
                UIElement targetUIElement = targetElement as UIElement; 
                if (targetUIElement == null)
                    targetUIElement = GetParentUIElementFromContentElement(targetElement as ContentElement); 
                else
                {
                    ContentElement targetContentElement = targetElement as ContentElement;
                    if (targetContentElement != null) 
                    {
                        // When Focus is changed we need to reset the base line 
                        targetContentElement.AddHandler(Keyboard.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(_LostFocus), true); 
                    }
                } 

                if (targetUIElement != null)
                {
                    // When layout is changed we need to reset the base line 
                    // Set up a layout invalidation listener.
                    targetUIElement.LayoutUpdated += new EventHandler(OnLayoutUpdated); 
 
                    // When Focus is changed we need to reset the base line
                    if (targetElement == targetUIElement) 
                        targetUIElement.AddHandler(Keyboard.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(_LostFocus), true);
                }

            } 

            _containerHashtable.Clear(); 
            return targetElement; 
        }
 
        // LayoutUpdated handler.
        private void OnLayoutUpdated(object sender, EventArgs e)
        {
            UIElement uiElement = sender as UIElement; 
            // Disconnect the layout listener.
            if (uiElement != null) 
            { 
                uiElement.LayoutUpdated -= new EventHandler(OnLayoutUpdated);
            } 

            _verticalBaseline = BASELINE_DEFAULT;
            _horizontalBaseline = BASELINE_DEFAULT;
        } 

        private void _LostFocus(object sender, KeyboardFocusChangedEventArgs e) 
        { 
            _verticalBaseline = BASELINE_DEFAULT;
            _horizontalBaseline = BASELINE_DEFAULT; 

            if (sender is UIElement)
                ((UIElement)sender).RemoveHandler(Keyboard.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(_LostFocus));
            else if (sender is ContentElement) 
                ((ContentElement)sender).RemoveHandler(Keyboard.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(_LostFocus));
        } 
 
        private bool IsEndlessLoop(DependencyObject element, DependencyObject container)
        { 
            object elementObject = element != null ? (object)element : _fakeNull;

            // If entry exists then we have endless loop
            Hashtable elementTable = _containerHashtable[container] as Hashtable; 
            if (elementTable != null)
            { 
                if (elementTable[elementObject] != null) 
                    return true;
            } 
            else
            {
                // Adding the entry to the collection
                elementTable = new Hashtable(10); 
                _containerHashtable[container] = elementTable;
            } 
 
            elementTable[elementObject] = BooleanBoxes.TrueBox;
            return false; 
        }

        private void ResetBaseLines(double value, bool horizontalDirection)
        { 
            if (horizontalDirection)
            { 
                _verticalBaseline = BASELINE_DEFAULT; 
                if (_horizontalBaseline == BASELINE_DEFAULT)
                    _horizontalBaseline = value; 
            }
            else // vertical direction
            {
                _horizontalBaseline = BASELINE_DEFAULT; 
                if (_verticalBaseline == BASELINE_DEFAULT)
                    _verticalBaseline = value; 
            } 
        }
        private DependencyObject FindNextInDirection(DependencyObject sourceElement, Rect sourceRect, DependencyObject container, FocusNavigationDirection direction, double startRange, double endRange) 
        {
            DependencyObject result = null;
            Rect resultRect = Rect.Empty;
            double resultScore = 0d; 
            bool searchInsideContainer = sourceElement == null;
            DependencyObject currElement = container; 
            while ((currElement = GetNextInTree(currElement, container)) != null) 
            {
                if (currElement != sourceElement && IsTabStopOrGroup(currElement)) 
                {
                    Rect currentRect = GetRectangle(currElement);
                    bool isInDirection = IsInDirection(sourceRect, currentRect, direction);
                    bool isInRange = IsInRange(sourceElement, currElement, sourceRect, currentRect, direction, startRange, endRange); 
                    if (searchInsideContainer || isInDirection || isInRange)
                    { 
                        double score = isInRange ? GetPerpDistance(sourceRect, currentRect, direction) : GetDistance(sourceRect, currentRect, direction); 

                        // Keep the first element in the result 
                        if (result == null)
                        {
                            result = currElement;
                            resultRect = currentRect; 
                            resultScore = score;
                        } 
                        else if (DoubleUtil.LessThan(score, resultScore) || (DoubleUtil.AreClose(score, resultScore) && GetDistance(sourceRect, resultRect, direction) > GetDistance(sourceRect, currentRect, direction))) 
                        {
                            result = currElement; 
                            resultRect = currentRect;
                            resultScore = score;
                        }
                    } 
                }
            } 
 
            return result;
        } 

        private DependencyObject MoveNext(DependencyObject sourceElement, DependencyObject container, FocusNavigationDirection direction, double startRange, double endRange)
        {
            Debug.Assert(!(sourceElement == null && container == null), "Both sourceElement and container cannot be null"); 

            if (container == null) 
            { 
                container = GetGroupParent(sourceElement);
                Debug.Assert(container != null, "container cannot be null"); 
            }

            // If we get to the tree root, return null
            if (container == sourceElement) 
                return null;
 
            if (IsEndlessLoop(sourceElement, container)) 
                return null;
 
            KeyboardNavigationMode mode = GetKeyNavigationMode(container);
            bool searchInsideContainer = (sourceElement == null);

            // Don't navigate inside None containers 
            if (mode == KeyboardNavigationMode.None && searchInsideContainer)
                return null; 
 
            Rect sourceRect = GetRectangle(searchInsideContainer ? container : sourceElement );
            bool horizontalDirection = direction == FocusNavigationDirection.Right || direction == FocusNavigationDirection.Left; 

            // Reset the baseline when we change the direction
            ResetBaseLines(horizontalDirection ? sourceRect.Top : sourceRect.Left, horizontalDirection);
 
            // If range is not set - use source rect
            if (startRange == BASELINE_DEFAULT || endRange == BASELINE_DEFAULT) 
            { 
                startRange = horizontalDirection ? sourceRect.Top : sourceRect.Left;
                endRange = horizontalDirection ? sourceRect.Bottom : sourceRect.Right; 
            }

            // Navigate outside the container
            if (mode == KeyboardNavigationMode.Once && !searchInsideContainer) 
                return MoveNext(container, null, direction, startRange, endRange);
 
            DependencyObject result = FindNextInDirection(sourceElement, sourceRect, container, direction, startRange, endRange); 

            // If there is no next element in current container 
            if (result == null)
            {
                switch (mode)
                { 
                    case KeyboardNavigationMode.Cycle:
                        return MoveNext(null, container, direction, startRange, endRange); 
 
                    case KeyboardNavigationMode.Contained:
                        return null; 

                    default: // Continue, Once, None, Local - search outside the container
                        return MoveNext(container, null, direction, startRange, endRange);
                } 
            }
 
            // If the element is focusable and IsTabStop is true 
            if (IsTabStop(result))
                return result; 

            // Using ActiveElement if set
            DependencyObject activeElement = GetActiveElementChain(result);
            if (activeElement != null) 
                return activeElement;
 
            // Try to find focus inside the element 
            // result is not TabStop, which means it is a group
            DependencyObject insideElement = MoveNext(null, result, direction, startRange, endRange); 
            if (insideElement != null)
                return insideElement;

            return MoveNext(result, null, direction, startRange, endRange); 
        }
 
        private DependencyObject GetActiveElementChain(DependencyObject element) 
        {
            DependencyObject validActiveElement = null; 
            DependencyObject activeElement = element;
            while ((activeElement = GetActiveElement(activeElement)) != null)
            {
                if (IsTabStop(activeElement)) 
                    validActiveElement = activeElement;
            } 
 
            return validActiveElement;
        } 

        #endregion Directional Navigation

        #region Global tracking for entering MenuMode 

        // ISSUE: how do we deal with deactivate? 
 
        /////////////////////////////////////////////////////////////////////
        /// 
        /// Critical: accesses e.StagingItem.Input
        ///
        [SecurityCritical]
        private void ProcessForMenuMode(InputEventArgs inputEventArgs) 
        {
            // When ALT or F10 key up happens we should fire the EnterMenuMode event. 
            // We should not fire if: 
            // * there were any handled input events in between the key down and corresponding key up.
            // * another unmatched keydown or keyup happened 
            // * an unhandled mouse down/up happens

            if (inputEventArgs.RoutedEvent == Keyboard.LostKeyboardFocusEvent)
            { 
                KeyboardFocusChangedEventArgs args = inputEventArgs as KeyboardFocusChangedEventArgs;
                if (((args != null) && (args.NewFocus == null)) || inputEventArgs.Handled) 
                { 
                    // Focus went to null, stop tracking the last key down
                    _lastKeyPressed = Key.None; 
                }
            }
            // If a key is pressed down, remember it until the corresponding
            // key up.  Ignore repeated keydowns. 
            else if (inputEventArgs.RoutedEvent == Keyboard.KeyDownEvent)
            { 
                if (inputEventArgs.Handled) 
                    _lastKeyPressed = Key.None;
                else 
                {
                    KeyEventArgs keyEventArgs = inputEventArgs as KeyEventArgs;

                    if (!keyEventArgs.IsRepeat) 
                    {
                        if (_lastKeyPressed == Key.None) 
                        { 
                            if ((Keyboard.Modifiers & (ModifierKeys.Control | ModifierKeys.Shift | ModifierKeys.Windows)) == ModifierKeys.None)
                            { 
                                _lastKeyPressed = GetRealKey(keyEventArgs);
                            }
                        }
                        else 
                        {
                            // Another key was pressed down in between the one that we're tracking, so reset. 
                            _lastKeyPressed = Key.None; 
                        }
 
                        // Clear this bit, Win32 will see message and clear QF_FMENUSTATUS.
                        _win32MenuModeWorkAround = false;
                    }
                } 
            }
            // If a key up is received and matches the last key down 
            // and is a key that would cause us to enter menumode, 
            // raise the (internal) EnterMenuMode event.
            else if (inputEventArgs.RoutedEvent == Keyboard.KeyUpEvent) 
            {
                if (!inputEventArgs.Handled)
                {
                    KeyEventArgs keyEventArgs = inputEventArgs as KeyEventArgs; 
                    Key realKey = GetRealKey(keyEventArgs);
 
                    if (realKey == _lastKeyPressed && IsMenuKey(realKey)) 
                    {
                        EnableKeyboardCues(keyEventArgs.Source as DependencyObject, true); 
                        keyEventArgs.Handled = OnEnterMenuMode(keyEventArgs.Source);
                    }

                    if (_win32MenuModeWorkAround) 
                    {
                        if (IsMenuKey(realKey)) 
                        { 
                            _win32MenuModeWorkAround = false;
 
                            // Mark the event args as handled so that Win32 never
                            // sees this key up and doesn't enter menu-mode.
                            keyEventArgs.Handled = true;
                        } 
                    }
                    // If someone was listening for MenuMode and did something, 
                    // we need to make sure we don't let Win32 enter menu mode. 
                    else if (keyEventArgs.Handled)
                    { 
                        // Set this bit to true, this means that we will handle
                        // the next ALT-up if no one else does.
                        _win32MenuModeWorkAround = true;
                    } 
                }
                // No matter what we should reset and not track the last key anymore. 
                _lastKeyPressed = Key.None; 
            }
            // The following input events act to "cancel" the EnterMenuMode event 
            else if (inputEventArgs.RoutedEvent == Mouse.MouseDownEvent
                  || inputEventArgs.RoutedEvent == Mouse.MouseUpEvent)
            {
                _lastKeyPressed = Key.None; 

                // Win32 will see this message and will set QF_FMENUSTATUS to false. 
                _win32MenuModeWorkAround = false; 
            }
        } 

        private bool IsMenuKey(Key key)
        {
            return (key == Key.LeftAlt || key == Key.RightAlt || key == Key.F10); 
        }
 
        private Key GetRealKey(KeyEventArgs e) 
        {
            return (e.Key == Key.System) ? e.SystemKey : e.Key; 
        }

        /// 
        ///   SecurityCritical:This code gets  PresentationSource and passes it to event handlers 
        ///   TreatAsSafe: This code is safe inspite of passing the object because of 3 reasons
        ///                        1. We have a demand on adding the event handler so that no one external can attach 
        ///                        2. The one event handler that we are aware of does not expose the object 
        ///                        3. This code in the worst case will cause your app to go to menu mode
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private bool OnEnterMenuMode(object eventSource)
        {
            if (_weakEnterMenuModeHandlers == null) 
                return false;
 
            lock (_weakEnterMenuModeHandlers) 
            {
                if (_weakEnterMenuModeHandlers.Count == 0) 
                {
                    return false;
                }
 
                // Bug 940610: no way to get PresentationSource of event in PostProcessInput
                // WORKAROUND: For now I will try to get the source of the event with 
                //             PresentationSource.FromVisual.  If that fails, try to get the 
                //             source of the active window.
                PresentationSource source = null; 

                if (eventSource != null)
                {
                    Visual eventSourceVisual = eventSource as Visual; 
                    source = (eventSourceVisual != null) ? PresentationSource.CriticalFromVisual(eventSourceVisual) : null;
                } 
                else 
                {
                    // If Keyboard.FocusedElement is null we'll have to fall back here. 
                    IntPtr activeWindow = MS.Win32.UnsafeNativeMethods.GetActiveWindow();

                    if (activeWindow != IntPtr.Zero)
                    { 
                        source = HwndSource.CriticalFromHwnd(activeWindow);
                    } 
                } 

                // Can't fire the event if the event didn't happen in any source 
                if (source == null)
                {
                    return false;
                } 

                EventArgs e = EventArgs.Empty; 
                bool handled = false; 

                for (int i = 0; i < _weakEnterMenuModeHandlers.Count; i++) 
                {
                    EnterMenuModeEventHandler currentHandler = _weakEnterMenuModeHandlers[i].Target as EnterMenuModeEventHandler;

                    if (currentHandler != null) 
                    {
                        if (currentHandler(source, e)) 
                        { 
                            handled = true;
                            break; 
                        }
                    }
                    else
                    { 
                        _weakEnterMenuModeHandlers.RemoveAt(i);
                        i--; 
                    } 
                }
 
                return handled;
            }
        }
 
        /// 
        ///     Called when ALT or F10 is pressed anywhere in the global scope 
        ///  
        /// 
        ///     Critical: This code causes the handler attached to get an object of type presentationsource 
        ///                  The add is critical, the remove is ok
        ///     TreatAsSafe: There is a demand on this
        /// 
        internal event EnterMenuModeEventHandler EnterMenuMode 
        {
            [SecurityCritical,SecurityTreatAsSafe] 
            add 
            {
                SecurityHelper.DemandUIWindowPermission(); 

                if (_weakEnterMenuModeHandlers == null)
                    _weakEnterMenuModeHandlers = new List(1);
 
                lock (_weakEnterMenuModeHandlers)
                { 
                    // Cleanup the list in case some of the weakEnterMenuModeHandlers is disposed 
                    for (int i = 0; i < _weakEnterMenuModeHandlers.Count; i++)
                    { 
                        if (!(_weakEnterMenuModeHandlers[i].Target is EnterMenuModeEventHandler))
                        {
                            _weakEnterMenuModeHandlers.RemoveAt(i);
                            i--; 
                        }
                    } 
                    _weakEnterMenuModeHandlers.Add(new WeakReference(value)); 
                }
            } 
            remove
            {
                if (_weakEnterMenuModeHandlers != null)
                { 
                    lock (_weakEnterMenuModeHandlers)
                    { 
                        for (int i = 0; i < _weakEnterMenuModeHandlers.Count; i++) 
                        {
                            EnterMenuModeEventHandler current = _weakEnterMenuModeHandlers[i].Target as EnterMenuModeEventHandler; 

                            if (current == null || current == value)
                            {
                                _weakEnterMenuModeHandlers.RemoveAt(i); 
                                i--;
                            } 
                        } 
                    }
                } 
            }
        }

        internal delegate bool EnterMenuModeEventHandler(object sender, EventArgs e); 

        // Used to track what the last key was pressed so that 
        // we can fire the EnterMenuMode event. 
        // Will be reset to Key.None when an unmatched KeyUp or other input event happens
        private Key _lastKeyPressed = Key.None; 

        // List of WeakReferences to delegates to be invoked when EnterMenuMode happens
        private List _weakEnterMenuModeHandlers;
 
        // Fix for bug 936302: (JevanSa)
        //     The DefaultWindowProcWorker (windows/core/ntuser/kernel/dwp.c) 
        //     listens for ALT down followed by ALT up with nothing in between. 
        //     When ALT goes down they set QF_FMENUSTATUS.  When ALT up happens,
        //     if QF_FMENUSTATUS is still set, they open the system menu (or 
        //     menu for the window if there is one).  If any keystrokes happen
        //     in between, they clear QF_FMENUSTATUS.
        //
        //     Consider the following sequence: 
        //       1) KeyDown(Alt) - neither Win32 nor Avalon respond
        //       2) KeyUp(Alt) - Avalon handles the event, Win32 is skipped 
        //       3) KeyDown(Alt) - Avalon handles the event, Win32 is skipped 
        //       4) KeyUp(Alt) - Avalon does not respond, Win32 handles the message
        //                       (and enters "Invisible" MenuMode) 
        //
        //     Here, from the point of view of the DWP, there was just ALT down
        //     followed by ALT up.  We must fool the DWP somehow so that they
        //     clear clear the QF_FMENUSTATUS bit before #4. 
        //
        //     Currently the best way DwayneN and I have come up with is to 
        //     mark the event has handled in case #4 so that the DWP 
        //     never sees the ALT up in #4.  We set this bit when #2 happens.
        //     If we see an unhandled ALT-up and this bit is set, we mark the 
        //     event as handled.  If we see any unhandled key down or mouse up/down
        //     we can clear this bit.
        private bool _win32MenuModeWorkAround;
 
        #endregion
 
        #region UIState 

        ///  
        ///     Critical: accesses the RawUIStateInputReport
        /// 
        [SecurityCritical]
        private void ProcessForUIState(InputEventArgs inputEventArgs) 
        {
            PresentationSource source; 
            RawUIStateInputReport report = ExtractRawUIStateInputReport(inputEventArgs, InputManager.InputReportEvent); 

            if (report != null && (source = report.InputSource) != null) 
            {
                // handle accelerator cue display
                if ((report.Targets & RawUIStateTargets.HideAccelerators) != 0)
                { 
                    Visual root = source.RootVisual;
                    bool enable = (report.Action == RawUIStateActions.Clear); 
 
                    EnableKeyboardCues(root, enable);
                } 
            }
        }

        ///  
        ///     Critical: accesses the RawUIStateInputReport
        ///  
        [SecurityCritical] 
        private RawUIStateInputReport ExtractRawUIStateInputReport(InputEventArgs e, RoutedEvent Event)
        { 
            RawUIStateInputReport uiStateInputReport = null;
            InputReportEventArgs input = e as InputReportEventArgs;

            if (input != null) 
            {
                if (input.Report.Type == InputType.Keyboard && input.RoutedEvent == Event) 
                { 
                    uiStateInputReport = input.Report as RawUIStateInputReport;
                } 
            }

            return uiStateInputReport;
        } 

        #endregion UIState 
 
        #region FocusEnterMainFocusScope weak event
 
        // The event is raised when KeyboardFocus enters the main focus scope (visual tree root)
        // Selector and TreeView listen for this event to update their ActiveSelection property
        internal event EventHandler FocusEnterMainFocusScope
        { 
            add
            { 
                lock (_weakFocusEnterMainFocusScopeHandlers) 
                {
                    _weakFocusEnterMainFocusScopeHandlers.Add(new WeakReference(value)); 
                }
            }
            remove
            { 
                lock (_weakFocusEnterMainFocusScopeHandlers)
                { 
                    for (int i = 0; i < _weakFocusEnterMainFocusScopeHandlers.Count; i++) 
                    {
                        object handler = _weakFocusEnterMainFocusScopeHandlers[i].Target; 
                        if (handler == null || (EventHandler)handler == value)
                        {
                            _weakFocusEnterMainFocusScopeHandlers.RemoveAt(i);
                            i--; 
                        }
                    } 
                } 
            }
        } 

        private void NotifyFocusEnterMainFocusScope(object sender, EventArgs e)
        {
            if (_weakFocusEnterMainFocusScopeHandlers != null) 
            {
                for (int i = 0; i < _weakFocusEnterMainFocusScopeHandlers.Count; i++) 
                { 
                    EventHandler handler = _weakFocusEnterMainFocusScopeHandlers[i].Target as EventHandler;
                    if (handler != null) 
                    {
                        handler(sender, e);
                    }
                    else 
                    {
                        _weakFocusEnterMainFocusScopeHandlers.RemoveAt(i); 
                        i--; 
                    }
                } 
            }
        }

        private List _weakFocusEnterMainFocusScopeHandlers = new List(1); 
        #endregion
 
        #region Data 

        private const double BASELINE_DEFAULT = Double.MinValue; 
        private double _verticalBaseline = BASELINE_DEFAULT;
        private double _horizontalBaseline = BASELINE_DEFAULT;
        private DependencyProperty _navigationProperty = null;
        private Hashtable _containerHashtable = new Hashtable(10); 
        private static object _fakeNull = new object();
 
        #endregion Data 
    }
} 



 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK