From 56e92dfdf255231aff0034d2e197fd096da7f0c0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 7 Jan 2019 13:41:10 +0100 Subject: QSplashScreen: Fix positioning in multimonitor setups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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ø --- src/widgets/widgets/qsplashscreen.cpp | 57 +++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 10 deletions(-) (limited to 'src/widgets/widgets') 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 #include #include #include @@ -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(qt_widget_private(QApplication::desktop())); + return desktopWidgetPrivate->screens.indexOf(const_cast(dsw)); +} + +const QScreen *QSplashScreenPrivate::screenFor(const QWidget *w) +{ + for (const QWidget *p = w; p !=nullptr ; p = p->parentWidget()) { + if (auto dsw = qobject_cast(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(); } /*! -- cgit v1.2.3 From 3eac688ec005833509bffc7097c378af9c5b515f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 10 Jan 2019 08:46:52 +0100 Subject: Documentation: Add \nullptr macro and use where applicable Qt for Python users reading the documentation assume that int(0) can be passed for pointer parameters. Use the newly introduced \nullptr to disambiguate this. In a follow-up step, the \nullptr macro can be defined as None when generating the Qt for Python documentation. Task-number: PYSIDE-903 Change-Id: I3a45f87175a0668ab5f3f95f0aff409f7e3ef027 Reviewed-by: Cristian Maureira-Fredes Reviewed-by: Christian Tismer Reviewed-by: Venugopal Shivashankar Reviewed-by: Paul Wicking --- src/widgets/widgets/qabstractbutton.cpp | 2 +- src/widgets/widgets/qabstractspinbox.cpp | 2 +- src/widgets/widgets/qmenu.cpp | 2 +- src/widgets/widgets/qmenubar.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/widgets/widgets') diff --git a/src/widgets/widgets/qabstractbutton.cpp b/src/widgets/widgets/qabstractbutton.cpp index 5854472ff0..f30a3bc7b8 100644 --- a/src/widgets/widgets/qabstractbutton.cpp +++ b/src/widgets/widgets/qabstractbutton.cpp @@ -805,7 +805,7 @@ bool QAbstractButton::autoExclusive() const Returns the group that this button belongs to. If the button is not a member of any QButtonGroup, this function - returns 0. + returns \nullptr. \sa QButtonGroup */ diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index 4e1aa51b4b..00ac5034e9 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -692,7 +692,7 @@ QLineEdit *QAbstractSpinBox::lineEdit() const QAbstractSpinBox takes ownership of the new lineEdit - If QLineEdit::validator() for the \a lineEdit returns 0, the internal + If QLineEdit::validator() for the \a lineEdit returns \nullptr, the internal validator of the spinbox will be set on the line edit. */ diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index e3c29ff6ee..48253b52b0 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -2283,7 +2283,7 @@ int QMenu::columnCount() const } /*! - Returns the item at \a pt; returns 0 if there is no item there. + Returns the item at \a pt; returns \nullptr if there is no item there. */ QAction *QMenu::actionAt(const QPoint &pt) const { diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index ce74a4c2ff..e7984078de 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -1581,7 +1581,7 @@ bool QMenuBar::eventFilter(QObject *object, QEvent *event) } /*! - Returns the QAction at \a pt. Returns 0 if there is no action at \a pt or if + Returns the QAction at \a pt. Returns \nullptr if there is no action at \a pt or if the location has a separator. \sa addAction(), addSeparator() -- cgit v1.2.3