diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-01-07 13:41:10 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-01-08 11:12:38 +0000 |
commit | 56e92dfdf255231aff0034d2e197fd096da7f0c0 (patch) | |
tree | d04050ca87ca220af89ed597cdeaac0e94a6f30d | |
parent | 5733dfbd90fd059e7310786faefb022b00289592 (diff) |
QSplashScreen: Fix positioning in multimonitor setups
Previously, QSplashScreen::setPixmap() used
QDesktopWidgetPrivate::screenGeometry().center() to determine
the screen position, which would always result in the primary screen
being used. That is counter to the documentation of QSplashScreen(QWidget *,
QPixmap), which states that a desktop screen widget can be passed
as parent to set the screen.
To fix that and make it easier to work with QScreen (which is the likely
outcome of QTBUG-62094), extract the setPixmap() to QSplashScreenPrivate
with an additional QScreen * parameter and add a helper to determine it. Do
not set a position in case no parent was passed so that
QPlatformWindow::initialGeometry() triggers, centering it over the cursor.
Fixes: QTBUG-72819
Task-number: QTBUG-62094
Change-Id: Ic38cfecd24c3ff6b82dff37702b627c5a50a3e1d
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
-rw-r--r-- | src/widgets/widgets/qsplashscreen.cpp | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/src/widgets/widgets/qsplashscreen.cpp b/src/widgets/widgets/qsplashscreen.cpp index 277d2fd99f..4af4f90119 100644 --- a/src/widgets/widgets/qsplashscreen.cpp +++ b/src/widgets/widgets/qsplashscreen.cpp @@ -46,6 +46,7 @@ #include "qpixmap.h" #include "qtextdocument.h" #include "qtextcursor.h" +#include <QtGui/qscreen.h> #include <QtGui/qwindow.h> #include <QtCore/qdebug.h> #include <QtCore/qelapsedtimer.h> @@ -69,6 +70,10 @@ public: int currAlign; inline QSplashScreenPrivate(); + + void setPixmap(const QPixmap &p, const QScreen *screen = nullptr); + + static const QScreen *screenFor(const QWidget *w); }; /*! @@ -143,8 +148,9 @@ QSplashScreen::QSplashScreen(const QPixmap &pixmap, Qt::WindowFlags f) QSplashScreen::QSplashScreen(QWidget *parent, const QPixmap &pixmap, Qt::WindowFlags f) : QWidget(*new QSplashScreenPrivate, parent, Qt::SplashScreen | Qt::FramelessWindowHint | f) { - d_func()->pixmap = pixmap; - setPixmap(d_func()->pixmap); // Does an implicit repaint + // Does an implicit repaint. Explicitly pass parent as QObject::parent() + // is still 0 here due to QWidget's special handling. + d_func()->setPixmap(pixmap, QSplashScreenPrivate::screenFor(parent)); } /*! @@ -276,16 +282,47 @@ void QSplashScreen::finish(QWidget *mainWin) */ void QSplashScreen::setPixmap(const QPixmap &pixmap) { - Q_D(QSplashScreen); + d_func()->setPixmap(pixmap, QSplashScreenPrivate::screenFor(this)); +} + +// In setPixmap(), resize and try to position on a screen according to: +// 1) If a QDesktopScreenWidget is found in the parent hierarchy, use that (see docs on +// QSplashScreen(QWidget *, QPixmap). +// 2) If a widget with associated QWindow is found, use that +// 3) When nothing can be found, do not position the widget, allowing for +// QPlatformWindow::initialGeometry() to center it over the cursor + +static inline int screenNumberOf(const QDesktopScreenWidget *dsw) +{ + auto desktopWidgetPrivate = + static_cast<QDesktopWidgetPrivate *>(qt_widget_private(QApplication::desktop())); + return desktopWidgetPrivate->screens.indexOf(const_cast<QDesktopScreenWidget *>(dsw)); +} + +const QScreen *QSplashScreenPrivate::screenFor(const QWidget *w) +{ + for (const QWidget *p = w; p !=nullptr ; p = p->parentWidget()) { + if (auto dsw = qobject_cast<const QDesktopScreenWidget *>(p)) + return QGuiApplication::screens().value(screenNumberOf(dsw)); + if (QWindow *window = p->windowHandle()) + return window->screen(); + } + return nullptr; +} + +void QSplashScreenPrivate::setPixmap(const QPixmap &p, const QScreen *screen) +{ + Q_Q(QSplashScreen); - d->pixmap = pixmap; - setAttribute(Qt::WA_TranslucentBackground, pixmap.hasAlpha()); + pixmap = p; + q->setAttribute(Qt::WA_TranslucentBackground, pixmap.hasAlpha()); - QRect r(QPoint(), d->pixmap.size() / d->pixmap.devicePixelRatio()); - resize(r.size()); - move(QDesktopWidgetPrivate::screenGeometry().center() - r.center()); - if (isVisible()) - repaint(); + QRect r(QPoint(), pixmap.size() / pixmap.devicePixelRatio()); + q->resize(r.size()); + if (screen) + q->move(screen->geometry().center() - r.center()); + if (q->isVisible()) + q->repaint(); } /*! |