Add accessors for QWindow and QScreen to QWidgetPrivate

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ø <tor.arne.vestbo@qt.io>
This commit is contained in:
Friedemann Kleint 2019-04-05 14:19:06 +02:00
parent cd563b3497
commit eed9a8fbd3
13 changed files with 72 additions and 92 deletions

View File

@ -47,6 +47,7 @@
#endif
#include <QtWidgets/QAction>
#include <qstyle.h>
#include <private/qwidget_p.h>
#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

View File

@ -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();

View File

@ -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);

View File

@ -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<QWidget *>(w))->associatedScreen())
screens = winScreen->virtualSiblings();
}
// Get the screen number from window position using screen geometry

View File

@ -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;

View File

@ -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<QWidgetWindow *>(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<QWidgetWindow *>(windowHandle());
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
q->setAttribute(Qt::WA_Mapped, false);

View File

@ -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 <typename T>
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

View File

@ -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());

View File

@ -380,23 +380,12 @@ int QWindowsStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm)
return QWindowsStylePrivate::InvalidMetric;
}
static QWindow *windowOf(const QWidget *w)
{
QWindow *result = nullptr;
if (w) {
result = w->windowHandle();
if (!result) {
if (const QWidget *np = w->nativeParentWidget())
result = np->windowHandle();
}
}
return result;
}
static QScreen *screenOf(const QWidget *w)
{
if (const QWindow *window = windowOf(w))
return window->screen();
if (w) {
if (auto screen = qt_widget_private(const_cast<QWidget *>(w))->associatedScreen())
return screen;
}
return QGuiApplication::primaryScreen();
}

View File

@ -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);
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();
}
// 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();

View File

@ -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());
}

View File

@ -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;

View File

@ -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;