diff options
-rw-r--r-- | src/quick/doc/src/includes/item.qdocinc | 3 | ||||
-rw-r--r-- | src/quick/items/qquickitem.cpp | 14 | ||||
-rw-r--r-- | tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml | 51 | ||||
-rw-r--r-- | tests/auto/quick/qquickitem2/tst_qquickitem.cpp | 72 |
4 files changed, 138 insertions, 2 deletions
diff --git a/src/quick/doc/src/includes/item.qdocinc b/src/quick/doc/src/includes/item.qdocinc index f70d3b483c..0dd3fc086f 100644 --- a/src/quick/doc/src/includes/item.qdocinc +++ b/src/quick/doc/src/includes/item.qdocinc @@ -3,6 +3,9 @@ The following properties of the item are used in the mapping: \l x, \l y, \l scale, \l rotation, \l transformOrigin, and \l [QML]{Item::}{transform}. +If the items are part of different scenes, the mapping includes +the relative position of the two scenes. + //! [mapping] diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 7b10b09b50..8a92841176 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -8734,8 +8734,12 @@ void QQuickItem::setContainmentMask(QObject *mask) QPointF QQuickItem::mapToItem(const QQuickItem *item, const QPointF &point) const { QPointF p = mapToScene(point); - if (item) + if (item) { + if (item->window() != window()) + p = item->window()->mapFromGlobal(window()->mapToGlobal(p)); + p = item->mapFromScene(p); + } return p; } @@ -8827,7 +8831,13 @@ QRectF QQuickItem::mapRectToScene(const QRectF &rect) const */ QPointF QQuickItem::mapFromItem(const QQuickItem *item, const QPointF &point) const { - QPointF p = item?item->mapToScene(point):point; + QPointF p = point; + if (item) { + p = item->mapToScene(point); + + if (item->window() != window()) + p = window()->mapFromGlobal(item->window()->mapToGlobal(p)); + } return mapFromScene(p); } diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml b/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml new file mode 100644 index 0000000000..8218c5230a --- /dev/null +++ b/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml @@ -0,0 +1,51 @@ +import QtQuick + +QtObject { + id: root + + property Window windowA: Window { + visible: true + flags: Qt.FramelessWindowHint + color: "green" + x: 100; y: 100 + width: 300; height: 300 + + Rectangle { + objectName: "childItem" + x: 50; y: 50 + width: 100; height: 100 + color: "red" + } + + Window { + objectName: "childWindow" + parent: windowA + x: 100; y: 100 + width: 100; height: 100 + visible: true + color: "blue" + + Rectangle { + objectName: "childItemInChildWindow" + x: 30; y: 30 + width: 50; height: 50 + color: "orange" + } + } + } + + property Window windowB: Window { + visible: true + flags: Qt.FramelessWindowHint + color: "magenta" + x: 500; y: 200 + width: 200; height: 200 + + Rectangle { + objectName: "childItem" + x: 50; y: 50 + width: 100; height: 100 + color: "cyan" + } + } +} diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index dd6ae73b95..2e2abbcd33 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -17,6 +17,7 @@ #include <QtQuick/private/qquickanchors_p.h> #include <QtGui/qstylehints.h> #include <private/qquickitem_p.h> +#include <QtQuickTest/QtQuickTest> #include <QtQuickTestUtils/private/qmlutils_p.h> #include <QtQuickTestUtils/private/visualtestutils_p.h> #include <QtQuickTestUtils/private/viewtestutils_p.h> @@ -88,6 +89,7 @@ private slots: void mapCoordinates_data(); void mapCoordinatesRect(); void mapCoordinatesRect_data(); + void mapCoordinatesWithWindows(); void propertyChanges(); void nonexistentPropertyConnection(); void transforms(); @@ -2800,6 +2802,76 @@ void tst_QQuickItem::mapCoordinatesRect_data() QTest::newRow(QTest::toString(i)) << i << i << i << i; } +void tst_QQuickItem::mapCoordinatesWithWindows() +{ + QQmlComponent component(&engine, testFileUrl("mapCoordinatesWithWindows.qml")); + std::unique_ptr<QObject> root(component.create()); + QVERIFY(root); + + auto *windowA = root->property("windowA").value<QQuickWindow*>(); + QVERIFY(windowA); + + // The window container geometry, parenting, etc, is applied + // during polish, so to test these we need to wait for one. + QVERIFY(QQuickTest::qWaitForPolish(windowA)); + + auto *childItem = windowA->findChild<QQuickItem*>("childItem"); + QVERIFY(childItem); + + QPoint itemPos = childItem->position().toPoint(); + QCOMPARE(childItem->mapToScene({0, 0}), itemPos); + QCOMPARE(childItem->mapToGlobal({0, 0}), windowA->position() + itemPos); + + auto *childItemInChildWindow = windowA->findChild<QQuickItem*>("childItemInChildWindow"); + QVERIFY(childItemInChildWindow); + + QPoint windowItemPos = childItemInChildWindow->position().toPoint(); + QCOMPARE(childItemInChildWindow->mapToScene({0, 0}), windowItemPos); + QCOMPARE(childItemInChildWindow->mapToGlobal({0, 0}), windowA->position() + + childItemInChildWindow->window()->position() + windowItemPos); + + QCOMPARE(childItemInChildWindow->mapToItem(nullptr, {0, 0}), windowItemPos); + + auto globalItemOffset = [](QQuickItem *a, QQuickItem *b) { + return a->mapToGlobal({0, 0}) - b->mapToGlobal({0, 0}); + }; + + QCOMPARE(childItemInChildWindow->mapToItem(childItem, {0, 0}), + globalItemOffset(childItemInChildWindow, childItem)); + QCOMPARE(childItemInChildWindow->mapFromItem(childItem, {0, 0}), + globalItemOffset(childItem, childItemInChildWindow)); + + QCOMPARE(childItem->mapToItem(childItemInChildWindow, {0, 0}), + globalItemOffset(childItem, childItemInChildWindow)); + QCOMPARE(childItem->mapFromItem(childItemInChildWindow, {0, 0}), + globalItemOffset(childItemInChildWindow, childItem)); + + auto *windowB = root->property("windowB").value<QQuickWindow*>(); + QVERIFY(windowA); + auto *childItemInOtherWindow = windowB->findChild<QQuickItem*>("childItem"); + QVERIFY(childItemInOtherWindow); + + QCOMPARE(childItemInOtherWindow->mapToItem(childItem, {0, 0}), + globalItemOffset(childItemInOtherWindow, childItem)); + QCOMPARE(childItemInOtherWindow->mapFromItem(childItem, {0, 0}), + globalItemOffset(childItem, childItemInOtherWindow)); + + QCOMPARE(childItem->mapToItem(childItemInOtherWindow, {0, 0}), + globalItemOffset(childItem, childItemInOtherWindow)); + QCOMPARE(childItem->mapFromItem(childItemInOtherWindow, {0, 0}), + globalItemOffset(childItemInOtherWindow, childItem)); + + QCOMPARE(childItemInOtherWindow->mapToItem(childItemInChildWindow, {0, 0}), + globalItemOffset(childItemInOtherWindow, childItemInChildWindow)); + QCOMPARE(childItemInOtherWindow->mapFromItem(childItemInChildWindow, {0, 0}), + globalItemOffset(childItemInChildWindow, childItemInOtherWindow)); + + QCOMPARE(childItemInChildWindow->mapToItem(childItemInOtherWindow, {0, 0}), + globalItemOffset(childItemInChildWindow, childItemInOtherWindow)); + QCOMPARE(childItemInChildWindow->mapFromItem(childItemInOtherWindow, {0, 0}), + globalItemOffset(childItemInOtherWindow, childItemInChildWindow)); +} + void tst_QQuickItem::transforms_data() { QTest::addColumn<QByteArray>("qml"); |