Improve handling of screens in QWidgets.

Historically, the screen number of a QWidget was stored in
QTLWExtra::screenIndex which came in via the Q_WS_QWS platform.
The variable contained the screen number of the QDesktopScreenWidget
and the desired screen number for widget creation (from parent widget
or desktop parent widgets) and was not updated according to widget
geometry or when the associated QWindow moved to another screen.

Storing the screen number is problematic in Qt 5 since it may change
when the list of QScreens in QGuiApplication is rearranged.

This change renames it to initialScreen and changes its usage to only
contain a screen number when a screen is requested by parenting
on a desktop widget or reparenting. A value of -1 indicates no screen
is requested and the number should be deduced from the geometry.

For the usage in QDesktopScreenWidget, add a method to determine the
number via index in the list of QDesktopWidget.

Task-number: QTBUG-44070
Task-number: QTBUG-44213
Change-Id: I153d19073ad4b0fd14ef3d24caa6d3e76f350e82
Reviewed-by: Andy Shaw <andy.shaw@digia.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
This commit is contained in:
Friedemann Kleint 2015-02-04 13:23:26 +01:00
parent 4805714b0f
commit b3fc5e1ea3
4 changed files with 35 additions and 22 deletions

View File

@ -39,6 +39,13 @@
QT_BEGIN_NAMESPACE
int QDesktopScreenWidget::screenNumber() const
{
const QDesktopWidgetPrivate *desktopWidgetP
= static_cast<const QDesktopWidgetPrivate *>(qt_widget_private(QApplication::desktop()));
return desktopWidgetP->screens.indexOf(const_cast<QDesktopScreenWidget *>(this));
}
const QRect QDesktopWidget::screenGeometry(const QWidget *widget) const
{
if (!widget) {
@ -79,7 +86,7 @@ void QDesktopWidgetPrivate::_q_updateScreens()
for (int currentLength = screens.size(); currentLength < targetLength; ++currentLength) {
QScreen *qScreen = screenList.at(currentLength);
QDesktopScreenWidget *screenWidget = new QDesktopScreenWidget(currentLength);
QDesktopScreenWidget *screenWidget = new QDesktopScreenWidget;
screenWidget->setGeometry(qScreen->geometry());
QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)),
q, SLOT(_q_updateScreens()), Qt::QueuedConnection);

View File

@ -53,12 +53,12 @@ QT_BEGIN_NAMESPACE
class QDesktopScreenWidget : public QWidget {
Q_OBJECT
public:
QDesktopScreenWidget(int screenNumber = -1) : QWidget(0, Qt::Desktop)
QDesktopScreenWidget() : QWidget(Q_NULLPTR, Qt::Desktop)
{
setVisible(false);
QTLWExtra *topData = d_func()->topData();
topData->screenIndex = screenNumber;
}
int screenNumber() const;
};
class QDesktopWidgetPrivate : public QWidgetPrivate {

View File

@ -35,7 +35,7 @@
#include "qapplication_p.h"
#include "qbrush.h"
#include "qcursor.h"
#include "qdesktopwidget.h"
#include "qdesktopwidget_p.h"
#include "qevent.h"
#include "qhash.h"
#include "qlayout.h"
@ -1111,9 +1111,10 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
if (allWidgets)
allWidgets->insert(q);
QWidget *desktopWidget = 0;
int targetScreen = -1;
if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
desktopWidget = parentWidget;
const QDesktopScreenWidget *sw = qobject_cast<const QDesktopScreenWidget *>(parentWidget);
targetScreen = sw ? sw->screenNumber() : 0;
parentWidget = 0;
}
@ -1133,10 +1134,10 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
xinfo = desktopWidget->d_func()->xinfo;
}
#endif
if (desktopWidget) {
const int screen = desktopWidget->d_func()->topData()->screenIndex;
if (targetScreen >= 0) {
topData()->initialScreenIndex = targetScreen;
if (QWindow *window = q->windowHandle())
window->setScreen(QGuiApplication::screens().value(screen, 0));
window->setScreen(QGuiApplication::screens().value(targetScreen, Q_NULLPTR));
}
data.fstrut_dirty = true;
@ -1414,8 +1415,15 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
win->setGeometry(q->geometry());
else
win->resize(q->size());
if (win->isTopLevel())
win->setScreen(QGuiApplication::screens().value(topData()->screenIndex, 0));
if (win->isTopLevel()) {
int screenNumber = topData()->initialScreenIndex;
topData()->initialScreenIndex = -1;
if (screenNumber < 0) {
screenNumber = q->windowType() != Qt::Desktop
? QApplication::desktop()->screenNumber(q) : 0;
}
win->setScreen(QGuiApplication::screens().value(screenNumber, Q_NULLPTR));
}
QSurfaceFormat format = win->requestedFormat();
if ((flags & Qt::Window) && win->surfaceType() != QSurface::OpenGLSurface
@ -1715,7 +1723,7 @@ void QWidgetPrivate::createTLExtra()
x->embedded = 0;
x->window = 0;
x->shareContext = 0;
x->screenIndex = 0;
x->initialScreenIndex = -1;
#ifdef Q_WS_MAC
x->wasMaximized = false;
#endif // Q_WS_MAC
@ -10503,9 +10511,8 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
if (newparent && newparent->windowType() == Qt::Desktop) {
// make sure the widget is created on the same screen as the
// programmer specified desktop widget
// get the desktop's screen number
targetScreen = newparent->window()->d_func()->topData()->screenIndex;
const QDesktopScreenWidget *sw = qobject_cast<const QDesktopScreenWidget *>(newparent);
targetScreen = sw ? sw->screenNumber() : 0;
newparent = 0;
}
@ -10537,7 +10544,7 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
f |= Qt::Window;
if (targetScreen == -1) {
if (parent)
targetScreen = q->parentWidget()->window()->d_func()->topData()->screenIndex;
targetScreen = QApplication::desktop()->screenNumber(q->parentWidget()->window());
}
}
@ -10581,12 +10588,11 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
// move the window to the selected screen
if (!newparent && targetScreen != -1) {
if (maybeTopData())
maybeTopData()->screenIndex = targetScreen;
// only if it is already created
if (q->testAttribute(Qt::WA_WState_Created)) {
if (q->testAttribute(Qt::WA_WState_Created))
q->windowHandle()->setScreen(QGuiApplication::screens().value(targetScreen, 0));
}
else
topData()->initialScreenIndex = targetScreen;
}
}

View File

@ -212,7 +212,7 @@ struct QTLWExtra {
#endif
QWidgetWindow *window;
QOpenGLContext *shareContext;
quint32 screenIndex; // index in qplatformscreenlist
int initialScreenIndex; // Screen number when passing a QDesktop[Screen]Widget as parent.
};
struct QWExtra {