From fc9a9acbbeee58d14455b4b06a0ba717256f657b Mon Sep 17 00:00:00 2001 From: Pierre Rossi Date: Mon, 10 Jan 2011 18:46:19 +0100 Subject: 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) --- src/gui/widgets/qmenu.cpp | 61 +++++++++++++++++++++++++++++++++++++---------- src/gui/widgets/qmenu_p.h | 4 +++- 2 files changed, 51 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 666362bc94..b0ea00f811 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -226,6 +226,12 @@ QList > 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 diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h index b6efde34cc..005ce1d6ee 100644 --- a/src/gui/widgets/qmenu_p.h +++ b/src/gui/widgets/qmenu_p.h @@ -194,10 +194,13 @@ public: mutable QVector actionRects; mutable QHash 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; -- cgit v1.2.3