diff options
author | Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> | 2015-11-24 13:49:44 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> | 2015-11-27 22:50:17 +0000 |
commit | fb69a09a2490102ad0c3f6015e04942bb5df7505 (patch) | |
tree | 1f086e8f21cb2b312098850b7b602c2fe45776c1 | |
parent | b4c8e1517455becb138876c08b3bdd880a80770d (diff) |
QWidget::mapTo/FromGlobal(): Avoid calling QWindow helpers until shown.
The platform window geometry can be misleading until it has
been properly positioned and
QWindowPrivate::resizeEventPending has been cleared.
Task-number: QTBUG-49588
Task-number: QTBUG-48396
Change-Id: Ie065f62478fc8522a9ad51391bb897510afa5aad
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 10 | ||||
-rw-r--r-- | tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp | 56 |
2 files changed, 64 insertions, 2 deletions
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index b8b8640cea..229cfc0f85 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -12327,6 +12327,12 @@ QPaintEngine *QWidget::paintEngine() const return 0; //##### @@@ } +// Do not call QWindow::mapToGlobal() until QPlatformWindow is properly showing. +static inline bool canMapPosition(QWindow *window) +{ + return window->handle() && !qt_window_private(window)->resizeEventPending; +} + /*! \fn QPoint QWidget::mapToGlobal(const QPoint &pos) const @@ -12354,7 +12360,7 @@ QPoint QWidget::mapToGlobal(const QPoint &pos) const #endif // !QT_NO_GRAPHICSVIEW QWindow *window = w->windowHandle(); - if (window && window->handle()) + if (window && canMapPosition(window)) return window->mapToGlobal(QPoint(x, y)); x += w->data->crect.x(); @@ -12390,7 +12396,7 @@ QPoint QWidget::mapFromGlobal(const QPoint &pos) const #endif // !QT_NO_GRAPHICSVIEW QWindow *window = w->windowHandle(); - if (window && window->handle()) + if (window && canMapPosition(window)) return window->mapFromGlobal(QPoint(x, y)); x -= w->data->crect.x(); diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index 5ae0733965..b3f9c54f24 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -94,6 +94,7 @@ private slots: void task208001_stylesheet(); void activeSubMenuPosition(); + void activeSubMenuPositionExec(); void task242454_sizeHint(); void task176201_clear(); void task250673_activeMultiColumnSubMenuPosition(); @@ -694,6 +695,61 @@ void tst_QMenu::activeSubMenuPosition() #endif } +// QTBUG-49588, QTBUG-48396: activeSubMenuPositionExec() is the same as +// activeSubMenuPosition(), but uses QMenu::exec(), which produces a different +// sequence of events. Verify that the sub menu is positioned to the right of the +// main menu. +class SubMenuPositionExecMenu : public QMenu +{ + Q_OBJECT +public: + SubMenuPositionExecMenu() : QMenu("Menu-Title"), m_timerId(-1), m_timerTick(0) + { + addAction("Item 1"); + m_subMenu = addMenu("Submenu"); + m_subAction = m_subMenu->addAction("Sub-Item1"); + setActiveAction(m_subMenu->menuAction()); + } + +protected: + void showEvent(QShowEvent *e) Q_DECL_OVERRIDE + { + QVERIFY(m_subMenu->isVisible()); + QVERIFY2(m_subMenu->x() > x(), + (QByteArray::number(m_subMenu->x()) + ' ' + QByteArray::number(x())).constData()); + m_timerId = startTimer(50); + QMenu::showEvent(e); + } + + void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE + { + if (e->timerId() == m_timerId) { + switch (m_timerTick++) { + case 0: + m_subMenu->close(); + break; + case 1: + close(); + break; + } + } + } + +private: + int m_timerId; + int m_timerTick; + QMenu *m_subMenu; + QAction *m_subAction; +}; + +void tst_QMenu::activeSubMenuPositionExec() +{ +#ifndef Q_OS_WINCE + SubMenuPositionExecMenu menu; + menu.exec(QGuiApplication::primaryScreen()->availableGeometry().center()); +#endif // !Q_OS_WINCE +} + void tst_QMenu::task242454_sizeHint() { QMenu menu; |