MouseDevice.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Input / MouseDevice.cs / 1305600 / MouseDevice.cs

                            using System.Diagnostics; 
using System.Collections;
using System.Windows;
using System.Windows.Media;
using System.Windows.Interop; 
using System.Windows.Threading;
using System.Security; 
using System.Security.Permissions; 
using MS.Internal;
using MS.Internal.PresentationCore;                        // SecurityHelper 
using MS.Win32; // *NativeMethods
using System.Runtime.InteropServices;
using System;
 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID; 
 
#pragma warning disable 1634, 1691  // suppressing PreSharp warnings
 
// There's a choice of where to send MouseWheel events - to the element under
// the mouse (like IE does) or to the element with keyboard focus (like Win32
// does).  The latter choice lets you move the mouse away from the area you're
// scrolling and still use the wheel.  To get this effect, uncomment this line. 
//#define SEND_WHEEL_EVENTS_TO_FOCUS
 
 
namespace System.Windows.Input
{ 
    /// 
    ///     The MouseDevice class represents the mouse device to the
    ///     members of a context.
    ///  
    public abstract class MouseDevice : InputDevice
    { 
        ///  
        /// Critical - This is code that elevates AND creates the mouse device which
        ///             happens to hold the callback to filter mouse messages 
        /// TreatAsSafe: This constructor handles critical data but does not expose it
        ///             It stores instance but there are demands on the instances.
        /// 
       [SecurityCritical,SecurityTreatAsSafe] 
       internal MouseDevice(InputManager inputManager)
       { 
            _inputManager = new SecurityCriticalData(inputManager); 
            _inputManager.Value.PreProcessInput += new PreProcessInputEventHandler(PreProcessInput);
            _inputManager.Value.PreNotifyInput += new NotifyInputEventHandler(PreNotifyInput); 
            _inputManager.Value.PostProcessInput += new ProcessInputEventHandler(PostProcessInput);

            // Get information about how far two clicks of a double click can be considered
            // to be in the "same place and time". 
            //
            // The call here goes into the safe helper calls, more of a consistency in approach 
            // 
            _doubleClickDeltaX = SafeSystemMetrics.DoubleClickDeltaX;
            _doubleClickDeltaY = SafeSystemMetrics.DoubleClickDeltaY; 
            _doubleClickDeltaTime = SafeNativeMethods.GetDoubleClickTime();

            _overIsEnabledChangedEventHandler = new DependencyPropertyChangedEventHandler(OnOverIsEnabledChanged);
            _overIsVisibleChangedEventHandler = new DependencyPropertyChangedEventHandler(OnOverIsVisibleChanged); 
            _overIsHitTestVisibleChangedEventHandler  = new DependencyPropertyChangedEventHandler(OnOverIsHitTestVisibleChanged);
            _reevaluateMouseOverDelegate = new DispatcherOperationCallback(ReevaluateMouseOverAsync); 
            _reevaluateMouseOverOperation = null; 

            _captureIsEnabledChangedEventHandler = new DependencyPropertyChangedEventHandler(OnCaptureIsEnabledChanged); 
            _captureIsVisibleChangedEventHandler = new DependencyPropertyChangedEventHandler(OnCaptureIsVisibleChanged);
            _captureIsHitTestVisibleChangedEventHandler  = new DependencyPropertyChangedEventHandler(OnCaptureIsHitTestVisibleChanged);
            _reevaluateCaptureDelegate = new DispatcherOperationCallback(ReevaluateCaptureAsync);
            _reevaluateCaptureOperation = null; 

            _inputManager.Value.HitTestInvalidatedAsync += new EventHandler(OnHitTestInvalidatedAsync); 
        } 

        ///  
        ///     Gets the current state of the specified button from the device from either the underlying system or the StylusDevice
        /// 
        /// 
        ///     The mouse button to get the state of 
        /// 
        ///  
        ///     The state of the specified mouse button 
        /// 
        protected MouseButtonState GetButtonState(MouseButton mouseButton) 
        {
            if ( _stylusDevice != null )
                return _stylusDevice.GetMouseButtonState(mouseButton, this);
            else 
                return GetButtonStateFromSystem(mouseButton);
        } 
 
        /// 
        ///     Gets the current position of the mouse in screen co-ords from either the underlying system or the StylusDevice 
        /// 
        /// 
        ///     The current mouse location in screen co-ords
        ///  
        protected Point GetScreenPosition()
        { 
            if (_stylusDevice != null) 
                return _stylusDevice.GetMouseScreenPosition(this);
            else 
                return GetScreenPositionFromSystem();
        }

        ///  
        ///     Gets the current state of the specified button from the device from the underlying system
        ///  
        ///  
        ///     The mouse button to get the state of
        ///  
        /// 
        ///     The state of the specified mouse button
        /// 
        internal abstract MouseButtonState GetButtonStateFromSystem(MouseButton mouseButton); 

        ///  
        ///     Gets the current position of the mouse in screen co-ords from the underlying system 
        /// 
        ///  
        ///     The current mouse location in screen co-ords
        /// 
        /// 
        ///     Critical: accesses critical data (CriticalActiveSource) 
        ///     TreatAsSafe: doesn't expose critical data, just returns screen coordinates of non-critical data
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal Point GetScreenPositionFromSystem()
        { 
            // Win32 has issues reliably returning where the mouse is.  Until we figure
            // out a better way, just return the last mouse position in screen coordinates.

            Point ptScreen = new Point(0, 0); 

            // Security Mitigation: do not give out input state if the device is not active. 
            if (IsActive) 
            {
                try 
                {
                    PresentationSource activeSource = CriticalActiveSource;
                    if (activeSource != null)
                    { 
                        ptScreen = PointUtil.ClientToScreen(_lastPosition, activeSource);
                    } 
                } 
                catch (System.ComponentModel.Win32Exception)
                { 
                    // The window could be shutting down, so just return (0,0).
                    ptScreen = new Point(0, 0);
                }
            } 

            return ptScreen; 
        } 

        ///  
        ///     Gets the current position of the mouse in client co-ords of the current PresentationSource
        /// 
        /// 
        ///     The current mouse position in client co-ords 
        /// 
        ///  
        ///     Critical: Accesses SecurityCritical data CriticalActiveSource 
        ///     TreatAsSafe: Only uses it to pass to through to overloaded version of this method which
        ///                  in turn only uses it to pass to PointUtil.ScreenToClient to convert mouse 
        ///                  position from screen to client co-ords
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        protected Point GetClientPosition() 
        {
            Point ptClient = new Point(0, 0); 
            try 
            {
                PresentationSource activeSource = CriticalActiveSource; 
                if (activeSource != null)
                {
                    ptClient = GetClientPosition(activeSource);
                } 
            }
            catch (System.ComponentModel.Win32Exception) 
            { 
                // The window could be shutting down, so just return (0,0).
                ptClient = new Point(0, 0); 
            }

            return ptClient;
        } 

        ///  
        ///     Gets the current position of the mouse in client co-ords of the specified PresentationSource 
        /// 
        ///  
        ///     The current mouse position in client co-ords
        /// 
        protected Point GetClientPosition(PresentationSource presentationSource)
        { 
            Point ptScreen = GetScreenPosition();
            Point ptClient = PointUtil.ScreenToClient(ptScreen, presentationSource); 
 
            return ptClient;
        } 

        /// 
        ///     Returns the element that input from this device is sent to.
        ///  
        public override IInputElement Target
        { 
            get 
            {
//                 VerifyAccess(); 

                // Return the element that the mouse is over.  If the mouse
                // has been captured, the mouse will be considered "over"
                // the capture point if the mouse is outside of the 
                // captured element (or subtree).
                return _mouseOver; 
            } 
        }
 
        /// 
        ///     Returns the PresentationSource that is reporting input for this device.
        /// 
        ///  
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///  
        /// 
        /// Critical - accesses critical data ( _activeSource)
        /// PublicOK - there is a demand. 
        ///

        public override PresentationSource ActiveSource
        { 
            [SecurityCritical ]
            get 
            { 
                SecurityHelper.DemandUIWindowPermission();
                if (_inputSource != null) 
                {
                    return _inputSource.Value;
                }
                return null; 
            }
        } 
 
        /// 
        ///     Returns the PresentationSource that is reporting input for this device. 
        /// 
        /// 
        ///     Critical - accesses critical data (_inputSource) and returns it.
        ///  
        internal PresentationSource CriticalActiveSource
        { 
            [SecurityCritical] 
            get
            { 
                if (_inputSource != null)
                {
                    return _inputSource.Value;
                } 
                return null;
            } 
        } 

        ///  
        ///     Returns the element that the mouse is over.
        /// 
        /// 
        ///     The mouse is considered directly over an element if the mouse 
        ///     has been captured to that element.
        ///  
        public IInputElement DirectlyOver 
        {
            get 
            {
//                 VerifyAccess();
                return _mouseOver;
            } 
        }
 
        ///  
        ///     Returns the element that the mouse is over regardless of
        ///     its IsEnabled state. 
        /// 
        [FriendAccessAllowed]
        internal IInputElement RawDirectlyOver
        { 
            get
            { 
                if (_rawMouseOver != null) 
                {
                    IInputElement rawMouseOver = (IInputElement)_rawMouseOver.Target; 
                    if (rawMouseOver != null)
                    {
                        return rawMouseOver;
                    } 
                }
 
                return DirectlyOver; 
            }
        } 

        /// 
        ///     Returns the element that has captured the mouse.
        ///  
        public IInputElement Captured
        { 
            get 
            {
//                 VerifyAccess(); 
                return _mouseCapture;
            }
        }
 
        /// 
        ///     Returns the element that has captured the mouse. 
        ///  
        internal CaptureMode CapturedMode
        { 
            get
            {
                return _captureMode;
            } 
        }
 
        ///  
        ///     Captures the mouse to a particular element.
        ///  
        public bool Capture(IInputElement element)
        {
            return Capture(element, CaptureMode.Element);
        } 

        ///  
        ///     Captures the mouse to a particular element. 
        /// 
        ///  
        ///     Critical: This element acceses PresentationSource , MouseInputProvider (critical data)
        ///     PublicOK: This operation is inherently safe and does not store or expose the critical data
        /// 
        [SecurityCritical] 
        public bool Capture(IInputElement element, CaptureMode captureMode)
        { 
            int timeStamp = Environment.TickCount; 
//             VerifyAccess();
 
            if (!(captureMode == CaptureMode.None || captureMode == CaptureMode.Element || captureMode == CaptureMode.SubTree))
            {
                throw new System.ComponentModel.InvalidEnumArgumentException("captureMode", (int)captureMode, typeof(CaptureMode));
            } 

            if (element == null) 
            { 
                captureMode = CaptureMode.None;
            } 

            if (captureMode == CaptureMode.None)
            {
                element = null; 
            }
 
            // Validate that elt is either a UIElement or a ContentElement 
            DependencyObject eltDO = element as DependencyObject;
            if (eltDO != null && !InputElement.IsValid(element)) 
            {
                throw new InvalidOperationException(SR.Get(SRID.Invalid_IInputElement, eltDO.GetType()));
            }
 
            bool success = false;
 
            // The element we are capturing to must be both enabled and visible. 
            if (element is UIElement)
            { 
                UIElement e = element as UIElement;

                #pragma warning suppress 6506 // e is obviously not null
                if(e.IsVisible && e.IsEnabled) 
                {
                    success = true; 
                } 
            }
            else if (element is ContentElement) 
            {
                ContentElement ce = element as ContentElement;

                #pragma warning suppress 6506 // ce is obviosuly not null 
                if(ce.IsEnabled) // There is no IsVisible property for ContentElement
                { 
                    success = true; 
                }
            } 
            else if (element is UIElement3D)
            {
                UIElement3D e = element as UIElement3D;
 
                #pragma warning suppress 6506 // e is obviously not null
                if(e.IsVisible && e.IsEnabled) 
                { 
                    success = true;
                } 
            }
            else
            {
                // Setting capture to null. 
                success = true;
            } 
 
            if(success)
            { 
                success = false;

                // Find a mouse input provider that provides input for either
                // the new element (if taking capture) or the existing capture 
                // element (if releasing capture).
                IMouseInputProvider mouseInputProvider = null; 
                if (element != null) 
                {
                    DependencyObject containingVisual = InputElement.GetContainingVisual(eltDO); 
                    if (containingVisual != null)
                    {
                        PresentationSource captureSource = PresentationSource.CriticalFromVisual(containingVisual);
                        if (captureSource != null) 
                        {
                            mouseInputProvider = captureSource.GetInputProvider(typeof(MouseDevice)) as IMouseInputProvider; 
                        } 
                    }
                } 
                else if (_mouseCapture != null)
                {
                    mouseInputProvider = _providerCapture.Value;
                } 

                // If we found a mouse input provider, ask it to either capture 
                // or release the mouse for us. 
                if(mouseInputProvider != null)
                { 
                    if (element != null)
                    {
                        success = mouseInputProvider.CaptureMouse();
 
                        if (success)
                        { 
                            ChangeMouseCapture(element, mouseInputProvider, captureMode, timeStamp); 
                        }
                    } 
                    else
                    {
                        mouseInputProvider.ReleaseMouseCapture();
 
                        // If we had capture, the input provider will release it.  That will
                        // cause a RawMouseAction.CancelCapture to be processed, which will 
                        // update our internal states. 
                        success = true;
                    } 
                }
            }

            return success; 
        }
 
        // 
        // Find an IMouseInputProvider on which the cursor can be set
        /// 
        ///     Critical: This code accesses critical data (InputManager and InputProviders).
        ///               It also returns critical data
        /// 
        [SecurityCritical] 
        private IMouseInputProvider FindMouseInputProviderForCursor( )
        { 
            // The shape of this API goes on the assumption that, like Win32, the cursor 
            // is set for the whole desktop, not just a particular element or a particular
            // root visual.  So instead of trying to find the IMouseInputProvider 
            // that covers a particular element, we just find any IMouseInputProvider
            // and set the cursor on it.

            IMouseInputProvider mouseInputProvider = null; 

            IEnumerator inputProviders = _inputManager.Value.UnsecureInputProviders.GetEnumerator(); 
 
            while (inputProviders.MoveNext())
            { 
                IMouseInputProvider provider = inputProviders.Current as IMouseInputProvider;
                if (provider != null )
                {
                    mouseInputProvider = provider; 
                    break;
                } 
            } 

            return mouseInputProvider; 

        }

        ///  
        /// The override cursor
        ///  
        public Cursor OverrideCursor 
        {
            get 
            {
//                 VerifyAccess();

                return _overrideCursor; 
            }
 
            set 
            {
//                 VerifyAccess(); 

                _overrideCursor = value;
                UpdateCursorPrivate();
            } 
        }
 
        ///  
        /// Set the cursor
        ///  
        /// The new cursor
        /// Note that this cursor doesn't apply any particular UIElement, it applies
        ///          to the whole desktop.
        ///  
        /// 
        ///     Critical: Cause an elevation to unmanaged Code permission, also accesses critical data MouseInputProvider 
        ///     PublicOK: Calling SetCursor is a safe operation since it only affects current app.Also it does not 
        ///     expose critical data (IMouseInputProvider)
        ///  
        [SecurityCritical]
        public bool SetCursor(Cursor cursor)
        {
//             VerifyAccess(); 

            // Override the cursor if one is set. 
            if (_overrideCursor != null) 
            {
                cursor = _overrideCursor; 
            }

            if (cursor == null)
            { 
                cursor = Cursors.None;
            } 
            // Get a mouse provider 
            IMouseInputProvider mouseInputProvider = FindMouseInputProviderForCursor();
 
            // If we found one, set the cursor
            if (mouseInputProvider != null)
                return mouseInputProvider.SetCursor(cursor);
            else 
                return false;
 
        } 

        ///  
        ///     The state of the left button.
        /// 
        public MouseButtonState LeftButton
        { 
            get
            { 
                return GetButtonState(MouseButton.Left); 
            }
        } 

        /// 
        ///     The state of the right button.
        ///  
        public MouseButtonState RightButton
        { 
            get 
            {
                return GetButtonState(MouseButton.Right); 
            }
        }

        ///  
        ///     The state of the middle button.
        ///  
        public MouseButtonState MiddleButton 
        {
            get 
            {
                return GetButtonState(MouseButton.Middle);
            }
        } 

        ///  
        ///     The state of the first extended button. 
        /// 
        public MouseButtonState XButton1 
        {
            get
            {
                return GetButtonState(MouseButton.XButton1); 
            }
        } 
 
        /// 
        ///     The state of the second extended button. 
        /// 
        public MouseButtonState XButton2
        {
            get 
            {
                return GetButtonState(MouseButton.XButton2); 
            } 
        }
 
        /// 
        ///     Calculates the position of the mouse relative to
        ///     a particular element.
        ///  
        ///
        ///     Critical - accesses critical data _inputSource.Value 
        ///     PublicOK - we do the elevation of _inputSource to get RootVisual. 
        ///
        [SecurityCritical  ] 
        public Point GetPosition(IInputElement relativeTo)
        {
//             VerifyAccess();
 
            // Validate that relativeTo is either a UIElement or a ContentElement
            if (relativeTo != null && !InputElement.IsValid(relativeTo)) 
            { 
                throw new InvalidOperationException(SR.Get(SRID.Invalid_IInputElement, relativeTo.GetType()));
            } 

            PresentationSource relativePresentationSource = null;

            if (relativeTo != null) 
            {
                DependencyObject dependencyObject = relativeTo as  DependencyObject; 
                DependencyObject containingVisual = InputElement.GetContainingVisual(dependencyObject); 

                if (containingVisual != null) 
                {
                    relativePresentationSource = PresentationSource.CriticalFromVisual(containingVisual);
                }
            } 
            else
            { 
                if (_inputSource != null) 
                {
                    relativePresentationSource = _inputSource.Value; 
                }
            }

 
            // Verify that we have a valid PresentationSource with a valid RootVisual
            // - if we don't we won't be able to invoke ClientToRoot or TranslatePoint and 
            //   we will just return 0,0 
            if (relativePresentationSource == null || relativePresentationSource.RootVisual == null)
            { 
                return new Point(0, 0);
            }

            Point ptClient; 
            Point ptRoot;
            bool success; 
            Point ptRelative; 

            ptClient    = GetClientPosition(relativePresentationSource); 
            ptRoot      = PointUtil.TryClientToRoot(ptClient, relativePresentationSource, false, out success);
            if (!success)
            {
                // ClientToRoot failed, usually because the client area is degenerate. 
                // Just return 0,0
                return new Point(0, 0); 
            } 
            ptRelative  = InputElement.TranslatePoint(ptRoot, relativePresentationSource.RootVisual, (DependencyObject)relativeTo);
 
            return ptRelative;
        }

        ///  
        /// 
        internal void ReevaluateMouseOver(DependencyObject element, DependencyObject oldParent, bool isCoreParent) 
        { 
            if (element != null)
            { 
                if (isCoreParent)
                {
                    MouseOverTreeState.SetCoreParent(element, oldParent);
                } 
                else
                { 
                    MouseOverTreeState.SetLogicalParent(element, oldParent); 
                }
            } 

            // It would be best to re-evaluate anything dependent on the hit-test results
            // immediately after layout & rendering are complete.  Unfortunately this can
            // lead to an infinite loop.  Consider the following scenario: 
            //
            // If the mouse is over an element, hide it. 
            // 
            // This never resolves to a "correct" state.  When the mouse moves over the
            // element, the element is hidden, so the mouse is no longer over it, so the 
            // element is shown, but that means the mouse is over it again.  Repeat.
            //
            // We push our re-evaluation to a priority lower than input processing so that
            // the user can change the input device to avoid the infinite loops, or close 
            // the app if nothing else works.
            // 
            if (_reevaluateMouseOverOperation == null) 
            {
                _reevaluateMouseOverOperation = Dispatcher.BeginInvoke(DispatcherPriority.Input, _reevaluateMouseOverDelegate, null); 
            }
        }

        ///  
        /// 
        ///  
        ///  
        private object ReevaluateMouseOverAsync(object arg)
        { 
            _reevaluateMouseOverOperation = null;

            Synchronize();
 
            // Refresh MouseOverProperty so that ReverseInherited Flags are updated.
            // 
            // We only need to do this is there is any information about the old 
            // tree state.  This is because it is possible (even likely) that
            // Synchronize() would have already done this if we hit-tested to a 
            // different element.
            if (_mouseOverTreeState != null && !_mouseOverTreeState.IsEmpty)
            {
                UIElement.MouseOverProperty.OnOriginValueChanged(_mouseOver as DependencyObject, _mouseOver as DependencyObject, ref _mouseOverTreeState); 
            }
 
            return null; 
        }
 
        /// 
        /// 
        internal void ReevaluateCapture(DependencyObject element, DependencyObject oldParent, bool isCoreParent)
        { 
            if (element != null)
            { 
                if (isCoreParent) 
                {
                    MouseCaptureWithinTreeState.SetCoreParent(element, oldParent); 
                }
                else
                {
                    MouseCaptureWithinTreeState.SetLogicalParent(element, oldParent); 
                }
            } 
 
            // We re-evaluate the captured element to be consistent with how
            // we re-evaluate the element the mouse is over. 
            //
            // See ReevaluateMouseOver for details.
            //
            if (_reevaluateCaptureOperation == null) 
            {
                _reevaluateCaptureOperation = Dispatcher.BeginInvoke(DispatcherPriority.Input, _reevaluateCaptureDelegate, null); 
            } 
        }
 
        /// 
        ///
        /// 
        ///  
        /// 
        private object ReevaluateCaptureAsync(object arg) 
        { 
            _reevaluateCaptureOperation = null;
 
            if (_mouseCapture == null )
                return null;

            bool killCapture = false; 

            DependencyObject dependencyObject = _mouseCapture as DependencyObject; 
 
            //
            // First, check things like IsEnabled, IsVisible, etc. on a 
            // UIElement vs. ContentElement basis.
            //
            if (InputElement.IsUIElement(dependencyObject))
            { 
                killCapture = !ValidateUIElementForCapture((UIElement)_mouseCapture);
            } 
            else if (InputElement.IsContentElement(dependencyObject)) 
            {
                killCapture = !ValidateContentElementForCapture((ContentElement)_mouseCapture); 
            }
            else if (InputElement.IsUIElement3D(dependencyObject))
            {
                killCapture = !ValidateUIElement3DForCapture((UIElement3D)_mouseCapture); 
            }
 
            // 
            // Second, if we still haven't thought of a reason to kill capture, validate
            // it on a Visual basis for things like still being in the right tree. 
            //
            if (killCapture == false)
            {
                DependencyObject containingVisual = InputElement.GetContainingVisual(dependencyObject); 
                killCapture = !ValidateVisualForCapture(containingVisual);
            } 
 
            //
            // Lastly, if we found any reason above, kill capture. 
            //
            if (killCapture)
            {
                Capture(null); 
            }
 
            // Refresh MouseCaptureWithinProperty so that ReverseInherited flags are updated. 
            //
            // We only need to do this is there is any information about the old 
            // tree state.  This is because it is possible (even likely) that
            // we would have already killed capture if the capture criteria was
            // no longer met.
            if (_mouseCaptureWithinTreeState != null && !_mouseCaptureWithinTreeState.IsEmpty) 
            {
                UIElement.MouseCaptureWithinProperty.OnOriginValueChanged(_mouseCapture as DependencyObject, _mouseCapture as DependencyObject, ref _mouseCaptureWithinTreeState); 
            } 

            return null; 
        }

        private bool ValidateUIElementForCapture(UIElement element)
        { 
            if (element.IsEnabled == false)
                return false; 
 
            if (element.IsVisible == false)
                return false; 

            if (element.IsHitTestVisible == false)
                return false;
 
            return true;
        } 
 
        private bool ValidateUIElement3DForCapture(UIElement3D element)
        { 
            if (element.IsEnabled == false)
                return false;

            if (element.IsVisible == false) 
                return false;
 
            if (element.IsHitTestVisible == false) 
                return false;
 
            return true;
        }

 
        private bool ValidateContentElementForCapture(ContentElement element)
        { 
            if (element.IsEnabled == false) 
                return false;
 
            // NOTE: there are no IsVisible or IsHitTestVisible properties for ContentElements.

            return true;
        } 

        ///  
        ///     Critical: This code accesses critical data (CriticalActiveSource) 
        ///     TreatAsSafe: Although it accesses critical data it does not modify or expose it, only compares against it.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private bool ValidateVisualForCapture(DependencyObject visual)
        {
            if (visual == null) 
                return false;
 
            PresentationSource presentationSource = PresentationSource.CriticalFromVisual(visual); 

            if (presentationSource == null) 
                return false;

            if (presentationSource != CriticalActiveSource)
                return false; 

            return true; 
        } 

        private void OnOverIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) 
        {
            // The element that the mouse is over just became disabled.
            //
            // We need to resynchronize the mouse so that we can figure out who 
            // the mouse is over now.
 
            ReevaluateMouseOver(null, null, true); 
        }
 
        private void OnOverIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            // The element that the mouse is over just became non-visible (collapsed or hidden).
            // 
            // We need to resynchronize the mouse so that we can figure out who
            // the mouse is over now. 
 
            ReevaluateMouseOver(null, null, true);
        } 

        private void OnOverIsHitTestVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            // The element that the mouse is over was affected by a change in hit-test visibility. 
            //
            // We need to resynchronize the mouse so that we can figure out who 
            // the mouse is over now. 

            ReevaluateMouseOver(null, null, true); 
        }

        private void OnCaptureIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
        { 
            // The element that the mouse is captured to just became disabled.
            // 
            // We need to re-evaluate the element that has mouse capture since 
            // we can't allow the mouse to remain captured by a disabled element.
 
            ReevaluateCapture(null, null, true);
        }

        private void OnCaptureIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) 
        {
            // The element that the mouse is captured to just became non-visible (collapsed or hidden). 
            // 
            // We need to re-evaluate the element that has mouse capture since
            // we can't allow the mouse to remain captured by a non-visible element. 

            ReevaluateCapture(null, null, true);
        }
 
        private void OnCaptureIsHitTestVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        { 
            // The element that the mouse is captured to was affected by a change in hit-test visibility. 
            //
            // We need to re-evaluate the element that has mouse capture since 
            // we can't allow the mouse to remain captured by a non-hittest-visible element.

            ReevaluateCapture(null, null, true);
        } 

        private void OnHitTestInvalidatedAsync(object sender, EventArgs e) 
        { 
            // The hit-test result may have changed.
            Synchronize(); 
        }

        /// 
        ///     Forces the mouse to resynchronize. 
        /// 
        ///  
        ///     Critical - asserts HwndSource via CriticalActiveSource 
        ///     PublicOK: This code does not expose the HwndSource or store it, nor is
        ///                 this operation risky. 
        /// 
        [SecurityCritical]
        public void Synchronize()
        { 
            // System.Console.WriteLine("Synchronize");
//             VerifyAccess(); 
 
            // Simulate a mouse move
            PresentationSource activeSource = CriticalActiveSource; 
            if (activeSource != null && activeSource.CompositionTarget != null && !activeSource.CompositionTarget.IsDisposed)
            {
                int timeStamp = Environment.TickCount;
                Point ptClient = GetClientPosition(); 

                RawMouseInputReport report = new RawMouseInputReport(InputMode.Foreground, 
                                                                     timeStamp, 
                                                                     activeSource,
                                                                     RawMouseActions.AbsoluteMove, 
                                                                     (int) ptClient.X,
                                                                     (int) ptClient.Y,
                                                                     0,
                                                                     IntPtr.Zero); 
                report._isSynchronize = true;
 
                InputReportEventArgs inputReportEventArgs; 
                if (_stylusDevice != null)
                { 
                    // if we have a current stylusdevice .. use it
                    inputReportEventArgs = new InputReportEventArgs(_stylusDevice, report);
                }
                else 
                {
                    inputReportEventArgs = new InputReportEventArgs(this, report); 
                } 

                inputReportEventArgs.RoutedEvent=InputManager.PreviewInputReportEvent; 

                //ProcessInput has a linkdemand
                _inputManager.Value.ProcessInput(inputReportEventArgs);
            } 
        }
 
        ///  
        ///     Forces the mouse cursor to be updated.
        ///  
        public void UpdateCursor()
        {
            // Call Forwarded
            UpdateCursorPrivate(); 
        }
 
        ///  
        ///     Forces the mouse cursor to be updated.
        ///  
        /// 
        ///     This method has been added just because changing the public
        ///     API UpdateCursor will be a breaking change
        ///  
        /// 
        ///     Critical:This code access input manager and causes cursor to be updated 
        ///     TreatAsSafe: No risky critical data stored and inputs and outputs are safe. 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        private bool UpdateCursorPrivate()
        {
            int timeStamp = Environment.TickCount;
            QueryCursorEventArgs queryCursor = new QueryCursorEventArgs(this, timeStamp); 
            queryCursor.Cursor = Cursors.Arrow;
            queryCursor.RoutedEvent=Mouse.QueryCursorEvent; 
            //ProcessInput has a linkdemand 
            _inputManager.Value.ProcessInput(queryCursor);
            return queryCursor.Handled; 
        }

        /// 
        ///     Critical: This code accesses link demanded method PresentationSource.AddSourcechangedhandler 
        ///     and remove for the same
        ///     TreatAsSafe: This code does not expose the PresentationSource and simply changes the mouse over element 
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private void ChangeMouseOver(IInputElement mouseOver, int timestamp) 
        {
            DependencyObject o = null;

            if (_mouseOver != mouseOver) 
            {
                // Console.WriteLine("ChangeMouseOver(" + mouseOver + ")"); 
 
                // Update the critical piece of data.
                IInputElement oldMouseOver = _mouseOver; 
                _mouseOver = mouseOver;

                using(Dispatcher.DisableProcessing()) // Disable reentrancy due to locks taken
                { 
                    // Adjust the handlers we use to track everything.
                    if(oldMouseOver != null) 
                    { 
                        o = oldMouseOver as DependencyObject;
                        if (InputElement.IsUIElement(o)) 
                        {
                            ((UIElement)o).IsEnabledChanged -= _overIsEnabledChangedEventHandler;
                            ((UIElement)o).IsVisibleChanged -= _overIsVisibleChangedEventHandler;
                            ((UIElement)o).IsHitTestVisibleChanged -= _overIsHitTestVisibleChangedEventHandler; 
                        }
                        else if (InputElement.IsContentElement(o)) 
                        { 
                            ((ContentElement)o).IsEnabledChanged -= _overIsEnabledChangedEventHandler;
 
                            // NOTE: there are no IsVisible or IsHitTestVisible properties for ContentElements.
                            //
                            // ((ContentElement)o).IsVisibleChanged -= _overIsVisibleChangedEventHandler;
                            // ((ContentElement)o).IsHitTestVisibleChanged -= _overIsHitTestVisibleChangedEventHandler; 
                        }
                        else if (InputElement.IsUIElement3D(o)) 
                        { 
                            ((UIElement3D)o).IsEnabledChanged -= _overIsEnabledChangedEventHandler;
                            ((UIElement3D)o).IsVisibleChanged -= _overIsVisibleChangedEventHandler; 
                            ((UIElement3D)o).IsHitTestVisibleChanged -= _overIsHitTestVisibleChangedEventHandler;
                        }
                    }
                    if(_mouseOver != null) 
                    {
                        o = _mouseOver as DependencyObject; 
                        if (InputElement.IsUIElement(o)) 
                        {
                            ((UIElement)o).IsEnabledChanged += _overIsEnabledChangedEventHandler; 
                            ((UIElement)o).IsVisibleChanged += _overIsVisibleChangedEventHandler;
                            ((UIElement)o).IsHitTestVisibleChanged += _overIsHitTestVisibleChangedEventHandler;
                        }
                        else if (InputElement.IsContentElement(o)) 
                        {
                            ((ContentElement)o).IsEnabledChanged += _overIsEnabledChangedEventHandler; 
 
                            // NOTE: there are no IsVisible or IsHitTestVisible properties for ContentElements.
                            // 
                            // ((ContentElement)o).IsVisibleChanged += _overIsVisibleChangedEventHandler;
                            // ((ContentElement)o).IsHitTestVisibleChanged += _overIsHitTestVisibleChangedEventHandler;
                        }
                        else if (InputElement.IsUIElement3D(o)) 
                        {
                            ((UIElement3D)o).IsEnabledChanged += _overIsEnabledChangedEventHandler; 
                            ((UIElement3D)o).IsVisibleChanged += _overIsVisibleChangedEventHandler; 
                            ((UIElement3D)o).IsHitTestVisibleChanged += _overIsHitTestVisibleChangedEventHandler;
                        } 
                    }
                }

                // Oddly enough, update the IsMouseOver property first.  This is 
                // so any callbacks will see the more-common IsMouseOver property
                // set correctly. 
                UIElement.MouseOverProperty.OnOriginValueChanged(oldMouseOver as DependencyObject, _mouseOver as DependencyObject, ref _mouseOverTreeState); 

                // Invalidate the IsMouseDirectlyOver property. 
                if (oldMouseOver != null)
                {
                    o = oldMouseOver as DependencyObject;
                    o.SetValue(UIElement.IsMouseDirectlyOverPropertyKey, false); // Same property for ContentElements 
                }
                if (_mouseOver != null) 
                { 
                    o = _mouseOver as DependencyObject;
                    o.SetValue(UIElement.IsMouseDirectlyOverPropertyKey, true); // Same property for ContentElements 
                }
            }
        }
        ///  
        ///     Critical: This code acceses InputManager and MouseProvider which are critical data.
        ///               It also calls into ProcessInput which is a critical method and could be used 
        ///               for input spoofing. 
        ///     TreatAsSafe: This operation is ok to expose since mouse capture is ok. Even if you get the
        ///               source changed events you cannot get to the sources themselves 
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        private void ChangeMouseCapture(IInputElement mouseCapture, IMouseInputProvider providerCapture, CaptureMode captureMode, int timestamp)
        { 
            DependencyObject o = null;
 
            if(mouseCapture != _mouseCapture) 
            {
                // Console.WriteLine("ChangeMouseCapture(" + mouseCapture + ")"); 

                // Update the critical pieces of data.
                IInputElement oldMouseCapture = _mouseCapture;
                _mouseCapture = mouseCapture; 
                if (_mouseCapture != null)
                { 
                    _providerCapture = new SecurityCriticalDataClass(providerCapture); 
                }
                else 
                {
                    _providerCapture = null;
                }
                _captureMode = captureMode; 

                using (Dispatcher.DisableProcessing()) // Disable reentrancy due to locks taken 
                { 
                    // Adjust the handlers we use to track everything.
                    if (oldMouseCapture != null) 
                    {
                        o = oldMouseCapture as DependencyObject;
                        if (InputElement.IsUIElement(o))
                        { 
                            ((UIElement)o).IsEnabledChanged -= _captureIsEnabledChangedEventHandler;
                            ((UIElement)o).IsVisibleChanged -= _captureIsVisibleChangedEventHandler; 
                            ((UIElement)o).IsHitTestVisibleChanged -= _captureIsHitTestVisibleChangedEventHandler; 
                        }
                        else if (InputElement.IsContentElement(o)) 
                        {
                            ((ContentElement)o).IsEnabledChanged -= _captureIsEnabledChangedEventHandler;

                            // NOTE: there are no IsVisible or IsHitTestVisible properties for ContentElements. 
                            //
                            // ((ContentElement)o).IsVisibleChanged -= _captureIsVisibleChangedEventHandler; 
                            // ((ContentElement)o).IsHitTestVisibleChanged -= _captureIsHitTestVisibleChangedEventHandler; 
                        }
                        else if (InputElement.IsUIElement3D(o)) 
                        {
                            ((UIElement3D)o).IsEnabledChanged -= _captureIsEnabledChangedEventHandler;
                            ((UIElement3D)o).IsVisibleChanged -= _captureIsVisibleChangedEventHandler;
                            ((UIElement3D)o).IsHitTestVisibleChanged -= _captureIsHitTestVisibleChangedEventHandler; 
                        }
                    } 
                    if (_mouseCapture != null) 
                    {
                        o = _mouseCapture as DependencyObject; 
                        if (InputElement.IsUIElement(o))
                        {
                            ((UIElement)o).IsEnabledChanged += _captureIsEnabledChangedEventHandler;
                            ((UIElement)o).IsVisibleChanged += _captureIsVisibleChangedEventHandler; 
                            ((UIElement)o).IsHitTestVisibleChanged += _captureIsHitTestVisibleChangedEventHandler;
                        } 
                        else if (InputElement.IsContentElement(o)) 
                        {
                            ((ContentElement)o).IsEnabledChanged += _captureIsEnabledChangedEventHandler; 

                            // NOTE: there are no IsVisible or IsHitTestVisible properties for ContentElements.
                            //
                            // ((ContentElement)o).IsVisibleChanged += _captureIsVisibleChangedEventHandler; 
                            // ((ContentElement)o).IsHitTestVisibleChanged += _captureIsHitTestVisibleChangedEventHandler;
                        } 
                        else if (InputElement.IsUIElement3D(o)) 
                        {
                            ((UIElement3D)o).IsEnabledChanged += _captureIsEnabledChangedEventHandler; 
                            ((UIElement3D)o).IsVisibleChanged += _captureIsVisibleChangedEventHandler;
                            ((UIElement3D)o).IsHitTestVisibleChanged += _captureIsHitTestVisibleChangedEventHandler;
                        }
                    } 
                }
 
                // Oddly enough, update the IsMouseCaptureWithin property first.  This is 
                // so any callbacks will see the more-common IsMouseCaptureWithin property
                // set correctly. 
                UIElement.MouseCaptureWithinProperty.OnOriginValueChanged(oldMouseCapture as DependencyObject, _mouseCapture as DependencyObject, ref _mouseCaptureWithinTreeState);

                // Invalidate the IsMouseCaptured properties.
                if (oldMouseCapture != null) 
                {
                    o = oldMouseCapture as DependencyObject; 
                    o.SetValue(UIElement.IsMouseCapturedPropertyKey, false); // Same property for ContentElements 
                }
                if (_mouseCapture != null) 
                {
                    o = _mouseCapture as DependencyObject;
                    o.SetValue(UIElement.IsMouseCapturedPropertyKey, true); // Same property for ContentElements
                } 

                // Send the LostMouseCapture and GotMouseCapture events. 
                if (oldMouseCapture != null) 
                {
                    MouseEventArgs lostCapture = new MouseEventArgs(this, timestamp, _stylusDevice); 
                    lostCapture.RoutedEvent=Mouse.LostMouseCaptureEvent;
                    lostCapture.Source= oldMouseCapture;
                    //ProcessInput has a linkdemand
                    _inputManager.Value.ProcessInput(lostCapture); 
                }
                if (_mouseCapture != null) 
                { 
                    MouseEventArgs gotCapture = new MouseEventArgs(this, timestamp, _stylusDevice);
                    gotCapture.RoutedEvent=Mouse.GotMouseCaptureEvent; 
                    gotCapture.Source= _mouseCapture;
                    //ProcessInput has a linkdemand
                    _inputManager.Value.ProcessInput(gotCapture);
                } 

                // Force a mouse move so we can update the mouse over. 
                Synchronize(); 
            }
        } 

        /// 
        ///  Critical: This code acceses data that was got from an unsafe call (_doubleClickDeltaX,_doubleClickDeltaX)
        ///            It also accesses HwndSource and InputManager and can be used for Input spoofing. 
        ///            accesses e.StagingItem.Input
        ///  
        [SecurityCritical] 
        private void PreProcessInput(object sender, PreProcessInputEventArgs e)
        { 
            if (e.StagingItem.Input.RoutedEvent == InputManager.PreviewInputReportEvent)
            {
                InputReportEventArgs inputReportEventArgs = e.StagingItem.Input as InputReportEventArgs;
 
                if (!inputReportEventArgs.Handled && inputReportEventArgs.Report.Type == InputType.Mouse)
                { 
                    RawMouseInputReport rawMouseInputReport = (RawMouseInputReport)inputReportEventArgs.Report; 

 
                    // Normally we only process mouse input that is from our
                    // active visual manager.  The only exception to this is
                    // the activate report, which is how we change the visual
                    // manager that is active. 
                    if ((rawMouseInputReport.Actions & RawMouseActions.Activate) == RawMouseActions.Activate)
                    { 
                        // Console.WriteLine("RawMouseActions.Activate"); 

                        // If other actions are being reported besides the 
                        // activate, separate them into different events.
                        if ((rawMouseInputReport.Actions & ~RawMouseActions.Activate) != 0)
                        {
                            // Cancel this event.  We'll push a new event for the activate. 
                            e.Cancel();
 
                            // Push a new RawMouseInputReport for the non-activate actions. 
                            RawMouseInputReport reportActions = new RawMouseInputReport(rawMouseInputReport.Mode,
                                                                                        rawMouseInputReport.Timestamp, 
                                                                                        rawMouseInputReport.InputSource,
                                                                                        rawMouseInputReport.Actions & ~RawMouseActions.Activate,
                                                                                        rawMouseInputReport.X,
                                                                                        rawMouseInputReport.Y, 
                                                                                        rawMouseInputReport.Wheel,
                                                                                        rawMouseInputReport.ExtraInformation); 
                            InputReportEventArgs actionsArgs = new InputReportEventArgs(inputReportEventArgs.Device, reportActions); 
                            actionsArgs.RoutedEvent=InputManager.PreviewInputReportEvent;
                            e.PushInput(actionsArgs, null); 

                            // Create a new RawMouseInputReport for the activate.
                            RawMouseInputReport reportActivate = new RawMouseInputReport(rawMouseInputReport.Mode,
                                                                                         rawMouseInputReport.Timestamp, 
                                                                                         rawMouseInputReport.InputSource,
                                                                                         RawMouseActions.Activate, 
                                                                                         rawMouseInputReport.X, 
                                                                                         rawMouseInputReport.Y,
                                                                                         rawMouseInputReport.Wheel, 
                                                                                         rawMouseInputReport.ExtraInformation);

                            // Push a new RawMouseInputReport for the activate.
                            InputReportEventArgs activateArgs = new InputReportEventArgs(inputReportEventArgs.Device, reportActivate); 
                            activateArgs.RoutedEvent=InputManager.PreviewInputReportEvent;
                            e.PushInput(activateArgs, null); 
                        } 
                    }
                    // Only process mouse input that is from our active PresentationSource. 
                    else if ((_inputSource != null) && (rawMouseInputReport.InputSource == _inputSource.Value))
                    {
                        // We need to remember the StylusDevice that generated this input.  Use the _tagStylusDevice
                        // to store this in before we take over the inputReport Device and loose it.  Any 
                        // input reports we re-push need to preserve this too.  This is used to set the StylusDevice
                        // property on MouseEventArgs. 
                        InputDevice inputDevice = e.StagingItem.GetData(_tagStylusDevice) as StylusDevice; 

                        if (inputDevice == null) 
                        {
                            inputDevice = inputReportEventArgs.Device as StylusDevice;
                            if (inputDevice != null)
                            { 
                                e.StagingItem.SetData(_tagStylusDevice, inputDevice);
                            } 
                        } 

                        // Claim the input for the mouse. 
                        inputReportEventArgs.Device = this;

                        // If the input is reporting mouse deactivation, we need
                        // to ensure that the element receives a final leave. 
                        // Note that activation could have been moved to another
                        // visual manager in our app, which means that the leave 
                        // was already sent.  So only do this if the deactivate 
                        // event is from the visual manager that we think is active.
                        if ((rawMouseInputReport.Actions & RawMouseActions.Deactivate) == RawMouseActions.Deactivate) 
                        {
                            if (_mouseOver != null)
                            {
                                // Push back this event, and cancel the current processing. 
                                e.PushInput(e.StagingItem);
                                e.Cancel(); 
                                _isPhysicallyOver = false; 
                                ChangeMouseOver(null, e.StagingItem.Input.Timestamp);
                            } 
                        }

                        // If the input is reporting mouse movement, we need to check
                        // if we need to update our sense of "mouse over". 
                        //
                        if ((rawMouseInputReport.Actions & RawMouseActions.AbsoluteMove) == RawMouseActions.AbsoluteMove) 
                        { 
                            // If other actions are being reported besides the
                            // move, separate them into different events. 
                            if ((rawMouseInputReport.Actions & ~(RawMouseActions.AbsoluteMove | RawMouseActions.QueryCursor)) != 0)
                            {
                                // Cancel this event.  We'll push a new event for the move.
                                e.Cancel(); 

                                // Push a new RawMouseInputReport for the non-move actions. 
                                RawMouseInputReport reportActions = new RawMouseInputReport(rawMouseInputReport.Mode, 
                                                                                            rawMouseInputReport.Timestamp,
                                                                                            rawMouseInputReport.InputSource, 
                                                                                            rawMouseInputReport.Actions & ~(RawMouseActions.AbsoluteMove | RawMouseActions.QueryCursor),
                                                                                            0,
                                                                                            0,
                                                                                            rawMouseInputReport.Wheel, 
                                                                                            rawMouseInputReport.ExtraInformation);
                                InputReportEventArgs actionsArgs = new InputReportEventArgs(inputDevice, reportActions); 
                                actionsArgs.RoutedEvent=InputManager.PreviewInputReportEvent; 
                                e.PushInput(actionsArgs, null);
 
                                // Push a new RawMouseInputReport for the AbsoluteMove.
                                RawMouseInputReport reportMove = new RawMouseInputReport(rawMouseInputReport.Mode,
                                                                                         rawMouseInputReport.Timestamp,
                                                                                         rawMouseInputReport.InputSource, 
                                                                                         rawMouseInputReport.Actions & (RawMouseActions.AbsoluteMove | RawMouseActions.QueryCursor),
                                                                                         rawMouseInputReport.X, 
                                                                                         rawMouseInputReport.Y, 
                                                                                         0,
                                                                                         IntPtr.Zero); 
                                InputReportEventArgs moveArgs = new InputReportEventArgs(inputDevice, reportMove);
                                moveArgs.RoutedEvent=InputManager.PreviewInputReportEvent;
                                e.PushInput(moveArgs, null);
                            } 
                            else
                            { 
                                // Convert the point from client coordinates into "root" coordinates. 
                                // We do this in the pre-process stage because it is possible that
                                // this conversion will fail, in which case we want to cancel the 
                                // mouse move event.
                                bool success = true;
                                Point ptClient = new Point(rawMouseInputReport.X, rawMouseInputReport.Y);
                                Point ptRoot = PointUtil.TryClientToRoot(ptClient, rawMouseInputReport.InputSource, false, out success); 
                                if(success)
                                { 
                                    e.StagingItem.SetData(_tagRootPoint, ptRoot); 
                                }
                                else 
                                {
                                    e.Cancel();
                                }
                            } 
                        }
                    } 
                } 
            }
            else 
            {
                // All mouse event processing should only happen if we still have an active input source.

                if (_inputSource != null) 
                {
                    if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseDownEvent) 
                    { 
                        MouseButtonEventArgs mouseButtonEventArgs = e.StagingItem.Input as MouseButtonEventArgs;
 
                        if (_mouseCapture != null && !_isPhysicallyOver)
                        {
                            // The mouse is not physically over the capture point (or
                            // subtree), so raise the PreviewMouseDownOutsideCapturedElement 
                            // event first.
                            MouseButtonEventArgs clickThrough = new MouseButtonEventArgs(this, mouseButtonEventArgs.Timestamp, mouseButtonEventArgs.ChangedButton, GetStylusDevice(e.StagingItem)); 
                            clickThrough.RoutedEvent=Mouse.PreviewMouseDownOutsideCapturedElementEvent; 
                            //ProcessInput has a linkdemand
                            _inputManager.Value.ProcessInput(clickThrough); 
                        }
                    }

                    else if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseUpEvent) 
                    {
                        MouseButtonEventArgs mouseButtonEventArgs = e.StagingItem.Input as MouseButtonEventArgs; 
 
                        if (_mouseCapture != null && !_isPhysicallyOver)
                        { 
                            // The mouse is not physically over the capture point (or
                            // subtree), so raise the PreviewMouseUpOutsideCapturedElement
                            // event first.
                            MouseButtonEventArgs clickThrough = new MouseButtonEventArgs(this, mouseButtonEventArgs.Timestamp, mouseButtonEventArgs.ChangedButton, GetStylusDevice(e.StagingItem)); 
                            clickThrough.RoutedEvent=Mouse.PreviewMouseUpOutsideCapturedElementEvent;
                            //ProcessInput has a linkdemand 
                            _inputManager.Value.ProcessInput(clickThrough); 
                        }
                    } 
                }
            }

        } 

        ///  
        ///     Critical: This code accesses data that was got off an unmanaged call (_doubleClickDeltaX,_doubleClickDeltaY) 
        ///     It also accesss Input Source and can be used for input spoofing
        ///     accesses e.StagingItem.Input 
        /// 
        [SecurityCritical]
        private void PreNotifyInput(object sender, NotifyInputEventArgs e)
        { 
            if ( e.StagingItem.Input.RoutedEvent == InputManager.PreviewInputReportEvent )
            { 
                InputReportEventArgs inputReportEventArgs = e.StagingItem.Input as InputReportEventArgs; 

                if (!inputReportEventArgs.Handled && inputReportEventArgs.Report.Type == InputType.Mouse) 
                {
                    RawMouseInputReport rawMouseInputReport = (RawMouseInputReport) inputReportEventArgs.Report;

                    // Generally, we need to check against redundant actions. 
                    // We never prevent the raw event from going through, but we
                    // will only generate the high-level events for non-redundant 
                    // actions.  We store the set of non-redundant actions in 
                    // the dictionary of this event.
 
                    // Get the current Non-Redundant Actions for this event and
                    // make a copy.  We will compare the original value against the copy
                    // at the end of this function and write it back in if changed.
 
                    RawMouseActions actions = GetNonRedundantActions(e);
                    RawMouseActions originalActions = actions; 
 
                    _stylusDevice = GetStylusDevice(e.StagingItem);
 
                    // Normally we only process mouse input that is from our
                    // active presentation source.  The only exception to this is
                    // the activate report, which is how we change the visual
                    // manager that is active. 
                    if ((rawMouseInputReport.Actions & RawMouseActions.Activate) == RawMouseActions.Activate)
                    { 
                        // System.Console.WriteLine("Initializing the mouse state."); 

                        actions |= RawMouseActions.Activate; 

                        _positionRelativeToOver.X = 0;
                        _positionRelativeToOver.Y = 0;
 
                        _lastPosition.X = rawMouseInputReport.X;
                        _lastPosition.Y = rawMouseInputReport.Y; 
                        _forceUpdateLastPosition = true; 

                        _stylusDevice = inputReportEventArgs.Device as StylusDevice; 

                        // if the existing source is null, no need to do any special-case handling
                        if (_inputSource == null)
                        { 
                            _inputSource = new SecurityCriticalDataClass(rawMouseInputReport.InputSource);
                        } 
                        // if the new source is the same as the old source, don't bother doing anything 
                        else if (_inputSource.Value != rawMouseInputReport.InputSource)
                        { 
                            IMouseInputProvider toDeactivate = _inputSource.Value.GetInputProvider(typeof(MouseDevice)) as IMouseInputProvider;

                            // All mouse information is now restricted to this presentation source.
                            _inputSource = new SecurityCriticalDataClass(rawMouseInputReport.InputSource); 

                            if (toDeactivate != null) 
                            { 
                                toDeactivate.NotifyDeactivate();
                            } 
                        }
                    }

                    // Only process mouse input that is from our active presentation source. 
                    if ((_inputSource != null) && (rawMouseInputReport.InputSource == _inputSource.Value))
                    { 
                        // If the input is reporting mouse deactivation, we need 
                        // to break any capture we may have.  Note that we only do
                        // this if the presentation source associated with this event 
                        // is the same presentation source we are already over.
                        if ((rawMouseInputReport.Actions & RawMouseActions.Deactivate) == RawMouseActions.Deactivate)
                        {
                            // Console.WriteLine("RawMouseActions.Deactivate"); 
                            Debug.Assert(_mouseOver == null, "_mouseOver should be null because we have called ChangeMouseOver(null) already.");
                            _inputSource = null; 
 
                            ChangeMouseCapture(null, null, CaptureMode.None, e.StagingItem.Input.Timestamp);
                        } 

                        if ((rawMouseInputReport.Actions & RawMouseActions.CancelCapture) == RawMouseActions.CancelCapture)
                        {
                            // Console.WriteLine("RawMouseActions.CancelCapture"); 
                            ChangeMouseCapture(null, null, CaptureMode.None, e.StagingItem.Input.Timestamp);
                        } 
 
                        // If the input is reporting mouse movement, only update the
                        // set of non-redundant actions if the position changed. 
                        if ((rawMouseInputReport.Actions & RawMouseActions.AbsoluteMove) == RawMouseActions.AbsoluteMove) //
                        {
                            //Console.WriteLine("RawMouseActions.AbsoluteMove: X=" + rawMouseInputReport.X + " Y=" + rawMouseInputReport.Y );
 
                            // Translate the mouse coordinates to both root relative and "mouseOver" relate.
                            // - Note: "mouseOver" in this case is the element the mouse "was" over before this move. 
                            bool mouseOverAvailable = false; 
                            Point ptClient = new Point(rawMouseInputReport.X, rawMouseInputReport.Y);
                            Point ptRoot = (Point) e.StagingItem.GetData(_tagRootPoint); 
                            Point ptRelativeToOver = InputElement.TranslatePoint(ptRoot, rawMouseInputReport.InputSource.RootVisual, (DependencyObject)_mouseOver, out mouseOverAvailable);

                            IInputElement mouseOver = _mouseOver; // assume mouse is still over whatever it was before
                            IInputElement rawMouseOver = (_rawMouseOver != null) ? (IInputElement)_rawMouseOver.Target : null; 
                            bool isPhysicallyOver = _isPhysicallyOver;
                            bool isGlobalChange = ArePointsClose(ptClient, _lastPosition) == false;  // determine if the mouse actually physically moved 
 
                            // Invoke Hit Test logic to determine what element the mouse will be over AFTER the move is processed.
                            // - Only do this if: 
                            //      - The mouse physcially moved (isGlobalChange)
                            //      - We are simulating a mouse move (_isSynchronize)
                            //      - mouseOver isn't availabe (!mouseOverAvailable)  Could be caused by a degenerate transform.
                            // - This is to mitigate the redundant AbsoluteMove notifications associated with QueryCursor 
                            if (isGlobalChange || rawMouseInputReport._isSynchronize || !mouseOverAvailable)
                            { 
                                isPhysicallyOver = true;  // assume mouse is physical over element, we'll set it false if it's due to capture 

                                switch (_captureMode) 
                                {
                                    // In this case there is no capture, so a simple hit test will determine which element becomes "mouseOver"
                                    case CaptureMode.None:
                                        { 
                                            if (rawMouseInputReport._isSynchronize)
                                            { 
                                                GlobalHitTest(true, ptClient, _inputSource.Value, out mouseOver, out rawMouseOver); 
                                            }
                                            else 
                                            {
                                                LocalHitTest(true, ptClient, _inputSource.Value, out mouseOver, out rawMouseOver);
                                            }
 
                                            if (mouseOver == rawMouseOver)
                                            { 
                                                // Since they are the same, there is no reason to process rawMouseOver 
                                                rawMouseOver = null;
                                            } 

                                            // We understand UIElements and ContentElements.
                                            // If we are over something else (like a raw visual)
                                            // find the containing element. 
                                            if (!InputElement.IsValid(mouseOver))
                                                mouseOver = InputElement.GetContainingInputElement(mouseOver as DependencyObject); 
                                            if ((rawMouseOver != null) && !InputElement.IsValid(rawMouseOver)) 
                                                rawMouseOver = InputElement.GetContainingInputElement(rawMouseOver as DependencyObject);
                                        } 
                                        break;

                                    // In this case, capture is to a specific element, so it will ALWAYS become "mouseOver"
                                    // - however, we do a hit test to see if the mouse is actually physically over the element, 
                                    // - if it is not, we toggle isPhysicallyOver
                                    case CaptureMode.Element: 
                                        if (rawMouseInputReport._isSynchronize) 
                                        {
                                            mouseOver = GlobalHitTest(true, ptClient, _inputSource.Value); 
                                        }
                                        else
                                        {
                                            mouseOver = LocalHitTest(true, ptClient, _inputSource.Value); 
                                        }
 
                                        // There is no reason to process rawMouseOver when 
                                        // the element should always be the one with mouse capture.
                                        rawMouseOver = null; 

                                        if (mouseOver != _mouseCapture)
                                        {
                                            // Always consider the mouse over the capture point. 
                                            mouseOver = _mouseCapture;
                                            isPhysicallyOver = false; 
                                        } 
                                        break;
 
                                    // In this case, capture is set to an entire subtree.  We use simple hit testing to determine
                                    // which, if any element in the subtree it is over, and set "mouseOver to that element
                                    // If it is not over any specific subtree element, "mouseOver" is set to the root of the subtree.
                                    // - Note: a subtree can span multiple HWNDs 
                                    case CaptureMode.SubTree:
                                        { 
                                            IInputElement mouseCapture = InputElement.GetContainingInputElement(_mouseCapture as DependencyObject); 
                                            if (mouseCapture != null)
                                            { 
                                                // We need to re-hit-test to get the "real" UIElement we are over.
                                                // This allows us to have our capture-to-subtree span multiple windows.

                                                // GlobalHitTest always returns an IInputElement, so we are sure to have one. 
                                                GlobalHitTest(true, ptClient, _inputSource.Value, out mouseOver, out rawMouseOver);
                                            } 
 
                                            if (mouseOver != null && !InputElement.IsValid(mouseOver) )
                                                mouseOver = InputElement.GetContainingInputElement(mouseOver as DependencyObject); 

                                            // Make sure that the element we hit is acutally underneath
                                            // our captured element.  Because we did a global hit test, we
                                            // could have hit an element in a completely different window. 
                                            //
                                            // Note that we support the child being in a completely different window. 
                                            // So we use the GetUIParent method instead of just looking at 
                                            // visual/content parents.
                                            if (mouseOver != null) 
                                            {
                                                IInputElement ieTest = mouseOver;
                                                UIElement eTest = null;
                                                ContentElement ceTest = null; 
                                                UIElement3D e3DTest = null;
 
                                                while (ieTest != null && ieTest != mouseCapture) 
                                                {
                                                    eTest = ieTest as UIElement; 

                                                    if (eTest != null)
                                                    {
                                                        ieTest = InputElement.GetContainingInputElement(eTest.GetUIParent(true)); 
                                                    }
                                                    else 
                                                    { 
                                                        ceTest = ieTest as ContentElement;
 
                                                        if (ceTest != null)
                                                        {
                                                            ieTest = InputElement.GetContainingInputElement(ceTest.GetUIParent(true));
                                                        } 
                                                        else
                                                        { 
                                                            e3DTest = ieTest as UIElement3D; // Should never fail. 

                                                            ieTest = InputElement.GetContainingInputElement(e3DTest.GetUIParent(true)); 
                                                        }
                                                    }
                                                }
 
                                                // If we missed the capture point, we didn't hit anything.
                                                if (ieTest != mouseCapture) 
                                                { 
                                                    mouseOver = _mouseCapture;
                                                    isPhysicallyOver = false; 

                                                    // Since they are the same, there is no reason to process rawMouseOver
                                                    rawMouseOver = null;
                                                } 
                                            }
                                            else 
                                            { 
                                                // We didn't hit anything.  Consider the mouse over the capture point.
                                                mouseOver = _mouseCapture; 
                                                isPhysicallyOver = false;

                                                // Since they are the same, there is no reason to process rawMouseOver
                                                rawMouseOver = null; 
                                            }
 
                                            if (rawMouseOver != null) 
                                            {
                                                if (mouseOver == rawMouseOver) 
                                                {
                                                    // Since they are the same, there is no reason to process rawMouseOver
                                                    rawMouseOver = null;
                                                } 
                                                else if (!InputElement.IsValid(rawMouseOver))
                                                { 
                                                    rawMouseOver = InputElement.GetContainingInputElement(rawMouseOver as DependencyObject); 
                                                }
                                            } 
                                        }
                                        break;
                                }
                            } 

                            _isPhysicallyOver = mouseOver == null ? false : isPhysicallyOver; 
 
                            // Now that we've determine what element the mouse is over now (mouseOver)
                            // - we need to check if it's changed 

                            bool isMouseOverChange = mouseOver != _mouseOver;

                            // If mouseOver changed, we need to recalculate the ptRelativeToOver, because "Over" changed! 

                            if (isMouseOverChange) 
                            { 
                                ptRelativeToOver = InputElement.TranslatePoint(ptRoot, rawMouseInputReport.InputSource.RootVisual, (DependencyObject)mouseOver);
                            } 

                            //Console.WriteLine("RawMouseActions.AbsoluteMove: mouse moved over " + (isMouseOverChange ? "same" : "different") + " element.  old=" + _mouseOver + " new=" + mouseOver);
                            //Console.WriteLine("RawMouseActions.AbsoluteMove: capture=" + _mouseCapture);
 
                            // Check to see if the local mouse position changed.  This can be
                            // caused by a change to the geometry of the 
                            // element we are over or a change in which element 
                            // we are over.
                            // 
                            bool isLocalChange = isMouseOverChange || ArePointsClose(ptRelativeToOver, _positionRelativeToOver) == false;

                            // Console.WriteLine("RawMouseActions.AbsoluteMove: isGlobalChange=" + isGlobalChange + " isLocalChange=" + isLocalChange);
 
                            // We only update our cached position (_lastPosition & _positionRelativeToOver )
                            // if we have moved "far enough" allowing small incrementaly moves to accumulate 
 
                            if (isGlobalChange || isLocalChange || _forceUpdateLastPosition)
                            { 
                                _forceUpdateLastPosition = false;

                                _lastPosition = ptClient;
                                _positionRelativeToOver = ptRelativeToOver; 

                                if (isMouseOverChange) 
                                { 
                                    ChangeMouseOver(mouseOver, e.StagingItem.Input.Timestamp);
                                } 

                                if ((_rawMouseOver == null) && (rawMouseOver != null))
                                {
                                    _rawMouseOver = new WeakReference(rawMouseOver); 
                                }
                                else if (_rawMouseOver != null) 
                                { 
                                    _rawMouseOver.Target = rawMouseOver;
                                } 

                                // Console.WriteLine("RawMouseActions.AbsoluteMove: ptRoot=" + ptRoot);

                                actions |= RawMouseActions.AbsoluteMove; // 

                                // In most cases the sequence of messages received from the system are HitTest, SetCursor & MouseMove. 
                                // The SetCursor message in this case will be traslated into an Avalon MouseMove & QueryCursor. 
                                // The MouseMove message to follow is redundant and is thrown away.
                                // But imagine a case where Capture is taken. Here the system produces only two messages HitTest & MouseMove. 
                                // Hence we translate the MouseMove into an Avalon MouseMove & QueryCursor.
                                // Logically MouseMove and QueryCursor go as a pair.
                                actions |= RawMouseActions.QueryCursor;
                            } 
                        }
 
                        // Mouse wheel rotate events are never considered redundant. 
                        if ((rawMouseInputReport.Actions & RawMouseActions.VerticalWheelRotate) == RawMouseActions.VerticalWheelRotate)
                        { 
                            // Console.WriteLine("RawMouseActions.VerticalWheelRotate");

                            actions |= RawMouseActions.VerticalWheelRotate;
 
                            // Tell the InputManager that the MostRecentDevice is us.
                            _inputManager.Value.MostRecentInputDevice = this; 
                        } 

                        // Mouse query cursor events are never considered redundant. 
                        if ((rawMouseInputReport.Actions & RawMouseActions.QueryCursor) == RawMouseActions.QueryCursor)
                        {
                            // Console.WriteLine("RawMouseActions.QueryCursor");
 
                            actions |= RawMouseActions.QueryCursor;
                        } 
 
                        RawMouseActions[] ButtonPressActions =
                        { 
                            RawMouseActions.Button1Press,
                            RawMouseActions.Button2Press,
                            RawMouseActions.Button3Press,
                            RawMouseActions.Button4Press, 
                            RawMouseActions.Button5Press
                        }; 
 
                        RawMouseActions[] ButtonReleaseActions =
                        { 
                            RawMouseActions.Button1Release,
                            RawMouseActions.Button2Release,
                            RawMouseActions.Button3Release,
                            RawMouseActions.Button4Release, 
                            RawMouseActions.Button5Release
                        }; 
 
                        for (int iButton = 0; iButton < 5; iButton++)
                        { 
                            if ((rawMouseInputReport.Actions & ButtonPressActions[iButton]) == ButtonPressActions[iButton])
                            {
                                actions |= ButtonPressActions[iButton];
 
                                // Tell the InputManager that the MostRecentDevice is us.
                                _inputManager.Value.MostRecentInputDevice = this; 
                            } 

                            if ((rawMouseInputReport.Actions & ButtonReleaseActions[iButton]) == ButtonReleaseActions[iButton]) 
                            {
                                actions |= ButtonReleaseActions[iButton];

                                // Tell the InputManager that the MostRecentDevice is us. 
                                _inputManager.Value.MostRecentInputDevice = this;
                            } 
                        } 
                    }
 
                    if (actions != originalActions)
                    {
                        e.StagingItem.SetData(_tagNonRedundantActions, actions);
                    } 
                }
            } 
            else 
            {
                // All mouse event processing should only happen if we still have an active input source. 

                if (_inputSource != null)
                {
                    // During the PreviewMouseDown event, we update the click count, if there are 
                    // multiple "quick" clicks in approximately the "same" location (as defined
                    // by the hosting environment, aka the registry). 
                    if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseDownEvent) 
                    {
                        MouseButtonEventArgs mouseButtonArgs = e.StagingItem.Input as MouseButtonEventArgs; 
                        StylusDevice stylusDevice = GetStylusDevice(e.StagingItem);
                        Point ptClient = GetClientPosition();

                        _clickCount = CalculateClickCount(mouseButtonArgs.ChangedButton, mouseButtonArgs.Timestamp, stylusDevice, ptClient); 
                        if (_clickCount == 1)
                        { 
                            // we need to reset out data, since this is the start of the click count process... 
                            _lastClick = ptClient;
                            _lastButton = mouseButtonArgs.ChangedButton; 
                            _lastClickTime = mouseButtonArgs.Timestamp;
                        }
                        // Put the updated count into the args.
                        mouseButtonArgs.ClickCount = _clickCount; 
                    }
                } 
            } 
        }
 
        // Due to the inexactness of math calculations of
        // floating-point numbers, we use the AreClose method
        // to determine if the coordinates are close enough
        // to consider the same. 

        private bool ArePointsClose(Point A, Point B) 
        { 
            return MS.Internal.DoubleUtil.AreClose(A.X, B.X) && MS.Internal.DoubleUtil.AreClose(A.Y, B.Y);
        } 

        /// 
        ///     Critical: This code elevates permissions by calling unsafe native methods, also this
        ///     function is not ok to expose publicly and hence the critical. 
        ///     accesses e.StagingItem.Input
        ///  
        [SecurityCritical] 
        private void PostProcessInput(object sender, ProcessInputEventArgs e)
        { 
            // PreviewMouseWheel --> MouseWheel
            if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseWheelEvent)
            {
                if (!e.StagingItem.Input.Handled) 
                {
                    MouseWheelEventArgs previewWheel = (MouseWheelEventArgs) e.StagingItem.Input; 
                    MouseWheelEventArgs wheel = new MouseWheelEventArgs(this, previewWheel.Timestamp, previewWheel.Delta); 
                    wheel.RoutedEvent=Mouse.MouseWheelEvent;
 
                    #if SEND_WHEEL_EVENTS_TO_FOCUS
                    // wheel events are treated as if they came from the
                    // element with keyboard focus
                    wheel.Source = previewWheel.Source; 
                    #endif
 
                    e.PushInput(wheel, e.StagingItem); 
                }
            } 

            // PreviewMouseDown --> MouseDown
            if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseDownEvent)
            { 
                if (!e.StagingItem.Input.Handled)
                { 
                    MouseButtonEventArgs previewDown = (MouseButtonEventArgs) e.StagingItem.Input; 
                    MouseButtonEventArgs down = new MouseButtonEventArgs(this, previewDown.Timestamp, previewDown.ChangedButton, GetStylusDevice(e.StagingItem));
                    down.ClickCount = previewDown.ClickCount; 
                    down.RoutedEvent=Mouse.MouseDownEvent;
                    e.PushInput(down, e.StagingItem);
                }
            } 

            // PreviewMouseUp --> MouseUp 
            if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseUpEvent) 
            {
                if (!e.StagingItem.Input.Handled) 
                {
                    MouseButtonEventArgs previewUp = (MouseButtonEventArgs) e.StagingItem.Input;
                    MouseButtonEventArgs up = new MouseButtonEventArgs(this, previewUp.Timestamp, previewUp.ChangedButton, GetStylusDevice(e.StagingItem));
                    up.RoutedEvent=Mouse.MouseUpEvent; 
                    e.PushInput(up, e.StagingItem);
                } 
            } 

            // PreviewMouseMove --> MouseMove 
            if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseMoveEvent)
            {
                if (!e.StagingItem.Input.Handled)
                { 
                    MouseEventArgs previewMove = (MouseEventArgs) e.StagingItem.Input;
                    MouseEventArgs move = new MouseEventArgs(this, previewMove.Timestamp, GetStylusDevice(e.StagingItem)); 
                    move.RoutedEvent=Mouse.MouseMoveEvent; 
                    e.PushInput(move, e.StagingItem);
                } 
            }

            // We are finished processing the QueryCursor event.  Just update the
            // mouse cursor to be what was decided during the event route. 
            if (e.StagingItem.Input.RoutedEvent == Mouse.QueryCursorEvent)
            { 
 
                QueryCursorEventArgs queryCursor = (QueryCursorEventArgs)e.StagingItem.Input;
 

                SetCursor(queryCursor.Cursor);

            } 

            if (e.StagingItem.Input.RoutedEvent == InputManager.InputReportEvent) 
            { 
                InputReportEventArgs inputReportEventArgs = e.StagingItem.Input as InputReportEventArgs;
 
                if (!inputReportEventArgs.Handled && inputReportEventArgs.Report.Type == InputType.Mouse)
                {
                    RawMouseInputReport rawMouseInputReport = (RawMouseInputReport) inputReportEventArgs.Report;
 
                    // Only process mouse input that is from our active visual manager.
                    if ((_inputSource != null) && (rawMouseInputReport.InputSource == _inputSource.Value)) 
                    { 
                        // In general, this is where we promote the non-redundant
                        // reported actions to our premier events. 
                        RawMouseActions actions = GetNonRedundantActions(e);

                        // Raw Activate --> Raw MouseMove
                        // Whenever the mouse device is activated we need to 
                        // cause a mouse move so that elements realize that
                        // the mouse is over them again.  In most cases, the 
                        // action that caused the mouse to activate is a move, 
                        // but this is to guard against any other cases.
                        if ((actions & RawMouseActions.Activate) == RawMouseActions.Activate) 
                        {
                            Synchronize();
                        }
 
                        // Raw --> PreviewMouseWheel
                        if ((actions & RawMouseActions.VerticalWheelRotate) == RawMouseActions.VerticalWheelRotate) // 
                        { 
                            MouseWheelEventArgs previewWheel = new MouseWheelEventArgs(this, rawMouseInputReport.Timestamp, rawMouseInputReport.Wheel);
 
                            previewWheel.RoutedEvent=Mouse.PreviewMouseWheelEvent;

                            #if SEND_WHEEL_EVENTS_TO_FOCUS
                            // wheel events are treated as if they came from the 
                            // element with keyboard focus
                            DependencyObject focus = Keyboard.FocusedElement as DependencyObject; 
                            if (focus != null) 
                            {
                                previewWheel.Source = focus; 
                            }
                            #endif

                            e.PushInput(previewWheel, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseDown 
                        if ((actions & RawMouseActions.Button1Press) == RawMouseActions.Button1Press)
                        { 
                            MouseButtonEventArgs previewDown = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.Left, GetStylusDevice(e.StagingItem));

                            previewDown.RoutedEvent=Mouse.PreviewMouseDownEvent;
                            e.PushInput(previewDown, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseUp 
                        if ((actions & RawMouseActions.Button1Release) == RawMouseActions.Button1Release)
                        { 
                            MouseButtonEventArgs previewUp = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.Left, GetStylusDevice(e.StagingItem));

                            previewUp.RoutedEvent=Mouse.PreviewMouseUpEvent;
                            e.PushInput(previewUp, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseDown 
                        if ((actions & RawMouseActions.Button2Press) == RawMouseActions.Button2Press)
                        { 
                            MouseButtonEventArgs previewDown = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.Right, GetStylusDevice(e.StagingItem));

                            previewDown.RoutedEvent=Mouse.PreviewMouseDownEvent;
                            e.PushInput(previewDown, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseUp 
                        if ((actions & RawMouseActions.Button2Release) == RawMouseActions.Button2Release)
                        { 
                            MouseButtonEventArgs previewUp = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.Right, GetStylusDevice(e.StagingItem));

                            previewUp.RoutedEvent=Mouse.PreviewMouseUpEvent;
                            e.PushInput(previewUp, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseDown 
                        if ((actions & RawMouseActions.Button3Press) == RawMouseActions.Button3Press)
                        { 
                            MouseButtonEventArgs previewDown = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.Middle, GetStylusDevice(e.StagingItem));

                            previewDown.RoutedEvent=Mouse.PreviewMouseDownEvent;
                            e.PushInput(previewDown, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseUp 
                        if ((actions & RawMouseActions.Button3Release) == RawMouseActions.Button3Release)
                        { 
                            MouseButtonEventArgs previewUp = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.Middle, GetStylusDevice(e.StagingItem));

                            previewUp.RoutedEvent=Mouse.PreviewMouseUpEvent;
                            e.PushInput(previewUp, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseDown 
                        if ((actions & RawMouseActions.Button4Press) == RawMouseActions.Button4Press)
                        { 
                            MouseButtonEventArgs previewDown = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.XButton1, GetStylusDevice(e.StagingItem));

                            previewDown.RoutedEvent=Mouse.PreviewMouseDownEvent;
                            e.PushInput(previewDown, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseUp 
                        if ((actions & RawMouseActions.Button4Release) == RawMouseActions.Button4Release)
                        { 
                            MouseButtonEventArgs previewUp = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.XButton1, GetStylusDevice(e.StagingItem));

                            previewUp.RoutedEvent=Mouse.PreviewMouseUpEvent;
                            e.PushInput(previewUp, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseDown 
                        if ((actions & RawMouseActions.Button5Press) == RawMouseActions.Button5Press)
                        { 
                            MouseButtonEventArgs previewDown = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.XButton2, GetStylusDevice(e.StagingItem));

                            previewDown.RoutedEvent=Mouse.PreviewMouseDownEvent;
                            e.PushInput(previewDown, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseUp 
                        if ((actions & RawMouseActions.Button5Release) == RawMouseActions.Button5Release)
                        { 
                            MouseButtonEventArgs previewUp = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.XButton2, GetStylusDevice(e.StagingItem));

                            previewUp.RoutedEvent=Mouse.PreviewMouseUpEvent;
                            e.PushInput(previewUp, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseMove 
                        if ((actions & RawMouseActions.AbsoluteMove) == RawMouseActions.AbsoluteMove) //
                        { 
                            MouseEventArgs previewMove = new MouseEventArgs(this, rawMouseInputReport.Timestamp, GetStylusDevice(e.StagingItem));

                            previewMove.RoutedEvent=Mouse.PreviewMouseMoveEvent;
                            e.PushInput(previewMove, e.StagingItem); 
                        }
 
                        // Raw --> QueryCursor 
                        if ((actions & RawMouseActions.QueryCursor) == RawMouseActions.QueryCursor)
                        { 
                            inputReportEventArgs.Handled = UpdateCursorPrivate();
                        }
                    }
                } 
            }
        } 
 
        private RawMouseActions GetNonRedundantActions(NotifyInputEventArgs e)
        { 
            RawMouseActions actions = new RawMouseActions();

            // The CLR throws a null-ref exception if it tries to unbox a
            // null.  So we have to special case that. 
            object o = e.StagingItem.GetData(_tagNonRedundantActions);
            if (o != null) 
            { 
                actions = (RawMouseActions) o;
            } 

            return actions;
        }
 
        internal static IInputElement GlobalHitTest(bool clientUnits, Point pt, PresentationSource inputSource)
        { 
            IInputElement enabledHit; 
            IInputElement originalHit;
            GlobalHitTest(clientUnits, pt, inputSource, out enabledHit, out originalHit); 

            return enabledHit;
        }
 
        internal static IInputElement GlobalHitTest(Point ptClient, PresentationSource inputSource)
        { 
            return GlobalHitTest(true, ptClient, inputSource); 
        }
 
        // Take a point relative the the specified visual manager, and translate
        // up to the screen, hit-test to a window, and then hit-test down to an
        // element.
        ///  
        ///     Critical: This code accesses PresentationSource and returns element which is hittest
        ///     TreatAsSafe: This function is safe to expose. Only the element being clicked on is returned. 
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private static void GlobalHitTest(bool clientUnits, Point pt, PresentationSource inputSource, out IInputElement enabledHit, out IInputElement originalHit) 
        {
            enabledHit = originalHit = null;

            Point ptClient = clientUnits ? pt : PointUtil.RootToClient(pt, inputSource); 

            // Note: this only works for HWNDs for now. 
            HwndSource source = inputSource as HwndSource; 
            if (source != null && source.CompositionTarget != null && !source.IsHandleNull)
            { 

                Point ptScreen = PointUtil.ClientToScreen(ptClient, source);
                IntPtr hwndHit = IntPtr.Zero ;
                HwndSource sourceHit = null ; 

                // Hit-test for a window. 
                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); // BlessedAssert: 
                try
                { 
                    // Find the HWND under the point.
                    hwndHit = UnsafeNativeMethods.WindowFromPoint((int)ptScreen.X, (int)ptScreen.Y);

                    // Make sure the window is enabled! 
                    if (!SafeNativeMethods.IsWindowEnabled(new HandleRef(null, hwndHit)))
                    { 
                        hwndHit = IntPtr.Zero; 
                    }
                } 
                finally
                {
                    CodeAccessPermission.RevertAssert();
                } 
                if (hwndHit != IntPtr.Zero)
                { 
                    // See if this is one of our windows. 
                    sourceHit = HwndSource.CriticalFromHwnd(hwndHit);
                } 
                if (sourceHit != null && sourceHit.Dispatcher == inputSource.CompositionTarget.Dispatcher)
                {
                    Point ptClientHit = PointUtil.ScreenToClient(ptScreen, sourceHit);
 
                    // Perform a local hit-test within this visual manager.
                    LocalHitTest(true, ptClientHit, sourceHit, out enabledHit, out originalHit); 
                } 
            }
        } 

        internal static IInputElement LocalHitTest(bool clientUnits, Point pt, PresentationSource inputSource)
        {
            IInputElement enabledHit; 
            IInputElement originalHit;
            LocalHitTest(clientUnits, pt, inputSource, out enabledHit, out originalHit); 
 
            return enabledHit;
        } 

        internal static IInputElement LocalHitTest(Point ptClient, PresentationSource inputSource)
        {
            return LocalHitTest(true, ptClient, inputSource); 
        }
 
        // Take a point relative the the specified visual manager and hit-test 
        // down to an element.
        ///  
        ///     Critical: This code accesses PresentationSource and returns element which is hittest
        ///     TreatAsSafe: This function is safe to expose. Only the element being clicked on is returned.
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        private static void LocalHitTest(bool clientUnits, Point pt, PresentationSource inputSource, out IInputElement enabledHit, out IInputElement originalHit)
        { 
            enabledHit = originalHit = null; 

            // Hit-test starting from the root UIElement. 
            // Note: this restricts us to windows with UIElement as the root (not just visuals).
            if (inputSource != null)
            {
                UIElement root = inputSource.RootVisual as UIElement; 
                if(root != null)
                { 
                    Point rootPt = clientUnits ? PointUtil.ClientToRoot(pt, inputSource) : pt; 
                    root.InputHitTest(rootPt, out enabledHit, out originalHit);
                } 
            }
        }

        internal bool IsSameSpot(Point newPosition, StylusDevice stylusDevice) 
        {
            int doubleClickDeltaX = (stylusDevice != null)?stylusDevice.DoubleTapDeltaX:_doubleClickDeltaX; 
            int doubleClickDeltaY = (stylusDevice != null)?stylusDevice.DoubleTapDeltaY:_doubleClickDeltaY; 

            // Is the delta coordinates of this click close enough to the last click? 
            return (Math.Abs(newPosition.X - _lastClick.X) < doubleClickDeltaX) &&
                   (Math.Abs(newPosition.Y - _lastClick.Y) < doubleClickDeltaY);
        }
 
        internal int CalculateClickCount(MouseButton button, int timeStamp, StylusDevice stylusDevice, Point downPt)
        { 
            // How long since the last click? 
            int timeSpan = timeStamp - _lastClickTime;
 
            int doubleClickDeltaTime = (stylusDevice != null)?stylusDevice.DoubleTapDeltaTime:_doubleClickDeltaTime;

            // Is the delta coordinates of this click close enough to the last click?
            bool isSameSpot = IsSameSpot(downPt, stylusDevice); 

            // Is this the same mouse button as the last click? 
            bool isSameButton = (_lastButton == button); 

            // Now check everything to see if this is a multi-click. 
            if (timeSpan < doubleClickDeltaTime
                  && isSameSpot
                  && isSameButton)
            { 
                // Yes, increment the count
                return _clickCount +1; 
            } 
            else
            { 
                // No, not a multi-click.
                return 1;
            }
        } 

        internal Point PositionRelativeToOver 
        { 
            get
            { 
                return _positionRelativeToOver;
            }
        }
 
        internal Point NonRelativePosition
        { 
            get 
            {
                return _lastPosition; 
            }
        }

        ///  
        ///     Critical: accesses critical data (_inputSource)
        ///     TreatAsSafe: doesn't expose critical data, just returns true/false. 
        ///  
        internal bool IsActive
        { 
            [SecurityCritical, SecurityTreatAsSafe]
            get
            {
                return _inputSource != null && _inputSource.Value != null; 
            }
        } 
 
        // Helper to access the StylusDevice property.
        private StylusDevice GetStylusDevice(StagingAreaInputItem stagingItem) 
        {
            return stagingItem.GetData(_tagStylusDevice) as StylusDevice;
        }
 
        internal StylusDevice StylusDevice
        { 
            get 
            {
                return _stylusDevice; 
            }
        }

        private DeferredElementTreeState MouseOverTreeState 
        {
            get 
            { 
                if (_mouseOverTreeState == null)
                { 
                    _mouseOverTreeState = new DeferredElementTreeState();
                }

                return _mouseOverTreeState; 
            }
        } 
 
        private DeferredElementTreeState MouseCaptureWithinTreeState
        { 
            get
            {
                if (_mouseCaptureWithinTreeState == null)
                { 
                    _mouseCaptureWithinTreeState = new DeferredElementTreeState();
                } 
 
                return _mouseCaptureWithinTreeState;
            } 
        }

        /// 
        ///     This data is not safe to expose as it holds refrence to PresentationSource 
        /// 
        private SecurityCriticalDataClass _inputSource; 
 
        /// 
        ///     This data is not safe to expose as it holds refrence to PresentationSource 
        /// 
        private SecurityCriticalData _inputManager;

        private IInputElement _mouseOver; 
        private DeferredElementTreeState _mouseOverTreeState;
        private bool _isPhysicallyOver; 
        private WeakReference _rawMouseOver; 

        private IInputElement _mouseCapture; 
        private DeferredElementTreeState _mouseCaptureWithinTreeState;
        private SecurityCriticalDataClass _providerCapture;
        private CaptureMode _captureMode;
 
        private DependencyPropertyChangedEventHandler _overIsEnabledChangedEventHandler;
        private DependencyPropertyChangedEventHandler _overIsVisibleChangedEventHandler; 
        private DependencyPropertyChangedEventHandler _overIsHitTestVisibleChangedEventHandler; 
        private DispatcherOperationCallback _reevaluateMouseOverDelegate;
        private DispatcherOperation _reevaluateMouseOverOperation; 

        private DependencyPropertyChangedEventHandler _captureIsEnabledChangedEventHandler;
        private DependencyPropertyChangedEventHandler _captureIsVisibleChangedEventHandler;
        private DependencyPropertyChangedEventHandler _captureIsHitTestVisibleChangedEventHandler; 
        private DispatcherOperationCallback _reevaluateCaptureDelegate;
        private DispatcherOperation _reevaluateCaptureOperation; 
 
        // Device state we track
        private Point _positionRelativeToOver = new Point(); 
        private Point _lastPosition = new Point();
        private bool _forceUpdateLastPosition = false;

        // Data tags for information we pass around the staging area. 
        private object _tagNonRedundantActions = new object();
        private object _tagStylusDevice = new object(); 
        private object _tagRootPoint = new object(); 

        // Information used to distinguish double-clicks (actually, multi clicks) from 
        // multiple independent clicks.
        private Point _lastClick = new Point();
        private MouseButton _lastButton;
        private int _clickCount; 
        private int _lastClickTime;
        private int _doubleClickDeltaTime; 
        private int _doubleClickDeltaX; 
        private int _doubleClickDeltaY;
 
        private Cursor _overrideCursor;

        // Reference to StylusDevice to defer to for physical mouse state (position/button state)
        private StylusDevice _stylusDevice = null; 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System.Diagnostics; 
using System.Collections;
using System.Windows;
using System.Windows.Media;
using System.Windows.Interop; 
using System.Windows.Threading;
using System.Security; 
using System.Security.Permissions; 
using MS.Internal;
using MS.Internal.PresentationCore;                        // SecurityHelper 
using MS.Win32; // *NativeMethods
using System.Runtime.InteropServices;
using System;
 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID; 
 
#pragma warning disable 1634, 1691  // suppressing PreSharp warnings
 
// There's a choice of where to send MouseWheel events - to the element under
// the mouse (like IE does) or to the element with keyboard focus (like Win32
// does).  The latter choice lets you move the mouse away from the area you're
// scrolling and still use the wheel.  To get this effect, uncomment this line. 
//#define SEND_WHEEL_EVENTS_TO_FOCUS
 
 
namespace System.Windows.Input
{ 
    /// 
    ///     The MouseDevice class represents the mouse device to the
    ///     members of a context.
    ///  
    public abstract class MouseDevice : InputDevice
    { 
        ///  
        /// Critical - This is code that elevates AND creates the mouse device which
        ///             happens to hold the callback to filter mouse messages 
        /// TreatAsSafe: This constructor handles critical data but does not expose it
        ///             It stores instance but there are demands on the instances.
        /// 
       [SecurityCritical,SecurityTreatAsSafe] 
       internal MouseDevice(InputManager inputManager)
       { 
            _inputManager = new SecurityCriticalData(inputManager); 
            _inputManager.Value.PreProcessInput += new PreProcessInputEventHandler(PreProcessInput);
            _inputManager.Value.PreNotifyInput += new NotifyInputEventHandler(PreNotifyInput); 
            _inputManager.Value.PostProcessInput += new ProcessInputEventHandler(PostProcessInput);

            // Get information about how far two clicks of a double click can be considered
            // to be in the "same place and time". 
            //
            // The call here goes into the safe helper calls, more of a consistency in approach 
            // 
            _doubleClickDeltaX = SafeSystemMetrics.DoubleClickDeltaX;
            _doubleClickDeltaY = SafeSystemMetrics.DoubleClickDeltaY; 
            _doubleClickDeltaTime = SafeNativeMethods.GetDoubleClickTime();

            _overIsEnabledChangedEventHandler = new DependencyPropertyChangedEventHandler(OnOverIsEnabledChanged);
            _overIsVisibleChangedEventHandler = new DependencyPropertyChangedEventHandler(OnOverIsVisibleChanged); 
            _overIsHitTestVisibleChangedEventHandler  = new DependencyPropertyChangedEventHandler(OnOverIsHitTestVisibleChanged);
            _reevaluateMouseOverDelegate = new DispatcherOperationCallback(ReevaluateMouseOverAsync); 
            _reevaluateMouseOverOperation = null; 

            _captureIsEnabledChangedEventHandler = new DependencyPropertyChangedEventHandler(OnCaptureIsEnabledChanged); 
            _captureIsVisibleChangedEventHandler = new DependencyPropertyChangedEventHandler(OnCaptureIsVisibleChanged);
            _captureIsHitTestVisibleChangedEventHandler  = new DependencyPropertyChangedEventHandler(OnCaptureIsHitTestVisibleChanged);
            _reevaluateCaptureDelegate = new DispatcherOperationCallback(ReevaluateCaptureAsync);
            _reevaluateCaptureOperation = null; 

            _inputManager.Value.HitTestInvalidatedAsync += new EventHandler(OnHitTestInvalidatedAsync); 
        } 

        ///  
        ///     Gets the current state of the specified button from the device from either the underlying system or the StylusDevice
        /// 
        /// 
        ///     The mouse button to get the state of 
        /// 
        ///  
        ///     The state of the specified mouse button 
        /// 
        protected MouseButtonState GetButtonState(MouseButton mouseButton) 
        {
            if ( _stylusDevice != null )
                return _stylusDevice.GetMouseButtonState(mouseButton, this);
            else 
                return GetButtonStateFromSystem(mouseButton);
        } 
 
        /// 
        ///     Gets the current position of the mouse in screen co-ords from either the underlying system or the StylusDevice 
        /// 
        /// 
        ///     The current mouse location in screen co-ords
        ///  
        protected Point GetScreenPosition()
        { 
            if (_stylusDevice != null) 
                return _stylusDevice.GetMouseScreenPosition(this);
            else 
                return GetScreenPositionFromSystem();
        }

        ///  
        ///     Gets the current state of the specified button from the device from the underlying system
        ///  
        ///  
        ///     The mouse button to get the state of
        ///  
        /// 
        ///     The state of the specified mouse button
        /// 
        internal abstract MouseButtonState GetButtonStateFromSystem(MouseButton mouseButton); 

        ///  
        ///     Gets the current position of the mouse in screen co-ords from the underlying system 
        /// 
        ///  
        ///     The current mouse location in screen co-ords
        /// 
        /// 
        ///     Critical: accesses critical data (CriticalActiveSource) 
        ///     TreatAsSafe: doesn't expose critical data, just returns screen coordinates of non-critical data
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal Point GetScreenPositionFromSystem()
        { 
            // Win32 has issues reliably returning where the mouse is.  Until we figure
            // out a better way, just return the last mouse position in screen coordinates.

            Point ptScreen = new Point(0, 0); 

            // Security Mitigation: do not give out input state if the device is not active. 
            if (IsActive) 
            {
                try 
                {
                    PresentationSource activeSource = CriticalActiveSource;
                    if (activeSource != null)
                    { 
                        ptScreen = PointUtil.ClientToScreen(_lastPosition, activeSource);
                    } 
                } 
                catch (System.ComponentModel.Win32Exception)
                { 
                    // The window could be shutting down, so just return (0,0).
                    ptScreen = new Point(0, 0);
                }
            } 

            return ptScreen; 
        } 

        ///  
        ///     Gets the current position of the mouse in client co-ords of the current PresentationSource
        /// 
        /// 
        ///     The current mouse position in client co-ords 
        /// 
        ///  
        ///     Critical: Accesses SecurityCritical data CriticalActiveSource 
        ///     TreatAsSafe: Only uses it to pass to through to overloaded version of this method which
        ///                  in turn only uses it to pass to PointUtil.ScreenToClient to convert mouse 
        ///                  position from screen to client co-ords
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        protected Point GetClientPosition() 
        {
            Point ptClient = new Point(0, 0); 
            try 
            {
                PresentationSource activeSource = CriticalActiveSource; 
                if (activeSource != null)
                {
                    ptClient = GetClientPosition(activeSource);
                } 
            }
            catch (System.ComponentModel.Win32Exception) 
            { 
                // The window could be shutting down, so just return (0,0).
                ptClient = new Point(0, 0); 
            }

            return ptClient;
        } 

        ///  
        ///     Gets the current position of the mouse in client co-ords of the specified PresentationSource 
        /// 
        ///  
        ///     The current mouse position in client co-ords
        /// 
        protected Point GetClientPosition(PresentationSource presentationSource)
        { 
            Point ptScreen = GetScreenPosition();
            Point ptClient = PointUtil.ScreenToClient(ptScreen, presentationSource); 
 
            return ptClient;
        } 

        /// 
        ///     Returns the element that input from this device is sent to.
        ///  
        public override IInputElement Target
        { 
            get 
            {
//                 VerifyAccess(); 

                // Return the element that the mouse is over.  If the mouse
                // has been captured, the mouse will be considered "over"
                // the capture point if the mouse is outside of the 
                // captured element (or subtree).
                return _mouseOver; 
            } 
        }
 
        /// 
        ///     Returns the PresentationSource that is reporting input for this device.
        /// 
        ///  
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///  
        /// 
        /// Critical - accesses critical data ( _activeSource)
        /// PublicOK - there is a demand. 
        ///

        public override PresentationSource ActiveSource
        { 
            [SecurityCritical ]
            get 
            { 
                SecurityHelper.DemandUIWindowPermission();
                if (_inputSource != null) 
                {
                    return _inputSource.Value;
                }
                return null; 
            }
        } 
 
        /// 
        ///     Returns the PresentationSource that is reporting input for this device. 
        /// 
        /// 
        ///     Critical - accesses critical data (_inputSource) and returns it.
        ///  
        internal PresentationSource CriticalActiveSource
        { 
            [SecurityCritical] 
            get
            { 
                if (_inputSource != null)
                {
                    return _inputSource.Value;
                } 
                return null;
            } 
        } 

        ///  
        ///     Returns the element that the mouse is over.
        /// 
        /// 
        ///     The mouse is considered directly over an element if the mouse 
        ///     has been captured to that element.
        ///  
        public IInputElement DirectlyOver 
        {
            get 
            {
//                 VerifyAccess();
                return _mouseOver;
            } 
        }
 
        ///  
        ///     Returns the element that the mouse is over regardless of
        ///     its IsEnabled state. 
        /// 
        [FriendAccessAllowed]
        internal IInputElement RawDirectlyOver
        { 
            get
            { 
                if (_rawMouseOver != null) 
                {
                    IInputElement rawMouseOver = (IInputElement)_rawMouseOver.Target; 
                    if (rawMouseOver != null)
                    {
                        return rawMouseOver;
                    } 
                }
 
                return DirectlyOver; 
            }
        } 

        /// 
        ///     Returns the element that has captured the mouse.
        ///  
        public IInputElement Captured
        { 
            get 
            {
//                 VerifyAccess(); 
                return _mouseCapture;
            }
        }
 
        /// 
        ///     Returns the element that has captured the mouse. 
        ///  
        internal CaptureMode CapturedMode
        { 
            get
            {
                return _captureMode;
            } 
        }
 
        ///  
        ///     Captures the mouse to a particular element.
        ///  
        public bool Capture(IInputElement element)
        {
            return Capture(element, CaptureMode.Element);
        } 

        ///  
        ///     Captures the mouse to a particular element. 
        /// 
        ///  
        ///     Critical: This element acceses PresentationSource , MouseInputProvider (critical data)
        ///     PublicOK: This operation is inherently safe and does not store or expose the critical data
        /// 
        [SecurityCritical] 
        public bool Capture(IInputElement element, CaptureMode captureMode)
        { 
            int timeStamp = Environment.TickCount; 
//             VerifyAccess();
 
            if (!(captureMode == CaptureMode.None || captureMode == CaptureMode.Element || captureMode == CaptureMode.SubTree))
            {
                throw new System.ComponentModel.InvalidEnumArgumentException("captureMode", (int)captureMode, typeof(CaptureMode));
            } 

            if (element == null) 
            { 
                captureMode = CaptureMode.None;
            } 

            if (captureMode == CaptureMode.None)
            {
                element = null; 
            }
 
            // Validate that elt is either a UIElement or a ContentElement 
            DependencyObject eltDO = element as DependencyObject;
            if (eltDO != null && !InputElement.IsValid(element)) 
            {
                throw new InvalidOperationException(SR.Get(SRID.Invalid_IInputElement, eltDO.GetType()));
            }
 
            bool success = false;
 
            // The element we are capturing to must be both enabled and visible. 
            if (element is UIElement)
            { 
                UIElement e = element as UIElement;

                #pragma warning suppress 6506 // e is obviously not null
                if(e.IsVisible && e.IsEnabled) 
                {
                    success = true; 
                } 
            }
            else if (element is ContentElement) 
            {
                ContentElement ce = element as ContentElement;

                #pragma warning suppress 6506 // ce is obviosuly not null 
                if(ce.IsEnabled) // There is no IsVisible property for ContentElement
                { 
                    success = true; 
                }
            } 
            else if (element is UIElement3D)
            {
                UIElement3D e = element as UIElement3D;
 
                #pragma warning suppress 6506 // e is obviously not null
                if(e.IsVisible && e.IsEnabled) 
                { 
                    success = true;
                } 
            }
            else
            {
                // Setting capture to null. 
                success = true;
            } 
 
            if(success)
            { 
                success = false;

                // Find a mouse input provider that provides input for either
                // the new element (if taking capture) or the existing capture 
                // element (if releasing capture).
                IMouseInputProvider mouseInputProvider = null; 
                if (element != null) 
                {
                    DependencyObject containingVisual = InputElement.GetContainingVisual(eltDO); 
                    if (containingVisual != null)
                    {
                        PresentationSource captureSource = PresentationSource.CriticalFromVisual(containingVisual);
                        if (captureSource != null) 
                        {
                            mouseInputProvider = captureSource.GetInputProvider(typeof(MouseDevice)) as IMouseInputProvider; 
                        } 
                    }
                } 
                else if (_mouseCapture != null)
                {
                    mouseInputProvider = _providerCapture.Value;
                } 

                // If we found a mouse input provider, ask it to either capture 
                // or release the mouse for us. 
                if(mouseInputProvider != null)
                { 
                    if (element != null)
                    {
                        success = mouseInputProvider.CaptureMouse();
 
                        if (success)
                        { 
                            ChangeMouseCapture(element, mouseInputProvider, captureMode, timeStamp); 
                        }
                    } 
                    else
                    {
                        mouseInputProvider.ReleaseMouseCapture();
 
                        // If we had capture, the input provider will release it.  That will
                        // cause a RawMouseAction.CancelCapture to be processed, which will 
                        // update our internal states. 
                        success = true;
                    } 
                }
            }

            return success; 
        }
 
        // 
        // Find an IMouseInputProvider on which the cursor can be set
        /// 
        ///     Critical: This code accesses critical data (InputManager and InputProviders).
        ///               It also returns critical data
        /// 
        [SecurityCritical] 
        private IMouseInputProvider FindMouseInputProviderForCursor( )
        { 
            // The shape of this API goes on the assumption that, like Win32, the cursor 
            // is set for the whole desktop, not just a particular element or a particular
            // root visual.  So instead of trying to find the IMouseInputProvider 
            // that covers a particular element, we just find any IMouseInputProvider
            // and set the cursor on it.

            IMouseInputProvider mouseInputProvider = null; 

            IEnumerator inputProviders = _inputManager.Value.UnsecureInputProviders.GetEnumerator(); 
 
            while (inputProviders.MoveNext())
            { 
                IMouseInputProvider provider = inputProviders.Current as IMouseInputProvider;
                if (provider != null )
                {
                    mouseInputProvider = provider; 
                    break;
                } 
            } 

            return mouseInputProvider; 

        }

        ///  
        /// The override cursor
        ///  
        public Cursor OverrideCursor 
        {
            get 
            {
//                 VerifyAccess();

                return _overrideCursor; 
            }
 
            set 
            {
//                 VerifyAccess(); 

                _overrideCursor = value;
                UpdateCursorPrivate();
            } 
        }
 
        ///  
        /// Set the cursor
        ///  
        /// The new cursor
        /// Note that this cursor doesn't apply any particular UIElement, it applies
        ///          to the whole desktop.
        ///  
        /// 
        ///     Critical: Cause an elevation to unmanaged Code permission, also accesses critical data MouseInputProvider 
        ///     PublicOK: Calling SetCursor is a safe operation since it only affects current app.Also it does not 
        ///     expose critical data (IMouseInputProvider)
        ///  
        [SecurityCritical]
        public bool SetCursor(Cursor cursor)
        {
//             VerifyAccess(); 

            // Override the cursor if one is set. 
            if (_overrideCursor != null) 
            {
                cursor = _overrideCursor; 
            }

            if (cursor == null)
            { 
                cursor = Cursors.None;
            } 
            // Get a mouse provider 
            IMouseInputProvider mouseInputProvider = FindMouseInputProviderForCursor();
 
            // If we found one, set the cursor
            if (mouseInputProvider != null)
                return mouseInputProvider.SetCursor(cursor);
            else 
                return false;
 
        } 

        ///  
        ///     The state of the left button.
        /// 
        public MouseButtonState LeftButton
        { 
            get
            { 
                return GetButtonState(MouseButton.Left); 
            }
        } 

        /// 
        ///     The state of the right button.
        ///  
        public MouseButtonState RightButton
        { 
            get 
            {
                return GetButtonState(MouseButton.Right); 
            }
        }

        ///  
        ///     The state of the middle button.
        ///  
        public MouseButtonState MiddleButton 
        {
            get 
            {
                return GetButtonState(MouseButton.Middle);
            }
        } 

        ///  
        ///     The state of the first extended button. 
        /// 
        public MouseButtonState XButton1 
        {
            get
            {
                return GetButtonState(MouseButton.XButton1); 
            }
        } 
 
        /// 
        ///     The state of the second extended button. 
        /// 
        public MouseButtonState XButton2
        {
            get 
            {
                return GetButtonState(MouseButton.XButton2); 
            } 
        }
 
        /// 
        ///     Calculates the position of the mouse relative to
        ///     a particular element.
        ///  
        ///
        ///     Critical - accesses critical data _inputSource.Value 
        ///     PublicOK - we do the elevation of _inputSource to get RootVisual. 
        ///
        [SecurityCritical  ] 
        public Point GetPosition(IInputElement relativeTo)
        {
//             VerifyAccess();
 
            // Validate that relativeTo is either a UIElement or a ContentElement
            if (relativeTo != null && !InputElement.IsValid(relativeTo)) 
            { 
                throw new InvalidOperationException(SR.Get(SRID.Invalid_IInputElement, relativeTo.GetType()));
            } 

            PresentationSource relativePresentationSource = null;

            if (relativeTo != null) 
            {
                DependencyObject dependencyObject = relativeTo as  DependencyObject; 
                DependencyObject containingVisual = InputElement.GetContainingVisual(dependencyObject); 

                if (containingVisual != null) 
                {
                    relativePresentationSource = PresentationSource.CriticalFromVisual(containingVisual);
                }
            } 
            else
            { 
                if (_inputSource != null) 
                {
                    relativePresentationSource = _inputSource.Value; 
                }
            }

 
            // Verify that we have a valid PresentationSource with a valid RootVisual
            // - if we don't we won't be able to invoke ClientToRoot or TranslatePoint and 
            //   we will just return 0,0 
            if (relativePresentationSource == null || relativePresentationSource.RootVisual == null)
            { 
                return new Point(0, 0);
            }

            Point ptClient; 
            Point ptRoot;
            bool success; 
            Point ptRelative; 

            ptClient    = GetClientPosition(relativePresentationSource); 
            ptRoot      = PointUtil.TryClientToRoot(ptClient, relativePresentationSource, false, out success);
            if (!success)
            {
                // ClientToRoot failed, usually because the client area is degenerate. 
                // Just return 0,0
                return new Point(0, 0); 
            } 
            ptRelative  = InputElement.TranslatePoint(ptRoot, relativePresentationSource.RootVisual, (DependencyObject)relativeTo);
 
            return ptRelative;
        }

        ///  
        /// 
        internal void ReevaluateMouseOver(DependencyObject element, DependencyObject oldParent, bool isCoreParent) 
        { 
            if (element != null)
            { 
                if (isCoreParent)
                {
                    MouseOverTreeState.SetCoreParent(element, oldParent);
                } 
                else
                { 
                    MouseOverTreeState.SetLogicalParent(element, oldParent); 
                }
            } 

            // It would be best to re-evaluate anything dependent on the hit-test results
            // immediately after layout & rendering are complete.  Unfortunately this can
            // lead to an infinite loop.  Consider the following scenario: 
            //
            // If the mouse is over an element, hide it. 
            // 
            // This never resolves to a "correct" state.  When the mouse moves over the
            // element, the element is hidden, so the mouse is no longer over it, so the 
            // element is shown, but that means the mouse is over it again.  Repeat.
            //
            // We push our re-evaluation to a priority lower than input processing so that
            // the user can change the input device to avoid the infinite loops, or close 
            // the app if nothing else works.
            // 
            if (_reevaluateMouseOverOperation == null) 
            {
                _reevaluateMouseOverOperation = Dispatcher.BeginInvoke(DispatcherPriority.Input, _reevaluateMouseOverDelegate, null); 
            }
        }

        ///  
        /// 
        ///  
        ///  
        private object ReevaluateMouseOverAsync(object arg)
        { 
            _reevaluateMouseOverOperation = null;

            Synchronize();
 
            // Refresh MouseOverProperty so that ReverseInherited Flags are updated.
            // 
            // We only need to do this is there is any information about the old 
            // tree state.  This is because it is possible (even likely) that
            // Synchronize() would have already done this if we hit-tested to a 
            // different element.
            if (_mouseOverTreeState != null && !_mouseOverTreeState.IsEmpty)
            {
                UIElement.MouseOverProperty.OnOriginValueChanged(_mouseOver as DependencyObject, _mouseOver as DependencyObject, ref _mouseOverTreeState); 
            }
 
            return null; 
        }
 
        /// 
        /// 
        internal void ReevaluateCapture(DependencyObject element, DependencyObject oldParent, bool isCoreParent)
        { 
            if (element != null)
            { 
                if (isCoreParent) 
                {
                    MouseCaptureWithinTreeState.SetCoreParent(element, oldParent); 
                }
                else
                {
                    MouseCaptureWithinTreeState.SetLogicalParent(element, oldParent); 
                }
            } 
 
            // We re-evaluate the captured element to be consistent with how
            // we re-evaluate the element the mouse is over. 
            //
            // See ReevaluateMouseOver for details.
            //
            if (_reevaluateCaptureOperation == null) 
            {
                _reevaluateCaptureOperation = Dispatcher.BeginInvoke(DispatcherPriority.Input, _reevaluateCaptureDelegate, null); 
            } 
        }
 
        /// 
        ///
        /// 
        ///  
        /// 
        private object ReevaluateCaptureAsync(object arg) 
        { 
            _reevaluateCaptureOperation = null;
 
            if (_mouseCapture == null )
                return null;

            bool killCapture = false; 

            DependencyObject dependencyObject = _mouseCapture as DependencyObject; 
 
            //
            // First, check things like IsEnabled, IsVisible, etc. on a 
            // UIElement vs. ContentElement basis.
            //
            if (InputElement.IsUIElement(dependencyObject))
            { 
                killCapture = !ValidateUIElementForCapture((UIElement)_mouseCapture);
            } 
            else if (InputElement.IsContentElement(dependencyObject)) 
            {
                killCapture = !ValidateContentElementForCapture((ContentElement)_mouseCapture); 
            }
            else if (InputElement.IsUIElement3D(dependencyObject))
            {
                killCapture = !ValidateUIElement3DForCapture((UIElement3D)_mouseCapture); 
            }
 
            // 
            // Second, if we still haven't thought of a reason to kill capture, validate
            // it on a Visual basis for things like still being in the right tree. 
            //
            if (killCapture == false)
            {
                DependencyObject containingVisual = InputElement.GetContainingVisual(dependencyObject); 
                killCapture = !ValidateVisualForCapture(containingVisual);
            } 
 
            //
            // Lastly, if we found any reason above, kill capture. 
            //
            if (killCapture)
            {
                Capture(null); 
            }
 
            // Refresh MouseCaptureWithinProperty so that ReverseInherited flags are updated. 
            //
            // We only need to do this is there is any information about the old 
            // tree state.  This is because it is possible (even likely) that
            // we would have already killed capture if the capture criteria was
            // no longer met.
            if (_mouseCaptureWithinTreeState != null && !_mouseCaptureWithinTreeState.IsEmpty) 
            {
                UIElement.MouseCaptureWithinProperty.OnOriginValueChanged(_mouseCapture as DependencyObject, _mouseCapture as DependencyObject, ref _mouseCaptureWithinTreeState); 
            } 

            return null; 
        }

        private bool ValidateUIElementForCapture(UIElement element)
        { 
            if (element.IsEnabled == false)
                return false; 
 
            if (element.IsVisible == false)
                return false; 

            if (element.IsHitTestVisible == false)
                return false;
 
            return true;
        } 
 
        private bool ValidateUIElement3DForCapture(UIElement3D element)
        { 
            if (element.IsEnabled == false)
                return false;

            if (element.IsVisible == false) 
                return false;
 
            if (element.IsHitTestVisible == false) 
                return false;
 
            return true;
        }

 
        private bool ValidateContentElementForCapture(ContentElement element)
        { 
            if (element.IsEnabled == false) 
                return false;
 
            // NOTE: there are no IsVisible or IsHitTestVisible properties for ContentElements.

            return true;
        } 

        ///  
        ///     Critical: This code accesses critical data (CriticalActiveSource) 
        ///     TreatAsSafe: Although it accesses critical data it does not modify or expose it, only compares against it.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private bool ValidateVisualForCapture(DependencyObject visual)
        {
            if (visual == null) 
                return false;
 
            PresentationSource presentationSource = PresentationSource.CriticalFromVisual(visual); 

            if (presentationSource == null) 
                return false;

            if (presentationSource != CriticalActiveSource)
                return false; 

            return true; 
        } 

        private void OnOverIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) 
        {
            // The element that the mouse is over just became disabled.
            //
            // We need to resynchronize the mouse so that we can figure out who 
            // the mouse is over now.
 
            ReevaluateMouseOver(null, null, true); 
        }
 
        private void OnOverIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            // The element that the mouse is over just became non-visible (collapsed or hidden).
            // 
            // We need to resynchronize the mouse so that we can figure out who
            // the mouse is over now. 
 
            ReevaluateMouseOver(null, null, true);
        } 

        private void OnOverIsHitTestVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            // The element that the mouse is over was affected by a change in hit-test visibility. 
            //
            // We need to resynchronize the mouse so that we can figure out who 
            // the mouse is over now. 

            ReevaluateMouseOver(null, null, true); 
        }

        private void OnCaptureIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
        { 
            // The element that the mouse is captured to just became disabled.
            // 
            // We need to re-evaluate the element that has mouse capture since 
            // we can't allow the mouse to remain captured by a disabled element.
 
            ReevaluateCapture(null, null, true);
        }

        private void OnCaptureIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) 
        {
            // The element that the mouse is captured to just became non-visible (collapsed or hidden). 
            // 
            // We need to re-evaluate the element that has mouse capture since
            // we can't allow the mouse to remain captured by a non-visible element. 

            ReevaluateCapture(null, null, true);
        }
 
        private void OnCaptureIsHitTestVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        { 
            // The element that the mouse is captured to was affected by a change in hit-test visibility. 
            //
            // We need to re-evaluate the element that has mouse capture since 
            // we can't allow the mouse to remain captured by a non-hittest-visible element.

            ReevaluateCapture(null, null, true);
        } 

        private void OnHitTestInvalidatedAsync(object sender, EventArgs e) 
        { 
            // The hit-test result may have changed.
            Synchronize(); 
        }

        /// 
        ///     Forces the mouse to resynchronize. 
        /// 
        ///  
        ///     Critical - asserts HwndSource via CriticalActiveSource 
        ///     PublicOK: This code does not expose the HwndSource or store it, nor is
        ///                 this operation risky. 
        /// 
        [SecurityCritical]
        public void Synchronize()
        { 
            // System.Console.WriteLine("Synchronize");
//             VerifyAccess(); 
 
            // Simulate a mouse move
            PresentationSource activeSource = CriticalActiveSource; 
            if (activeSource != null && activeSource.CompositionTarget != null && !activeSource.CompositionTarget.IsDisposed)
            {
                int timeStamp = Environment.TickCount;
                Point ptClient = GetClientPosition(); 

                RawMouseInputReport report = new RawMouseInputReport(InputMode.Foreground, 
                                                                     timeStamp, 
                                                                     activeSource,
                                                                     RawMouseActions.AbsoluteMove, 
                                                                     (int) ptClient.X,
                                                                     (int) ptClient.Y,
                                                                     0,
                                                                     IntPtr.Zero); 
                report._isSynchronize = true;
 
                InputReportEventArgs inputReportEventArgs; 
                if (_stylusDevice != null)
                { 
                    // if we have a current stylusdevice .. use it
                    inputReportEventArgs = new InputReportEventArgs(_stylusDevice, report);
                }
                else 
                {
                    inputReportEventArgs = new InputReportEventArgs(this, report); 
                } 

                inputReportEventArgs.RoutedEvent=InputManager.PreviewInputReportEvent; 

                //ProcessInput has a linkdemand
                _inputManager.Value.ProcessInput(inputReportEventArgs);
            } 
        }
 
        ///  
        ///     Forces the mouse cursor to be updated.
        ///  
        public void UpdateCursor()
        {
            // Call Forwarded
            UpdateCursorPrivate(); 
        }
 
        ///  
        ///     Forces the mouse cursor to be updated.
        ///  
        /// 
        ///     This method has been added just because changing the public
        ///     API UpdateCursor will be a breaking change
        ///  
        /// 
        ///     Critical:This code access input manager and causes cursor to be updated 
        ///     TreatAsSafe: No risky critical data stored and inputs and outputs are safe. 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        private bool UpdateCursorPrivate()
        {
            int timeStamp = Environment.TickCount;
            QueryCursorEventArgs queryCursor = new QueryCursorEventArgs(this, timeStamp); 
            queryCursor.Cursor = Cursors.Arrow;
            queryCursor.RoutedEvent=Mouse.QueryCursorEvent; 
            //ProcessInput has a linkdemand 
            _inputManager.Value.ProcessInput(queryCursor);
            return queryCursor.Handled; 
        }

        /// 
        ///     Critical: This code accesses link demanded method PresentationSource.AddSourcechangedhandler 
        ///     and remove for the same
        ///     TreatAsSafe: This code does not expose the PresentationSource and simply changes the mouse over element 
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private void ChangeMouseOver(IInputElement mouseOver, int timestamp) 
        {
            DependencyObject o = null;

            if (_mouseOver != mouseOver) 
            {
                // Console.WriteLine("ChangeMouseOver(" + mouseOver + ")"); 
 
                // Update the critical piece of data.
                IInputElement oldMouseOver = _mouseOver; 
                _mouseOver = mouseOver;

                using(Dispatcher.DisableProcessing()) // Disable reentrancy due to locks taken
                { 
                    // Adjust the handlers we use to track everything.
                    if(oldMouseOver != null) 
                    { 
                        o = oldMouseOver as DependencyObject;
                        if (InputElement.IsUIElement(o)) 
                        {
                            ((UIElement)o).IsEnabledChanged -= _overIsEnabledChangedEventHandler;
                            ((UIElement)o).IsVisibleChanged -= _overIsVisibleChangedEventHandler;
                            ((UIElement)o).IsHitTestVisibleChanged -= _overIsHitTestVisibleChangedEventHandler; 
                        }
                        else if (InputElement.IsContentElement(o)) 
                        { 
                            ((ContentElement)o).IsEnabledChanged -= _overIsEnabledChangedEventHandler;
 
                            // NOTE: there are no IsVisible or IsHitTestVisible properties for ContentElements.
                            //
                            // ((ContentElement)o).IsVisibleChanged -= _overIsVisibleChangedEventHandler;
                            // ((ContentElement)o).IsHitTestVisibleChanged -= _overIsHitTestVisibleChangedEventHandler; 
                        }
                        else if (InputElement.IsUIElement3D(o)) 
                        { 
                            ((UIElement3D)o).IsEnabledChanged -= _overIsEnabledChangedEventHandler;
                            ((UIElement3D)o).IsVisibleChanged -= _overIsVisibleChangedEventHandler; 
                            ((UIElement3D)o).IsHitTestVisibleChanged -= _overIsHitTestVisibleChangedEventHandler;
                        }
                    }
                    if(_mouseOver != null) 
                    {
                        o = _mouseOver as DependencyObject; 
                        if (InputElement.IsUIElement(o)) 
                        {
                            ((UIElement)o).IsEnabledChanged += _overIsEnabledChangedEventHandler; 
                            ((UIElement)o).IsVisibleChanged += _overIsVisibleChangedEventHandler;
                            ((UIElement)o).IsHitTestVisibleChanged += _overIsHitTestVisibleChangedEventHandler;
                        }
                        else if (InputElement.IsContentElement(o)) 
                        {
                            ((ContentElement)o).IsEnabledChanged += _overIsEnabledChangedEventHandler; 
 
                            // NOTE: there are no IsVisible or IsHitTestVisible properties for ContentElements.
                            // 
                            // ((ContentElement)o).IsVisibleChanged += _overIsVisibleChangedEventHandler;
                            // ((ContentElement)o).IsHitTestVisibleChanged += _overIsHitTestVisibleChangedEventHandler;
                        }
                        else if (InputElement.IsUIElement3D(o)) 
                        {
                            ((UIElement3D)o).IsEnabledChanged += _overIsEnabledChangedEventHandler; 
                            ((UIElement3D)o).IsVisibleChanged += _overIsVisibleChangedEventHandler; 
                            ((UIElement3D)o).IsHitTestVisibleChanged += _overIsHitTestVisibleChangedEventHandler;
                        } 
                    }
                }

                // Oddly enough, update the IsMouseOver property first.  This is 
                // so any callbacks will see the more-common IsMouseOver property
                // set correctly. 
                UIElement.MouseOverProperty.OnOriginValueChanged(oldMouseOver as DependencyObject, _mouseOver as DependencyObject, ref _mouseOverTreeState); 

                // Invalidate the IsMouseDirectlyOver property. 
                if (oldMouseOver != null)
                {
                    o = oldMouseOver as DependencyObject;
                    o.SetValue(UIElement.IsMouseDirectlyOverPropertyKey, false); // Same property for ContentElements 
                }
                if (_mouseOver != null) 
                { 
                    o = _mouseOver as DependencyObject;
                    o.SetValue(UIElement.IsMouseDirectlyOverPropertyKey, true); // Same property for ContentElements 
                }
            }
        }
        ///  
        ///     Critical: This code acceses InputManager and MouseProvider which are critical data.
        ///               It also calls into ProcessInput which is a critical method and could be used 
        ///               for input spoofing. 
        ///     TreatAsSafe: This operation is ok to expose since mouse capture is ok. Even if you get the
        ///               source changed events you cannot get to the sources themselves 
        /// 
        [SecurityCritical,SecurityTreatAsSafe]
        private void ChangeMouseCapture(IInputElement mouseCapture, IMouseInputProvider providerCapture, CaptureMode captureMode, int timestamp)
        { 
            DependencyObject o = null;
 
            if(mouseCapture != _mouseCapture) 
            {
                // Console.WriteLine("ChangeMouseCapture(" + mouseCapture + ")"); 

                // Update the critical pieces of data.
                IInputElement oldMouseCapture = _mouseCapture;
                _mouseCapture = mouseCapture; 
                if (_mouseCapture != null)
                { 
                    _providerCapture = new SecurityCriticalDataClass(providerCapture); 
                }
                else 
                {
                    _providerCapture = null;
                }
                _captureMode = captureMode; 

                using (Dispatcher.DisableProcessing()) // Disable reentrancy due to locks taken 
                { 
                    // Adjust the handlers we use to track everything.
                    if (oldMouseCapture != null) 
                    {
                        o = oldMouseCapture as DependencyObject;
                        if (InputElement.IsUIElement(o))
                        { 
                            ((UIElement)o).IsEnabledChanged -= _captureIsEnabledChangedEventHandler;
                            ((UIElement)o).IsVisibleChanged -= _captureIsVisibleChangedEventHandler; 
                            ((UIElement)o).IsHitTestVisibleChanged -= _captureIsHitTestVisibleChangedEventHandler; 
                        }
                        else if (InputElement.IsContentElement(o)) 
                        {
                            ((ContentElement)o).IsEnabledChanged -= _captureIsEnabledChangedEventHandler;

                            // NOTE: there are no IsVisible or IsHitTestVisible properties for ContentElements. 
                            //
                            // ((ContentElement)o).IsVisibleChanged -= _captureIsVisibleChangedEventHandler; 
                            // ((ContentElement)o).IsHitTestVisibleChanged -= _captureIsHitTestVisibleChangedEventHandler; 
                        }
                        else if (InputElement.IsUIElement3D(o)) 
                        {
                            ((UIElement3D)o).IsEnabledChanged -= _captureIsEnabledChangedEventHandler;
                            ((UIElement3D)o).IsVisibleChanged -= _captureIsVisibleChangedEventHandler;
                            ((UIElement3D)o).IsHitTestVisibleChanged -= _captureIsHitTestVisibleChangedEventHandler; 
                        }
                    } 
                    if (_mouseCapture != null) 
                    {
                        o = _mouseCapture as DependencyObject; 
                        if (InputElement.IsUIElement(o))
                        {
                            ((UIElement)o).IsEnabledChanged += _captureIsEnabledChangedEventHandler;
                            ((UIElement)o).IsVisibleChanged += _captureIsVisibleChangedEventHandler; 
                            ((UIElement)o).IsHitTestVisibleChanged += _captureIsHitTestVisibleChangedEventHandler;
                        } 
                        else if (InputElement.IsContentElement(o)) 
                        {
                            ((ContentElement)o).IsEnabledChanged += _captureIsEnabledChangedEventHandler; 

                            // NOTE: there are no IsVisible or IsHitTestVisible properties for ContentElements.
                            //
                            // ((ContentElement)o).IsVisibleChanged += _captureIsVisibleChangedEventHandler; 
                            // ((ContentElement)o).IsHitTestVisibleChanged += _captureIsHitTestVisibleChangedEventHandler;
                        } 
                        else if (InputElement.IsUIElement3D(o)) 
                        {
                            ((UIElement3D)o).IsEnabledChanged += _captureIsEnabledChangedEventHandler; 
                            ((UIElement3D)o).IsVisibleChanged += _captureIsVisibleChangedEventHandler;
                            ((UIElement3D)o).IsHitTestVisibleChanged += _captureIsHitTestVisibleChangedEventHandler;
                        }
                    } 
                }
 
                // Oddly enough, update the IsMouseCaptureWithin property first.  This is 
                // so any callbacks will see the more-common IsMouseCaptureWithin property
                // set correctly. 
                UIElement.MouseCaptureWithinProperty.OnOriginValueChanged(oldMouseCapture as DependencyObject, _mouseCapture as DependencyObject, ref _mouseCaptureWithinTreeState);

                // Invalidate the IsMouseCaptured properties.
                if (oldMouseCapture != null) 
                {
                    o = oldMouseCapture as DependencyObject; 
                    o.SetValue(UIElement.IsMouseCapturedPropertyKey, false); // Same property for ContentElements 
                }
                if (_mouseCapture != null) 
                {
                    o = _mouseCapture as DependencyObject;
                    o.SetValue(UIElement.IsMouseCapturedPropertyKey, true); // Same property for ContentElements
                } 

                // Send the LostMouseCapture and GotMouseCapture events. 
                if (oldMouseCapture != null) 
                {
                    MouseEventArgs lostCapture = new MouseEventArgs(this, timestamp, _stylusDevice); 
                    lostCapture.RoutedEvent=Mouse.LostMouseCaptureEvent;
                    lostCapture.Source= oldMouseCapture;
                    //ProcessInput has a linkdemand
                    _inputManager.Value.ProcessInput(lostCapture); 
                }
                if (_mouseCapture != null) 
                { 
                    MouseEventArgs gotCapture = new MouseEventArgs(this, timestamp, _stylusDevice);
                    gotCapture.RoutedEvent=Mouse.GotMouseCaptureEvent; 
                    gotCapture.Source= _mouseCapture;
                    //ProcessInput has a linkdemand
                    _inputManager.Value.ProcessInput(gotCapture);
                } 

                // Force a mouse move so we can update the mouse over. 
                Synchronize(); 
            }
        } 

        /// 
        ///  Critical: This code acceses data that was got from an unsafe call (_doubleClickDeltaX,_doubleClickDeltaX)
        ///            It also accesses HwndSource and InputManager and can be used for Input spoofing. 
        ///            accesses e.StagingItem.Input
        ///  
        [SecurityCritical] 
        private void PreProcessInput(object sender, PreProcessInputEventArgs e)
        { 
            if (e.StagingItem.Input.RoutedEvent == InputManager.PreviewInputReportEvent)
            {
                InputReportEventArgs inputReportEventArgs = e.StagingItem.Input as InputReportEventArgs;
 
                if (!inputReportEventArgs.Handled && inputReportEventArgs.Report.Type == InputType.Mouse)
                { 
                    RawMouseInputReport rawMouseInputReport = (RawMouseInputReport)inputReportEventArgs.Report; 

 
                    // Normally we only process mouse input that is from our
                    // active visual manager.  The only exception to this is
                    // the activate report, which is how we change the visual
                    // manager that is active. 
                    if ((rawMouseInputReport.Actions & RawMouseActions.Activate) == RawMouseActions.Activate)
                    { 
                        // Console.WriteLine("RawMouseActions.Activate"); 

                        // If other actions are being reported besides the 
                        // activate, separate them into different events.
                        if ((rawMouseInputReport.Actions & ~RawMouseActions.Activate) != 0)
                        {
                            // Cancel this event.  We'll push a new event for the activate. 
                            e.Cancel();
 
                            // Push a new RawMouseInputReport for the non-activate actions. 
                            RawMouseInputReport reportActions = new RawMouseInputReport(rawMouseInputReport.Mode,
                                                                                        rawMouseInputReport.Timestamp, 
                                                                                        rawMouseInputReport.InputSource,
                                                                                        rawMouseInputReport.Actions & ~RawMouseActions.Activate,
                                                                                        rawMouseInputReport.X,
                                                                                        rawMouseInputReport.Y, 
                                                                                        rawMouseInputReport.Wheel,
                                                                                        rawMouseInputReport.ExtraInformation); 
                            InputReportEventArgs actionsArgs = new InputReportEventArgs(inputReportEventArgs.Device, reportActions); 
                            actionsArgs.RoutedEvent=InputManager.PreviewInputReportEvent;
                            e.PushInput(actionsArgs, null); 

                            // Create a new RawMouseInputReport for the activate.
                            RawMouseInputReport reportActivate = new RawMouseInputReport(rawMouseInputReport.Mode,
                                                                                         rawMouseInputReport.Timestamp, 
                                                                                         rawMouseInputReport.InputSource,
                                                                                         RawMouseActions.Activate, 
                                                                                         rawMouseInputReport.X, 
                                                                                         rawMouseInputReport.Y,
                                                                                         rawMouseInputReport.Wheel, 
                                                                                         rawMouseInputReport.ExtraInformation);

                            // Push a new RawMouseInputReport for the activate.
                            InputReportEventArgs activateArgs = new InputReportEventArgs(inputReportEventArgs.Device, reportActivate); 
                            activateArgs.RoutedEvent=InputManager.PreviewInputReportEvent;
                            e.PushInput(activateArgs, null); 
                        } 
                    }
                    // Only process mouse input that is from our active PresentationSource. 
                    else if ((_inputSource != null) && (rawMouseInputReport.InputSource == _inputSource.Value))
                    {
                        // We need to remember the StylusDevice that generated this input.  Use the _tagStylusDevice
                        // to store this in before we take over the inputReport Device and loose it.  Any 
                        // input reports we re-push need to preserve this too.  This is used to set the StylusDevice
                        // property on MouseEventArgs. 
                        InputDevice inputDevice = e.StagingItem.GetData(_tagStylusDevice) as StylusDevice; 

                        if (inputDevice == null) 
                        {
                            inputDevice = inputReportEventArgs.Device as StylusDevice;
                            if (inputDevice != null)
                            { 
                                e.StagingItem.SetData(_tagStylusDevice, inputDevice);
                            } 
                        } 

                        // Claim the input for the mouse. 
                        inputReportEventArgs.Device = this;

                        // If the input is reporting mouse deactivation, we need
                        // to ensure that the element receives a final leave. 
                        // Note that activation could have been moved to another
                        // visual manager in our app, which means that the leave 
                        // was already sent.  So only do this if the deactivate 
                        // event is from the visual manager that we think is active.
                        if ((rawMouseInputReport.Actions & RawMouseActions.Deactivate) == RawMouseActions.Deactivate) 
                        {
                            if (_mouseOver != null)
                            {
                                // Push back this event, and cancel the current processing. 
                                e.PushInput(e.StagingItem);
                                e.Cancel(); 
                                _isPhysicallyOver = false; 
                                ChangeMouseOver(null, e.StagingItem.Input.Timestamp);
                            } 
                        }

                        // If the input is reporting mouse movement, we need to check
                        // if we need to update our sense of "mouse over". 
                        //
                        if ((rawMouseInputReport.Actions & RawMouseActions.AbsoluteMove) == RawMouseActions.AbsoluteMove) 
                        { 
                            // If other actions are being reported besides the
                            // move, separate them into different events. 
                            if ((rawMouseInputReport.Actions & ~(RawMouseActions.AbsoluteMove | RawMouseActions.QueryCursor)) != 0)
                            {
                                // Cancel this event.  We'll push a new event for the move.
                                e.Cancel(); 

                                // Push a new RawMouseInputReport for the non-move actions. 
                                RawMouseInputReport reportActions = new RawMouseInputReport(rawMouseInputReport.Mode, 
                                                                                            rawMouseInputReport.Timestamp,
                                                                                            rawMouseInputReport.InputSource, 
                                                                                            rawMouseInputReport.Actions & ~(RawMouseActions.AbsoluteMove | RawMouseActions.QueryCursor),
                                                                                            0,
                                                                                            0,
                                                                                            rawMouseInputReport.Wheel, 
                                                                                            rawMouseInputReport.ExtraInformation);
                                InputReportEventArgs actionsArgs = new InputReportEventArgs(inputDevice, reportActions); 
                                actionsArgs.RoutedEvent=InputManager.PreviewInputReportEvent; 
                                e.PushInput(actionsArgs, null);
 
                                // Push a new RawMouseInputReport for the AbsoluteMove.
                                RawMouseInputReport reportMove = new RawMouseInputReport(rawMouseInputReport.Mode,
                                                                                         rawMouseInputReport.Timestamp,
                                                                                         rawMouseInputReport.InputSource, 
                                                                                         rawMouseInputReport.Actions & (RawMouseActions.AbsoluteMove | RawMouseActions.QueryCursor),
                                                                                         rawMouseInputReport.X, 
                                                                                         rawMouseInputReport.Y, 
                                                                                         0,
                                                                                         IntPtr.Zero); 
                                InputReportEventArgs moveArgs = new InputReportEventArgs(inputDevice, reportMove);
                                moveArgs.RoutedEvent=InputManager.PreviewInputReportEvent;
                                e.PushInput(moveArgs, null);
                            } 
                            else
                            { 
                                // Convert the point from client coordinates into "root" coordinates. 
                                // We do this in the pre-process stage because it is possible that
                                // this conversion will fail, in which case we want to cancel the 
                                // mouse move event.
                                bool success = true;
                                Point ptClient = new Point(rawMouseInputReport.X, rawMouseInputReport.Y);
                                Point ptRoot = PointUtil.TryClientToRoot(ptClient, rawMouseInputReport.InputSource, false, out success); 
                                if(success)
                                { 
                                    e.StagingItem.SetData(_tagRootPoint, ptRoot); 
                                }
                                else 
                                {
                                    e.Cancel();
                                }
                            } 
                        }
                    } 
                } 
            }
            else 
            {
                // All mouse event processing should only happen if we still have an active input source.

                if (_inputSource != null) 
                {
                    if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseDownEvent) 
                    { 
                        MouseButtonEventArgs mouseButtonEventArgs = e.StagingItem.Input as MouseButtonEventArgs;
 
                        if (_mouseCapture != null && !_isPhysicallyOver)
                        {
                            // The mouse is not physically over the capture point (or
                            // subtree), so raise the PreviewMouseDownOutsideCapturedElement 
                            // event first.
                            MouseButtonEventArgs clickThrough = new MouseButtonEventArgs(this, mouseButtonEventArgs.Timestamp, mouseButtonEventArgs.ChangedButton, GetStylusDevice(e.StagingItem)); 
                            clickThrough.RoutedEvent=Mouse.PreviewMouseDownOutsideCapturedElementEvent; 
                            //ProcessInput has a linkdemand
                            _inputManager.Value.ProcessInput(clickThrough); 
                        }
                    }

                    else if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseUpEvent) 
                    {
                        MouseButtonEventArgs mouseButtonEventArgs = e.StagingItem.Input as MouseButtonEventArgs; 
 
                        if (_mouseCapture != null && !_isPhysicallyOver)
                        { 
                            // The mouse is not physically over the capture point (or
                            // subtree), so raise the PreviewMouseUpOutsideCapturedElement
                            // event first.
                            MouseButtonEventArgs clickThrough = new MouseButtonEventArgs(this, mouseButtonEventArgs.Timestamp, mouseButtonEventArgs.ChangedButton, GetStylusDevice(e.StagingItem)); 
                            clickThrough.RoutedEvent=Mouse.PreviewMouseUpOutsideCapturedElementEvent;
                            //ProcessInput has a linkdemand 
                            _inputManager.Value.ProcessInput(clickThrough); 
                        }
                    } 
                }
            }

        } 

        ///  
        ///     Critical: This code accesses data that was got off an unmanaged call (_doubleClickDeltaX,_doubleClickDeltaY) 
        ///     It also accesss Input Source and can be used for input spoofing
        ///     accesses e.StagingItem.Input 
        /// 
        [SecurityCritical]
        private void PreNotifyInput(object sender, NotifyInputEventArgs e)
        { 
            if ( e.StagingItem.Input.RoutedEvent == InputManager.PreviewInputReportEvent )
            { 
                InputReportEventArgs inputReportEventArgs = e.StagingItem.Input as InputReportEventArgs; 

                if (!inputReportEventArgs.Handled && inputReportEventArgs.Report.Type == InputType.Mouse) 
                {
                    RawMouseInputReport rawMouseInputReport = (RawMouseInputReport) inputReportEventArgs.Report;

                    // Generally, we need to check against redundant actions. 
                    // We never prevent the raw event from going through, but we
                    // will only generate the high-level events for non-redundant 
                    // actions.  We store the set of non-redundant actions in 
                    // the dictionary of this event.
 
                    // Get the current Non-Redundant Actions for this event and
                    // make a copy.  We will compare the original value against the copy
                    // at the end of this function and write it back in if changed.
 
                    RawMouseActions actions = GetNonRedundantActions(e);
                    RawMouseActions originalActions = actions; 
 
                    _stylusDevice = GetStylusDevice(e.StagingItem);
 
                    // Normally we only process mouse input that is from our
                    // active presentation source.  The only exception to this is
                    // the activate report, which is how we change the visual
                    // manager that is active. 
                    if ((rawMouseInputReport.Actions & RawMouseActions.Activate) == RawMouseActions.Activate)
                    { 
                        // System.Console.WriteLine("Initializing the mouse state."); 

                        actions |= RawMouseActions.Activate; 

                        _positionRelativeToOver.X = 0;
                        _positionRelativeToOver.Y = 0;
 
                        _lastPosition.X = rawMouseInputReport.X;
                        _lastPosition.Y = rawMouseInputReport.Y; 
                        _forceUpdateLastPosition = true; 

                        _stylusDevice = inputReportEventArgs.Device as StylusDevice; 

                        // if the existing source is null, no need to do any special-case handling
                        if (_inputSource == null)
                        { 
                            _inputSource = new SecurityCriticalDataClass(rawMouseInputReport.InputSource);
                        } 
                        // if the new source is the same as the old source, don't bother doing anything 
                        else if (_inputSource.Value != rawMouseInputReport.InputSource)
                        { 
                            IMouseInputProvider toDeactivate = _inputSource.Value.GetInputProvider(typeof(MouseDevice)) as IMouseInputProvider;

                            // All mouse information is now restricted to this presentation source.
                            _inputSource = new SecurityCriticalDataClass(rawMouseInputReport.InputSource); 

                            if (toDeactivate != null) 
                            { 
                                toDeactivate.NotifyDeactivate();
                            } 
                        }
                    }

                    // Only process mouse input that is from our active presentation source. 
                    if ((_inputSource != null) && (rawMouseInputReport.InputSource == _inputSource.Value))
                    { 
                        // If the input is reporting mouse deactivation, we need 
                        // to break any capture we may have.  Note that we only do
                        // this if the presentation source associated with this event 
                        // is the same presentation source we are already over.
                        if ((rawMouseInputReport.Actions & RawMouseActions.Deactivate) == RawMouseActions.Deactivate)
                        {
                            // Console.WriteLine("RawMouseActions.Deactivate"); 
                            Debug.Assert(_mouseOver == null, "_mouseOver should be null because we have called ChangeMouseOver(null) already.");
                            _inputSource = null; 
 
                            ChangeMouseCapture(null, null, CaptureMode.None, e.StagingItem.Input.Timestamp);
                        } 

                        if ((rawMouseInputReport.Actions & RawMouseActions.CancelCapture) == RawMouseActions.CancelCapture)
                        {
                            // Console.WriteLine("RawMouseActions.CancelCapture"); 
                            ChangeMouseCapture(null, null, CaptureMode.None, e.StagingItem.Input.Timestamp);
                        } 
 
                        // If the input is reporting mouse movement, only update the
                        // set of non-redundant actions if the position changed. 
                        if ((rawMouseInputReport.Actions & RawMouseActions.AbsoluteMove) == RawMouseActions.AbsoluteMove) //
                        {
                            //Console.WriteLine("RawMouseActions.AbsoluteMove: X=" + rawMouseInputReport.X + " Y=" + rawMouseInputReport.Y );
 
                            // Translate the mouse coordinates to both root relative and "mouseOver" relate.
                            // - Note: "mouseOver" in this case is the element the mouse "was" over before this move. 
                            bool mouseOverAvailable = false; 
                            Point ptClient = new Point(rawMouseInputReport.X, rawMouseInputReport.Y);
                            Point ptRoot = (Point) e.StagingItem.GetData(_tagRootPoint); 
                            Point ptRelativeToOver = InputElement.TranslatePoint(ptRoot, rawMouseInputReport.InputSource.RootVisual, (DependencyObject)_mouseOver, out mouseOverAvailable);

                            IInputElement mouseOver = _mouseOver; // assume mouse is still over whatever it was before
                            IInputElement rawMouseOver = (_rawMouseOver != null) ? (IInputElement)_rawMouseOver.Target : null; 
                            bool isPhysicallyOver = _isPhysicallyOver;
                            bool isGlobalChange = ArePointsClose(ptClient, _lastPosition) == false;  // determine if the mouse actually physically moved 
 
                            // Invoke Hit Test logic to determine what element the mouse will be over AFTER the move is processed.
                            // - Only do this if: 
                            //      - The mouse physcially moved (isGlobalChange)
                            //      - We are simulating a mouse move (_isSynchronize)
                            //      - mouseOver isn't availabe (!mouseOverAvailable)  Could be caused by a degenerate transform.
                            // - This is to mitigate the redundant AbsoluteMove notifications associated with QueryCursor 
                            if (isGlobalChange || rawMouseInputReport._isSynchronize || !mouseOverAvailable)
                            { 
                                isPhysicallyOver = true;  // assume mouse is physical over element, we'll set it false if it's due to capture 

                                switch (_captureMode) 
                                {
                                    // In this case there is no capture, so a simple hit test will determine which element becomes "mouseOver"
                                    case CaptureMode.None:
                                        { 
                                            if (rawMouseInputReport._isSynchronize)
                                            { 
                                                GlobalHitTest(true, ptClient, _inputSource.Value, out mouseOver, out rawMouseOver); 
                                            }
                                            else 
                                            {
                                                LocalHitTest(true, ptClient, _inputSource.Value, out mouseOver, out rawMouseOver);
                                            }
 
                                            if (mouseOver == rawMouseOver)
                                            { 
                                                // Since they are the same, there is no reason to process rawMouseOver 
                                                rawMouseOver = null;
                                            } 

                                            // We understand UIElements and ContentElements.
                                            // If we are over something else (like a raw visual)
                                            // find the containing element. 
                                            if (!InputElement.IsValid(mouseOver))
                                                mouseOver = InputElement.GetContainingInputElement(mouseOver as DependencyObject); 
                                            if ((rawMouseOver != null) && !InputElement.IsValid(rawMouseOver)) 
                                                rawMouseOver = InputElement.GetContainingInputElement(rawMouseOver as DependencyObject);
                                        } 
                                        break;

                                    // In this case, capture is to a specific element, so it will ALWAYS become "mouseOver"
                                    // - however, we do a hit test to see if the mouse is actually physically over the element, 
                                    // - if it is not, we toggle isPhysicallyOver
                                    case CaptureMode.Element: 
                                        if (rawMouseInputReport._isSynchronize) 
                                        {
                                            mouseOver = GlobalHitTest(true, ptClient, _inputSource.Value); 
                                        }
                                        else
                                        {
                                            mouseOver = LocalHitTest(true, ptClient, _inputSource.Value); 
                                        }
 
                                        // There is no reason to process rawMouseOver when 
                                        // the element should always be the one with mouse capture.
                                        rawMouseOver = null; 

                                        if (mouseOver != _mouseCapture)
                                        {
                                            // Always consider the mouse over the capture point. 
                                            mouseOver = _mouseCapture;
                                            isPhysicallyOver = false; 
                                        } 
                                        break;
 
                                    // In this case, capture is set to an entire subtree.  We use simple hit testing to determine
                                    // which, if any element in the subtree it is over, and set "mouseOver to that element
                                    // If it is not over any specific subtree element, "mouseOver" is set to the root of the subtree.
                                    // - Note: a subtree can span multiple HWNDs 
                                    case CaptureMode.SubTree:
                                        { 
                                            IInputElement mouseCapture = InputElement.GetContainingInputElement(_mouseCapture as DependencyObject); 
                                            if (mouseCapture != null)
                                            { 
                                                // We need to re-hit-test to get the "real" UIElement we are over.
                                                // This allows us to have our capture-to-subtree span multiple windows.

                                                // GlobalHitTest always returns an IInputElement, so we are sure to have one. 
                                                GlobalHitTest(true, ptClient, _inputSource.Value, out mouseOver, out rawMouseOver);
                                            } 
 
                                            if (mouseOver != null && !InputElement.IsValid(mouseOver) )
                                                mouseOver = InputElement.GetContainingInputElement(mouseOver as DependencyObject); 

                                            // Make sure that the element we hit is acutally underneath
                                            // our captured element.  Because we did a global hit test, we
                                            // could have hit an element in a completely different window. 
                                            //
                                            // Note that we support the child being in a completely different window. 
                                            // So we use the GetUIParent method instead of just looking at 
                                            // visual/content parents.
                                            if (mouseOver != null) 
                                            {
                                                IInputElement ieTest = mouseOver;
                                                UIElement eTest = null;
                                                ContentElement ceTest = null; 
                                                UIElement3D e3DTest = null;
 
                                                while (ieTest != null && ieTest != mouseCapture) 
                                                {
                                                    eTest = ieTest as UIElement; 

                                                    if (eTest != null)
                                                    {
                                                        ieTest = InputElement.GetContainingInputElement(eTest.GetUIParent(true)); 
                                                    }
                                                    else 
                                                    { 
                                                        ceTest = ieTest as ContentElement;
 
                                                        if (ceTest != null)
                                                        {
                                                            ieTest = InputElement.GetContainingInputElement(ceTest.GetUIParent(true));
                                                        } 
                                                        else
                                                        { 
                                                            e3DTest = ieTest as UIElement3D; // Should never fail. 

                                                            ieTest = InputElement.GetContainingInputElement(e3DTest.GetUIParent(true)); 
                                                        }
                                                    }
                                                }
 
                                                // If we missed the capture point, we didn't hit anything.
                                                if (ieTest != mouseCapture) 
                                                { 
                                                    mouseOver = _mouseCapture;
                                                    isPhysicallyOver = false; 

                                                    // Since they are the same, there is no reason to process rawMouseOver
                                                    rawMouseOver = null;
                                                } 
                                            }
                                            else 
                                            { 
                                                // We didn't hit anything.  Consider the mouse over the capture point.
                                                mouseOver = _mouseCapture; 
                                                isPhysicallyOver = false;

                                                // Since they are the same, there is no reason to process rawMouseOver
                                                rawMouseOver = null; 
                                            }
 
                                            if (rawMouseOver != null) 
                                            {
                                                if (mouseOver == rawMouseOver) 
                                                {
                                                    // Since they are the same, there is no reason to process rawMouseOver
                                                    rawMouseOver = null;
                                                } 
                                                else if (!InputElement.IsValid(rawMouseOver))
                                                { 
                                                    rawMouseOver = InputElement.GetContainingInputElement(rawMouseOver as DependencyObject); 
                                                }
                                            } 
                                        }
                                        break;
                                }
                            } 

                            _isPhysicallyOver = mouseOver == null ? false : isPhysicallyOver; 
 
                            // Now that we've determine what element the mouse is over now (mouseOver)
                            // - we need to check if it's changed 

                            bool isMouseOverChange = mouseOver != _mouseOver;

                            // If mouseOver changed, we need to recalculate the ptRelativeToOver, because "Over" changed! 

                            if (isMouseOverChange) 
                            { 
                                ptRelativeToOver = InputElement.TranslatePoint(ptRoot, rawMouseInputReport.InputSource.RootVisual, (DependencyObject)mouseOver);
                            } 

                            //Console.WriteLine("RawMouseActions.AbsoluteMove: mouse moved over " + (isMouseOverChange ? "same" : "different") + " element.  old=" + _mouseOver + " new=" + mouseOver);
                            //Console.WriteLine("RawMouseActions.AbsoluteMove: capture=" + _mouseCapture);
 
                            // Check to see if the local mouse position changed.  This can be
                            // caused by a change to the geometry of the 
                            // element we are over or a change in which element 
                            // we are over.
                            // 
                            bool isLocalChange = isMouseOverChange || ArePointsClose(ptRelativeToOver, _positionRelativeToOver) == false;

                            // Console.WriteLine("RawMouseActions.AbsoluteMove: isGlobalChange=" + isGlobalChange + " isLocalChange=" + isLocalChange);
 
                            // We only update our cached position (_lastPosition & _positionRelativeToOver )
                            // if we have moved "far enough" allowing small incrementaly moves to accumulate 
 
                            if (isGlobalChange || isLocalChange || _forceUpdateLastPosition)
                            { 
                                _forceUpdateLastPosition = false;

                                _lastPosition = ptClient;
                                _positionRelativeToOver = ptRelativeToOver; 

                                if (isMouseOverChange) 
                                { 
                                    ChangeMouseOver(mouseOver, e.StagingItem.Input.Timestamp);
                                } 

                                if ((_rawMouseOver == null) && (rawMouseOver != null))
                                {
                                    _rawMouseOver = new WeakReference(rawMouseOver); 
                                }
                                else if (_rawMouseOver != null) 
                                { 
                                    _rawMouseOver.Target = rawMouseOver;
                                } 

                                // Console.WriteLine("RawMouseActions.AbsoluteMove: ptRoot=" + ptRoot);

                                actions |= RawMouseActions.AbsoluteMove; // 

                                // In most cases the sequence of messages received from the system are HitTest, SetCursor & MouseMove. 
                                // The SetCursor message in this case will be traslated into an Avalon MouseMove & QueryCursor. 
                                // The MouseMove message to follow is redundant and is thrown away.
                                // But imagine a case where Capture is taken. Here the system produces only two messages HitTest & MouseMove. 
                                // Hence we translate the MouseMove into an Avalon MouseMove & QueryCursor.
                                // Logically MouseMove and QueryCursor go as a pair.
                                actions |= RawMouseActions.QueryCursor;
                            } 
                        }
 
                        // Mouse wheel rotate events are never considered redundant. 
                        if ((rawMouseInputReport.Actions & RawMouseActions.VerticalWheelRotate) == RawMouseActions.VerticalWheelRotate)
                        { 
                            // Console.WriteLine("RawMouseActions.VerticalWheelRotate");

                            actions |= RawMouseActions.VerticalWheelRotate;
 
                            // Tell the InputManager that the MostRecentDevice is us.
                            _inputManager.Value.MostRecentInputDevice = this; 
                        } 

                        // Mouse query cursor events are never considered redundant. 
                        if ((rawMouseInputReport.Actions & RawMouseActions.QueryCursor) == RawMouseActions.QueryCursor)
                        {
                            // Console.WriteLine("RawMouseActions.QueryCursor");
 
                            actions |= RawMouseActions.QueryCursor;
                        } 
 
                        RawMouseActions[] ButtonPressActions =
                        { 
                            RawMouseActions.Button1Press,
                            RawMouseActions.Button2Press,
                            RawMouseActions.Button3Press,
                            RawMouseActions.Button4Press, 
                            RawMouseActions.Button5Press
                        }; 
 
                        RawMouseActions[] ButtonReleaseActions =
                        { 
                            RawMouseActions.Button1Release,
                            RawMouseActions.Button2Release,
                            RawMouseActions.Button3Release,
                            RawMouseActions.Button4Release, 
                            RawMouseActions.Button5Release
                        }; 
 
                        for (int iButton = 0; iButton < 5; iButton++)
                        { 
                            if ((rawMouseInputReport.Actions & ButtonPressActions[iButton]) == ButtonPressActions[iButton])
                            {
                                actions |= ButtonPressActions[iButton];
 
                                // Tell the InputManager that the MostRecentDevice is us.
                                _inputManager.Value.MostRecentInputDevice = this; 
                            } 

                            if ((rawMouseInputReport.Actions & ButtonReleaseActions[iButton]) == ButtonReleaseActions[iButton]) 
                            {
                                actions |= ButtonReleaseActions[iButton];

                                // Tell the InputManager that the MostRecentDevice is us. 
                                _inputManager.Value.MostRecentInputDevice = this;
                            } 
                        } 
                    }
 
                    if (actions != originalActions)
                    {
                        e.StagingItem.SetData(_tagNonRedundantActions, actions);
                    } 
                }
            } 
            else 
            {
                // All mouse event processing should only happen if we still have an active input source. 

                if (_inputSource != null)
                {
                    // During the PreviewMouseDown event, we update the click count, if there are 
                    // multiple "quick" clicks in approximately the "same" location (as defined
                    // by the hosting environment, aka the registry). 
                    if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseDownEvent) 
                    {
                        MouseButtonEventArgs mouseButtonArgs = e.StagingItem.Input as MouseButtonEventArgs; 
                        StylusDevice stylusDevice = GetStylusDevice(e.StagingItem);
                        Point ptClient = GetClientPosition();

                        _clickCount = CalculateClickCount(mouseButtonArgs.ChangedButton, mouseButtonArgs.Timestamp, stylusDevice, ptClient); 
                        if (_clickCount == 1)
                        { 
                            // we need to reset out data, since this is the start of the click count process... 
                            _lastClick = ptClient;
                            _lastButton = mouseButtonArgs.ChangedButton; 
                            _lastClickTime = mouseButtonArgs.Timestamp;
                        }
                        // Put the updated count into the args.
                        mouseButtonArgs.ClickCount = _clickCount; 
                    }
                } 
            } 
        }
 
        // Due to the inexactness of math calculations of
        // floating-point numbers, we use the AreClose method
        // to determine if the coordinates are close enough
        // to consider the same. 

        private bool ArePointsClose(Point A, Point B) 
        { 
            return MS.Internal.DoubleUtil.AreClose(A.X, B.X) && MS.Internal.DoubleUtil.AreClose(A.Y, B.Y);
        } 

        /// 
        ///     Critical: This code elevates permissions by calling unsafe native methods, also this
        ///     function is not ok to expose publicly and hence the critical. 
        ///     accesses e.StagingItem.Input
        ///  
        [SecurityCritical] 
        private void PostProcessInput(object sender, ProcessInputEventArgs e)
        { 
            // PreviewMouseWheel --> MouseWheel
            if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseWheelEvent)
            {
                if (!e.StagingItem.Input.Handled) 
                {
                    MouseWheelEventArgs previewWheel = (MouseWheelEventArgs) e.StagingItem.Input; 
                    MouseWheelEventArgs wheel = new MouseWheelEventArgs(this, previewWheel.Timestamp, previewWheel.Delta); 
                    wheel.RoutedEvent=Mouse.MouseWheelEvent;
 
                    #if SEND_WHEEL_EVENTS_TO_FOCUS
                    // wheel events are treated as if they came from the
                    // element with keyboard focus
                    wheel.Source = previewWheel.Source; 
                    #endif
 
                    e.PushInput(wheel, e.StagingItem); 
                }
            } 

            // PreviewMouseDown --> MouseDown
            if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseDownEvent)
            { 
                if (!e.StagingItem.Input.Handled)
                { 
                    MouseButtonEventArgs previewDown = (MouseButtonEventArgs) e.StagingItem.Input; 
                    MouseButtonEventArgs down = new MouseButtonEventArgs(this, previewDown.Timestamp, previewDown.ChangedButton, GetStylusDevice(e.StagingItem));
                    down.ClickCount = previewDown.ClickCount; 
                    down.RoutedEvent=Mouse.MouseDownEvent;
                    e.PushInput(down, e.StagingItem);
                }
            } 

            // PreviewMouseUp --> MouseUp 
            if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseUpEvent) 
            {
                if (!e.StagingItem.Input.Handled) 
                {
                    MouseButtonEventArgs previewUp = (MouseButtonEventArgs) e.StagingItem.Input;
                    MouseButtonEventArgs up = new MouseButtonEventArgs(this, previewUp.Timestamp, previewUp.ChangedButton, GetStylusDevice(e.StagingItem));
                    up.RoutedEvent=Mouse.MouseUpEvent; 
                    e.PushInput(up, e.StagingItem);
                } 
            } 

            // PreviewMouseMove --> MouseMove 
            if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseMoveEvent)
            {
                if (!e.StagingItem.Input.Handled)
                { 
                    MouseEventArgs previewMove = (MouseEventArgs) e.StagingItem.Input;
                    MouseEventArgs move = new MouseEventArgs(this, previewMove.Timestamp, GetStylusDevice(e.StagingItem)); 
                    move.RoutedEvent=Mouse.MouseMoveEvent; 
                    e.PushInput(move, e.StagingItem);
                } 
            }

            // We are finished processing the QueryCursor event.  Just update the
            // mouse cursor to be what was decided during the event route. 
            if (e.StagingItem.Input.RoutedEvent == Mouse.QueryCursorEvent)
            { 
 
                QueryCursorEventArgs queryCursor = (QueryCursorEventArgs)e.StagingItem.Input;
 

                SetCursor(queryCursor.Cursor);

            } 

            if (e.StagingItem.Input.RoutedEvent == InputManager.InputReportEvent) 
            { 
                InputReportEventArgs inputReportEventArgs = e.StagingItem.Input as InputReportEventArgs;
 
                if (!inputReportEventArgs.Handled && inputReportEventArgs.Report.Type == InputType.Mouse)
                {
                    RawMouseInputReport rawMouseInputReport = (RawMouseInputReport) inputReportEventArgs.Report;
 
                    // Only process mouse input that is from our active visual manager.
                    if ((_inputSource != null) && (rawMouseInputReport.InputSource == _inputSource.Value)) 
                    { 
                        // In general, this is where we promote the non-redundant
                        // reported actions to our premier events. 
                        RawMouseActions actions = GetNonRedundantActions(e);

                        // Raw Activate --> Raw MouseMove
                        // Whenever the mouse device is activated we need to 
                        // cause a mouse move so that elements realize that
                        // the mouse is over them again.  In most cases, the 
                        // action that caused the mouse to activate is a move, 
                        // but this is to guard against any other cases.
                        if ((actions & RawMouseActions.Activate) == RawMouseActions.Activate) 
                        {
                            Synchronize();
                        }
 
                        // Raw --> PreviewMouseWheel
                        if ((actions & RawMouseActions.VerticalWheelRotate) == RawMouseActions.VerticalWheelRotate) // 
                        { 
                            MouseWheelEventArgs previewWheel = new MouseWheelEventArgs(this, rawMouseInputReport.Timestamp, rawMouseInputReport.Wheel);
 
                            previewWheel.RoutedEvent=Mouse.PreviewMouseWheelEvent;

                            #if SEND_WHEEL_EVENTS_TO_FOCUS
                            // wheel events are treated as if they came from the 
                            // element with keyboard focus
                            DependencyObject focus = Keyboard.FocusedElement as DependencyObject; 
                            if (focus != null) 
                            {
                                previewWheel.Source = focus; 
                            }
                            #endif

                            e.PushInput(previewWheel, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseDown 
                        if ((actions & RawMouseActions.Button1Press) == RawMouseActions.Button1Press)
                        { 
                            MouseButtonEventArgs previewDown = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.Left, GetStylusDevice(e.StagingItem));

                            previewDown.RoutedEvent=Mouse.PreviewMouseDownEvent;
                            e.PushInput(previewDown, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseUp 
                        if ((actions & RawMouseActions.Button1Release) == RawMouseActions.Button1Release)
                        { 
                            MouseButtonEventArgs previewUp = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.Left, GetStylusDevice(e.StagingItem));

                            previewUp.RoutedEvent=Mouse.PreviewMouseUpEvent;
                            e.PushInput(previewUp, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseDown 
                        if ((actions & RawMouseActions.Button2Press) == RawMouseActions.Button2Press)
                        { 
                            MouseButtonEventArgs previewDown = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.Right, GetStylusDevice(e.StagingItem));

                            previewDown.RoutedEvent=Mouse.PreviewMouseDownEvent;
                            e.PushInput(previewDown, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseUp 
                        if ((actions & RawMouseActions.Button2Release) == RawMouseActions.Button2Release)
                        { 
                            MouseButtonEventArgs previewUp = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.Right, GetStylusDevice(e.StagingItem));

                            previewUp.RoutedEvent=Mouse.PreviewMouseUpEvent;
                            e.PushInput(previewUp, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseDown 
                        if ((actions & RawMouseActions.Button3Press) == RawMouseActions.Button3Press)
                        { 
                            MouseButtonEventArgs previewDown = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.Middle, GetStylusDevice(e.StagingItem));

                            previewDown.RoutedEvent=Mouse.PreviewMouseDownEvent;
                            e.PushInput(previewDown, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseUp 
                        if ((actions & RawMouseActions.Button3Release) == RawMouseActions.Button3Release)
                        { 
                            MouseButtonEventArgs previewUp = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.Middle, GetStylusDevice(e.StagingItem));

                            previewUp.RoutedEvent=Mouse.PreviewMouseUpEvent;
                            e.PushInput(previewUp, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseDown 
                        if ((actions & RawMouseActions.Button4Press) == RawMouseActions.Button4Press)
                        { 
                            MouseButtonEventArgs previewDown = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.XButton1, GetStylusDevice(e.StagingItem));

                            previewDown.RoutedEvent=Mouse.PreviewMouseDownEvent;
                            e.PushInput(previewDown, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseUp 
                        if ((actions & RawMouseActions.Button4Release) == RawMouseActions.Button4Release)
                        { 
                            MouseButtonEventArgs previewUp = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.XButton1, GetStylusDevice(e.StagingItem));

                            previewUp.RoutedEvent=Mouse.PreviewMouseUpEvent;
                            e.PushInput(previewUp, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseDown 
                        if ((actions & RawMouseActions.Button5Press) == RawMouseActions.Button5Press)
                        { 
                            MouseButtonEventArgs previewDown = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.XButton2, GetStylusDevice(e.StagingItem));

                            previewDown.RoutedEvent=Mouse.PreviewMouseDownEvent;
                            e.PushInput(previewDown, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseUp 
                        if ((actions & RawMouseActions.Button5Release) == RawMouseActions.Button5Release)
                        { 
                            MouseButtonEventArgs previewUp = new MouseButtonEventArgs(this, rawMouseInputReport.Timestamp, MouseButton.XButton2, GetStylusDevice(e.StagingItem));

                            previewUp.RoutedEvent=Mouse.PreviewMouseUpEvent;
                            e.PushInput(previewUp, e.StagingItem); 
                        }
 
                        // Raw --> PreviewMouseMove 
                        if ((actions & RawMouseActions.AbsoluteMove) == RawMouseActions.AbsoluteMove) //
                        { 
                            MouseEventArgs previewMove = new MouseEventArgs(this, rawMouseInputReport.Timestamp, GetStylusDevice(e.StagingItem));

                            previewMove.RoutedEvent=Mouse.PreviewMouseMoveEvent;
                            e.PushInput(previewMove, e.StagingItem); 
                        }
 
                        // Raw --> QueryCursor 
                        if ((actions & RawMouseActions.QueryCursor) == RawMouseActions.QueryCursor)
                        { 
                            inputReportEventArgs.Handled = UpdateCursorPrivate();
                        }
                    }
                } 
            }
        } 
 
        private RawMouseActions GetNonRedundantActions(NotifyInputEventArgs e)
        { 
            RawMouseActions actions = new RawMouseActions();

            // The CLR throws a null-ref exception if it tries to unbox a
            // null.  So we have to special case that. 
            object o = e.StagingItem.GetData(_tagNonRedundantActions);
            if (o != null) 
            { 
                actions = (RawMouseActions) o;
            } 

            return actions;
        }
 
        internal static IInputElement GlobalHitTest(bool clientUnits, Point pt, PresentationSource inputSource)
        { 
            IInputElement enabledHit; 
            IInputElement originalHit;
            GlobalHitTest(clientUnits, pt, inputSource, out enabledHit, out originalHit); 

            return enabledHit;
        }
 
        internal static IInputElement GlobalHitTest(Point ptClient, PresentationSource inputSource)
        { 
            return GlobalHitTest(true, ptClient, inputSource); 
        }
 
        // Take a point relative the the specified visual manager, and translate
        // up to the screen, hit-test to a window, and then hit-test down to an
        // element.
        ///  
        ///     Critical: This code accesses PresentationSource and returns element which is hittest
        ///     TreatAsSafe: This function is safe to expose. Only the element being clicked on is returned. 
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private static void GlobalHitTest(bool clientUnits, Point pt, PresentationSource inputSource, out IInputElement enabledHit, out IInputElement originalHit) 
        {
            enabledHit = originalHit = null;

            Point ptClient = clientUnits ? pt : PointUtil.RootToClient(pt, inputSource); 

            // Note: this only works for HWNDs for now. 
            HwndSource source = inputSource as HwndSource; 
            if (source != null && source.CompositionTarget != null && !source.IsHandleNull)
            { 

                Point ptScreen = PointUtil.ClientToScreen(ptClient, source);
                IntPtr hwndHit = IntPtr.Zero ;
                HwndSource sourceHit = null ; 

                // Hit-test for a window. 
                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); // BlessedAssert: 
                try
                { 
                    // Find the HWND under the point.
                    hwndHit = UnsafeNativeMethods.WindowFromPoint((int)ptScreen.X, (int)ptScreen.Y);

                    // Make sure the window is enabled! 
                    if (!SafeNativeMethods.IsWindowEnabled(new HandleRef(null, hwndHit)))
                    { 
                        hwndHit = IntPtr.Zero; 
                    }
                } 
                finally
                {
                    CodeAccessPermission.RevertAssert();
                } 
                if (hwndHit != IntPtr.Zero)
                { 
                    // See if this is one of our windows. 
                    sourceHit = HwndSource.CriticalFromHwnd(hwndHit);
                } 
                if (sourceHit != null && sourceHit.Dispatcher == inputSource.CompositionTarget.Dispatcher)
                {
                    Point ptClientHit = PointUtil.ScreenToClient(ptScreen, sourceHit);
 
                    // Perform a local hit-test within this visual manager.
                    LocalHitTest(true, ptClientHit, sourceHit, out enabledHit, out originalHit); 
                } 
            }
        } 

        internal static IInputElement LocalHitTest(bool clientUnits, Point pt, PresentationSource inputSource)
        {
            IInputElement enabledHit; 
            IInputElement originalHit;
            LocalHitTest(clientUnits, pt, inputSource, out enabledHit, out originalHit); 
 
            return enabledHit;
        } 

        internal static IInputElement LocalHitTest(Point ptClient, PresentationSource inputSource)
        {
            return LocalHitTest(true, ptClient, inputSource); 
        }
 
        // Take a point relative the the specified visual manager and hit-test 
        // down to an element.
        ///  
        ///     Critical: This code accesses PresentationSource and returns element which is hittest
        ///     TreatAsSafe: This function is safe to expose. Only the element being clicked on is returned.
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        private static void LocalHitTest(bool clientUnits, Point pt, PresentationSource inputSource, out IInputElement enabledHit, out IInputElement originalHit)
        { 
            enabledHit = originalHit = null; 

            // Hit-test starting from the root UIElement. 
            // Note: this restricts us to windows with UIElement as the root (not just visuals).
            if (inputSource != null)
            {
                UIElement root = inputSource.RootVisual as UIElement; 
                if(root != null)
                { 
                    Point rootPt = clientUnits ? PointUtil.ClientToRoot(pt, inputSource) : pt; 
                    root.InputHitTest(rootPt, out enabledHit, out originalHit);
                } 
            }
        }

        internal bool IsSameSpot(Point newPosition, StylusDevice stylusDevice) 
        {
            int doubleClickDeltaX = (stylusDevice != null)?stylusDevice.DoubleTapDeltaX:_doubleClickDeltaX; 
            int doubleClickDeltaY = (stylusDevice != null)?stylusDevice.DoubleTapDeltaY:_doubleClickDeltaY; 

            // Is the delta coordinates of this click close enough to the last click? 
            return (Math.Abs(newPosition.X - _lastClick.X) < doubleClickDeltaX) &&
                   (Math.Abs(newPosition.Y - _lastClick.Y) < doubleClickDeltaY);
        }
 
        internal int CalculateClickCount(MouseButton button, int timeStamp, StylusDevice stylusDevice, Point downPt)
        { 
            // How long since the last click? 
            int timeSpan = timeStamp - _lastClickTime;
 
            int doubleClickDeltaTime = (stylusDevice != null)?stylusDevice.DoubleTapDeltaTime:_doubleClickDeltaTime;

            // Is the delta coordinates of this click close enough to the last click?
            bool isSameSpot = IsSameSpot(downPt, stylusDevice); 

            // Is this the same mouse button as the last click? 
            bool isSameButton = (_lastButton == button); 

            // Now check everything to see if this is a multi-click. 
            if (timeSpan < doubleClickDeltaTime
                  && isSameSpot
                  && isSameButton)
            { 
                // Yes, increment the count
                return _clickCount +1; 
            } 
            else
            { 
                // No, not a multi-click.
                return 1;
            }
        } 

        internal Point PositionRelativeToOver 
        { 
            get
            { 
                return _positionRelativeToOver;
            }
        }
 
        internal Point NonRelativePosition
        { 
            get 
            {
                return _lastPosition; 
            }
        }

        ///  
        ///     Critical: accesses critical data (_inputSource)
        ///     TreatAsSafe: doesn't expose critical data, just returns true/false. 
        ///  
        internal bool IsActive
        { 
            [SecurityCritical, SecurityTreatAsSafe]
            get
            {
                return _inputSource != null && _inputSource.Value != null; 
            }
        } 
 
        // Helper to access the StylusDevice property.
        private StylusDevice GetStylusDevice(StagingAreaInputItem stagingItem) 
        {
            return stagingItem.GetData(_tagStylusDevice) as StylusDevice;
        }
 
        internal StylusDevice StylusDevice
        { 
            get 
            {
                return _stylusDevice; 
            }
        }

        private DeferredElementTreeState MouseOverTreeState 
        {
            get 
            { 
                if (_mouseOverTreeState == null)
                { 
                    _mouseOverTreeState = new DeferredElementTreeState();
                }

                return _mouseOverTreeState; 
            }
        } 
 
        private DeferredElementTreeState MouseCaptureWithinTreeState
        { 
            get
            {
                if (_mouseCaptureWithinTreeState == null)
                { 
                    _mouseCaptureWithinTreeState = new DeferredElementTreeState();
                } 
 
                return _mouseCaptureWithinTreeState;
            } 
        }

        /// 
        ///     This data is not safe to expose as it holds refrence to PresentationSource 
        /// 
        private SecurityCriticalDataClass _inputSource; 
 
        /// 
        ///     This data is not safe to expose as it holds refrence to PresentationSource 
        /// 
        private SecurityCriticalData _inputManager;

        private IInputElement _mouseOver; 
        private DeferredElementTreeState _mouseOverTreeState;
        private bool _isPhysicallyOver; 
        private WeakReference _rawMouseOver; 

        private IInputElement _mouseCapture; 
        private DeferredElementTreeState _mouseCaptureWithinTreeState;
        private SecurityCriticalDataClass _providerCapture;
        private CaptureMode _captureMode;
 
        private DependencyPropertyChangedEventHandler _overIsEnabledChangedEventHandler;
        private DependencyPropertyChangedEventHandler _overIsVisibleChangedEventHandler; 
        private DependencyPropertyChangedEventHandler _overIsHitTestVisibleChangedEventHandler; 
        private DispatcherOperationCallback _reevaluateMouseOverDelegate;
        private DispatcherOperation _reevaluateMouseOverOperation; 

        private DependencyPropertyChangedEventHandler _captureIsEnabledChangedEventHandler;
        private DependencyPropertyChangedEventHandler _captureIsVisibleChangedEventHandler;
        private DependencyPropertyChangedEventHandler _captureIsHitTestVisibleChangedEventHandler; 
        private DispatcherOperationCallback _reevaluateCaptureDelegate;
        private DispatcherOperation _reevaluateCaptureOperation; 
 
        // Device state we track
        private Point _positionRelativeToOver = new Point(); 
        private Point _lastPosition = new Point();
        private bool _forceUpdateLastPosition = false;

        // Data tags for information we pass around the staging area. 
        private object _tagNonRedundantActions = new object();
        private object _tagStylusDevice = new object(); 
        private object _tagRootPoint = new object(); 

        // Information used to distinguish double-clicks (actually, multi clicks) from 
        // multiple independent clicks.
        private Point _lastClick = new Point();
        private MouseButton _lastButton;
        private int _clickCount; 
        private int _lastClickTime;
        private int _doubleClickDeltaTime; 
        private int _doubleClickDeltaX; 
        private int _doubleClickDeltaY;
 
        private Cursor _overrideCursor;

        // Reference to StylusDevice to defer to for physical mouse state (position/button state)
        private StylusDevice _stylusDevice = null; 
    }
} 

// 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