From 7febf0b30e8a6d74f0d78b0e727c52d18672a991 Mon Sep 17 00:00:00 2001 From: Volodymyr Zibarov Date: Mon, 11 Apr 2022 23:52:51 +0300 Subject: [PATCH] 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 --- src/widgets/kernel/qwidget_p.h | 39 +++++++++++------------------ src/widgets/widgets/qpushbutton.cpp | 2 +- src/widgets/widgets/qtoolbutton.cpp | 2 +- 3 files changed, 16 insertions(+), 27 deletions(-) diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index a6af19b030..f59a6f759e 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -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) diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp index cacc0f22d1..97650979e0 100644 --- a/src/widgets/widgets/qpushbutton.cpp +++ b/src/widgets/widgets/qpushbutton.cpp @@ -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(); diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp index f4e1610fee..c3a400d3d3 100644 --- a/src/widgets/widgets/qtoolbutton.cpp +++ b/src/widgets/widgets/qtoolbutton.cpp @@ -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()) {