private void DragMove(Func <IInputElement, Point> getPosition, bool isCreatingCopy)
        {
            if (!m_initialMousePositionToAdorner.HasValue)
            {
                return;
            }

            if (!m_isDragging)
            {
                var position = getPosition.Invoke(m_adornerLayer);

                if (DragDropHelper.IsMouseMoveDrag(m_initialMousePositionToAdorner.Value, position))
                {
                    m_draggedElementGhost = DragSourceManagerBase.CreateDraggedElementGhost(m_draggedElement, isCreatingCopy);

                    this.OnDragStart(getPosition);
                    this.IsDragging = true;
                }
            }

            if (m_isDragging)
            {
                this.OnDragMove(getPosition);
                this.UpdateGhost(getPosition);
            }
        }
        internal DragSourceManagerBase(UIElement draggedElement, AdornerLayer adornerLayer, UIElement container, bool enableAutoScroll, bool showGhost)
        {
            if (draggedElement == null)
            {
                throw new ArgumentNullException("draggedElement");
            }

            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            m_draggedElement = draggedElement;
            m_container      = container;
            m_adornerLayer   = (adornerLayer != null) ? adornerLayer : AdornerLayer.GetAdornerLayer(container);
            m_showGhost      = showGhost;

            if (enableAutoScroll)
            {
                var scrollViewer = DragSourceManagerBase.GetScrollViewer(draggedElement);
                if (scrollViewer != null)
                {
                    m_autoScrollManager = new AutoScrollManager(scrollViewer);
                }
            }
        }
        private void DragStart(Func <IInputElement, Point> getPosition)
        {
            var parent = DragSourceManagerBase.GetPopupOrWindow(m_draggedElement);
            var draggedElementPosition = getPosition.Invoke(m_draggedElement);

            m_isPopup = (parent is Popup);
            m_initialMousePositionToAdorner        = (m_adornerLayer != null) ? getPosition.Invoke(m_adornerLayer) : default(Point? );
            m_initialMousePositionToDraggedElement = draggedElementPosition;
            m_mouseToScreenPositionFactor          = DragSourceManagerBase.CalculateMouseToScreenPositionFactor(parent);
            m_draggedElementMouseOffset            = new Vector(draggedElementPosition.X, draggedElementPosition.Y);

            if (m_autoScrollManager != null)
            {
                m_autoScrollManager.Start();
            }

            this.IsDragStarted = true;
        }
        private static Vector CalculateMouseToScreenPositionFactor(FrameworkElement element)
        {
            if (element == null)
            {
                return(new Vector(1d, 1d));
            }

            var source = PresentationSource.FromVisual(element);

            if (source == null)
            {
                var parent = DragSourceManagerBase.GetPopupParent(element);
                while (parent != null)
                {
                    source = PresentationSource.FromDependencyObject(parent);
                    if (source != null)
                    {
                        break;
                    }

                    parent = DragSourceManagerBase.GetPopupParent(parent);
                }
            }

            double x, y;

            if (source != null)
            {
                var deviceUnits = source.CompositionTarget.TransformToDevice;
                x = deviceUnits.M11;
                y = deviceUnits.M22;
            }
            else
            {
                using (var hwnd = new HwndSource(new HwndSourceParameters()))
                {
                    var deviceUnits = hwnd.CompositionTarget.TransformToDevice;
                    x = deviceUnits.M11;
                    y = deviceUnits.M22;
                }
            }

            return(new Vector((x == 0d) ? 1d : 1d / x, (y == 0d) ? 1d : 1d / y));
        }