Fix multiscreen menu popup positioning corner case
A QMenuBar may span multiple screens. Its menus will then open on the screen which the bottom middle of the action rect is at, and will snap to that screen's geometry if needed. However it can happen that the bottomLeft() of the action rect is on a different screen from the selected popup screen, in which case mapping this point to global coordinates can give incorrect coordinates if the screens have different scale factors. The x value will be corrected by the screen snapping if needed. Use the y from the screen test point, which will be correct for the selected screen. Task-number: QTBUG-73231 Change-Id: If9a39f6b832a64f2f701868f2be0d3a6468fe553 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>bb10
parent
36e65785ec
commit
6272dddadd
|
|
@ -286,16 +286,23 @@ void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
|
|||
activeMenuPriv->causedPopup.action = action;
|
||||
|
||||
QRect adjustedActionRect = actionRect(action);
|
||||
QPoint pos(q->mapToGlobal(QPoint(adjustedActionRect.left(), adjustedActionRect.bottom() + 1)));
|
||||
QPoint popupPos = adjustedActionRect.bottomLeft() + QPoint(0, 1);
|
||||
|
||||
//we put the popup menu on the screen containing the bottom-center of the action rect
|
||||
QScreen *menubarScreen = q->window()->windowHandle()->screen();
|
||||
QPointer<QScreen> popupScreen = menubarScreen->virtualSiblingAt(pos + QPoint(adjustedActionRect.width() / 2, 0));
|
||||
QPoint screenTestPos = q->mapToGlobal(popupPos + QPoint(adjustedActionRect.width() / 2, 0));
|
||||
QPointer<QScreen> popupScreen = menubarScreen->virtualSiblingAt(screenTestPos);
|
||||
if (!popupScreen)
|
||||
popupScreen = menubarScreen;
|
||||
std::swap(popupScreen, activeMenuPriv->popupScreen);
|
||||
const QSize popup_size = activeMenu->sizeHint();
|
||||
std::swap(popupScreen, activeMenuPriv->popupScreen);
|
||||
|
||||
// Use screenTestPos.y() for the popup y position. This is the correct global y
|
||||
// consistent with the selected screen in cases where the action rect spans
|
||||
// multiple screens with different scale factors.
|
||||
QPoint pos(q->mapToGlobal(popupPos).x(), screenTestPos.y());
|
||||
|
||||
QRect screenRect = popupScreen->geometry();
|
||||
pos = QPoint(qMax(pos.x(), screenRect.x()), qMax(pos.y(), screenRect.y()));
|
||||
const bool fitUp = (pos.y() - popup_size.height() >= screenRect.top());
|
||||
|
|
|
|||
Loading…
Reference in New Issue