QGraphicsScene: Fix popup position for QGraphicsProxyWidget

screenGeometry() for proxy widget was returning visible part of the
scene instead of screen geometry for enclosing first view

Pass button center position to screenGeometry() to get correct screen
for cases when graphics view occupies two screens

Fixes: QTBUG-98785
Pick-to: 6.2 6.3
Change-Id: Idaeb3c3faf739751c93624a06fa0fd3d65388236
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Volodymyr Zibarov 2022-04-11 23:52:51 +03:00
parent 72793ef31d
commit 7febf0b30e
3 changed files with 16 additions and 27 deletions

View File

@ -473,27 +473,22 @@ public:
// These helper functions return the (available) geometry for the screen
// the widget is on, and takes care if this one is embedded in a QGraphicsView.
static QRect graphicsViewParentRect(const QWidget *widget)
static QWidget *parentGraphicsView(const QWidget *widget)
{
QRect rect;
#if QT_CONFIG(graphicsview)
QGraphicsProxyWidget *ancestorProxy = widget->d_func()->nearestGraphicsProxyWidget(widget);
//It's embedded if it has an ancestor
if (ancestorProxy) {
if (!bypassGraphicsProxyWidget(widget) && ancestorProxy->scene() != nullptr) {
// One view, let be smart and return the viewport rect then the popup is aligned
if (ancestorProxy->scene()->views().size() == 1) {
QGraphicsView *view = ancestorProxy->scene()->views().at(0);
rect = view->mapToScene(view->viewport()->rect()).boundingRect().toRect();
} else {
rect = ancestorProxy->scene()->sceneRect().toRect();
if (!ancestorProxy->scene()->views().empty()) {
return ancestorProxy->scene()->views().at(0);
}
}
}
#else
Q_UNUSED(widget);
#endif
return rect;
return nullptr;
}
static QRect screenGeometry(const QWidget *widget)
@ -506,11 +501,10 @@ public:
return availableScreenGeometry(widget, QPoint(), false);
}
static QRect screenGeometry(const QWidget *widget, const QPoint &globalPosition, bool hasPosition = true)
static QScreen *screen(const QWidget *widget, const QPoint &globalPosition, bool hasPosition = true)
{
QRect rect = graphicsViewParentRect(widget);
if (!rect.isNull())
return rect;
while (QWidget *view = parentGraphicsView(widget))
widget = view;
QScreen *screen = nullptr;
if (hasPosition)
@ -518,22 +512,17 @@ public:
if (!screen)
screen = widget->screen();
return screen->geometry();
return screen;
}
static QRect screenGeometry(const QWidget *widget, const QPoint &globalPosition, bool hasPosition = true)
{
return screen(widget, globalPosition, hasPosition)->geometry();
}
static QRect availableScreenGeometry(const QWidget *widget, const QPoint &globalPosition, bool hasPosition = true)
{
QRect rect = graphicsViewParentRect(widget);
if (!rect.isNull())
return rect;
QScreen *screen = nullptr;
if (hasPosition)
screen = widget->screen()->virtualSiblingAt(globalPosition);
if (!screen)
screen = widget->screen();
return screen->availableGeometry();
return screen(widget, globalPosition, hasPosition)->availableGeometry();
}
inline void setRedirected(QPaintDevice *replacement, const QPoint &offset)

View File

@ -643,7 +643,7 @@ QPoint QPushButtonPrivate::adjustedMenuPosition()
QPoint globalPos = q->mapToGlobal(rect.topLeft());
int x = globalPos.x();
int y = globalPos.y();
const QRect availableGeometry = QWidgetPrivate::availableScreenGeometry(q);
const QRect availableGeometry = QWidgetPrivate::availableScreenGeometry(q, q->mapToGlobal(rect.center()));
if (horizontal) {
if (globalPos.y() + rect.height() + menuSize.height() <= availableGeometry.bottom()) {
y += rect.height();

View File

@ -724,7 +724,7 @@ static QPoint positionMenu(const QToolButton *q, bool horizontal,
{
QPoint p;
const QRect rect = q->rect(); // Find screen via point in case of QGraphicsProxyWidget.
const QRect screen = QWidgetPrivate::availableScreenGeometry(q);
const QRect screen = QWidgetPrivate::availableScreenGeometry(q, q->mapToGlobal(rect.center()));
if (horizontal) {
if (q->isRightToLeft()) {
if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.bottom()) {