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>
This commit is contained in:
parent
5733dfbd90
commit
56e92dfdf2
@ -46,6 +46,7 @@
|
|||||||
#include "qpixmap.h"
|
#include "qpixmap.h"
|
||||||
#include "qtextdocument.h"
|
#include "qtextdocument.h"
|
||||||
#include "qtextcursor.h"
|
#include "qtextcursor.h"
|
||||||
|
#include <QtGui/qscreen.h>
|
||||||
#include <QtGui/qwindow.h>
|
#include <QtGui/qwindow.h>
|
||||||
#include <QtCore/qdebug.h>
|
#include <QtCore/qdebug.h>
|
||||||
#include <QtCore/qelapsedtimer.h>
|
#include <QtCore/qelapsedtimer.h>
|
||||||
@ -69,6 +70,10 @@ public:
|
|||||||
int currAlign;
|
int currAlign;
|
||||||
|
|
||||||
inline QSplashScreenPrivate();
|
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)
|
QSplashScreen::QSplashScreen(QWidget *parent, const QPixmap &pixmap, Qt::WindowFlags f)
|
||||||
: QWidget(*new QSplashScreenPrivate, parent, Qt::SplashScreen | Qt::FramelessWindowHint | f)
|
: QWidget(*new QSplashScreenPrivate, parent, Qt::SplashScreen | Qt::FramelessWindowHint | f)
|
||||||
{
|
{
|
||||||
d_func()->pixmap = pixmap;
|
// Does an implicit repaint. Explicitly pass parent as QObject::parent()
|
||||||
setPixmap(d_func()->pixmap); // Does an implicit repaint
|
// 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)
|
void QSplashScreen::setPixmap(const QPixmap &pixmap)
|
||||||
{
|
{
|
||||||
Q_D(QSplashScreen);
|
d_func()->setPixmap(pixmap, QSplashScreenPrivate::screenFor(this));
|
||||||
|
}
|
||||||
|
|
||||||
d->pixmap = pixmap;
|
// In setPixmap(), resize and try to position on a screen according to:
|
||||||
setAttribute(Qt::WA_TranslucentBackground, pixmap.hasAlpha());
|
// 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
|
||||||
|
|
||||||
QRect r(QPoint(), d->pixmap.size() / d->pixmap.devicePixelRatio());
|
static inline int screenNumberOf(const QDesktopScreenWidget *dsw)
|
||||||
resize(r.size());
|
{
|
||||||
move(QDesktopWidgetPrivate::screenGeometry().center() - r.center());
|
auto desktopWidgetPrivate =
|
||||||
if (isVisible())
|
static_cast<QDesktopWidgetPrivate *>(qt_widget_private(QApplication::desktop()));
|
||||||
repaint();
|
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);
|
||||||
|
|
||||||
|
pixmap = p;
|
||||||
|
q->setAttribute(Qt::WA_TranslucentBackground, pixmap.hasAlpha());
|
||||||
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user