QMenu: make wide submenu appear on the same screen with its parent menu

On a multi-display system wide submenu might either appear on wrong
screen or not appear at all (depending on the specific display
configuration).

Task-number: QTBUG-56917
Change-Id: I40013b0bee340a01ae1c08a5e074afa63da4dbfd
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
Reviewed-by: Błażej Szczygieł <spaz16@wp.pl>
bb10
Oleg Yadrov 2017-01-13 10:33:49 -08:00
parent ad5565b643
commit f2e103296f
2 changed files with 38 additions and 2 deletions

View File

@ -3501,11 +3501,22 @@ void QMenu::internalDelayedPopup()
d->activeMenu->d_func()->causedPopup.widget = this;
d->activeMenu->d_func()->causedPopup.action = d->currentAction;
QRect screen;
#ifndef QT_NO_GRAPHICSVIEW
bool isEmbedded = !bypassGraphicsProxyWidget(this) && d->nearestGraphicsProxyWidget(this);
if (isEmbedded)
screen = d->popupGeometry(this);
else
#endif
screen = d->popupGeometry(QApplication::desktop()->screenNumber(pos()));
int subMenuOffset = style()->pixelMetric(QStyle::PM_SubMenuOverlap, 0, this);
const QRect actionRect(d->actionRect(d->currentAction));
const QPoint rightPos(mapToGlobal(QPoint(actionRect.right() + subMenuOffset + 1, actionRect.top())));
QPoint subMenuPos(mapToGlobal(QPoint(actionRect.right() + subMenuOffset + 1, actionRect.top())));
if (subMenuPos.x() > screen.right())
subMenuPos.setX(QCursor::pos().x());
d->activeMenu->popup(rightPos);
d->activeMenu->popup(subMenuPos);
d->sloppyState.setSubMenuPopup(actionRect, d->currentAction, d->activeMenu);
#if !defined(Q_OS_DARWIN)

View File

@ -113,6 +113,7 @@ private slots:
#endif
void QTBUG_56917_wideMenuSize();
void QTBUG_56917_wideMenuScreenNumber();
void QTBUG_56917_wideSubmenuScreenNumber();
protected slots:
void onActivated(QAction*);
void onHighlighted(QAction*);
@ -1348,5 +1349,29 @@ void tst_QMenu::QTBUG_56917_wideMenuScreenNumber()
}
}
void tst_QMenu::QTBUG_56917_wideSubmenuScreenNumber()
{
if (QApplication::styleHints()->showIsFullScreen())
QSKIP("The platform defaults to windows being fullscreen.");
// submenu must appear on the same screen where its parent menu is shown
QString longString;
longString.fill(QLatin1Char('Q'), 3000);
for (int i = 0; i < QApplication::desktop()->screenCount(); i++) {
QMenu menu;
QMenu submenu("Submenu");
submenu.addAction(longString);
QAction *action = menu.addMenu(&submenu);
menu.popup(QApplication::desktop()->screen(i)->geometry().center());
QVERIFY(QTest::qWaitForWindowExposed(&menu));
QVERIFY(menu.isVisible());
QTest::mouseClick(&menu, Qt::LeftButton, 0, menu.actionGeometry(action).center());
QTest::qWait(100);
QVERIFY(QTest::qWaitForWindowExposed(&submenu));
QVERIFY(submenu.isVisible());
QCOMPARE(QApplication::desktop()->screenNumber(&submenu), i);
}
}
QTEST_MAIN(tst_QMenu)
#include "tst_qmenu.moc"