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:
Pierre Rossi 2011-01-10 18:46:19 +01:00 committed by Olivier Goffart
parent a74f09044e
commit fc9a9acbbe
2 changed files with 51 additions and 14 deletions

View File

@ -226,6 +226,12 @@ QList<QPointer<QWidget> > QMenuPrivate::calcCausedStack() const
}
void QMenuPrivate::updateActionRects() const
{
Q_Q(const QMenu);
updateActionRects(popupGeometry(q));
}
void QMenuPrivate::updateActionRects(const QRect &screen) const
{
Q_Q(const QMenu);
if (!itemsDirty)
@ -237,20 +243,10 @@ void QMenuPrivate::updateActionRects() const
actionRects.resize(actions.count());
actionRects.fill(QRect());
//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;
}
}
int lastVisibleAction = getLastVisibleAction();
int max_column_width = 0,
dh = popupGeometry(q).height(),
dh = screen.height(),
y = 0;
QStyle *style = q->style();
QStyleOption opt;
@ -381,6 +377,34 @@ void QMenuPrivate::updateActionRects() const
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
{
int index = actions.indexOf(act);
@ -1812,9 +1836,20 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
else
#endif
screen = d->popupGeometry(QApplication::desktop()->screenNumber(p));
const int desktopFrame = style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, this);
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
if (!atAction && QApplication::keypadNavigationEnabled()) {
// Try to have one item activated

View File

@ -194,10 +194,13 @@ public:
mutable QVector<QRect> actionRects;
mutable QHash<QAction *, QWidget *> widgetItems;
void updateActionRects() const;
void updateActionRects(const QRect &screen) const;
QRect popupGeometry(const QWidget *widget) const;
QRect popupGeometry(int screen = -1) const;
mutable uint ncols : 4; //4 bits is probably plenty
uint collapsibleSeparators : 1;
QSize adjustMenuSizeForScreen(const QRect & screen);
int getLastVisibleAction() const;
bool activationRecursionGuard;
@ -296,7 +299,6 @@ public:
void updateLayoutDirection();
//menu fading/scrolling effects
bool doChildEffects;