Fix a bug with menu overflowing from a lower resolution second screen.
The menu needs to take into account the screen geometry of the screen it's about to be shown on (not the last screen it was shown on) when updating its actions rects Task-number: QTBUG-2748 Reviewed-by: Thierry (cherry picked from commit b10265efba544b1e4820f45b86354d442f6abf26)
This commit is contained in:
parent
a74f09044e
commit
fc9a9acbbe
@ -226,6 +226,12 @@ QList<QPointer<QWidget> > QMenuPrivate::calcCausedStack() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void QMenuPrivate::updateActionRects() const
|
void QMenuPrivate::updateActionRects() const
|
||||||
|
{
|
||||||
|
Q_Q(const QMenu);
|
||||||
|
updateActionRects(popupGeometry(q));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMenuPrivate::updateActionRects(const QRect &screen) const
|
||||||
{
|
{
|
||||||
Q_Q(const QMenu);
|
Q_Q(const QMenu);
|
||||||
if (!itemsDirty)
|
if (!itemsDirty)
|
||||||
@ -237,20 +243,10 @@ void QMenuPrivate::updateActionRects() const
|
|||||||
actionRects.resize(actions.count());
|
actionRects.resize(actions.count());
|
||||||
actionRects.fill(QRect());
|
actionRects.fill(QRect());
|
||||||
|
|
||||||
//let's try to get the last visible action
|
int lastVisibleAction = getLastVisibleAction();
|
||||||
int lastVisibleAction = actions.count() - 1;
|
|
||||||
for(;lastVisibleAction >= 0; --lastVisibleAction) {
|
|
||||||
const QAction *action = actions.at(lastVisibleAction);
|
|
||||||
if (action->isVisible()) {
|
|
||||||
//removing trailing separators
|
|
||||||
if (action->isSeparator() && collapsibleSeparators)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int max_column_width = 0,
|
int max_column_width = 0,
|
||||||
dh = popupGeometry(q).height(),
|
dh = screen.height(),
|
||||||
y = 0;
|
y = 0;
|
||||||
QStyle *style = q->style();
|
QStyle *style = q->style();
|
||||||
QStyleOption opt;
|
QStyleOption opt;
|
||||||
@ -381,6 +377,34 @@ void QMenuPrivate::updateActionRects() const
|
|||||||
itemsDirty = 0;
|
itemsDirty = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSize QMenuPrivate::adjustMenuSizeForScreen(const QRect &screen)
|
||||||
|
{
|
||||||
|
Q_Q(QMenu);
|
||||||
|
QSize ret = screen.size();
|
||||||
|
itemsDirty = true;
|
||||||
|
updateActionRects(screen);
|
||||||
|
const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q);
|
||||||
|
ret.setWidth(actionRects.at(getLastVisibleAction()).right() + fw);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QMenuPrivate::getLastVisibleAction() const
|
||||||
|
{
|
||||||
|
//let's try to get the last visible action
|
||||||
|
int lastVisibleAction = actions.count() - 1;
|
||||||
|
for (;lastVisibleAction >= 0; --lastVisibleAction) {
|
||||||
|
const QAction *action = actions.at(lastVisibleAction);
|
||||||
|
if (action->isVisible()) {
|
||||||
|
//removing trailing separators
|
||||||
|
if (action->isSeparator() && collapsibleSeparators)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lastVisibleAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QRect QMenuPrivate::actionRect(QAction *act) const
|
QRect QMenuPrivate::actionRect(QAction *act) const
|
||||||
{
|
{
|
||||||
int index = actions.indexOf(act);
|
int index = actions.indexOf(act);
|
||||||
@ -1812,9 +1836,20 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
screen = d->popupGeometry(QApplication::desktop()->screenNumber(p));
|
screen = d->popupGeometry(QApplication::desktop()->screenNumber(p));
|
||||||
|
|
||||||
const int desktopFrame = style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, this);
|
const int desktopFrame = style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, this);
|
||||||
bool adjustToDesktop = !window()->testAttribute(Qt::WA_DontShowOnScreen);
|
bool adjustToDesktop = !window()->testAttribute(Qt::WA_DontShowOnScreen);
|
||||||
|
|
||||||
|
// if the screens have very different geometries and the menu is too big, we have to recalculate
|
||||||
|
if (size.height() > screen.height() || size.width() > screen.width()) {
|
||||||
|
size = d->adjustMenuSizeForScreen(screen);
|
||||||
|
adjustToDesktop = true;
|
||||||
|
}
|
||||||
|
// Layout is not right, we might be able to save horizontal space
|
||||||
|
if (d->ncols >1 && size.height() < screen.height()) {
|
||||||
|
size = d->adjustMenuSizeForScreen(screen);
|
||||||
|
adjustToDesktop = true;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef QT_KEYPAD_NAVIGATION
|
#ifdef QT_KEYPAD_NAVIGATION
|
||||||
if (!atAction && QApplication::keypadNavigationEnabled()) {
|
if (!atAction && QApplication::keypadNavigationEnabled()) {
|
||||||
// Try to have one item activated
|
// Try to have one item activated
|
||||||
|
@ -194,10 +194,13 @@ public:
|
|||||||
mutable QVector<QRect> actionRects;
|
mutable QVector<QRect> actionRects;
|
||||||
mutable QHash<QAction *, QWidget *> widgetItems;
|
mutable QHash<QAction *, QWidget *> widgetItems;
|
||||||
void updateActionRects() const;
|
void updateActionRects() const;
|
||||||
|
void updateActionRects(const QRect &screen) const;
|
||||||
QRect popupGeometry(const QWidget *widget) const;
|
QRect popupGeometry(const QWidget *widget) const;
|
||||||
QRect popupGeometry(int screen = -1) const;
|
QRect popupGeometry(int screen = -1) const;
|
||||||
mutable uint ncols : 4; //4 bits is probably plenty
|
mutable uint ncols : 4; //4 bits is probably plenty
|
||||||
uint collapsibleSeparators : 1;
|
uint collapsibleSeparators : 1;
|
||||||
|
QSize adjustMenuSizeForScreen(const QRect & screen);
|
||||||
|
int getLastVisibleAction() const;
|
||||||
|
|
||||||
bool activationRecursionGuard;
|
bool activationRecursionGuard;
|
||||||
|
|
||||||
@ -296,7 +299,6 @@ public:
|
|||||||
|
|
||||||
void updateLayoutDirection();
|
void updateLayoutDirection();
|
||||||
|
|
||||||
|
|
||||||
//menu fading/scrolling effects
|
//menu fading/scrolling effects
|
||||||
bool doChildEffects;
|
bool doChildEffects;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user