File: System\Windows\Input\Stylus\Common\StylusDevice.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\PresentationCore\PresentationCore.csproj (PresentationCore)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using MS.Internal;
using MS.Internal.PresentationCore;                        // SecurityHelper
using MS.Win32;
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.Security;
using System.Windows;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Input.StylusWisp;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;
using SR = MS.Internal.PresentationCore.SR;
 
namespace System.Windows.Input
{
    /// <summary>
    ///     The StylusDevice class represents the stylus device
    /// </summary>
    public sealed class StylusDevice : InputDevice
    {
        #region Implementation
 
        /// <summary>
        ///
        /// 
        /// The implementation root for the internal StylusDevice hierarchy.
        /// This exists since this class now operates as a public wrapper to an internal
        /// hierarchy rooted with StylusDeviceBase.
        /// </summary>
        internal StylusDeviceBase StylusDeviceImpl { get; set; } = null;
 
        #endregion
 
        #region Constructor
 
        /// <summary>
        /// Constructor taking a base implementation
        /// </summary>
        /// <param name="impl">The base of the internal hierarchy</param>
        internal StylusDevice(StylusDeviceBase impl)
        {
            ArgumentNullException.ThrowIfNull(impl);
 
            StylusDeviceImpl = impl;
        }
 
        #endregion
 
        #region Public API
 
        /// <summary>
        ///     Returns the element that input from this device is sent to.
        /// </summary>
        public override IInputElement Target
        {
            get
            {
                VerifyAccess();
                return StylusDeviceImpl.Target;
            }
        }
 
        /// <summary>
        ///     Returns whether the StylusDevice object has been internally disposed.
        /// </summary>
        public bool IsValid
        {
            get
            {
                return StylusDeviceImpl.IsValid;
            }
        }
 
        /// <summary>
        ///     Returns the PresentationSource that is reporting input for this device.
        /// </summary>
        /// <remarks>
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        /// </remarks>
        public override PresentationSource ActiveSource
        {
            get
            {
                return StylusDeviceImpl.ActiveSource;
            }
        }
 
        /// <summary>
        ///     Returns the element that the stylus is over.
        /// </summary>
        public IInputElement DirectlyOver
        {
            get
            {
                VerifyAccess();
                return StylusDeviceImpl.DirectlyOver;
            }
        }
 
        /// <summary>
        ///     Returns the element that has captured the stylus.
        /// </summary>
        public IInputElement Captured
        {
            get
            {
                VerifyAccess();
                return StylusDeviceImpl.Captured;
            }
        }
 
        /// <summary>
        ///     Captures the stylus to a particular element.
        /// </summary>
        public bool Capture(IInputElement element, CaptureMode captureMode)
        {
            return StylusDeviceImpl.Capture(element, captureMode);
        }
 
        /// <summary>
        ///     Captures the stylus to a particular element.
        /// </summary>
        public bool Capture(IInputElement element)
        {
            // No need for calling ApplyTemplate since we forward the call.
 
            return Capture(element, CaptureMode.Element);
        }
 
        /// <summary>
        ///     Forces the stylusdevice to resynchronize at it's current location and state.
        ///     It can conditionally generate a Stylus Move/InAirMove (at the current location) if a change
        ///     in hittesting is detected that requires an event be generated to update elements 
        ///     to the current state (typically due to layout changes without Stylus changes).  
        ///     Has the same behavior as MouseDevice.Synchronize().
        /// </summary>
        public void Synchronize()
        {
            StylusDeviceImpl.Synchronize();
        }
 
        /// <summary>
        /// Returns the tablet associated with the StylusDevice
        /// </summary>
        public TabletDevice TabletDevice
        {
            get
            {
                return StylusDeviceImpl.TabletDevice;
            }
        }
 
        /// <summary>
        /// Returns the name of the StylusDevice
        /// </summary>
        public string Name
        {
            get
            {
                VerifyAccess();
                return StylusDeviceImpl.Name;
            }
        }
 
        /// <summary>
        /// Returns the friendly representation of the StylusDevice
        /// </summary>
        public override string ToString()
        {
            return String.Format(CultureInfo.CurrentCulture, "{0}({1})", base.ToString(), this.Name);
        }
 
        /// <summary>
        /// Returns the hardware id of the StylusDevice
        /// </summary>
        public int Id
        {
            get
            {
                VerifyAccess();
                return StylusDeviceImpl.Id;
            }
        }
 
        /// <summary>
        ///     Returns a StylusPointCollection object for processing the data in the packet.
        ///     This method creates a new StylusPointCollection and copies the data.
        /// </summary>
        public StylusPointCollection GetStylusPoints(IInputElement relativeTo)
        {
            VerifyAccess();
 
            return StylusDeviceImpl.GetStylusPoints(relativeTo);
        }
 
        /// <summary>
        ///     Returns a StylusPointCollection object for processing the data in the packet.
        ///     This method creates a new StylusPointCollection and copies the data.
        /// </summary>
        public StylusPointCollection GetStylusPoints(IInputElement relativeTo, StylusPointDescription subsetToReformatTo)
        {
            return StylusDeviceImpl.GetStylusPoints(relativeTo, subsetToReformatTo);
        }
 
        /// <summary>
        /// Returns the button collection that is associated with the StylusDevice.
        /// </summary>
        public StylusButtonCollection StylusButtons
        {
            get
            {
                VerifyAccess();
                return StylusDeviceImpl.StylusButtons;
            }
        }
 
        /// <summary>
        ///     Calculates the position of the stylus relative to a particular element.
        /// </summary>
        public Point GetPosition(IInputElement relativeTo)
        {
            VerifyAccess();
            return StylusDeviceImpl.GetPosition(relativeTo);
        }
 
        /// <summary>
        ///     Indicates the stylus is not touching the surface.
        ///     InAir events are general sent at a lower frequency.
        /// </summary>
        public bool InAir
        {
            get
            {
                VerifyAccess();
                return StylusDeviceImpl.InAir;
            }
        }
 
        /// <summary>
        ///     Indicates stylusDevice is in the inverted state.
        /// </summary>
        public bool Inverted
        {
            get
            {
                VerifyAccess();
                return StylusDeviceImpl.Inverted;
            }
        }
 
        /// <summary>
        ///     Indicates stylusDevice is in the inverted state.
        /// </summary>
        public bool InRange
        {
            get
            {
                VerifyAccess();
                return StylusDeviceImpl.InRange;
            }
        }
 
        #endregion
 
        #region Internal API
 
        internal int DoubleTapDeltaX
        {
            get { return StylusDeviceImpl.DoubleTapDeltaX; }
        }
 
        internal int DoubleTapDeltaY
        {
            get { return StylusDeviceImpl.DoubleTapDeltaY; }
        }
 
        internal int DoubleTapDeltaTime
        {
            get { return StylusDeviceImpl.DoubleTapDeltaTime; }
        }
 
        /// <summary>
        ///     Gets the current position of the mouse in screen co-ords
        /// </summary>
        /// <param name="mouseDevice">
        ///     The MouseDevice that is making the request
        /// </param>
        /// <returns>
        ///     The current mouse location in screen co-ords
        /// </returns>
        /// <remarks>
        ///     This is the hook where the Input system (via the MouseDevice) can call back into
        ///     the Stylus system when we are processing Stylus events instead of Mouse events
        /// </remarks>
        internal Point GetMouseScreenPosition(MouseDevice mouseDevice)
        {
            return StylusDeviceImpl.GetMouseScreenPosition(mouseDevice);
        }
 
        /// <summary>
        ///     Gets the current state of the specified button
        /// </summary>
        /// <param name="mouseButton">
        ///     The mouse button to get the state of
        /// </param>
        /// <param name="mouseDevice">
        ///     The MouseDevice that is making the request
        /// </param>
        /// <returns>
        ///     The state of the specified mouse button
        /// </returns>
        /// <remarks>
        ///     This is the hook where the Input system (via the MouseDevice) can call back into
        ///     the Stylus system when we are processing Stylus events instead of Mouse events
        /// </remarks>
        internal MouseButtonState GetMouseButtonState(MouseButton mouseButton, MouseDevice mouseDevice)
        {
            return StylusDeviceImpl.GetMouseButtonState(mouseButton, mouseDevice);
        }
 
        #endregion
 
        #region Static Functions
 
        internal static IInputElement LocalHitTest(PresentationSource inputSource, Point pt)
        {
            return MouseDevice.LocalHitTest(pt, inputSource);
        }
 
        internal static IInputElement GlobalHitTest(PresentationSource inputSource, Point pt)
        {
            return MouseDevice.GlobalHitTest(pt, inputSource);
        }
 
        /// <summary>
        /// Gets the transform relative to a particular element in the visual tree.
        /// </summary>
        internal static GeneralTransform GetElementTransform(IInputElement relativeTo)
        {
            GeneralTransform elementTransform = Transform.Identity;
            DependencyObject doRelativeTo = relativeTo as DependencyObject;
 
            if (doRelativeTo != null)
            {
                Visual visualFirstAncestor = VisualTreeHelper.GetContainingVisual2D(InputElement.GetContainingVisual(doRelativeTo));
                Visual visualRoot = VisualTreeHelper.GetContainingVisual2D(InputElement.GetRootVisual(doRelativeTo));
 
                GeneralTransform g = visualRoot.TransformToDescendant(visualFirstAncestor);
                if (g != null)
                {
                    elementTransform = g;
                }
            }
 
            return elementTransform;
        }
 
        #endregion
 
        #region Casting
 
        /// <summary>
        /// Function to convert any implementation class
        /// </summary>
        /// <typeparam name="T">The type to convert to</typeparam>
        /// <returns>An instance of the derived type</returns>
        internal T As<T>()
            where T : StylusDeviceBase
        {
            return StylusDeviceImpl as T;
        }
 
        #endregion
    }
}