diff --git a/src/private/Utils_p.h b/src/private/Utils_p.h index 065458b2..1bf4550e 100644 --- a/src/private/Utils_p.h +++ b/src/private/Utils_p.h @@ -74,6 +74,11 @@ inline bool usesNativeDraggingAndResizing() return usesNativeTitleBar() || usesAeroSnapWithCustomDecos(); } +inline void activateWindow(QWindow *window) +{ + window->requestActivate(); +} + inline bool windowManagerHasTranslucency() { #ifdef QT_X11EXTRAS_LIB @@ -128,6 +133,16 @@ inline QSize screenSizeForWidget(const QWidget *widget) return screenSizeForWindow(widget->window()->windowHandle()); } +inline QPoint mapToGlobal(QWidget *w, QPoint p) +{ + return w->mapToGlobal(p); +} + +inline void activateWindow(QWidget *widget) +{ + widget->activateWindow(); +} + #else inline int screenNumberForWidget(const QQuickItem *w) @@ -140,6 +155,11 @@ inline QSize screenSizeForWidget(const QQuickItem *w) return screenSizeForWindow(w->window()); } +inline QPoint mapToGlobal(QQuickItem *item, QPoint p) +{ + return item->mapToGlobal(p).toPoint(); +} + #endif }; diff --git a/tests/tst_common.cpp b/tests/tst_common.cpp index 2ae31960..de8e5c01 100644 --- a/tests/tst_common.cpp +++ b/tests/tst_common.cpp @@ -129,6 +129,8 @@ private Q_SLOTS: void tst_toggleMiddleDockCrash(); void tst_stealFrame(); void tst_setFloatingWhenWasTabbed(); + void tst_setFloatingWhenSideBySide(); + void tst_dockWindowWithTwoSideBySideFramesIntoCenter(); }; void TestCommon::tst_simple1() @@ -2193,4 +2195,86 @@ void TestCommon::tst_setFloatingWhenWasTabbed() Testing::waitForDeleted(window); } +void TestCommon::tst_setFloatingWhenSideBySide() +{ + // Tests DockWidget::setFloating(false|true) when side-by-side (it should put it where it was) + EnsureTopLevelsDeleted e; + + { + // 1. Create a MainWindow with two docked dock-widgets, then float the first one. + auto m = createMainWindow(); + auto dock1 = createDockWidget("dock1", new QPushButton("one")); + auto dock2 = createDockWidget("dock2", new QPushButton("two")); + m->addDockWidget(dock1, KDDockWidgets::Location_OnLeft); + m->addDockWidget(dock2, KDDockWidgets::Location_OnRight); + + QPointer frame1 = dock1->frame(); + dock1->setFloating(true); + QVERIFY(dock1->isFloating()); + auto fw = dock1->floatingWindow(); + QVERIFY(fw); + + //2. Put it back, via setFloating(). It should return to its place. + dock1->setFloating(false); + + QVERIFY(!dock1->isFloating()); + QVERIFY(!dock1->isTabbed()); + + Testing::waitForDeleted(fw); + } + + { + // 2. Tests a case where restoring a dock widget wouldn't make it use all its available space + auto m = createMainWindow(QSize(800, 500), MainWindowOption_None); + auto dock1 = createDockWidget("dock1", new QPushButton("one")); + auto dock2 = createDockWidget("dock2", new QPushButton("two")); + auto dock3 = createDockWidget("dock3", new QPushButton("three")); + auto dropArea = m->dropArea(); + MultiSplitter *layout = dropArea; + m->addDockWidget(dock1, KDDockWidgets::Location_OnLeft); + m->addDockWidget(dock2, KDDockWidgets::Location_OnRight); + m->addDockWidget(dock3, KDDockWidgets::Location_OnRight); + auto f2 = dock2->frame(); + Item *item2 = layout->itemForFrame(f2); + QVERIFY(item2); + dock2->close(); + dock3->close(); + Testing::waitForDeleted(f2); + dock2->show(); + Testing::waitForResize(dock2); + + QCOMPARE(item2->geometry(), dock2->frame()->QWidgetAdapter::geometry()); + layout->checkSanity(); + + // Cleanup + dock3->deleteLater(); + Testing::waitForDeleted(dock3); + } +} + +void TestCommon::tst_dockWindowWithTwoSideBySideFramesIntoCenter() +{ + EnsureTopLevelsDeleted e; + + auto m = createMainWindow(); + auto fw = createFloatingWindow(); + auto dock2 = createDockWidget("doc2", Qt::red); + nestDockWidget(dock2, fw->dropArea(), nullptr, KDDockWidgets::Location_OnLeft); + QCOMPARE(fw->frames().size(), 2); + QVERIFY(fw->dropArea()->checkSanity()); + + auto fw2 = createFloatingWindow(); + fw2->move(fw->x() + fw->width() + 100, fw->y()); + + dragFloatingWindowTo(fw, fw2->geometry().center()); + QVERIFY(fw2->dropArea()->checkSanity()); + + QCOMPARE(fw2->frames().size(), 1); + auto f2 = fw2->frames().constFirst(); + QCOMPARE(f2->dockWidgetCount(), 3); + QVERIFY(Testing::waitForDeleted(fw)); + delete fw2; +} + + #include "tst_common.moc" diff --git a/tests/tst_docks.cpp b/tests/tst_docks.cpp index bf968eb5..fdca75eb 100644 --- a/tests/tst_docks.cpp +++ b/tests/tst_docks.cpp @@ -63,10 +63,6 @@ using namespace KDDockWidgets; using namespace KDDockWidgets::Tests; using namespace Layouting; -static bool s_pauseBeforePress = false; // for debugging -static bool s_pauseBeforeMove = false; // for debugging -#define DEBUGGING_PAUSE_DURATION 5000 // 5 seconds - static QPoint dragPointForWidget(Frame *frame, int index) { auto frameW = static_cast(frame); @@ -80,86 +76,6 @@ static QPoint dragPointForWidget(Frame *frame, int index) } } -static QWidget *draggableFor(QWidget *w) -{ - QWidget *draggable = nullptr; - if (auto dock = qobject_cast(w)) { - if (auto frame = dock->frame()) - draggable = frame->titleBar(); - } else if (auto fw = qobject_cast(w)) { - auto frame = fw->hasSingleFrame() ? static_cast(fw->frames().first()) - : nullptr; - draggable = ((KDDockWidgets::Config::self().flags() & KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible) && frame && frame->hasTabsVisible()) ? static_cast(frame->tabWidget()->asWidget()) - : static_cast(fw->titleBar()); - - } else if (qobject_cast(w) || qobject_cast(w)) { - draggable = w; - } - - qDebug() << "Draggable is" << draggable; - return draggable; -} - -static void drag(QWidget *sourceWidget, QPoint pressGlobalPos, QPoint globalDest, - ButtonActions buttonActions = ButtonActions(ButtonAction_Press) | ButtonAction_Release) -{ - if (buttonActions & ButtonAction_Press) { - if (s_pauseBeforePress) - QTest::qWait(DEBUGGING_PAUSE_DURATION); - - pressOn(pressGlobalPos, sourceWidget); - } - - sourceWidget->window()->activateWindow(); - - if (s_pauseBeforeMove) - QTest::qWait(DEBUGGING_PAUSE_DURATION); - - qDebug() << "Moving sourceWidget to" << globalDest - << "; sourceWidget->size=" << sourceWidget->size() - << "; from=" << QCursor::pos(); - moveMouseTo(globalDest, sourceWidget); - qDebug() << "Arrived at" << QCursor::pos(); - pressGlobalPos = sourceWidget->mapToGlobal(QPoint(10, 10)); - if (buttonActions & ButtonAction_Release) - releaseOn(globalDest, sourceWidget); -} - -static void drag(QWidget *sourceWidget, QPoint globalDest, - ButtonActions buttonActions = ButtonActions(ButtonAction_Press) | ButtonAction_Release) -{ - Q_ASSERT(sourceWidget && sourceWidget->isVisible()); - - QWidget *draggable = draggableFor(sourceWidget); - - Q_ASSERT(draggable && draggable->isVisible()); - const QPoint pressGlobalPos = draggable->mapToGlobal(QPoint(6, 6)); - - drag(draggable, pressGlobalPos, globalDest, buttonActions); -} - -static void dragFloatingWindowTo(FloatingWindow *fw, QPoint globalDest, - ButtonActions buttonActions = ButtonActions(ButtonAction_Press) | ButtonAction_Release) -{ - auto draggable = draggableFor(fw); - Q_ASSERT(draggable && draggable->isVisible()); - drag(draggable, draggable->mapToGlobal(QPoint(10, 10)), globalDest, buttonActions); -} - -static void dragFloatingWindowTo(FloatingWindow *fw, DropArea *target, DropIndicatorOverlayInterface::DropLocation dropLocation) -{ - auto draggable = draggableFor(fw); - - // First we drag over it, so the drop indicators appear: - drag(draggable, draggable->mapToGlobal(QPoint(10, 10)), target->window()->mapToGlobal(target->window()->rect().center()), ButtonAction_Press); - - // Now we drag over the drop indicator and only then release mouse: - DropIndicatorOverlayInterface *dropIndicatorOverlay = target->dropIndicatorOverlay(); - const QPoint dropPoint = dropIndicatorOverlay->posForIndicator(dropLocation); - - drag(draggable, QPoint(), dropPoint, ButtonAction_Release); -} - inline int widgetMinLength(const QWidget *w, Qt::Orientation o) { const QSize sz = Widget_qwidget::widgetMinSize(w); @@ -284,7 +200,6 @@ private Q_SLOTS: void tst_dock2FloatingWidgetsTabbed(); void tst_close(); void tst_preventClose(); - void tst_dockWindowWithTwoSideBySideFramesIntoCenter(); void tst_dockWindowWithTwoSideBySideFramesIntoLeft(); void tst_dockWindowWithTwoSideBySideFramesIntoRight(); void tst_posAfterLeftDetach(); @@ -304,7 +219,6 @@ private Q_SLOTS: void tst_notClosable(); void tst_constraintsAfterPlaceholder(); - void tst_setFloatingWhenSideBySide(); void tst_setFloatingAfterDraggedFromTabToSideBySide(); void tst_setFloatingAFrameWithTabs(); void tst_setVisibleFalseWhenSideBySide(); @@ -413,14 +327,6 @@ Frame* createFrameWithWidget(const QString &name, MultiSplitter *parent, int min return frame; } -FloatingWindow *createFloatingWindow() -{ - static int count = 0; - count++; - auto dock = createDockWidget(QString("docfw %1").arg(count), Qt::green); - return dock->morphIntoFloatingWindow(); -} - void TestDocks::tst_createFloatingWindow() { EnsureTopLevelsDeleted e; @@ -610,7 +516,7 @@ void TestDocks::tst_close() QPointer frame1 = dock1->frame(); QVERIFY(dock1->isVisible()); QVERIFY(dock1->window()->isVisible()); - QVERIFY(frame1->QWidget::isVisible()); + QVERIFY(frame1->QWidgetAdapter::isVisible()); QCOMPARE(dock1->window(), window.data()); QVERIFY(dock1->close()); @@ -625,7 +531,7 @@ void TestDocks::tst_close() frame1 = dock1->frame(); QVERIFY(dock1->isVisible()); QVERIFY(dock1->window()->isVisible()); - QVERIFY(frame1->QWidget::isVisible()); + QVERIFY(frame1->QWidgetAdapter::isVisible()); QCOMPARE(dock1->window(), window.data()); QVERIFY(window->close()); @@ -646,14 +552,14 @@ void TestDocks::tst_close() auto da = mainwindow->dropArea(); QVERIFY(da->checkSanity()); - QCOMPARE(leftDock->frame()->QWidget::x(), 0); + QCOMPARE(leftDock->frame()->QWidgetAdapter::x(), 0); - QCOMPARE(centralDock->frame()->QWidget::x(), leftDock->frame()->QWidget::geometry().right() + Item::separatorThickness + 1); - QCOMPARE(rightDock->frame()->QWidget::x(), centralDock->frame()->QWidget::geometry().right() + Item::separatorThickness + 1); + QCOMPARE(centralDock->frame()->QWidgetAdapter::x(), leftDock->frame()->QWidgetAdapter::geometry().right() + Item::separatorThickness + 1); + QCOMPARE(rightDock->frame()->QWidgetAdapter::x(), centralDock->frame()->QWidgetAdapter::geometry().right() + Item::separatorThickness + 1); leftDock->close(); QTest::qWait(250); // TODO: wait for some signal - QCOMPARE(centralDock->frame()->QWidget::x(), 0); - QCOMPARE(rightDock->frame()->QWidget::x(), centralDock->frame()->QWidget::geometry().right() + Item::separatorThickness + 1); + QCOMPARE(centralDock->frame()->QWidgetAdapter::x(), 0); + QCOMPARE(rightDock->frame()->QWidgetAdapter::x(), centralDock->frame()->QWidgetAdapter::geometry().right() + Item::separatorThickness + 1); rightDock->close(); QTest::qWait(250); // TODO: wait for some signal @@ -664,13 +570,13 @@ void TestDocks::tst_close() // 1.9 Close tabbed dock, side docks will maintain their position mainwindow = createSimpleNestedMainWindow(¢ralDock, &leftDock, &rightDock); - const int leftX = leftDock->frame()->QWidget::x(); - const int rightX = rightDock->frame()->QWidget::x(); + const int leftX = leftDock->frame()->QWidgetAdapter::x(); + const int rightX = rightDock->frame()->QWidgetAdapter::x(); centralDock->close(); - QCOMPARE(leftDock->frame()->QWidget::x(), leftX); - QCOMPARE(rightDock->frame()->QWidget::x(), rightX); + QCOMPARE(leftDock->frame()->QWidgetAdapter::x(), leftX); + QCOMPARE(rightDock->frame()->QWidgetAdapter::x(), rightX); delete leftDock; delete rightDock; delete centralDock; delete dock1; @@ -746,30 +652,6 @@ void TestDocks::tst_preventClose() QVERIFY(Testing::waitForDeleted(dock1)); } -void TestDocks::tst_dockWindowWithTwoSideBySideFramesIntoCenter() -{ - EnsureTopLevelsDeleted e; - - auto m = createMainWindow(); - auto fw = createFloatingWindow(); - auto dock2 = createDockWidget("doc2", Qt::red); - nestDockWidget(dock2, fw->dropArea(), nullptr, KDDockWidgets::Location_OnLeft); - QCOMPARE(fw->frames().size(), 2); - QVERIFY(fw->dropArea()->checkSanity()); - - auto fw2 = createFloatingWindow(); - fw2->move(fw->x() + fw->width() + 100, fw->y()); - - dragFloatingWindowTo(fw, fw2->geometry().center()); - QVERIFY(fw2->dropArea()->checkSanity()); - - QCOMPARE(fw2->frames().size(), 1); - auto f2 = fw2->frames().constFirst(); - QCOMPARE(f2->dockWidgetCount(), 3); - QVERIFY(Testing::waitForDeleted(fw)); - delete fw2; -} - void TestDocks::tst_dockWindowWithTwoSideBySideFramesIntoLeft() { EnsureTopLevelsDeleted e; @@ -1483,7 +1365,7 @@ void TestDocks::tst_addDockWidgetToMainWindow() QCOMPARE(dock1->window(), m.get()); QCOMPARE(dock2->window(), m.get()); QVERIFY(dock1->frame()->QWidget::y() > dock2->frame()->QWidget::y()); - QCOMPARE(dock1->frame()->QWidget::x(), dock2->frame()->QWidget::x()); + QCOMPARE(dock1->frame()->QWidgetAdapter::x(), dock2->frame()->QWidgetAdapter::x()); } void TestDocks::tst_addDockWidgetToContainingWindow() @@ -1501,8 +1383,8 @@ void TestDocks::tst_addDockWidgetToContainingWindow() QCOMPARE(dock2->window(), dock3->window()); QVERIFY(dock3->frame()->QWidget::y() < dock2->frame()->QWidget::y()); - QVERIFY(dock1->frame()->QWidget::x() < dock2->frame()->QWidget::x()); - QCOMPARE(dock2->frame()->QWidget::x(), dock3->frame()->QWidget::x()); + QVERIFY(dock1->frame()->QWidgetAdapter::x() < dock2->frame()->QWidgetAdapter::x()); + QCOMPARE(dock2->frame()->QWidgetAdapter::x(), dock3->frame()->QWidgetAdapter::x()); QWidget *window = dock1->window(); delete dock1; @@ -1795,63 +1677,6 @@ void TestDocks::tst_constraintsAfterPlaceholder() Testing::waitForDeleted(dock1); } -void TestDocks::tst_setFloatingWhenSideBySide() -{ - // Tests DockWidget::setFloating(false|true) when side-by-side (it should put it where it was) - EnsureTopLevelsDeleted e; - - { - // 1. Create a MainWindow with two docked dock-widgets, then float the first one. - auto m = createMainWindow(); - auto dock1 = createDockWidget("dock1", new QPushButton("one")); - auto dock2 = createDockWidget("dock2", new QPushButton("two")); - m->addDockWidget(dock1, KDDockWidgets::Location_OnLeft); - m->addDockWidget(dock2, KDDockWidgets::Location_OnRight); - - QPointer frame1 = dock1->frame(); - dock1->setFloating(true); - QVERIFY(dock1->isFloating()); - auto fw = dock1->floatingWindow(); - QVERIFY(fw); - - //2. Put it back, via setFloating(). It should return to its place. - dock1->setFloating(false); - - QVERIFY(!dock1->isFloating()); - QVERIFY(!dock1->isTabbed()); - - Testing::waitForDeleted(fw); - } - - { - // 2. Tests a case where restoring a dock widget wouldn't make it use all its available space - auto m = createMainWindow(QSize(800, 500), MainWindowOption_None); - auto dock1 = createDockWidget("dock1", new QPushButton("one")); - auto dock2 = createDockWidget("dock2", new QPushButton("two")); - auto dock3 = createDockWidget("dock3", new QPushButton("three")); - auto dropArea = m->dropArea(); - MultiSplitter *layout = dropArea; - m->addDockWidget(dock1, KDDockWidgets::Location_OnLeft); - m->addDockWidget(dock2, KDDockWidgets::Location_OnRight); - m->addDockWidget(dock3, KDDockWidgets::Location_OnRight); - auto f2 = dock2->frame(); - Item *item2 = layout->itemForFrame(f2); - QVERIFY(item2); - dock2->close(); - dock3->close(); - Testing::waitForDeleted(f2); - dock2->show(); - Testing::waitForResize(dock2); - - QCOMPARE(item2->geometry(), dock2->frame()->QWidget::geometry()); - layout->checkSanity(); - - // Cleanup - dock3->deleteLater(); - Testing::waitForDeleted(dock3); - } -} - void TestDocks::tst_setFloatingAfterDraggedFromTabToSideBySide() { EnsureTopLevelsDeleted e; @@ -1983,7 +1808,7 @@ void TestDocks::tst_setVisibleFalseWhenSideBySide() // 2. Check that the parent frame also is hidden now dock1->setVisible(false); - QVERIFY(!dock1->frame()->QWidget::isVisible()); + QVERIFY(!dock1->frame()->QWidgetAdapter::isVisible()); // Cleanup m->deleteLater(); diff --git a/tests/utils.cpp b/tests/utils.cpp index 8d439448..e538eaf7 100644 --- a/tests/utils.cpp +++ b/tests/utils.cpp @@ -176,7 +176,7 @@ bool KDDockWidgets::Tests::shouldBlacklistWarning(const QString &msg, const QStr msg.contains(QLatin1String("There's multiple MainWindows, not sure what to do about parenting")); } -void KDDockWidgets::Tests::doubleClickOn(QPoint globalPos, QWidget *receiver) +void KDDockWidgets::Tests::doubleClickOn(QPoint globalPos, WidgetType *receiver) { QCursor::setPos(globalPos); QMouseEvent ev(QEvent::MouseButtonDblClick, receiver->mapFromGlobal(globalPos), receiver->window()->mapFromGlobal(globalPos), globalPos, @@ -184,7 +184,7 @@ void KDDockWidgets::Tests::doubleClickOn(QPoint globalPos, QWidget *receiver) qApp->sendEvent(receiver, &ev); } -void KDDockWidgets::Tests::pressOn(QPoint globalPos, QWidget *receiver) +void KDDockWidgets::Tests::pressOn(QPoint globalPos, WidgetType *receiver) { QCursor::setPos(globalPos); QMouseEvent ev(QEvent::MouseButtonPress, receiver->mapFromGlobal(globalPos), receiver->window()->mapFromGlobal(globalPos), globalPos, @@ -192,24 +192,23 @@ void KDDockWidgets::Tests::pressOn(QPoint globalPos, QWidget *receiver) qApp->sendEvent(receiver, &ev); } -void KDDockWidgets::Tests::releaseOn(QPoint globalPos, QWidget *receiver) +void KDDockWidgets::Tests::releaseOn(QPoint globalPos, WidgetType *receiver) { QMouseEvent ev(QEvent::MouseButtonRelease, receiver->mapFromGlobal(globalPos), receiver->window()->mapFromGlobal(globalPos), globalPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); qApp->sendEvent(receiver, &ev); } -void KDDockWidgets::Tests::clickOn(QPoint globalPos, QWidget *receiver) +void KDDockWidgets::Tests::clickOn(QPoint globalPos, WidgetType *receiver) { pressOn(globalPos, receiver); releaseOn(globalPos, receiver); } -void KDDockWidgets::Tests::moveMouseTo(QPoint globalDest, QWidget *receiver) +void KDDockWidgets::Tests::moveMouseTo(QPoint globalDest, WidgetType *receiver) { - QPoint globalSrc(receiver->mapToGlobal(QPoint(5, 5))); - - QPointer receiverP = receiver; + QPoint globalSrc = KDDockWidgets::mapToGlobal(receiver, QPoint(5, 5)); + auto receiverP = Tests::make_qpointer(receiver); while (globalSrc != globalDest) { if (globalSrc.x() < globalDest.x()) { diff --git a/tests/utils.h b/tests/utils.h index ff3318e8..f28110a5 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -16,8 +16,14 @@ #include "DropIndicatorOverlayInterface_p.h" #include "DockWidgetBase.h" #include "Config.h" +#include "TitleBar_p.h" +#include "FloatingWindow_p.h" +#include "DropArea_p.h" +#include "Utils_p.h" #ifdef KDDOCKWIDGETS_QTWIDGETS +# include "widgets/TabWidgetWidget_p.h" +# include "widgets/FrameWidget_p.h" # include # include #else @@ -26,9 +32,14 @@ #include #include +#include #include +static bool s_pauseBeforePress = false; // for debugging +static bool s_pauseBeforeMove = false; // for debugging +#define DEBUGGING_PAUSE_DURATION 5000 // 5 seconds + // clazy:excludeall=ctor-missing-parent-argument,missing-qobject-macro,range-loop,missing-typeinfo,detaching-member,function-args-by-ref,non-pod-global-static,reserve-candidates namespace KDDockWidgets { @@ -237,11 +248,104 @@ public: #endif -void doubleClickOn(QPoint globalPos, QWidget *receiver); -void pressOn(QPoint globalPos, QWidget *receiver); -void releaseOn(QPoint globalPos, QWidget *receiver); -void clickOn(QPoint globalPos, QWidget *receiver); -void moveMouseTo(QPoint globalDest, QWidget *receiver); +void doubleClickOn(QPoint globalPos, WidgetType *receiver); +void pressOn(QPoint globalPos, WidgetType *receiver); +void releaseOn(QPoint globalPos, WidgetType *receiver); +void clickOn(QPoint globalPos, WidgetType *receiver); +void moveMouseTo(QPoint globalDest, WidgetType *receiver); + +inline FloatingWindow *createFloatingWindow() +{ + static int count = 0; + count++; + auto dock = createDockWidget(QString("dock %1").arg(count), Qt::green); + return dock->morphIntoFloatingWindow(); +} + +inline WidgetType *draggableFor(WidgetType *w) +{ + WidgetType *draggable = nullptr; + if (auto dock = qobject_cast(w)) { + if (auto frame = dock->frame()) + draggable = frame->titleBar(); + } else if (auto fw = qobject_cast(w)) { +#ifdef KDDOCKWIDGETS_QTWIDGETS + auto frame = fw->hasSingleFrame() ? static_cast(fw->frames().first()) + : nullptr; + draggable = ((KDDockWidgets::Config::self().flags() & KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible) && frame && frame->hasTabsVisible()) ? static_cast(frame->tabWidget()->asWidget()) + : static_cast(fw->titleBar()); + } else if (qobject_cast(w)) { + draggable = w; +#else + Q_UNUSED(fw); +#endif + } else if (qobject_cast(w)) { + draggable = w; + } + + qDebug() << "Draggable is" << draggable; + return draggable; +} + +inline void drag(WidgetType *sourceWidget, QPoint pressGlobalPos, QPoint globalDest, + ButtonActions buttonActions = ButtonActions(ButtonAction_Press) | ButtonAction_Release) +{ + if (buttonActions & ButtonAction_Press) { + if (s_pauseBeforePress) + QTest::qWait(DEBUGGING_PAUSE_DURATION); + + pressOn(pressGlobalPos, sourceWidget); + } + + activateWindow(sourceWidget->window()); + + if (s_pauseBeforeMove) + QTest::qWait(DEBUGGING_PAUSE_DURATION); + + qDebug() << "Moving sourceWidget to" << globalDest + << "; sourceWidget->size=" << sourceWidget->size() + << "; from=" << QCursor::pos(); + moveMouseTo(globalDest, sourceWidget); + qDebug() << "Arrived at" << QCursor::pos(); + pressGlobalPos = KDDockWidgets::mapToGlobal(sourceWidget, QPoint(10, 10)); + if (buttonActions & ButtonAction_Release) + releaseOn(globalDest, sourceWidget); +} + +inline void drag(WidgetType *sourceWidget, QPoint globalDest, + ButtonActions buttonActions = ButtonActions(ButtonAction_Press) | ButtonAction_Release) +{ + Q_ASSERT(sourceWidget && sourceWidget->isVisible()); + + WidgetType *draggable = draggableFor(sourceWidget); + + Q_ASSERT(draggable && draggable->isVisible()); + const QPoint pressGlobalPos = KDDockWidgets::mapToGlobal(draggable, QPoint(6, 6)); + + drag(draggable, pressGlobalPos, globalDest, buttonActions); +} + +inline void dragFloatingWindowTo(FloatingWindow *fw, QPoint globalDest, + ButtonActions buttonActions = ButtonActions(ButtonAction_Press) | ButtonAction_Release) +{ + auto draggable = draggableFor(fw); + Q_ASSERT(draggable && draggable->isVisible()); + drag(draggable, KDDockWidgets::mapToGlobal(draggable, QPoint(10, 10)), globalDest, buttonActions); +} + +inline void dragFloatingWindowTo(FloatingWindow *fw, DropArea *target, DropIndicatorOverlayInterface::DropLocation dropLocation) +{ + auto draggable = draggableFor(fw); + + // First we drag over it, so the drop indicators appear: + drag(draggable, KDDockWidgets::mapToGlobal(draggable, QPoint(10, 10)), target->window()->mapToGlobal(target->window()->rect().center()), ButtonAction_Press); + + // Now we drag over the drop indicator and only then release mouse: + DropIndicatorOverlayInterface *dropIndicatorOverlay = target->dropIndicatorOverlay(); + const QPoint dropPoint = dropIndicatorOverlay->posForIndicator(dropLocation); + + drag(draggable, QPoint(), dropPoint, ButtonAction_Release); +} }