internal void OnFloatWindowEnterMove(FloatWindow floatWindow)
        {
            Debug.Assert(floatWindow != null);

            if (!IsDragging)
                BeginDrag(floatWindow, null, null);
        }
        internal void OnFloatWindowMove(FloatWindow floatWindow)
        {
            if (IsDraggingFloatWindow)
            {
                Debug.Assert(_floatWindow == floatWindow);

                Drag();
            }
        }
        internal void OnFloatWindowExitMove(FloatWindow floatWindow)
        {
            if (IsDraggingFloatWindow)
            {
                Debug.Assert(_floatWindow == floatWindow);

                EndDrag(!Keyboard.IsKeyDown(Key.Escape));
            }
        }
Пример #4
0
        /// <summary>
        /// Tries to move the dragged items from the <see cref="FloatWindow"/> into a
        /// <see cref="DockTabPanel"/>.
        /// </summary>
        private void DragFloatWindowIntoDockTabPanel()
        {
            Debug.Assert(_targetDockTabPane == null);
            Debug.Assert(_floatWindow != null);

            var dockTabPane = GetTargetPane() as DockTabPane;

            if (dockTabPane == null)
            {
                return; // No DockTabPane (view).
            }
            var dockTabPaneVM = dockTabPane.GetViewModel();

            if (dockTabPaneVM == null)
            {
                return; // No IDockTabPane (view-model).
            }
            if (GetDockTabItemAtMouse(dockTabPane) == null)
            {
                return; // No DockTabItem hit.
            }
            if (!CanDock(dockTabPaneVM, DockPosition.Inside))
            {
                return; // Docking not allowed.
            }
            // Remove currently dragged FloatWindow.
            var floatWindowVM = _floatWindow.GetViewModel();

            foreach (var item in _draggedItems)
            {
                DockHelper.Remove(floatWindowVM, item);
            }

            _floatWindow = null;
            Win32.ReleaseCapture(); // Exit Win32 move window loop.

            // Add items into target DockTabPane.
            _targetDockTabPane = dockTabPane;
            foreach (var item in _draggedItems)
            {
                item.DockState = dockTabPaneVM.DockState;
                dockTabPaneVM.Items.Add(item);
            }

            // Make sure the current item is selected in DockTabPane.
            _dockStrategy.Activate(_activeItem);

            // When the Win32 move window loop exits, the DockControl receives a LostMouseCapture
            // event. --> Defer dragging of the DockTabItems.
            _dockControl.Dispatcher.BeginInvoke(new Action(() =>
            {
                if (!_dockControl.IsMouseCaptured)
                {
                    if (!_dockControl.CaptureMouse())
                    {
                        // Failed to capture the mouse.
                        EndDrag(false);
                        return;
                    }
                    _dockControl.LostMouseCapture  += OnLostMouseCapture;
                    _dockControl.MouseMove         += OnMouseMove;
                    _dockControl.MouseLeftButtonUp += OnMouseLeftButtonUp;
                    _dockControl.PreviewKeyDown    += OnPreviewKeyDown;

                    _targetDockTabPane.PreviewKeyDown += OnPreviewKeyDown;

                    DragDockTabItems();
                }
            }));

            HideBorderDockIndicators();
            HidePaneIndicators();

            _dockControl.UpdateFloatWindows();

            _layoutChanged = true;
        }
        /// <summary>
        /// Limits the extent of the <see cref="FloatWindow"/> to a reasonable size.
        /// </summary>
        /// <param name="floatWindow">The <see cref="FloatWindow"/>.</param>
        /// <param name="fallbackSize">The fallback size. Can be (NaN, NaN).</param>
        private static void LimitFloatWindowSize(FloatWindow floatWindow, Size fallbackSize)
        {
            Debug.Assert(floatWindow != null);
            Debug.Assert(Numeric.IsNaN(fallbackSize.Width) || fallbackSize.Width > 0);
            Debug.Assert(Numeric.IsNaN(fallbackSize.Height) || fallbackSize.Height > 0);

            double maxWidth = SystemParameters.MaximizedPrimaryScreenWidth;
            double maxHeight = SystemParameters.MaximizedPrimaryScreenHeight;

            Size size = floatWindow.RenderSize;
            if (size.Width > maxWidth)
                floatWindow.Width = Numeric.IsNaN(fallbackSize.Width) ? maxWidth : fallbackSize.Width;
            if (size.Height > maxHeight)
                floatWindow.Height = Numeric.IsNaN(fallbackSize.Height) ? maxHeight : fallbackSize.Height;
        }
Пример #6
0
        /// <summary>
        /// Starts a drag operation.
        /// </summary>
        /// <param name="floatWindow">The <see cref="FloatWindow"/> to be dragged.</param>
        /// <param name="dockTabPane">The <see cref="DockTabPane"/> to be dragged.</param>
        /// <param name="dockTabItem">The <see cref="DockTabItem"/> to be dragged.</param>
        /// <returns>
        /// <see langword="true" /> if the drag operation has been started; otherwise,
        /// <see langword="false" /> if the drag operation could not be started (e.g. because the
        /// mouse could not be captured).
        /// </returns>
        private bool BeginDrag(FloatWindow floatWindow, DockTabPane dockTabPane, DockTabItem dockTabItem)
        {
            _dockStrategy = _dockControl.GetViewModel()?.DockStrategy;
            if (_dockStrategy == null || _dockStrategy.DockControl.IsLocked)
            {
                Reset();
                return(false);
            }

            FrameworkElement element     = null;
            IDockTabPane     draggedPane = null;
            IDockTabItem     draggedItem = null;

            if (floatWindow != null)
            {
                // User is dragging a FloatWindow.
                // (Note: Dragging of FloatWindows with nested layouts is not supported.)
                draggedPane  = floatWindow.GetViewModel()?.RootPane as IDockTabPane;
                element      = floatWindow;
                _floatWindow = floatWindow;
                _initialSize = floatWindow.RenderSize;

                // Start dragging immediately.
                _dragDeltaExceeded = true;
            }
            else if (dockTabItem != null)
            {
                // User is dragging a DockTabItem in a DockTabPanel.
                draggedItem        = dockTabItem.GetViewModel();
                element            = dockTabItem;
                _targetDockTabPane = dockTabPane;
                _initialSize       = dockTabPane.RenderSize;

                // Start dragging when threshold is exceeded.
                _initialMousePosition = WindowsHelper.GetMousePosition(_dockControl);
                _dragDeltaExceeded    = false;
            }
            else if (dockTabPane != null)
            {
                // User is dragging a DockTabPane.
                draggedPane           = dockTabPane.GetViewModel();
                element               = dockTabPane;
                _initialSize          = dockTabPane.RenderSize;
                _initialMousePosition = WindowsHelper.GetMousePosition(_dockControl);

                // Start dragging when threshold is exceeded.
                _initialMousePosition = WindowsHelper.GetMousePosition(_dockControl);
                _dragDeltaExceeded    = false;
            }

            if (draggedPane == null && draggedItem == null)
            {
                Reset();
                return(false);
            }

            // When the user is dragging the FloatWindow, the mouse is captured by Win32 move window
            // loop. When dragging a DockTabPane or DockTabItem, the mouse needs to be
            // captured to receive mouse events.
            if (_floatWindow == null)
            {
                if (!_dockControl.CaptureMouse())
                {
                    // Failed to capture the mouse.
                    Reset();
                    return(false);
                }

                _dockControl.LostMouseCapture  += OnLostMouseCapture;
                _dockControl.MouseLeftButtonUp += OnMouseLeftButtonUp;
                _dockControl.MouseMove         += OnMouseMove;
                _dockControl.PreviewKeyDown    += OnPreviewKeyDown;
                if (_targetDockTabPane != null)
                {
                    _targetDockTabPane.PreviewKeyDown += OnPreviewKeyDown;
                }
            }

            _dockStrategy.Begin();

            if (draggedPane != null)
            {
                _dockStrategy.Activate(draggedPane);
                _activeItem = draggedPane.SelectedItem;
                foreach (var item in draggedPane.Items)
                {
                    if (item.DockState == draggedPane.DockState)
                    {
                        _draggedItems.Add(item);
                    }
                }
            }
            else
            {
                Debug.Assert(draggedItem != null);

                _dockStrategy.Activate(draggedItem);
                _activeItem = draggedItem;
                _draggedItems.Add(draggedItem);
            }

            Debug.Assert(_draggedItems.Count > 0);

            // Determine whether dragged items may end in a FloatWindow.
            _canFloat = CanFloat();

            // Store the mouse offset relative to the dragged element.
            _mouseOffset = (Vector)WindowsHelper.GetMousePosition(element);

            // Remember information needed for a rollback.
            ReplaceItemsWithProxies(draggedPane ?? _targetDockTabPane.GetViewModel());
            _originalDockState = _draggedItems[0].DockState;
            BackupFloatWindowPosition();

            // Override mouse cursors. (Mouse cursor should not change to caret over text editor.)
            Mouse.OverrideCursor = Cursors.Arrow;

            return(true);
        }
Пример #7
0
        private void DragDockTabItemsIntoFloatWindow()
        {
            Debug.Assert(_floatWindow == null);

            if (_targetDockTabPane != null)
            {
                ClearTranslateTransform();

                _targetDockTabPane.PreviewKeyDown -= OnPreviewKeyDown;
                _targetDockTabPane = null;
            }

            _dockControl.LostMouseCapture  -= OnLostMouseCapture;
            _dockControl.MouseLeftButtonUp -= OnMouseLeftButtonUp;
            _dockControl.MouseMove         -= OnMouseMove;
            _dockControl.PreviewKeyDown    -= OnPreviewKeyDown;

            _dockControl.ReleaseMouseCapture();

            // Remove the dragged items from their current location.
            foreach (var item in _draggedItems)
            {
                DockHelper.Remove(_dockStrategy.DockControl.RootPane, item);

                foreach (var floatWindow in _dockStrategy.DockControl.FloatWindows)
                {
                    DockHelper.Remove(floatWindow, item);
                }

                DockHelper.Remove(_dockStrategy.DockControl.AutoHideLeft, item);
                DockHelper.Remove(_dockStrategy.DockControl.AutoHideRight, item);
                DockHelper.Remove(_dockStrategy.DockControl.AutoHideTop, item);
                DockHelper.Remove(_dockStrategy.DockControl.AutoHideBottom, item);
            }

            // Move items into a new FloatWindow.
            foreach (var item in _draggedItems)
            {
                item.DockState = DockState.Float;
            }

            var newPaneVM = _dockStrategy.CreateDockTabPane(_draggedItems[0], DockState.Float);

            for (int i = 1; i < _draggedItems.Count; i++)
            {
                newPaneVM.Items.Add(_draggedItems[i]);
            }

            var floatWindowVM = _dockStrategy.CreateFloatWindow();

            floatWindowVM.RootPane = newPaneVM;
            _dockStrategy.DockControl.FloatWindows.Add(floatWindowVM);
            _dockStrategy.Activate(_activeItem);
            _dockStrategy.Cleanup();

            // Get the newly created FloatWindow (view) from the DockControl.
            _floatWindow = GetFloatWindow(floatWindowVM);

            Debug.Assert(_floatWindow != null);

            LimitFloatWindowSize(_floatWindow, _initialSize);

            // Limit mouse offset to FloatWindow size.
            double actualWidth = _floatWindow.ActualWidth;

            if (actualWidth > 0)
            {
                _mouseOffset.X = Math.Min(_mouseOffset.X, actualWidth / 2);
            }

            Point position = GetFloatWindowPosition();

            _floatWindow.Left = position.X;
            _floatWindow.Top  = position.Y;

            // Wait until FloatWindow is loaded, initiate the Win32 move window loop.
            _floatWindow.Dispatcher.BeginInvoke(new Action(() =>
            {
                if (_floatWindow != null)
                {
                    LimitFloatWindowSize(_floatWindow, _initialSize);

                    // Limit mouse offset to FloatWindow size.
                    _mouseOffset.X = Math.Min(_mouseOffset.X, _floatWindow.ActualWidth / 2);
                    _mouseOffset.Y = Math.Max(_mouseOffset.Y, 8);

                    Point pos         = GetFloatWindowPosition();
                    _floatWindow.Left = pos.X;
                    _floatWindow.Top  = pos.Y;

                    if (Mouse.LeftButton == MouseButtonState.Pressed)
                    {
                        _floatWindow.DragMove();
                    }
                    else
                    {
                        EndDrag(true);
                    }
                }
            }), DispatcherPriority.Loaded); // Important: Action needs to be invoked before input.
        }
        internal void UpdateFloatWindows()
        {
            if (DockStrategy == null)
                return;

            var owner = Window.GetWindow(this);

            // Close obsolete FloatWindows.
            for (int i = _floatWindows.Count - 1; i >= 0; i--)
            {
                var floatWindow = _floatWindows[i];
                var floatWindowVM = floatWindow.GetViewModel();
                if (floatWindowVM == null
                    || !DockStrategy.DockControl.FloatWindows.Contains(floatWindowVM)
                    || !DockStrategy.IsVisible(floatWindowVM))
                {
                    // ----- Close FloatWindow.
                    floatWindow.Close();
                    _floatWindows.RemoveAt(i);
                }
            }

            // Open new FloatWindows.
            for (int i = 0; i < DockStrategy.DockControl.FloatWindows.Count; i++)
            {
                var floatWindowVM = DockStrategy.DockControl.FloatWindows[i];
                if (DockStrategy.IsVisible(floatWindowVM) && GetView(floatWindowVM) == null)
                {
                    // ----- Open FloatWindow.

                    // Make sure that the floating window stays on the screen.
                    // At least 30 pixels must be visible.
                    const double safety = 30;
                    double screenLeft = SystemParameters.VirtualScreenLeft;
                    double screenTop = SystemParameters.VirtualScreenTop;
                    double screenRight = screenLeft + SystemParameters.VirtualScreenWidth;
                    double screenBottom = screenTop + SystemParameters.VirtualScreenHeight;
                    floatWindowVM.Left = Math.Min(Math.Max(floatWindowVM.Left, screenLeft), screenRight - safety);
                    floatWindowVM.Top = Math.Min(Math.Max(floatWindowVM.Top, screenTop), screenBottom - safety);

                    var floatWindow = new FloatWindow(this)
                    {
                        DataContext = floatWindowVM,
                        Owner = owner,
                    };

                    bool autoWidth = Numeric.IsNaN(floatWindowVM.Width);
                    bool autoHeight = Numeric.IsNaN(floatWindowVM.Height);
                    if (autoWidth && autoHeight)
                        floatWindow.SizeToContent = SizeToContent.WidthAndHeight;
                    else if (autoWidth)
                        floatWindow.SizeToContent = SizeToContent.Width;
                    else if (autoHeight)
                        floatWindow.SizeToContent = SizeToContent.Height;
                    else
                        floatWindow.SizeToContent = SizeToContent.Manual;

                    floatWindow.SetBinding(ContentProperty, new Binding(nameof(IFloatWindow.RootPane)));
                    floatWindow.SetBinding(WidthProperty, new Binding(nameof(IFloatWindow.Width)) { Mode = BindingMode.TwoWay });
                    floatWindow.SetBinding(HeightProperty, new Binding(nameof(IFloatWindow.Height)) { Mode = BindingMode.TwoWay });
                    floatWindow.SetBinding(Window.LeftProperty, new Binding(nameof(IFloatWindow.Left)) { Mode = BindingMode.TwoWay });
                    floatWindow.SetBinding(Window.TopProperty, new Binding(nameof(IFloatWindow.Top)) { Mode = BindingMode.TwoWay });

                    floatWindow.Show();

                    // Bind WindowState after showing the window. Otherwise, it could be maximized
                    // on the wrong screen.
                    floatWindow.SetBinding(Window.WindowStateProperty, new Binding(nameof(IFloatWindow.WindowState)) { Mode = BindingMode.TwoWay });

                    _floatWindows.Add(floatWindow);
                }
            }
        }
Пример #9
0
        //--------------------------------------------------------------
        /// <summary>
        /// Resets all fields.
        /// </summary>
        private void Reset()
        {
            Debug.Assert(Mouse.Captured == null);
            Debug.Assert(_borderDockIndicators == null);
            Debug.Assert(_paneDockIndicators == null);
            Debug.Assert(
                _dockStrategy == null || !_dockStrategy.DockControl.GetDockElements().OfType<DockTabItemProxy>().Any(),
                "All item proxies should have been removed.");

            _dockStrategy = null;
            _draggedItems.Clear();
            _activeItem = null;
            _floatWindow = null;
            _targetDockTabPane = null;
            _layoutChanged = false;
            _initialMousePosition = new Point(double.NaN, double.NaN);
            _dragDeltaExceeded = false;
            _mouseOffset = new Vector(double.NaN, double.NaN);
            _initialSize = new Size(double.NaN, double.NaN);
            _canFloat = true;
            _originalDockState = DockState.Hide;
            _originalFloatWindow = null;
            _originalFloatLeft = 0;
            _originalFloatTop = 0;
        }
Пример #10
0
        /// <summary>
        /// Tries to move the dragged items from the <see cref="FloatWindow"/> into a
        /// <see cref="DockTabPanel"/>.
        /// </summary>
        private void DragFloatWindowIntoDockTabPanel()
        {
            Debug.Assert(_targetDockTabPane == null);
            Debug.Assert(_floatWindow != null);

            var dockTabPane = GetTargetPane() as DockTabPane;
            if (dockTabPane == null)
                return; // No DockTabPane (view).

            var dockTabPaneVM = dockTabPane.GetViewModel();
            if (dockTabPaneVM == null)
                return; // No IDockTabPane (view-model).

            if (GetDockTabItemAtMouse(dockTabPane) == null)
                return; // No DockTabItem hit.

            if (!CanDock(dockTabPaneVM, DockPosition.Inside))
                return; // Docking not allowed.

            // Remove currently dragged FloatWindow.
            var floatWindowVM = _floatWindow.GetViewModel();
            foreach (var item in _draggedItems)
                DockHelper.Remove(floatWindowVM, item);

            _floatWindow = null;
            Win32.ReleaseCapture(); // Exit Win32 move window loop.

            // Add items into target DockTabPane.
            _targetDockTabPane = dockTabPane;
            foreach (var item in _draggedItems)
            {
                item.DockState = dockTabPaneVM.DockState;
                dockTabPaneVM.Items.Add(item);
            }

            // Make sure the current item is selected in DockTabPane.
            _dockStrategy.Activate(_activeItem);

            // When the Win32 move window loop exits, the DockControl receives a LostMouseCapture
            // event. --> Defer dragging of the DockTabItems.
            _dockControl.Dispatcher.BeginInvoke(new Action(() =>
            {
                if (!_dockControl.IsMouseCaptured)
                {
                    if (!_dockControl.CaptureMouse())
                    {
                        // Failed to capture the mouse.
                        EndDrag(false);
                        return;
                    }
                    _dockControl.LostMouseCapture += OnLostMouseCapture;
                    _dockControl.MouseMove += OnMouseMove;
                    _dockControl.MouseLeftButtonUp += OnMouseLeftButtonUp;
                    _dockControl.PreviewKeyDown += OnPreviewKeyDown;

                    _targetDockTabPane.PreviewKeyDown += OnPreviewKeyDown;

                    DragDockTabItems();
                }
            }));

            HideBorderDockIndicators();
            HidePaneIndicators();

            _dockControl.UpdateFloatWindows();

            _layoutChanged = true;
        }
Пример #11
0
        private void DragDockTabItemsIntoFloatWindow()
        {
            Debug.Assert(_floatWindow == null);

            if (_targetDockTabPane != null)
            {
                ClearTranslateTransform();

                _targetDockTabPane.PreviewKeyDown -= OnPreviewKeyDown;
                _targetDockTabPane = null;
            }

            _dockControl.LostMouseCapture -= OnLostMouseCapture;
            _dockControl.MouseLeftButtonUp -= OnMouseLeftButtonUp;
            _dockControl.MouseMove -= OnMouseMove;
            _dockControl.PreviewKeyDown -= OnPreviewKeyDown;

            _dockControl.ReleaseMouseCapture();

            // Remove the dragged items from their current location.
            foreach (var item in _draggedItems)
            {
                DockHelper.Remove(_dockStrategy.DockControl.RootPane, item);

                foreach (var floatWindow in _dockStrategy.DockControl.FloatWindows)
                    DockHelper.Remove(floatWindow, item);

                DockHelper.Remove(_dockStrategy.DockControl.AutoHideLeft, item);
                DockHelper.Remove(_dockStrategy.DockControl.AutoHideRight, item);
                DockHelper.Remove(_dockStrategy.DockControl.AutoHideTop, item);
                DockHelper.Remove(_dockStrategy.DockControl.AutoHideBottom, item);
            }

            // Move items into a new FloatWindow.
            foreach (var item in _draggedItems)
                item.DockState = DockState.Float;

            var newPaneVM = _dockStrategy.CreateDockTabPane(_draggedItems[0], DockState.Float);
            for (int i = 1; i < _draggedItems.Count; i++)
                newPaneVM.Items.Add(_draggedItems[i]);

            var floatWindowVM = _dockStrategy.CreateFloatWindow();
            floatWindowVM.RootPane = newPaneVM;
            _dockStrategy.DockControl.FloatWindows.Add(floatWindowVM);
            _dockStrategy.Activate(_activeItem);
            _dockStrategy.Cleanup();

            // Get the newly created FloatWindow (view) from the DockControl.
            _floatWindow = GetFloatWindow(floatWindowVM);

            Debug.Assert(_floatWindow != null);

            LimitFloatWindowSize(_floatWindow, _initialSize);

            // Limit mouse offset to FloatWindow size.
            double actualWidth = _floatWindow.ActualWidth;
            if (actualWidth > 0)
                _mouseOffset.X = Math.Min(_mouseOffset.X, actualWidth / 2);

            Point position = GetFloatWindowPosition();
            _floatWindow.Left = position.X;
            _floatWindow.Top = position.Y;

            // Wait until FloatWindow is loaded, initiate the Win32 move window loop.
            _floatWindow.Dispatcher.BeginInvoke(new Action(() =>
            {
                if (_floatWindow != null)
                {
                    LimitFloatWindowSize(_floatWindow, _initialSize);

                    // Limit mouse offset to FloatWindow size.
                    _mouseOffset.X = Math.Min(_mouseOffset.X, _floatWindow.ActualWidth / 2);
                    _mouseOffset.Y = Math.Max(_mouseOffset.Y, 8);

                    Point pos = GetFloatWindowPosition();
                    _floatWindow.Left = pos.X;
                    _floatWindow.Top = pos.Y;

                    if (Mouse.LeftButton == MouseButtonState.Pressed)
                        _floatWindow.DragMove();
                    else
                        EndDrag(true);
                }
            }), DispatcherPriority.Loaded); // Important: Action needs to be invoked before input.
        }
Пример #12
0
        /// <summary>
        /// Starts a drag operation.
        /// </summary>
        /// <param name="floatWindow">The <see cref="FloatWindow"/> to be dragged.</param>
        /// <param name="dockTabPane">The <see cref="DockTabPane"/> to be dragged.</param>
        /// <param name="dockTabItem">The <see cref="DockTabItem"/> to be dragged.</param>
        /// <returns>
        /// <see langword="true" /> if the drag operation has been started; otherwise,
        /// <see langword="false" /> if the drag operation could not be started (e.g. because the
        /// mouse could not be captured).
        /// </returns>
        private bool BeginDrag(FloatWindow floatWindow, DockTabPane dockTabPane, DockTabItem dockTabItem)
        {
            _dockStrategy = _dockControl.GetViewModel()?.DockStrategy;
            if (_dockStrategy == null || _dockStrategy.DockControl.IsLocked)
            {
                Reset();
                return false;
            }

            FrameworkElement element = null;
            IDockTabPane draggedPane = null;
            IDockTabItem draggedItem = null;
            if (floatWindow != null)
            {
                // User is dragging a FloatWindow.
                // (Note: Dragging of FloatWindows with nested layouts is not supported.)
                draggedPane = floatWindow.GetViewModel()?.RootPane as IDockTabPane;
                element = floatWindow;
                _floatWindow = floatWindow;
                _initialSize = floatWindow.RenderSize;

                // Start dragging immediately.
                _dragDeltaExceeded = true;
            }
            else if (dockTabItem != null)
            {
                // User is dragging a DockTabItem in a DockTabPanel.
                draggedItem = dockTabItem.GetViewModel();
                element = dockTabItem;
                _targetDockTabPane = dockTabPane;
                _initialSize = dockTabPane.RenderSize;

                // Start dragging when threshold is exceeded.
                _initialMousePosition = WindowsHelper.GetMousePosition(_dockControl);
                _dragDeltaExceeded = false;
            }
            else if (dockTabPane != null)
            {
                // User is dragging a DockTabPane.
                draggedPane = dockTabPane.GetViewModel();
                element = dockTabPane;
                _initialSize = dockTabPane.RenderSize;
                _initialMousePosition = WindowsHelper.GetMousePosition(_dockControl);

                // Start dragging when threshold is exceeded.
                _initialMousePosition = WindowsHelper.GetMousePosition(_dockControl);
                _dragDeltaExceeded = false;
            }

            if (draggedPane == null && draggedItem == null)
            {
                Reset();
                return false;
            }

            // When the user is dragging the FloatWindow, the mouse is captured by Win32 move window
            // loop. When dragging a DockTabPane or DockTabItem, the mouse needs to be
            // captured to receive mouse events.
            if (_floatWindow == null)
            {
                if (!_dockControl.CaptureMouse())
                {
                    // Failed to capture the mouse.
                    Reset();
                    return false;
                }

                _dockControl.LostMouseCapture += OnLostMouseCapture;
                _dockControl.MouseLeftButtonUp += OnMouseLeftButtonUp;
                _dockControl.MouseMove += OnMouseMove;
                _dockControl.PreviewKeyDown += OnPreviewKeyDown;
                if (_targetDockTabPane != null)
                    _targetDockTabPane.PreviewKeyDown += OnPreviewKeyDown;
            }

            _dockStrategy.Begin();

            if (draggedPane != null)
            {
                _dockStrategy.Activate(draggedPane);
                _activeItem = draggedPane.SelectedItem;
                foreach (var item in draggedPane.Items)
                    if (item.DockState == draggedPane.DockState)
                        _draggedItems.Add(item);
            }
            else
            {
                Debug.Assert(draggedItem != null);

                _dockStrategy.Activate(draggedItem);
                _activeItem = draggedItem;
                _draggedItems.Add(draggedItem);
            }

            Debug.Assert(_draggedItems.Count > 0);

            // Determine whether dragged items may end in a FloatWindow.
            _canFloat = CanFloat();

            // Store the mouse offset relative to the dragged element.
            _mouseOffset = (Vector)WindowsHelper.GetMousePosition(element);

            // Remember information needed for a rollback.
            ReplaceItemsWithProxies(draggedPane ?? _targetDockTabPane.GetViewModel());
            _originalDockState = _draggedItems[0].DockState;
            BackupFloatWindowPosition();

            // Override mouse cursors. (Mouse cursor should not change to caret over text editor.)
            Mouse.OverrideCursor = Cursors.Arrow;

            return true;
        }