From eed9a8fbd300dafb2802b6c09c018fbda4e13ef1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 5 Apr 2019 14:19:06 +0200 Subject: Add accessors for QWindow and QScreen to QWidgetPrivate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite the existing accessor QWidgetPrivate::windowHandle() to accept a mode enumeration that has an "Any" convenience. Based on that, add QWidgetPrivate::associatedScreen(), which is seful in many places where scaling is performed. Prototypically simplify the code. Task-number: QTBUG-62094 Task-number: QTBUG-73231 Change-Id: I516288363d329bce9bc94e4951106f9357bc6cde Reviewed-by: Tor Arne Vestbø --- src/widgets/accessible/qaccessiblemenu.cpp | 13 ++++-------- src/widgets/dialogs/qmessagebox.cpp | 11 +++------- src/widgets/itemviews/qabstractitemview.cpp | 11 ++-------- src/widgets/kernel/qdesktopwidget.cpp | 12 ++--------- src/widgets/kernel/qopenglwidget.cpp | 7 ++----- src/widgets/kernel/qwidget.cpp | 31 +++++++++++++++++++++++++++-- src/widgets/kernel/qwidget_p.h | 17 ++++++++-------- src/widgets/kernel/qwidgetwindow.cpp | 5 +---- src/widgets/styles/qwindowsstyle.cpp | 17 +++------------- src/widgets/widgets/qcombobox.cpp | 22 +++++++++----------- src/widgets/widgets/qdockwidget.cpp | 8 ++++---- src/widgets/widgets/qlineedit_p.cpp | 4 +--- src/widgets/widgets/qmainwindowlayout.cpp | 6 +++--- 13 files changed, 72 insertions(+), 92 deletions(-) (limited to 'src') diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp index 507584eb02..7f87288520 100644 --- a/src/widgets/accessible/qaccessiblemenu.cpp +++ b/src/widgets/accessible/qaccessiblemenu.cpp @@ -47,6 +47,7 @@ #endif #include #include +#include #ifndef QT_NO_ACCESSIBILITY @@ -241,15 +242,9 @@ QObject *QAccessibleMenuItem::object() const /*! \reimp */ QWindow *QAccessibleMenuItem::window() const { - QWindow *result = nullptr; - if (!m_owner.isNull()) { - result = m_owner->windowHandle(); - if (!result) { - if (const QWidget *nativeParent = m_owner->nativeParentWidget()) - result = nativeParent->windowHandle(); - } - } - return result; + return m_owner.isNull() + ? nullptr + : qt_widget_private(m_owner.data())->windowHandle(QWidgetPrivate::WindowHandleMode::Closest); } QRect QAccessibleMenuItem::rect() const diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index f143e3b527..9bfea06a54 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -2662,14 +2662,9 @@ QPixmap QMessageBoxPrivate::standardIcon(QMessageBox::Icon icon, QMessageBox *mb break; } if (!tmpIcon.isNull()) { - QWindow *window = nullptr; - if (mb) { - window = mb->windowHandle(); - if (!window) { - if (const QWidget *nativeParent = mb->nativeParentWidget()) - window = nativeParent->windowHandle(); - } - } + QWindow *window = mb + ? qt_widget_private(mb)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest) + : nullptr; return tmpIcon.pixmap(window, QSize(iconSize, iconSize)); } return QPixmap(); diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index 95631ffa5f..1d1c144bb8 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -4461,15 +4461,8 @@ QPixmap QAbstractItemViewPrivate::renderToPixmap(const QModelIndexList &indexes, if (paintPairs.isEmpty()) return QPixmap(); - qreal scale = 1.0f; - - Q_Q(const QAbstractItemView); - QWidget *window = q->window(); - if (window) { - QWindow *windowHandle = window->windowHandle(); - if (windowHandle) - scale = windowHandle->devicePixelRatio(); - } + QWindow *window = windowHandle(WindowHandleMode::Closest); + const qreal scale = window ? window->devicePixelRatio() : qreal(1); QPixmap pixmap(r->size() * scale); pixmap.setDevicePixelRatio(scale); diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp index d17c7eb36c..ac0cfcf2f5 100644 --- a/src/widgets/kernel/qdesktopwidget.cpp +++ b/src/widgets/kernel/qdesktopwidget.cpp @@ -321,20 +321,12 @@ int QDesktopWidgetPrivate::screenNumber(const QWidget *w) if (screens.isEmpty()) // This should never happen return primaryScreen(); - const QWindow *winHandle = w->windowHandle(); - if (!winHandle) { - if (const QWidget *nativeParent = w->nativeParentWidget()) - winHandle = nativeParent->windowHandle(); - } - // If there is more than one virtual desktop if (screens.count() != screens.constFirst()->virtualSiblings().count()) { // Find the root widget, get a QScreen from it and use the // virtual siblings for checking the window position. - if (winHandle) { - if (const QScreen *winScreen = winHandle->screen()) - screens = winScreen->virtualSiblings(); - } + if (const QScreen *winScreen = qt_widget_private(const_cast(w))->associatedScreen()) + screens = winScreen->virtualSiblings(); } // Get the screen number from window position using screen geometry diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 374ea53726..ae7729b49b 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -1333,11 +1333,8 @@ int QOpenGLWidget::metric(QPaintDevice::PaintDeviceMetric metric) const if (d->inBackingStorePaint) return QWidget::metric(metric); - QWidget *tlw = window(); - QWindow *window = tlw ? tlw->windowHandle() : 0; - QScreen *screen = tlw && tlw->windowHandle() ? tlw->windowHandle()->screen() : 0; - if (!screen && QGuiApplication::primaryScreen()) - screen = QGuiApplication::primaryScreen(); + auto window = d->windowHandle(QWidgetPrivate::WindowHandleMode::TopLevel); + QScreen *screen = window ? window->screen() : QGuiApplication::primaryScreen(); const float dpmx = qt_defaultDpiX() * 100. / 2.54; const float dpmy = qt_defaultDpiY() * 100. / 2.54; diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 58963d5eec..be2906a743 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1252,6 +1252,33 @@ void QWidgetPrivate::createRecursively() } } +QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const +{ + if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) { + if (QTLWExtra *x = maybeTopData()) + return x->window; + } + if (mode == WindowHandleMode::Closest) { + if (auto nativeParent = q_func()->nativeParentWidget()) { + if (auto window = nativeParent->windowHandle()) + return window; + } + } + if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) { + if (auto topLevel = q_func()->topLevelWidget()) { + if (auto window = topLevel ->windowHandle()) + return window; + } + } + return nullptr; +} + +QScreen *QWidgetPrivate::associatedScreen() const +{ + if (auto window = windowHandle(WindowHandleMode::Closest)) + return window->screen(); + return nullptr; +} // ### fixme: Qt 6: Remove parameter window from QWidget::create() @@ -8103,7 +8130,7 @@ void QWidgetPrivate::show_sys() { Q_Q(QWidget); - QWidgetWindow *window = windowHandle(); + auto window = qobject_cast(windowHandle()); if (q->testAttribute(Qt::WA_DontShowOnScreen)) { invalidateBackingStore(q->rect()); @@ -8242,7 +8269,7 @@ void QWidgetPrivate::hide_sys() { Q_Q(QWidget); - QWidgetWindow *window = windowHandle(); + auto window = qobject_cast(windowHandle()); if (q->testAttribute(Qt::WA_DontShowOnScreen)) { q->setAttribute(Qt::WA_Mapped, false); diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index c073b8fb03..1f36c192f5 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -342,7 +342,15 @@ public: QPainter *sharedPainter() const; void setSharedPainter(QPainter *painter); QWidgetBackingStore *maybeBackingStore() const; - QWidgetWindow *windowHandle() const; + + enum class WindowHandleMode { + Direct, + Closest, + TopLevel + }; + QWindow *windowHandle(WindowHandleMode mode = WindowHandleMode::Direct) const; + + QScreen *associatedScreen() const; template void repaint(T t); @@ -1014,13 +1022,6 @@ inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const return x ? x->backingStoreTracker.data() : nullptr; } -inline QWidgetWindow *QWidgetPrivate::windowHandle() const -{ - if (QTLWExtra *x = maybeTopData()) - return x->window; - return nullptr; -} - QT_END_NAMESPACE #endif // QWIDGET_P_H diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 70b305326c..a5d9eee49d 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -592,10 +592,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) w->window()->raise(); } - QWindow *win = w->windowHandle(); - if (!win) - win = w->nativeParentWidget()->windowHandle(); - if (win) { + if (auto win = qt_widget_private(w)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest)) { const QRect globalGeometry = win->isTopLevel() ? win->geometry() : QRect(win->mapToGlobal(QPoint(0, 0)), win->size()); diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 7b5da9bfa8..3c0478b84e 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -380,23 +380,12 @@ int QWindowsStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm) return QWindowsStylePrivate::InvalidMetric; } -static QWindow *windowOf(const QWidget *w) +static QScreen *screenOf(const QWidget *w) { - QWindow *result = nullptr; if (w) { - result = w->windowHandle(); - if (!result) { - if (const QWidget *np = w->nativeParentWidget()) - result = np->windowHandle(); - } + if (auto screen = qt_widget_private(const_cast(w))->associatedScreen()) + return screen; } - return result; -} - -static QScreen *screenOf(const QWidget *w) -{ - if (const QWindow *window = windowOf(w)) - return window->screen(); return QGuiApplication::primaryScreen(); } diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index a1434203d3..a052f2df79 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -2838,19 +2838,15 @@ void QComboBox::showPopup() bool startTimer = !container->isVisible(); container->raise(); container->create(); - QWindow *containerWindow = container->window()->windowHandle(); - if (containerWindow) { - QWindow *win = window()->windowHandle(); - if (win) { - QScreen *currentScreen = win->screen(); - if (currentScreen && !currentScreen->virtualSiblings().contains(containerWindow->screen())) { - containerWindow->setScreen(currentScreen); - - // This seems to workaround an issue in xcb+multi GPU+multiscreen - // environment where the window might not always show up when screen - // is changed. - container->hide(); - } + if (QWindow *containerWindow = qt_widget_private(container)->windowHandle(QWidgetPrivate::WindowHandleMode::TopLevel)) { + QScreen *currentScreen = d->associatedScreen(); + if (currentScreen && !currentScreen->virtualSiblings().contains(containerWindow->screen())) { + containerWindow->setScreen(currentScreen); + + // This seems to workaround an issue in xcb+multi GPU+multiscreen + // environment where the window might not always show up when screen + // is changed. + container->hide(); } } container->show(); diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index f98e0e44db..b8b6c12bf3 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -1535,10 +1535,10 @@ bool QDockWidget::event(QEvent *event) d->toggleViewAction->setChecked(true); QPoint parentTopLeft(0, 0); if (isWindow()) { - if (const QWindow *window = windowHandle()) - parentTopLeft = window->screen()->availableVirtualGeometry().topLeft(); - else - parentTopLeft = QGuiApplication::primaryScreen()->availableVirtualGeometry().topLeft(); + const QScreen *screen = d->associatedScreen(); + parentTopLeft = screen + ? screen->availableVirtualGeometry().topLeft() + : QGuiApplication::primaryScreen()->availableVirtualGeometry().topLeft(); } emit visibilityChanged(geometry().right() >= parentTopLeft.x() && geometry().bottom() >= parentTopLeft.y()); } diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 21e70db0ac..7d580e50a5 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -355,9 +355,7 @@ QLineEditPrivate *QLineEditIconButton::lineEditPrivate() const void QLineEditIconButton::paintEvent(QPaintEvent *) { QPainter painter(this); - QWindow *window = nullptr; - if (const QWidget *nativeParent = nativeParentWidget()) - window = nativeParent->windowHandle(); + QWindow *window = qt_widget_private(this)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest); QIcon::Mode state = QIcon::Disabled; if (isEnabled()) state = isDown() ? QIcon::Active : QIcon::Normal; diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index f54835f23b..b8f997b782 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -2584,9 +2584,9 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos) } } for (QWidget *w : candidates) { - QWindow *handle1 = widget->windowHandle(); - QWindow *handle2 = w->windowHandle(); - if (handle1 && handle2 && handle1->screen() != handle2->screen()) + const QScreen *screen1 = qt_widget_private(widget)->associatedScreen(); + const QScreen *screen2 = qt_widget_private(w)->associatedScreen(); + if (screen1 && screen2 && screen1 != screen2) continue; if (!w->geometry().contains(mousePos)) continue; -- cgit v1.2.3