Skip to content

Commit

Permalink
Add QScreen::virtualSiblingAt() and use it in QMenubarPrivate::popupA…
Browse files Browse the repository at this point in the history
…ction

QGuiApplication::screenAt() is documented "If the point maps to more
than one set of virtual siblings, the first match is returned."
But in many cases it's possible to start from a known screen and
consider only its siblings, as when deciding where to open a QMenu
from a QMenuBar: the QMenuBar is already shown on some screen(s),
so the QMenu must be shown on a sibling from that set.  This function
should be useful in other such cases too, hence it might as well
be public API.

Task-number: QTBUG-76162
Change-Id: I83c74b40eb53f56fb285a6074a3dc2c0ea9c570b
Reviewed-by: Friedemann Kleint <[email protected]>
Reviewed-by: Tor Arne Vestbø <[email protected]>
  • Loading branch information
ec1oud committed Sep 19, 2019
1 parent e0cad1a commit ecc8367
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 10 deletions.
4 changes: 3 additions & 1 deletion src/gui/kernel/qguiapplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,9 @@ QList<QScreen *> QGuiApplication::screens()
The \a point is in relation to the virtualGeometry() of each set of virtual
siblings. If the point maps to more than one set of virtual siblings the first
match is returned.
match is returned. If you wish to search only the virtual desktop siblings
of a known screen (for example siblings of the screen of your application
window \c QWidget::windowHandle()->screen()), use QScreen::virtualSiblingAt().
\since 5.10
*/
Expand Down
19 changes: 19 additions & 0 deletions src/gui/kernel/qscreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,25 @@ void QScreenPrivate::updatePrimaryOrientation()
primaryOrientation = geometry.width() >= geometry.height() ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
}

/*!
Returns the screen at \a point within the set of \l QScreen::virtualSiblings(),
or \c nullptr if outside of any screen.
The \a point is in relation to the virtualGeometry() of each set of virtual
siblings.
\since 5.15
*/
QScreen *QScreen::virtualSiblingAt(const QPoint &point)
{
const auto &siblings = virtualSiblings();
for (QScreen *sibling : siblings) {
if (sibling->geometry().contains(point))
return sibling;
}
return nullptr;
}

/*!
Creates and returns a pixmap constructed by grabbing the contents
of the given \a window restricted by QRect(\a x, \a y, \a width,
Expand Down
1 change: 1 addition & 0 deletions src/gui/kernel/qscreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class Q_GUI_EXPORT QScreen : public QObject
QRect availableGeometry() const;

QList<QScreen *> virtualSiblings() const;
QScreen *virtualSiblingAt(const QPoint &point);

QSize virtualSize() const;
QRect virtualGeometry() const;
Expand Down
13 changes: 4 additions & 9 deletions src/widgets/widgets/qmenubar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,15 +324,10 @@ void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
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 *popupScreen = q->window()->windowHandle()->screen();
QPoint bottomMiddlePos = pos + QPoint(adjustedActionRect.width() / 2, 0);
const auto &siblings = popupScreen->virtualSiblings();
for (QScreen *sibling : siblings) {
if (sibling->geometry().contains(bottomMiddlePos)) {
popupScreen = sibling;
break;
}
}
QScreen *menubarScreen = q->window()->windowHandle()->screen();
QScreen *popupScreen = menubarScreen->virtualSiblingAt(pos + QPoint(adjustedActionRect.width() / 2, 0));
if (!popupScreen)
popupScreen = menubarScreen;
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());
Expand Down

0 comments on commit ecc8367

Please sign in to comment.