From 4220aa78703a252b964012240ff5664e0fe067c7 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 24 Apr 2020 10:17:05 +0200 Subject: [PATCH] Always open a submenu on the same screen where the parent menu is We've seen submenus opening on different screens in different scenarios, but probably there's never a sensible reason to do that. QWidgetPrivate::setScreenForPoint() can often give incorrect results in multi-screen desktop configurations; this is a way of avoiding that. Task-number: QTBUG-76162 Change-Id: I895696c6858ad953258c84b21117beea4c4fc01d Reviewed-by: Andy Shaw (cherry picked from commit c068edcecf6876c7b57abbe302ad8b1347e4445e) --- src/widgets/widgets/qmenu.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 8c21edb2211..65803b8691e 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -40,6 +40,7 @@ #include "qmenu.h" #include +#include #include "qdebug.h" #include "qstyle.h" @@ -2366,15 +2367,23 @@ void QMenu::popup(const QPoint &p, QAction *atAction) // Use d->popupScreen to remember, because initialScreenIndex will be reset after the first showing. // However if eventLoop exists, then exec() already did this by calling createWinId(); so leave it alone. (QTBUG-76162) if (!d->eventLoop) { + bool screenSet = false; const int screenIndex = d->topData()->initialScreenIndex; if (screenIndex >= 0) d->popupScreen = screenIndex; if (auto s = QGuiApplication::screens().value(d->popupScreen)) { if (d->setScreen(s)) d->itemsDirty = true; - } else if (d->setScreenForPoint(p)) { - d->itemsDirty = true; + screenSet = true; + } else if (QMenu *parentMenu = qobject_cast(parent())) { + // a submenu is always opened from an open parent menu, + // so show it on the same screen where the parent is. + if (d->setScreen(QMenuPrivate::get(parentMenu)->windowHandle()->screen())) + d->itemsDirty = true; + screenSet = true; } + if (!screenSet && d->setScreenForPoint(p)) + d->itemsDirty = true; } const bool contextMenu = d->isContextMenu();