diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2020-05-16 20:43:34 +0200 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2020-06-08 20:29:49 +0200 |
commit | 44fb925f50471ebc23dcccfaa4e9d9873b05d205 (patch) | |
tree | e4e212052b66242ff94aa98f6df7b15dbeb945f7 /src/widgets/kernel | |
parent | a061a646429c6e9d695458fc0ecb0021a30e12ee (diff) |
Phase 2 of removing QDesktopWidget
Remove QDestopWidget public header, simplify the implementation that
maintains a Qt::Desktop type QWidget for each QScreen, and turn
QWidget's initial target screen into a QScreen pointer.
QApplication::desktop() now takes an optional QScreen pointer, and
returns a QWidget pointer, so that applications and widgets can get
access to the root widget for a specific screen without having to
resort to private APIs.
QDesktopWidgetPrivate implementations to look up a screen for an index,
widget, or point are now all inline functions that thinly wrap
QGuiApplication::screens/screenAt calls. We should consider adding those
as convenience APIs to QScreen instead.
Note that QWidget::screen is assumed to return a valid pointer; there is
code that handles the case that it returns nullptr (but also code that
trusts that it never is nullptr), so this needs to be defined, verified
with tests, and asserted. We can then simplify the code further.
Change-Id: Ifc89be65a0dce265b6729feaf54121c35137cb94
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r-- | src/widgets/kernel/kernel.pri | 1 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication.cpp | 22 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication.h | 3 | ||||
-rw-r--r-- | src/widgets/kernel/qdesktopwidget.cpp | 182 | ||||
-rw-r--r-- | src/widgets/kernel/qdesktopwidget.h | 72 | ||||
-rw-r--r-- | src/widgets/kernel/qdesktopwidget_p.h | 100 | ||||
-rw-r--r-- | src/widgets/kernel/qtooltip.cpp | 32 | ||||
-rw-r--r-- | src/widgets/kernel/qwhatsthis.cpp | 1 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 45 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget_p.h | 36 |
10 files changed, 178 insertions, 316 deletions
diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri index b9dfdef5ee..462897b886 100644 --- a/src/widgets/kernel/kernel.pri +++ b/src/widgets/kernel/kernel.pri @@ -11,7 +11,6 @@ HEADERS += \ kernel/qapplication_p.h \ kernel/qwidgetrepaintmanager_p.h \ kernel/qboxlayout.h \ - kernel/qdesktopwidget.h \ kernel/qgridlayout.h \ kernel/qlayout.h \ kernel/qlayout_p.h \ diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 0e96e8bc69..1af94efdf9 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -42,7 +42,7 @@ #include "qapplication.h" #include "qclipboard.h" #include "qcursor.h" -#include "qdesktopwidget.h" +#include "qdesktopwidget_p.h" #include "qdir.h" #include "qevent.h" #include "qfile.h" @@ -2521,22 +2521,30 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget) /*! \internal - Returns the desktop widget (also called the root window). + Returns the desktop widget (also called the root window) for \a screen. + + If \a screen is nullptr, then the widget that represents the entire virtual + desktop is returned, and its geometry will be the union of all screens. + + Use the desktop widget for a specific screen as the parent of a new toplevel + widget to position the widget on a specific screen. The desktop may be composed of multiple screens, so it would be incorrect, for example, to attempt to \e center some widget in the desktop's geometry. - QDesktopWidget has various functions for obtaining useful geometries upon - the desktop, such as QDesktopWidget::screenGeometry() and - QDesktopWidget::availableGeometry(). + Use QScreen::geometry() and QScreen::availableGeometry() to get the dimensions + of a specific screen instead. */ -QDesktopWidget *QApplication::desktop() +QWidget *QApplication::desktop(QScreen *screen) { CHECK_QAPP_INSTANCE(nullptr) if (!qt_desktopWidget || // not created yet !(qt_desktopWidget->windowType() == Qt::Desktop)) { // reparented away qt_desktopWidget = new QDesktopWidget(); } - return qt_desktopWidget; + if (!screen) + return qt_desktopWidget; + QDesktopWidgetPrivate *dwp = static_cast<QDesktopWidgetPrivate*>(qt_widget_private(qt_desktopWidget)); + return dwp->widgetForScreen(screen); } /* diff --git a/src/widgets/kernel/qapplication.h b/src/widgets/kernel/qapplication.h index 1903aa48dc..36a7576c2d 100644 --- a/src/widgets/kernel/qapplication.h +++ b/src/widgets/kernel/qapplication.h @@ -51,7 +51,6 @@ QT_BEGIN_NAMESPACE -class QDesktopWidget; class QStyle; class QEventLoop; class QIcon; @@ -106,7 +105,7 @@ public: static QWidgetList allWidgets(); static QWidgetList topLevelWidgets(); - static QDesktopWidget *desktop(); + static QWidget *desktop(QScreen *screen = nullptr); static QWidget *activePopupWidget(); static QWidget *activeModalWidget(); diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp index dd74fbf53e..797980c7c5 100644 --- a/src/widgets/kernel/qdesktopwidget.cpp +++ b/src/widgets/kernel/qdesktopwidget.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -38,7 +38,6 @@ ****************************************************************************/ #include "qglobal.h" -#include "qdesktopwidget.h" #include "qdesktopwidget_p.h" #include "qscreen.h" #include "qwidget_p.h" @@ -50,109 +49,66 @@ QT_BEGIN_NAMESPACE QDesktopScreenWidget::QDesktopScreenWidget(QScreen *screen, const QRect &geometry) - : QWidget(nullptr, Qt::Desktop), m_screen(screen) + : QWidget(nullptr, Qt::Desktop) { setVisible(false); if (QWindow *winHandle = windowHandle()) winHandle->setScreen(screen); - setScreenGeometry(geometry); -} - -void QDesktopScreenWidget::setScreenGeometry(const QRect &geometry) -{ - m_geometry = geometry; setGeometry(geometry); } -int QDesktopScreenWidget::screenNumber() const +QScreen *QDesktopScreenWidget::screen() const { const QDesktopWidgetPrivate *desktopWidgetP = static_cast<const QDesktopWidgetPrivate *>(qt_widget_private(QApplication::desktop())); - return desktopWidgetP->screens.indexOf(const_cast<QDesktopScreenWidget *>(this)); -} - -const QRect QDesktopWidgetPrivate::screenGeometry(const QWidget *widget) -{ - if (Q_UNLIKELY(!widget)) { - qWarning("QDesktopWidget::screenGeometry(): Attempt " - "to get the screen geometry of a null widget"); - return QRect(); + for (auto it : qAsConst(desktopWidgetP->screenWidgets)) { + if (it.second == this) + return it.first; } - QRect rect = QWidgetPrivate::screenGeometry(widget); - if (rect.isNull()) - return screenGeometry(screenNumber(widget)); - else return rect; + return nullptr; } -const QRect QDesktopWidgetPrivate::availableGeometry(const QWidget *widget) +QDesktopWidgetPrivate::~QDesktopWidgetPrivate() { - if (Q_UNLIKELY(!widget)) { - qWarning("QDesktopWidget::availableGeometry(): Attempt " - "to get the available geometry of a null widget"); - return QRect(); - } - QRect rect = QWidgetPrivate::screenGeometry(widget); - if (rect.isNull()) - return availableGeometry(screenNumber(widget)); - else - return rect; + qDeleteAll(screenWidgets.values()); } -QDesktopScreenWidget *QDesktopWidgetPrivate::widgetForScreen(QScreen *qScreen) const -{ - foreach (QDesktopScreenWidget *widget, screens) { - if (widget->assignedScreen() == qScreen) - return widget; - } - return nullptr; -} - -void QDesktopWidgetPrivate::_q_updateScreens() +void QDesktopWidgetPrivate::updateScreens() { Q_Q(QDesktopWidget); const QList<QScreen *> screenList = QGuiApplication::screens(); - const int targetLength = screenList.length(); // Re-build our screens list. This is the easiest way to later compute which signals to emit. - // Create new screen widgets as necessary. While iterating, keep the old list in place so - // that widgetForScreen works. + // Create new screen widgets as necessary. // Furthermore, we note which screens have changed, and compute the overall virtual geometry. - QList<QDesktopScreenWidget *> newScreens; - QList<int> changedScreens; + QFlatMap<QScreen*, QDesktopScreenWidget*> newScreenWidgets; QRegion virtualGeometry; - for (int i = 0; i < targetLength; ++i) { - QScreen *qScreen = screenList.at(i); - const QRect screenGeometry = qScreen->geometry(); - QDesktopScreenWidget *screenWidget = widgetForScreen(qScreen); - if (screenWidget) { - // an old screen. update geometry and remember the index in the *new* list - if (screenGeometry != screenWidget->screenGeometry()) { - screenWidget->setScreenGeometry(screenGeometry); - changedScreens.push_back(i); - } - } else { + for (QScreen *screen : screenList) { + const QRect screenGeometry = screen->geometry(); + QDesktopScreenWidget *screenWidget = screenWidgets.value(screen); + if (!screenWidget) { // a new screen, create a widget and connect the signals. - screenWidget = new QDesktopScreenWidget(qScreen, screenGeometry); - QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)), - q, SLOT(_q_updateScreens()), Qt::QueuedConnection); - QObject::connect(qScreen, SIGNAL(destroyed()), - q, SLOT(_q_updateScreens()), Qt::QueuedConnection); + screenWidget = new QDesktopScreenWidget(screen, screenGeometry); + QObjectPrivate::connect(screen, &QScreen::geometryChanged, + this, &QDesktopWidgetPrivate::updateScreens, Qt::QueuedConnection); + QObjectPrivate::connect(screen, &QObject::destroyed, + this, &QDesktopWidgetPrivate::updateScreens, Qt::QueuedConnection); } // record all the screens and the overall geometry. - newScreens.push_back(screenWidget); + newScreenWidgets.insert(screen, screenWidget); virtualGeometry += screenGeometry; } // Now we apply the accumulated updates. - screens.swap(newScreens); // now [newScreens] is the old screen list - Q_ASSERT(screens.size() == targetLength); + qSwap(screenWidgets, newScreenWidgets); // now [newScreenWidgets] is the old screen list + Q_ASSERT(screenWidgets.size() == screenList.length()); q->setGeometry(virtualGeometry.boundingRect()); // Delete the QDesktopScreenWidget that are not used any more. - foreach (QDesktopScreenWidget *screen, newScreens) { - if (!screens.contains(screen)) - delete screen; + for (auto it : qAsConst(newScreenWidgets)) { + if (!screenWidgets.contains(it.first)) + delete it.second; } } @@ -161,90 +117,12 @@ QDesktopWidget::QDesktopWidget() { Q_D(QDesktopWidget); setObjectName(QLatin1String("desktop")); - d->_q_updateScreens(); - connect(qApp, SIGNAL(screenAdded(QScreen*)), this, SLOT(_q_updateScreens())); -} - -QDesktopWidget::~QDesktopWidget() -{ + d->updateScreens(); + QObjectPrivate::connect(qApp, &QApplication::screenAdded, d, &QDesktopWidgetPrivate::updateScreens); } -QWidget *QDesktopWidget::screen(int screen) -{ - Q_D(QDesktopWidget); - if (screen < 0 || screen >= d->screens.length()) - return d->screens.at(0); - return d->screens.at(screen); -} - -const QRect QDesktopWidgetPrivate::availableGeometry(int screenNo) -{ - const QScreen *screen = QDesktopWidgetPrivate::screen(screenNo); - return screen ? screen->availableGeometry() : QRect(); -} - -const QRect QDesktopWidgetPrivate::screenGeometry(int screenNo) -{ - const QScreen *screen = QDesktopWidgetPrivate::screen(screenNo); - return screen ? screen->geometry() : QRect(); -} - -int QDesktopWidgetPrivate::screenNumber(const QWidget *w) -{ - if (!w) - return 0; - - const QList<QScreen *> allScreens = QGuiApplication::screens(); - QList<QScreen *> screens = allScreens; - if (screens.isEmpty()) // This should never happen - return 0; - - // 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 (const QScreen *winScreen = qt_widget_private(const_cast<QWidget *>(w))->associatedScreen()) - screens = winScreen->virtualSiblings(); - } - - // Get the screen number from window position using screen geometry - // and proper screens. - QRect frame = w->frameGeometry(); - if (!w->isWindow()) - frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0))); - - QScreen *widgetScreen = nullptr; - int largestArea = 0; - foreach (QScreen *screen, screens) { - const QRect deviceIndependentScreenGeometry = - QHighDpi::fromNativePixels(screen->handle()->geometry(), screen); - const QRect intersected = deviceIndependentScreenGeometry.intersected(frame); - int area = intersected.width() * intersected.height(); - if (largestArea < area) { - widgetScreen = screen; - largestArea = area; - } - } - return allScreens.indexOf(widgetScreen); -} - -int QDesktopWidgetPrivate::screenNumber(const QPoint &p) -{ - QScreen *screen = QGuiApplication::screenAt(p); - return screen ? QGuiApplication::screens().indexOf(screen) : 0; -} - -QScreen *QDesktopWidgetPrivate::screen(int screenNo) -{ - QList<QScreen *> screens = QGuiApplication::screens(); - if (screenNo == -1) - screenNo = 0; - if (screenNo < 0 || screenNo >= screens.size()) - return nullptr; - return screens.at(screenNo); -} +QDesktopWidget::~QDesktopWidget() = default; QT_END_NAMESPACE -#include "moc_qdesktopwidget.cpp" #include "moc_qdesktopwidget_p.cpp" diff --git a/src/widgets/kernel/qdesktopwidget.h b/src/widgets/kernel/qdesktopwidget.h deleted file mode 100644 index 265f320b1f..0000000000 --- a/src/widgets/kernel/qdesktopwidget.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDESKTOPWIDGET_H -#define QDESKTOPWIDGET_H - -#include <QtWidgets/qtwidgetsglobal.h> -#include <QtWidgets/qwidget.h> - -QT_BEGIN_NAMESPACE - - -class QApplication; -class QDesktopWidgetPrivate; - -class Q_WIDGETS_EXPORT QDesktopWidget : public QWidget -{ - Q_OBJECT -public: - QDesktopWidget(); - ~QDesktopWidget(); - - QT_DEPRECATED_X("Use QScreen") QWidget *screen(int screen = -1); - -private: - Q_DISABLE_COPY(QDesktopWidget) - Q_DECLARE_PRIVATE(QDesktopWidget) - Q_PRIVATE_SLOT(d_func(), void _q_updateScreens()) - - friend class QApplication; - friend class QApplicationPrivate; -}; - -QT_END_NAMESPACE - -#endif // QDESKTOPWIDGET_H diff --git a/src/widgets/kernel/qdesktopwidget_p.h b/src/widgets/kernel/qdesktopwidget_p.h index b0ac13808d..d2845af17c 100644 --- a/src/widgets/kernel/qdesktopwidget_p.h +++ b/src/widgets/kernel/qdesktopwidget_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -52,56 +52,96 @@ #define QDESKTOPWIDGET_P_H #include <QtWidgets/private/qtwidgetsglobal_p.h> -#include "QDesktopWidget" #include "private/qwidget_p.h" -#include <QtCore/qalgorithms.h> #include <QtGui/qscreen.h> +#include <QtCore/private/qflatmap_p.h> QT_BEGIN_NAMESPACE -class QDesktopScreenWidget : public QWidget { +class QDesktopWidgetPrivate; + +class Q_WIDGETS_EXPORT QDesktopWidget : public QWidget +{ Q_OBJECT public: - explicit QDesktopScreenWidget(QScreen *screen, const QRect &geometry); + QDesktopWidget(); + ~QDesktopWidget(); - int screenNumber() const; - void setScreenGeometry(const QRect &geometry); - - QScreen *assignedScreen() const { return m_screen.data(); } - QRect screenGeometry() const { return m_geometry; } private: - // The widget updates its screen and geometry automatically. We need to save them separately - // to detect changes, and trigger the appropriate signals. - const QPointer<QScreen> m_screen; - QRect m_geometry; -}; + Q_DISABLE_COPY(QDesktopWidget) + Q_DECLARE_PRIVATE(QDesktopWidget) -class QDesktopWidgetPrivate : public QWidgetPrivate { - Q_DECLARE_PUBLIC(QDesktopWidget) + friend class QApplication; + friend class QApplicationPrivate; +}; +class QDesktopScreenWidget : public QWidget { + Q_OBJECT public: - ~QDesktopWidgetPrivate() { qDeleteAll(screens); } - void _q_updateScreens(); - QDesktopScreenWidget *widgetForScreen(QScreen *qScreen) const; + explicit QDesktopScreenWidget(QScreen *, const QRect &geometry); - static int screenNumber(const QWidget *widget = nullptr); - static int screenNumber(const QPoint &); + QScreen *screen() const; +}; - static QScreen *screen(int screenNo = -1); +class QDesktopWidgetPrivate : public QWidgetPrivate { + Q_DECLARE_PUBLIC(QDesktopWidget) - static const QRect screenGeometry(int screen = -1); - static const QRect screenGeometry(const QWidget *widget); - static const QRect screenGeometry(const QPoint &point) +public: + ~QDesktopWidgetPrivate(); + void updateScreens(); + QDesktopScreenWidget *widgetForScreen(QScreen *qScreen) const + { + return screenWidgets.value(qScreen); + } + + static inline int screenNumber(const QWidget *widget = nullptr) + { + if (!widget) + return 0; + return QGuiApplication::screens().indexOf(widget->screen()); + } + + static inline int screenNumber(const QPoint &point) + { + int screenNo = 0; + if (QScreen *screen = QGuiApplication::screenAt(point)) + screenNo = QGuiApplication::screens().indexOf(screen); + return screenNo; + } + + static inline QScreen *screen(int screenNo = -1) + { + const QList<QScreen *> screens = QGuiApplication::screens(); + if (screenNo == -1) + screenNo = 0; + if (screenNo < 0 || screenNo >= screens.size()) + return nullptr; + return screens.at(screenNo); + } + + static inline QRect screenGeometry(int screenNo = -1) + { + QRect rect; + if (const QScreen *s = screen(screenNo)) + rect = s->geometry(); + return rect; + } + static inline QRect screenGeometry(const QPoint &point) { return screenGeometry(screenNumber(point)); } - static const QRect availableGeometry(int screen = -1); - static const QRect availableGeometry(const QWidget *widget); - static const QRect availableGeometry(const QPoint &point) + static inline QRect availableGeometry(int screenNo = -1) + { + QRect rect; + if (const QScreen *s = screen(screenNo)) + rect = s->availableGeometry(); + return rect; + } + static inline QRect availableGeometry(const QPoint &point) { return availableGeometry(screenNumber(point)); } - QList<QDesktopScreenWidget *> screens; + QFlatMap<QScreen*, QDesktopScreenWidget*> screenWidgets; }; QT_END_NAMESPACE diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp index 80a87bb3cd..8aca4db58a 100644 --- a/src/widgets/kernel/qtooltip.cpp +++ b/src/widgets/kernel/qtooltip.cpp @@ -40,7 +40,6 @@ #include <QtWidgets/private/qtwidgetsglobal_p.h> #include <qapplication.h> -#include <qdesktopwidget.h> #include <private/qdesktopwidget_p.h> #include <qevent.h> #include <qpointer.h> @@ -139,7 +138,7 @@ public: bool tipChanged(const QPoint &pos, const QString &text, QObject *o); void placeTip(const QPoint &pos, QWidget *w); - static int getTipScreen(const QPoint &pos, QWidget *w); + static QScreen *getTipScreen(const QPoint &pos, QWidget *w); protected: void timerEvent(QTimerEvent *e) override; void paintEvent(QPaintEvent *e) override; @@ -366,12 +365,12 @@ bool QTipLabel::eventFilter(QObject *o, QEvent *e) return false; } -int QTipLabel::getTipScreen(const QPoint &pos, QWidget *w) +QScreen *QTipLabel::getTipScreen(const QPoint &pos, QWidget *w) { - if (QGuiApplication::primaryScreen()->virtualSiblings().size() > 1) - return QDesktopWidgetPrivate::screenNumber(pos); - else - return QDesktopWidgetPrivate::screenNumber(w); + int screenNo = QGuiApplication::primaryScreen()->virtualSiblings().size() > 1 + ? QDesktopWidgetPrivate::screenNumber(pos) + : QDesktopWidgetPrivate::screenNumber(w); + return QDesktopWidgetPrivate::screen(screenNo); } void QTipLabel::placeTip(const QPoint &pos, QWidget *w) @@ -396,8 +395,7 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w) #endif //QT_NO_STYLE_STYLESHEET QPoint p = pos; - const QScreen *screen = QGuiApplication::screens().value(getTipScreen(pos, w), - QGuiApplication::primaryScreen()); + const QScreen *screen = getTipScreen(pos, w); // a QScreen's handle *should* never be null, so this is a bit paranoid if (const QPlatformScreen *platformScreen = screen ? screen->handle() : nullptr) { const QSize cursorSize = QHighDpi::fromNativePixels(platformScreen->cursor()->size(), @@ -494,16 +492,18 @@ void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, cons } if (!text.isEmpty()){ // no tip can be reused, create new tip: + QWidget *tipLabelParent = [pos, w]() -> QWidget* { #ifdef Q_OS_WIN32 - // On windows, we can't use the widget as parent otherwise the window will be - // raised when the tooltip will be shown -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - new QTipLabel(text, pos, QApplication::desktop()->screen(QTipLabel::getTipScreen(pos, w)), msecDisplayTime); -QT_WARNING_POP + // On windows, we can't use the widget as parent otherwise the window will be + // raised when the tooltip will be shown + QScreen *screen = QTipLabel::getTipScreen(pos, w); + return QApplication::desktop(screen); #else - new QTipLabel(text, pos, w, msecDisplayTime); // sets QTipLabel::instance to itself + Q_UNUSED(pos); + return w; #endif + }(); + new QTipLabel(text, pos, tipLabelParent, msecDisplayTime); // sets QTipLabel::instance to itself QTipLabel::instance->setTipRect(w, rect); QTipLabel::instance->placeTip(pos, w); QTipLabel::instance->setObjectName(QLatin1String("qtooltip_label")); diff --git a/src/widgets/kernel/qwhatsthis.cpp b/src/widgets/kernel/qwhatsthis.cpp index fdf90acccc..c5a9989837 100644 --- a/src/widgets/kernel/qwhatsthis.cpp +++ b/src/widgets/kernel/qwhatsthis.cpp @@ -41,7 +41,6 @@ #include "qpointer.h" #include "qapplication.h" #include <private/qguiapplication_p.h> -#include "qdesktopwidget.h" #include <private/qdesktopwidget_p.h> #include "qevent.h" #include "qpixmap.h" diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 56e558eca0..c7303dde66 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -990,10 +990,10 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) if (allWidgets) allWidgets->insert(q); - int targetScreen = -1; + QScreen *targetScreen = nullptr; if (parentWidget && parentWidget->windowType() == Qt::Desktop) { const QDesktopScreenWidget *sw = qobject_cast<const QDesktopScreenWidget *>(parentWidget); - targetScreen = sw ? sw->screenNumber() : 0; + targetScreen = sw ? sw->screen() : nullptr; parentWidget = nullptr; } @@ -1006,10 +1006,10 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) } #endif - if (targetScreen >= 0) { - topData()->initialScreenIndex = targetScreen; + if (targetScreen) { + topData()->initialScreen = targetScreen; if (QWindow *window = q->windowHandle()) - window->setScreen(QGuiApplication::screens().value(targetScreen, nullptr)); + window->setScreen(targetScreen); } data.fstrut_dirty = true; @@ -1293,13 +1293,13 @@ void QWidgetPrivate::create() else win->resize(q->size()); if (win->isTopLevel()) { - int screenNumber = topData()->initialScreenIndex; - topData()->initialScreenIndex = -1; - if (screenNumber < 0) { - screenNumber = q->windowType() != Qt::Desktop - ? QDesktopWidgetPrivate::screenNumber(q) : 0; + QScreen *targetScreen = topData()->initialScreen; + topData()->initialScreen = nullptr; + if (!targetScreen) { + targetScreen = q->windowType() != Qt::Desktop + ? q->screen() : nullptr; } - win->setScreen(QGuiApplication::screens().value(screenNumber, nullptr)); + win->setScreen(targetScreen); } QSurfaceFormat format = win->requestedFormat(); @@ -1602,7 +1602,7 @@ void QWidgetPrivate::createTLExtra() x->sizeAdjusted = false; x->embedded = 0; x->window = nullptr; - x->initialScreenIndex = -1; + x->initialScreen = nullptr; #ifdef QWIDGET_EXTRA_DEBUG static int count = 0; @@ -2507,8 +2507,8 @@ QScreen *QWidget::screen() const return associatedScreen; if (auto topLevel = window()) { if (auto topData = qt_widget_private(topLevel)->topData()) { - if (auto initialScreen = QGuiApplicationPrivate::screen_list.value(topData->initialScreenIndex)) - return initialScreen; + if (topData->initialScreen) + return topData->initialScreen; } if (auto screenByPos = QGuiApplication::screenAt(topLevel->geometry().center())) return screenByPos; @@ -3472,8 +3472,7 @@ QPoint QWidget::pos() const issues with windows. \note Do not use this function to find the width of a screen on - a \l{QDesktopWidget}{multiple screen desktop}. Read - \l{QDesktopWidget#Screen Geometry}{this note} for details. + a multi-screen desktop. See QScreen for details. By default, this property contains a value that depends on the user's platform and screen geometry. @@ -10487,13 +10486,13 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) Qt::WindowFlags oldFlags = data.window_flags; bool wasCreated = q->testAttribute(Qt::WA_WState_Created); - int targetScreen = -1; + QScreen *targetScreen = nullptr; // Handle a request to move the widget to a particular screen if (newparent && newparent->windowType() == Qt::Desktop) { // make sure the widget is created on the same screen as the // programmer specified desktop widget const QDesktopScreenWidget *sw = qobject_cast<const QDesktopScreenWidget *>(newparent); - targetScreen = sw ? sw->screenNumber() : 0; + targetScreen = sw ? sw->screen() : nullptr; newparent = nullptr; } @@ -10523,9 +10522,9 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) if (!newparent) { f |= Qt::Window; - if (targetScreen == -1) { + if (!targetScreen) { if (parent) - targetScreen = QDesktopWidgetPrivate::screenNumber(q->parentWidget()->window()); + targetScreen = q->parentWidget()->window()->screen(); } } @@ -10568,12 +10567,12 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden); // move the window to the selected screen - if (!newparent && targetScreen != -1) { + if (!newparent && targetScreen) { // only if it is already created if (q->testAttribute(Qt::WA_WState_Created)) - q->windowHandle()->setScreen(QGuiApplication::screens().value(targetScreen, 0)); + q->windowHandle()->setScreen(targetScreen); else - topData()->initialScreenIndex = targetScreen; + topData()->initialScreen = targetScreen; } } diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 3e52a6ad2f..08954cc778 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -61,6 +61,7 @@ #include "QtGui/qinputmethod.h" #include "QtGui/qopengl.h" #include "QtGui/qsurfaceformat.h" +#include "QtGui/qscreen.h" #include "QtWidgets/qsizepolicy.h" #include "QtWidgets/qstyle.h" #include "QtWidgets/qapplication.h" @@ -144,8 +145,7 @@ struct QTLWExtra { QRect frameStrut; QRect normalGeometry; // used by showMin/maximized/FullScreen Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen - // ### TODO replace initialScreenIndex with QScreen *, in case the screens change at runtime - int initialScreenIndex; // Screen number when passing a QDesktop[Screen]Widget as parent. + QScreen *initialScreen; // Screen when passing a QDesktop[Screen]Widget as parent. #ifndef QT_NO_OPENGL std::vector<std::unique_ptr<QPlatformTextureList>> widgetTextures; @@ -476,13 +476,11 @@ public: void setModal_sys(); - // This is an helper function that return the available geometry for - // a widget and takes care is this one is in QGraphicsView. - // If the widget is not embed in a scene then the geometry available is - // null, we let QDesktopWidget decide for us. - static QRect screenGeometry(const QWidget *widget) + // These helper functions return the (available) geometry for the screen + // the widget is on, and takes care if this one is embedded in a QGraphicsView. + static QRect graphicsViewParentRect(const QWidget *widget) { - QRect screen; + QRect rect; #if QT_CONFIG(graphicsview) QGraphicsProxyWidget *ancestorProxy = widget->d_func()->nearestGraphicsProxyWidget(widget); //It's embedded if it has an ancestor @@ -491,16 +489,30 @@ public: // One view, let be smart and return the viewport rect then the popup is aligned if (ancestorProxy->scene()->views().size() == 1) { QGraphicsView *view = ancestorProxy->scene()->views().at(0); - screen = view->mapToScene(view->viewport()->rect()).boundingRect().toRect(); + rect = view->mapToScene(view->viewport()->rect()).boundingRect().toRect(); } else { - screen = ancestorProxy->scene()->sceneRect().toRect(); + rect = ancestorProxy->scene()->sceneRect().toRect(); } } } #else Q_UNUSED(widget); #endif - return screen; + return rect; + } + static QRect screenGeometry(const QWidget *widget) + { + QRect rect = graphicsViewParentRect(widget); + if (rect.isNull()) + rect = widget->screen()->geometry(); + return rect; + } + static QRect availableScreenGeometry(const QWidget *widget) + { + QRect rect = graphicsViewParentRect(widget); + if (rect.isNull()) + rect = widget->screen()->availableGeometry(); + return rect; } inline void setRedirected(QPaintDevice *replacement, const QPoint &offset) |