From ede4f5e23b08e9b2cc8fb6a449ee9f667b8da9fa Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 13 Sep 2012 12:14:13 +0300 Subject: [PATCH] Fix mapping to/from global coordinates for child/embedded windows. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit QWidget's mapToGlobal() and mapFromGlobal() functions assumed that if the widget reports it's a window or if it has no parent widget, it must be a top level window whose coordinates are in global coordinates. This is not true for child QWindows or embedded native windows (QAxWidgets). Changed the logic for mapping coordinates to use equivalent methods from QWindow if widget has a window handle, and changed QWindow's methods to map coordinates using native methods if window is embedded. Also fixed newly failing accessibility autotest. The geometry related failures there popped up because now the position of the rect returned by accessible interface is actually correct while widget geometry still reports position 0,0 before widget has shown up. Task-number: QTBUG-26436 Change-Id: I658fafd0ce01eb1604ba255efeeba3073ca0189f Reviewed-by: Samuel Rødal --- src/gui/kernel/qplatformwindow.cpp | 24 ++++++++++++++++++++++ src/gui/kernel/qplatformwindow.h | 2 ++ src/gui/kernel/qwindow.cpp | 12 +++++++++-- src/plugins/platforms/windows/qwindowswindow.cpp | 16 +++++++++++++++ src/plugins/platforms/windows/qwindowswindow.h | 3 +++ src/widgets/kernel/qwidget_qpa.cpp | 8 ++++++++ .../other/qaccessibility/tst_qaccessibility.cpp | 7 +++++++ 7 files changed, 70 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index 748a782..6200ad0 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -188,6 +188,30 @@ bool QPlatformWindow::isEmbedded(const QPlatformWindow *parentWindow) const } /*! + Translates the window coordinate \a pos to global screen + coordinates using native methods. This is required for embedded windows, + where the topmost QWindow coordinates are not global screen coordinates. + + Returns \a pos if there is no platform specific implementation. +*/ +QPoint QPlatformWindow::mapToGlobal(const QPoint &pos) const +{ + return pos; +} + +/*! + Translates the global screen coordinate \a pos to window + coordinates using native methods. This is required for embedded windows, + where the topmost QWindow coordinates are not global screen coordinates. + + Returns \a pos if there is no platform specific implementation. +*/ +QPoint QPlatformWindow::mapFromGlobal(const QPoint &pos) const +{ + return pos; +} + +/*! Requests setting the window state of this surface to \a type. Returns the actual state set. diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h index e278518..7d6bb80 100644 --- a/src/gui/kernel/qplatformwindow.h +++ b/src/gui/kernel/qplatformwindow.h @@ -104,6 +104,8 @@ public: virtual bool isExposed() const; virtual bool isActive() const; virtual bool isEmbedded(const QPlatformWindow *parentWindow) const; + virtual QPoint mapToGlobal(const QPoint &pos) const; + virtual QPoint mapFromGlobal(const QPoint &pos) const; virtual void propagateSizeHints(); diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 3b12768..a2447e2 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -1744,7 +1744,11 @@ bool QWindow::nativeEvent(const QByteArray &eventType, void *message, long *resu */ QPoint QWindow::mapToGlobal(const QPoint &pos) const { - return pos + d_func()->globalPosition(); + Q_D(const QWindow); + if (d->platformWindow && d->platformWindow->isEmbedded(0)) + return d->platformWindow->mapToGlobal(pos); + else + return pos + d_func()->globalPosition(); } @@ -1758,7 +1762,11 @@ QPoint QWindow::mapToGlobal(const QPoint &pos) const */ QPoint QWindow::mapFromGlobal(const QPoint &pos) const { - return pos - d_func()->globalPosition(); + Q_D(const QWindow); + if (d->platformWindow && d->platformWindow->isEmbedded(0)) + return d->platformWindow->mapFromGlobal(pos); + else + return pos - d_func()->globalPosition(); } diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index d9fcb99..1d458d5 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -849,6 +849,22 @@ bool QWindowsWindow::isEmbedded(const QPlatformWindow *parentWindow) const return m_data.embedded; } +QPoint QWindowsWindow::mapToGlobal(const QPoint &pos) const +{ + if (m_data.hwnd) + return QWindowsGeometryHint::mapToGlobal(m_data.hwnd, pos); + else + return pos; +} + +QPoint QWindowsWindow::mapFromGlobal(const QPoint &pos) const +{ + if (m_data.hwnd) + return QWindowsGeometryHint::mapFromGlobal(m_data.hwnd, pos); + else + return pos; +} + // partially from QWidgetPrivate::show_sys() void QWindowsWindow::show_sys() const { diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 2171c7f..a040aab 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -155,6 +155,9 @@ public: bool isVisible() const; virtual bool isActive() const; virtual bool isEmbedded(const QPlatformWindow *parentWindow) const; + virtual QPoint mapToGlobal(const QPoint &pos) const; + virtual QPoint mapFromGlobal(const QPoint &pos) const; + virtual Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); virtual Qt::WindowState setWindowState(Qt::WindowState state); diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index a94eceb..60a29ae 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -290,6 +290,10 @@ QPoint QWidget::mapToGlobal(const QPoint &pos) const int x = pos.x(), y = pos.y(); const QWidget *w = this; while (w) { + QWindow *window = w->windowHandle(); + if (window && window->handle()) + return window->mapToGlobal(QPoint(x, y)); + x += w->data->crect.x(); y += w->data->crect.y(); w = w->isWindow() ? 0 : w->parentWidget(); @@ -302,6 +306,10 @@ QPoint QWidget::mapFromGlobal(const QPoint &pos) const int x = pos.x(), y = pos.y(); const QWidget *w = this; while (w) { + QWindow *window = w->windowHandle(); + if (window && window->handle()) + return window->mapFromGlobal(QPoint(x, y)); + x -= w->data->crect.x(); y -= w->data->crect.y(); w = w->isWindow() ? 0 : w->parentWidget(); diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 3e937fe..e9fe51d 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -1489,6 +1489,8 @@ void tst_QAccessibility::spinBoxTest() QVERIFY(interface); QCOMPARE(interface->role(), QAccessible::SpinBox); + QVERIFY(QTest::qWaitForWindowExposed(spinBox)); + const QRect widgetRect = spinBox->geometry(); const QRect accessibleRect = interface->rect(); QCOMPARE(accessibleRect, widgetRect); @@ -1527,6 +1529,8 @@ void tst_QAccessibility::doubleSpinBoxTest() QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(doubleSpinBox); QVERIFY(interface); + QVERIFY(QTest::qWaitForWindowExposed(doubleSpinBox)); + const QRect widgetRect = doubleSpinBox->geometry(); const QRect accessibleRect = interface->rect(); QCOMPARE(accessibleRect, widgetRect); @@ -2197,6 +2201,8 @@ void tst_QAccessibility::dialTest() QVERIFY(interface); QCOMPARE(interface->childCount(), 0); + QVERIFY(QTest::qWaitForWindowExposed(&dial)); + QCOMPARE(interface->text(QAccessible::Value), QString::number(dial.value())); QCOMPARE(interface->rect(), dial.geometry()); @@ -2827,6 +2833,7 @@ void tst_QAccessibility::comboBoxTest() QComboBox combo; combo.addItems(QStringList() << "one" << "two" << "three"); combo.show(); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&combo); QCOMPARE(verifyHierarchy(iface), 0); -- 2.7.4