diff --git a/Changelog b/Changelog index a6faac1c..514ee258 100644 --- a/Changelog +++ b/Changelog @@ -7,7 +7,7 @@ sure to provide a sizeHint. * v1.3.1 (unreleased) - - + - Improve dragging across monitors with different dpi scaling * v1.3.0 (8 February 2021) - Experimental QtQuick support (#49) diff --git a/src/private/DragController.cpp b/src/private/DragController.cpp index fb150c48..25a4bb1b 100644 --- a/src/private/DragController.cpp +++ b/src/private/DragController.cpp @@ -255,6 +255,7 @@ void StateDragging::onEntry() dw->d->saveLastFloatingGeometry(); } + const bool needsUndocking = !q->m_draggable->isWindow(); q->m_windowBeingDragged = q->m_draggable->makeWindow(); if (q->m_windowBeingDragged) { #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) && defined(Q_OS_WIN) @@ -268,12 +269,17 @@ void StateDragging::onEntry() QWindow *window = fw->windowHandle(); - // Position the window before the drag start, otherwise if you move mouse too fast there will be an offset - window->setPosition(QCursor::pos() - q->m_offset); + if (needsUndocking) { + // Position the window before the drag start, otherwise if you move mouse too fast there will be an offset + // Only required when we've undocked/detached a window. + window->setPosition(QCursor::pos() - q->m_offset); + } // Start the native move window->startSystemMove(); } +#else + Q_UNUSED(needsUndocking); #endif qCDebug(state) << "StateDragging entered. m_draggable=" << q->m_draggable->asWidget() diff --git a/src/private/Draggable_p.h b/src/private/Draggable_p.h index c18ebf33..abf97b08 100644 --- a/src/private/Draggable_p.h +++ b/src/private/Draggable_p.h @@ -79,6 +79,12 @@ public: ///@brief Returns whether this draggable is a MDI window, being dragged internally within a main window virtual bool isMDI() const = 0; + /** + * @brief Returns whether this draggable is already a window. + * + * If true, means the drag will simply move the existing window, and no undocking/untabbing is involved. + */ + virtual bool isWindow() const = 0; private: class Private; Private *const d; diff --git a/src/private/FloatingWindow.cpp b/src/private/FloatingWindow.cpp index 674a1fb6..d8d356b6 100644 --- a/src/private/FloatingWindow.cpp +++ b/src/private/FloatingWindow.cpp @@ -502,3 +502,8 @@ bool FloatingWindow::isMDI() const { return false; } + +bool FloatingWindow::isWindow() const +{ + return true; +} diff --git a/src/private/FloatingWindow_p.h b/src/private/FloatingWindow_p.h index bfd92942..4de03dc5 100644 --- a/src/private/FloatingWindow_p.h +++ b/src/private/FloatingWindow_p.h @@ -51,6 +51,7 @@ public: // Draggable: std::unique_ptr makeWindow() override; DockWidgetBase *singleDockWidget() const override; + bool isWindow() const override; const QVector dockWidgets() const; const Frame::List frames() const; diff --git a/src/private/TabWidget.cpp b/src/private/TabWidget.cpp index 4148b127..fb9c3298 100644 --- a/src/private/TabWidget.cpp +++ b/src/private/TabWidget.cpp @@ -94,6 +94,12 @@ std::unique_ptr TabBar::makeWindow() return std::unique_ptr(new WindowBeingDragged(floatingWindow, draggable)); } +bool TabBar::isWindow() const +{ + // Same semantics as tab widget, no need to duplicate logic + return m_tabWidget->isWindow(); +} + void TabBar::onMousePress(QPoint localPos) { m_lastPressedDockWidget = dockWidgetAt(localPos); @@ -237,6 +243,16 @@ std::unique_ptr TabWidget::makeWindow() return std::unique_ptr(new WindowBeingDragged(floatingWindow, this)); } +bool TabWidget::isWindow() const +{ + if (auto floatingWindow = qobject_cast(asWidget()->window())) { + // Case of dragging via the tab widget when the title bar is hidden + return floatingWindow->hasSingleFrame(); + } + + return false; +} + DockWidgetBase *TabWidget::singleDockWidget() const { if (m_frame->hasSingleDockWidget()) diff --git a/src/private/TabWidget_p.h b/src/private/TabWidget_p.h index 356e21d5..23430c7a 100644 --- a/src/private/TabWidget_p.h +++ b/src/private/TabWidget_p.h @@ -57,6 +57,7 @@ public: // Draggable std::unique_ptr makeWindow() override; + bool isWindow() const override; void onMousePress(QPoint localPos); void onMouseDoubleClick(QPoint localPos); @@ -175,6 +176,7 @@ public: // Draggable interface std::unique_ptr makeWindow() override; DockWidgetBase *singleDockWidget() const override; + bool isWindow() const override; /// @reimp bool isMDI() const override; diff --git a/src/private/TitleBar.cpp b/src/private/TitleBar.cpp index 450cc45e..76649707 100644 --- a/src/private/TitleBar.cpp +++ b/src/private/TitleBar.cpp @@ -469,3 +469,8 @@ void TitleBar::updateFloatButton() setFloatButtonToolTip(floatingWindow() ? tr("Dock window") : tr("Undock window")); setFloatButtonVisible(supportsFloatingButton()); } + +bool TitleBar::isWindow() const +{ + return m_floatingWindow != nullptr; +} diff --git a/src/private/TitleBar_p.h b/src/private/TitleBar_p.h index 3caa95ee..eea16ff1 100644 --- a/src/private/TitleBar_p.h +++ b/src/private/TitleBar_p.h @@ -56,6 +56,7 @@ public: void setIcon(const QIcon &icon); std::unique_ptr makeWindow() override; + bool isWindow() const override; DockWidgetBase *singleDockWidget() const override;