Fix mapping to/from global coordinates for child/embedded windows.

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 <samuel.rodal@digia.com>
bb10
Miikka Heikkinen 2012-09-13 12:14:13 +03:00 committed by The Qt Project
parent beab941e1f
commit ede4f5e23b
7 changed files with 70 additions and 2 deletions

View File

@ -187,6 +187,30 @@ bool QPlatformWindow::isEmbedded(const QPlatformWindow *parentWindow) const
return false;
}
/*!
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.

View File

@ -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();

View File

@ -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();
}

View File

@ -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
{

View File

@ -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);

View File

@ -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();

View File

@ -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);