Fix menu size in multiscreen setups
During QMenuPrivate::popup() and QMenuBarPrivate::popupAction(), QMenuPrivate::popupGeometry() is called from updateActionRects() with screen = 0 several times (from sizeHint() and various event handlers triggered), which causes it to return the primary screen geometry always. To fix this for the non-QGraphicsView case, use the screen of the menu when it is visible or the screen stored in a newly introduced popupScreen member variable, which is set from a few places in QMenuPrivate::popup(). Fixes: QTBUG-118434 Pick-to: 6.7 6.6 6.5 Change-Id: I6b18593d313719d628b0856004197ac59f46c270 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
9069b7fb20
commit
8cd7a3d472
@ -292,6 +292,13 @@ inline bool QMenuPrivate::useFullScreenForPopup() const
|
||||
QRect QMenuPrivate::popupGeometry(QScreen *screen) const
|
||||
{
|
||||
Q_Q(const QMenu);
|
||||
if (screen == nullptr
|
||||
#if QT_CONFIG(graphicsview)
|
||||
&& q->graphicsProxyWidget() == nullptr
|
||||
#endif
|
||||
) {
|
||||
screen = q->isVisible() ? q->screen() : popupScreen.data();
|
||||
}
|
||||
if (useFullScreenForPopup())
|
||||
return screen ? screen->geometry()
|
||||
: QWidgetPrivate::screenGeometry(q);
|
||||
@ -2309,6 +2316,9 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
|
||||
void QMenuPrivate::popup(const QPoint &p, QAction *atAction, PositionFunction positionFunction)
|
||||
{
|
||||
Q_Q(QMenu);
|
||||
popupScreen = QGuiApplication::screenAt(p);
|
||||
QScopeGuard popupScreenGuard([this](){ popupScreen.clear(); });
|
||||
|
||||
if (scroll) { // reset scroll state from last popup
|
||||
if (scroll->scrollOffset)
|
||||
itemsDirty = 1; // sizeHint will be incorrect if there is previous scroll
|
||||
@ -2384,6 +2394,7 @@ void QMenuPrivate::popup(const QPoint &p, QAction *atAction, PositionFunction po
|
||||
pos = QPushButtonPrivate::get(causedButton)->adjustedMenuPosition();
|
||||
else
|
||||
pos = p;
|
||||
popupScreen = QGuiApplication::screenAt(pos);
|
||||
|
||||
const QSize menuSizeHint(q->sizeHint());
|
||||
QSize size = menuSizeHint;
|
||||
@ -2522,6 +2533,7 @@ void QMenuPrivate::popup(const QPoint &p, QAction *atAction, PositionFunction po
|
||||
}
|
||||
}
|
||||
}
|
||||
popupScreen = QGuiApplication::screenAt(pos);
|
||||
q->setGeometry(QRect(pos, size));
|
||||
#if QT_CONFIG(effects)
|
||||
int hGuess = q->isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll;
|
||||
|
@ -473,6 +473,11 @@ public:
|
||||
|
||||
mutable quint8 ncols = 0; // "255cols ought to be enough for anybody."
|
||||
|
||||
// Contains the screen of the popup point during popup(QPoint).
|
||||
// This is to make sure the screen is remembered,
|
||||
// when the menu contains many items on multiple screens
|
||||
QPointer<QScreen> popupScreen;
|
||||
|
||||
mutable bool itemsDirty : 1;
|
||||
mutable bool hasCheckableItems : 1;
|
||||
bool lastContextMenu : 1;
|
||||
|
@ -281,17 +281,21 @@ void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
|
||||
if (action->isEnabled() && action->menu()->isEnabled()) {
|
||||
closePopupMode = 0;
|
||||
activeMenu = action->menu();
|
||||
activeMenu->d_func()->causedPopup.widget = q;
|
||||
activeMenu->d_func()->causedPopup.action = action;
|
||||
auto *activeMenuPriv = activeMenu->d_func();
|
||||
activeMenuPriv->causedPopup.widget = q;
|
||||
activeMenuPriv->causedPopup.action = action;
|
||||
|
||||
QRect adjustedActionRect = actionRect(action);
|
||||
QPoint pos(q->mapToGlobal(QPoint(adjustedActionRect.left(), adjustedActionRect.bottom() + 1)));
|
||||
QSize popup_size = activeMenu->sizeHint();
|
||||
//we put the popup menu on the screen containing the bottom-center of the action rect
|
||||
QScreen *menubarScreen = q->window()->windowHandle()->screen();
|
||||
QScreen *popupScreen = menubarScreen->virtualSiblingAt(pos + QPoint(adjustedActionRect.width() / 2, 0));
|
||||
QPointer<QScreen> popupScreen = menubarScreen->virtualSiblingAt(pos + QPoint(adjustedActionRect.width() / 2, 0));
|
||||
if (!popupScreen)
|
||||
popupScreen = menubarScreen;
|
||||
std::swap(popupScreen, activeMenuPriv->popupScreen);
|
||||
const QSize popup_size = activeMenu->sizeHint();
|
||||
std::swap(popupScreen, activeMenuPriv->popupScreen);
|
||||
|
||||
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…
x
Reference in New Issue
Block a user