context: using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Drawing;
  using System.Runtime.InteropServices;
  using System.Threading;
  
  namespace ITouch
  {
  	// Destination object for touch/mouse/pen gestures.
  	internal interface IInteractionHandler
  	{
  		void ProcessInteractionEvent(InteractionOutput output);
  	}
  
  	// Passed as an argument to ProcessInteractionEvent.
  	internal class InteractionOutput
  	{
  		internal Win32touch.INTERACTION_CONTEXT_OUTPUT Data;
  
  		internal IntPtr InteractionContext
  		{
  			get { return _interactionContext; }
  		}
  
  		internal bool IsBegin()
  		{
  			return (Data.InteractionFlags & Win32touch.INTERACTION_FLAGS.BEGIN) != 0;
  		}
  
  		internal bool IsInertia()
  		{
  			return (Data.InteractionFlags & Win32touch.INTERACTION_FLAGS.INERTIA) != 0;
  		}
  
  		internal bool IsEnd()
  		{
  			return (Data.InteractionFlags & Win32touch.INTERACTION_FLAGS.END) != 0;
  		}
  
  		#region ** infrastructure
  
  		IntPtr _interactionContext;
  		IInteractionHandler _interactionHandler;
  		SynchronizationContext _syncContext;
  
  		internal InteractionOutput(IntPtr interactionContext, IInteractionHandler interactionHandler, SynchronizationContext syncContext)
  		{
  			_interactionContext = interactionContext;
  			_interactionHandler = interactionHandler;
  			_syncContext = syncContext;
  			Alive = true;
  		}
  
  		internal bool Alive { get; set; }
  
  		internal IInteractionHandler InteractionHandler
  		{
  			get { return _interactionHandler; }
  		}
  
  		internal SynchronizationContext SyncContext
  		{
  			get { return _syncContext; }
  		}
  
  		#endregion
  	}
  
  	[System.Security.SuppressUnmanagedCodeSecurity()]
  	internal static class Win32touch
  	{
  		//------------------------------------------------------------------
  		#region ** fields and utility methods
  
  		internal static readonly int CursorInfoSize;
  
  		#region ** infrastructure
  
  		static Timer _timer;
  		static Queue<InteractionOutput> _inertiaQueue;
  		static Dictionary<long, InteractionOutput> _listeners;
  		static INTERACTION_CONTEXT_OUTPUT_CALLBACK _callback;
  		static object _lockObj = new object();
  
  		static Win32touch()
  		{
  			CursorInfoSize = Marshal.SizeOf(new CURSORINFO());
  			_inertiaQueue = new Queue<InteractionOutput>();
  			_listeners = new Dictionary<long, InteractionOutput>();
  			_timer = new Timer(TimerElapsed, null, 100, 15);
  			_callback = CallbackFunction;
  		}
  
  		static void TimerElapsed(object state)
  		{
  			InteractionOutput[] items = null;
  			lock (_lockObj)
  			{
  				if (_inertiaQueue.Count > 0)
  				{
  					items = _inertiaQueue.ToArray();
  					_inertiaQueue.Clear();
  				}
  			}
  			if (items != null)
  			{
  				for (int i = 0; i < items.Length; i++)
  				{
  					InteractionOutput io = items[i];
  					for (int j = 0; j < i; j++)
  					{
  						if (items[j].InteractionContext == io.InteractionContext)
  						{
  							io = null;
  							break;
  						}
  					}
  					if (io != null && io.Alive)
  					{
  						io.SyncContext.Post(delegate(object obj)
  						{
  							InteractionOutput m = (InteractionOutput)obj;
  							if (m.Alive)
  							{
  								ProcessInertiaInteractionContext(m.InteractionContext);
  							}
  						}, io);
  					}
  				}
  			}
  		}
  
  		static void CallbackFunction(IntPtr ic, IntPtr outputPtr)
  		{
  			InteractionOutput io;
  			lock (_lockObj)
  			{
  				_listeners.TryGetValue(ic.ToInt64(), out io);
  			}
  			if (io != null)
  			{
  				io.Data = (INTERACTION_CONTEXT_OUTPUT)Marshal.PtrToStructure(outputPtr, typeof(INTERACTION_CONTEXT_OUTPUT));
  
  				io.InteractionHandler.ProcessInteractionEvent(io);
  
  				if (io.Alive && (io.Data.InteractionFlags & INTERACTION_FLAGS.INERTIA) != 0 &&
  					(io.Data.InteractionFlags & (INTERACTION_FLAGS.END | INTERACTION_FLAGS.CANCEL)) == 0)
  				{
  					lock (_lockObj)
  					{
  						_inertiaQueue.Enqueue(io);
  					}
  				}
  			}
  		}
  
  		#endregion
  
  		internal static IntPtr CreateInteractionContext(IInteractionHandler interactionHandler, SynchronizationContext syncContext)
  		{
  			IntPtr ic;
  			CreateInteractionContext(out ic);
  			InteractionOutput io = new InteractionOutput(ic, interactionHandler, syncContext);
  			lock (_lockObj)
  			{
  				_listeners.Add(ic.ToInt64(), io);
  			}
  			RegisterOutputCallbackInteractionContext(ic, Marshal.GetFunctionPointerForDelegate(_callback), ic);
  			return ic;
  		}
  
  		internal static void DisposeInteractionContext(IntPtr interactionContext)
  		{
  			if (interactionContext != IntPtr.Zero)
  			{
  				InteractionOutput io;
  				lock (_lockObj)
  				{
  					if (_listeners.TryGetValue(interactionContext.ToInt64(), out io))
  					{
  						io.Alive = false;
  						_listeners.Remove(interactionContext.ToInt64());
  					}
  				}
  				DestroyInteractionContext(interactionContext);
  			}
  		}
  
  		internal static int GET_POINTER_ID(IntPtr wParam)
  		{
  			return LOWORD(wParam);
  		}
  
  		internal static bool IS_POINTER_FLAG_SET(IntPtr wParam, POINTER_MESSAGE_FLAG flag)
  		{
  			return (HIWORD(wParam) & (int)flag) != 0;
  		}
  
  		internal static int HIWORD(IntPtr wParam)
  		{
  			return (int)((wParam.ToInt64() >> 16) & 0xffff);
  		}
  
  		internal static int LOWORD(IntPtr wParam)
  		{
  			return (int)(wParam.ToInt64() & 0xffff);
  		}
  
  		internal static int GET_WHEEL_DELTA(IntPtr wParam)
  		{
  			return GET_Y(wParam);
  		}
  
  		internal static int GET_X(IntPtr lParam)
  		{
  
gt: 			return (int)((short)(lParam.ToInt64() & 0xffff));