summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Arne Vestbø <[email protected]>2020-02-17 15:08:58 +0100
committerTor Arne Vestbø <[email protected]>2020-02-19 20:04:19 +0000
commit8c3cc07bf5254cb91b37a0000191871e9e32014e (patch)
tree04e79baebbb37dfd4fde9b9a1e2a6691861e4ef0
parentfc3226e7909812092e9e1acdd45140427b3a4cf0 (diff)
widgets: Translate QWindow move events into widget relative position
If a widget backed by a QWindow is moved we need to translate the window geometry into a position relative to the parent widget. In most cases this was incidentally working due to widgets backed by QWindows always having QWindow parents too, so the QWindow position was applicable to the widget as well. But when Qt::WA_DontCreateNativeAncestors is used this is no longer the case, and we would end up with a widget geometry that included the parent positions all the way up to the next native widget. The updatePos() function has been squashed into handleMoveEvent(), since we need to ensure the position in the move event sent to the widget is correct as well. Change-Id: I55894ad7ab42a6d4d65e446a332ecdd7dcdcc263 Reviewed-by: Tor Arne Vestbø <[email protected]>
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp37
-rw-r--r--src/widgets/kernel/qwidgetwindow_p.h1
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp36
3 files changed, 58 insertions, 16 deletions
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 904067afdaa..4ba5469e9d6 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -727,19 +727,6 @@ bool QWidgetWindow::updateSize()
return changed;
}
-bool QWidgetWindow::updatePos()
-{
- bool changed = false;
- if (m_widget->testAttribute(Qt::WA_OutsideWSRange))
- return changed;
- if (m_widget->data->crect.topLeft() != geometry().topLeft()) {
- changed = true;
- m_widget->data->crect.moveTopLeft(geometry().topLeft());
- }
- updateMargins();
- return changed;
-}
-
void QWidgetWindow::updateMargins()
{
const QMargins margins = frameMargins();
@@ -800,8 +787,28 @@ void QWidgetWindow::updateNormalGeometry()
void QWidgetWindow::handleMoveEvent(QMoveEvent *event)
{
- if (updatePos())
- QGuiApplication::forwardEvent(m_widget, event);
+ if (m_widget->testAttribute(Qt::WA_OutsideWSRange))
+ return;
+
+ auto oldPosition = m_widget->data->crect.topLeft();
+ auto newPosition = geometry().topLeft();
+
+ if (!m_widget->isTopLevel()) {
+ if (auto *nativeParent = m_widget->nativeParentWidget())
+ newPosition = m_widget->parentWidget()->mapFrom(nativeParent, newPosition);
+ }
+
+ bool changed = newPosition != oldPosition;
+
+ if (changed)
+ m_widget->data->crect.moveTopLeft(newPosition);
+
+ updateMargins(); // FIXME: Only do when changed?
+
+ if (changed) {
+ QMoveEvent widgetEvent(newPosition, oldPosition);
+ QGuiApplication::forwardEvent(m_widget, &widgetEvent, event);
+ }
}
void QWidgetWindow::handleResizeEvent(QResizeEvent *event)
diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h
index 80a345465de..5689e129c3c 100644
--- a/src/widgets/kernel/qwidgetwindow_p.h
+++ b/src/widgets/kernel/qwidgetwindow_p.h
@@ -125,7 +125,6 @@ private slots:
private:
void repaintWindow();
bool updateSize();
- bool updatePos();
void updateMargins();
void updateNormalGeometry();
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index d8f4881ffa3..31e77b2a628 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -310,6 +310,8 @@ private slots:
void hideOpaqueChildWhileHidden();
void updateWhileMinimized();
void alienWidgets();
+ void nativeWindowPosition_data();
+ void nativeWindowPosition();
void adjustSize();
void adjustSize_data();
void updateGeometry();
@@ -8211,6 +8213,40 @@ void tst_QWidget::alienWidgets()
}
}
+using WidgetAttributes = QVector<Qt::WidgetAttribute>;
+
+void tst_QWidget::nativeWindowPosition_data()
+{
+ QTest::addColumn<WidgetAttributes>("attributes");
+
+ QTest::newRow("non-native all the way")
+ << WidgetAttributes{};
+ QTest::newRow("native all the way")
+ << WidgetAttributes{ Qt::WA_NativeWindow };
+ QTest::newRow("native with non-native ancestor")
+ << WidgetAttributes{ Qt::WA_NativeWindow, Qt::WA_DontCreateNativeAncestors };
+}
+
+void tst_QWidget::nativeWindowPosition()
+{
+ QWidget topLevel;
+ QWidget child(&topLevel);
+ child.move(5, 5);
+
+ QWidget grandChild(&child);
+ grandChild.move(10, 10);
+
+ QFETCH(WidgetAttributes, attributes);
+ for (auto attribute : attributes)
+ grandChild.setAttribute(attribute);
+
+ topLevel.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+
+ QCOMPARE(child.pos(), QPoint(5, 5));
+ QCOMPARE(grandChild.pos(), QPoint(10, 10));
+}
+
class ASWidget : public QWidget
{
public: