From a78d66743171557d79b16c08be775e3ac15bb4ef Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 5 Dec 2019 09:33:50 +0100 Subject: Fix positioning of dynamically populated QToolButton::MenuButtonPopup's in screen corners The existing code positioning the menu in QToolButtonPrivate::popupTimerDone() had a clause checking whether any receivers were connnected to QMenu::aboutToShow() causing the sizeHint to be -1,-1 in that case (apparently trying to accommodate menus populated in slots). In that case, the checking for screen borders would not work, causing the similar checks in QMenu::popup() to trigger, potentially positioning the menu over the mouse. To solve this dilemma, add a parameter taking a std::function calulating the position of the menu from the sizeHint to QMenuPrivate::exec()/popup() and invoke that in QMenuPrivate::popup() after emitting QMenu::aboutToShow() when the sizeHint is known. Fixes: QTBUG-78966 Change-Id: I180bd2dc7eadcaca6cadca13745ed4a2dd89e412 Reviewed-by: Volker Hilsheimer --- src/widgets/widgets/qmenu.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/widgets/widgets/qmenu.cpp') diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index e3e3b07d71..701035fc32 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -2322,7 +2322,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction) d->popup(p, atAction); } -void QMenuPrivate::popup(const QPoint &p, QAction *atAction) +void QMenuPrivate::popup(const QPoint &p, QAction *atAction, PositionFunction positionFunction) { Q_Q(QMenu); if (scroll) { // reset scroll state from last popup @@ -2388,6 +2388,10 @@ void QMenuPrivate::popup(const QPoint &p, QAction *atAction) const QSize menuSizeHint(q->sizeHint()); QSize size = menuSizeHint; + + if (positionFunction) + pos = positionFunction(menuSizeHint); + const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, nullptr, q); bool adjustToDesktop = !q->window()->testAttribute(Qt::WA_DontShowOnScreen); @@ -2642,14 +2646,14 @@ QAction *QMenu::exec(const QPoint &p, QAction *action) return d->exec(p, action); } -QAction *QMenuPrivate::exec(const QPoint &p, QAction *action) +QAction *QMenuPrivate::exec(const QPoint &p, QAction *action, PositionFunction positionFunction) { Q_Q(QMenu); q->ensurePolished(); q->createWinId(); QEventLoop evtLoop; eventLoop = &evtLoop; - popup(p, action); + popup(p, action, positionFunction); QPointer guard = q; (void) evtLoop.exec(); -- cgit v1.2.3