void HandleTouchFrameReported(object sender, TouchFrameEventArgs e)
        {
            try {
                var pts = e.GetTouchPoints(this);
                var spts = e.GetTouchPoints((UIElement)Parent);

                var began = new List<CanvasTouch>();
                var ended = new List<CanvasTouch>();
                var moved = new List<CanvasTouch>();

                for (var i = 0; i < pts.Count; i++) {

                    var p = pts[i];
                    var handle = new IntPtr(p.TouchDevice.Id + 1);

                    var now = DateTime.UtcNow;

                    if (p.Action == TouchAction.Down) {

                        var pos = p.Position.ToPointF();

                        //
                        // Look for double taps
                        //
                        var tapCount = 1;

                        if (_lastDownTime.ContainsKey(handle) &&
                            _lastBeganPosition.ContainsKey(handle)) {
                            var dt = now - _lastDownTime[handle];

                            if (dt.TotalSeconds < 0.5 && pos.DistanceTo(_lastBeganPosition[handle]) < DoubleClickMinDistance) {
                                tapCount++;
                            }
                        }

                        //
                        // TouchBegan
                        //
                        var t = new CanvasTouch {
                            Handle = handle,
                            TapCount = tapCount,
                            CanvasLocation = pos,
                            CanvasPreviousLocation = pos,
                            SuperCanvasLocation = spts[i].Position.ToPointF(),
                            SuperCanvasPreviousLocation = spts[i].Position.ToPointF(),
                            PreviousTime = now,
                            Time = now,
                        };
                        _activeTouches[t.Handle] = t;
                        _lastDownTime[t.Handle] = now;
                        _lastBeganPosition[t.Handle] = pos;
                        began.Add(t);
                    }
                    else if (_activeTouches.ContainsKey(handle)) {
                        var t = _activeTouches[handle];

                        t.CanvasPreviousLocation = t.CanvasLocation;
                        t.SuperCanvasPreviousLocation = t.SuperCanvasLocation;
                        t.PreviousTime = t.Time;

                        t.CanvasLocation = p.Position.ToPointF();
                        t.SuperCanvasLocation = spts[i].Position.ToPointF();
                        t.Time = now;

                        if (p.Action == TouchAction.Move) {
                            moved.Add(t);
                        }
                        else {
                            ended.Add(t);
                        }
                    }
                }

                var del = Content;
                if (del != null && _touchEnabled) {
                    if (began.Count > 0) {
                        del.TouchesBegan(began.ToArray());
                    }
                    if (moved.Count > 0) {
                        del.TouchesMoved(moved.ToArray());
                    }
                    if (ended.Count > 0) {
                        del.TouchesEnded(ended.ToArray());
                    }
                }
            }
            catch (Exception err) {
                System.Diagnostics.Debug.WriteLine(err);
            }
        }
        void SilverlightGraphicsCanvas_PointerPressed(DispatcherTimerTickEventArgs sender, PointerEventArgs e)
        {
            var handle = new IntPtr(e.Pointer.PointerId);

            var now = DateTime.Now;
            var pos = ToPointF(e.GetCurrentPoint(this));

            //
            // Look for double taps
            //
            var tapCount = 1;

            if (_lastDownTime.ContainsKey(handle) &&
                _lastBeganPosition.ContainsKey(handle)) {
                var dt = now - _lastDownTime[handle];

                if (dt.TotalSeconds < 0.5 && pos.DistanceTo(_lastBeganPosition[handle]) < DoubleClickMinDistance) {
                    tapCount++;
                }
            }

            //
            // TouchBegan
            //
            var touch = new CanvasTouch {
                Handle = handle,
                Time = now,
                SuperCanvasLocation = ToPointF(e.GetCurrentPoint((UIElement)Parent)),
                CanvasLocation = pos,
                TapCount = tapCount,
            };
            touch.PreviousTime = touch.Time;
            touch.SuperCanvasPreviousLocation = touch.SuperCanvasLocation;
            touch.CanvasPreviousLocation = touch.CanvasLocation;

            _lastBeganPosition [handle] = pos;
            _lastDownTime[handle] = now;

            _activeTouches[handle] = touch;

            if (Delegate != null) {
                Delegate.TouchesBegan(new[] { touch });
            }
        }