summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r--src/widgets/kernel/qaction.h40
-rw-r--r--src/widgets/kernel/qaction_widgets.cpp45
-rw-r--r--src/widgets/kernel/qaction_widgets_p.h42
-rw-r--r--src/widgets/kernel/qactiongroup.h40
-rw-r--r--src/widgets/kernel/qapplication.cpp453
-rw-r--r--src/widgets/kernel/qapplication.h46
-rw-r--r--src/widgets/kernel/qapplication_p.h62
-rw-r--r--src/widgets/kernel/qboxlayout.cpp83
-rw-r--r--src/widgets/kernel/qboxlayout.h40
-rw-r--r--src/widgets/kernel/qformlayout.cpp289
-rw-r--r--src/widgets/kernel/qformlayout.h48
-rw-r--r--src/widgets/kernel/qgesture.cpp47
-rw-r--r--src/widgets/kernel/qgesture.h56
-rw-r--r--src/widgets/kernel/qgesture_p.h40
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp94
-rw-r--r--src/widgets/kernel/qgesturemanager_p.h50
-rw-r--r--src/widgets/kernel/qgesturerecognizer.cpp40
-rw-r--r--src/widgets/kernel/qgesturerecognizer.h40
-rw-r--r--src/widgets/kernel/qgridlayout.cpp50
-rw-r--r--src/widgets/kernel/qgridlayout.h40
-rw-r--r--src/widgets/kernel/qlayout.cpp85
-rw-r--r--src/widgets/kernel/qlayout.h40
-rw-r--r--src/widgets/kernel/qlayout_p.h40
-rw-r--r--src/widgets/kernel/qlayoutengine.cpp40
-rw-r--r--src/widgets/kernel/qlayoutengine_p.h40
-rw-r--r--src/widgets/kernel/qlayoutitem.cpp42
-rw-r--r--src/widgets/kernel/qlayoutitem.h40
-rw-r--r--src/widgets/kernel/qmacgesturerecognizer.cpp40
-rw-r--r--src/widgets/kernel/qmacgesturerecognizer_p.h40
-rw-r--r--src/widgets/kernel/qrhiwidget.cpp1309
-rw-r--r--src/widgets/kernel/qrhiwidget.h101
-rw-r--r--src/widgets/kernel/qrhiwidget_p.h64
-rw-r--r--src/widgets/kernel/qshortcut.h40
-rw-r--r--src/widgets/kernel/qshortcut_widgets.cpp60
-rw-r--r--src/widgets/kernel/qsizepolicy.cpp40
-rw-r--r--src/widgets/kernel/qsizepolicy.h41
-rw-r--r--src/widgets/kernel/qstackedlayout.cpp60
-rw-r--r--src/widgets/kernel/qstackedlayout.h40
-rw-r--r--src/widgets/kernel/qstandardgestures.cpp40
-rw-r--r--src/widgets/kernel/qstandardgestures_p.h40
-rw-r--r--src/widgets/kernel/qt_widgets_pch.h40
-rw-r--r--src/widgets/kernel/qtestsupport_widgets.cpp167
-rw-r--r--src/widgets/kernel/qtestsupport_widgets.h43
-rw-r--r--src/widgets/kernel/qtooltip.cpp88
-rw-r--r--src/widgets/kernel/qtooltip.h40
-rw-r--r--src/widgets/kernel/qtwidgetsglobal.h40
-rw-r--r--src/widgets/kernel/qtwidgetsglobal_p.h40
-rw-r--r--src/widgets/kernel/qwhatsthis.cpp62
-rw-r--r--src/widgets/kernel/qwhatsthis.h40
-rw-r--r--src/widgets/kernel/qwidget.cpp1619
-rw-r--r--src/widgets/kernel/qwidget.h60
-rw-r--r--src/widgets/kernel/qwidget_p.h173
-rw-r--r--src/widgets/kernel/qwidgetaction.cpp60
-rw-r--r--src/widgets/kernel/qwidgetaction.h41
-rw-r--r--src/widgets/kernel/qwidgetaction_p.h44
-rw-r--r--src/widgets/kernel/qwidgetrepaintmanager.cpp362
-rw-r--r--src/widgets/kernel/qwidgetrepaintmanager_p.h51
-rw-r--r--src/widgets/kernel/qwidgetsvariant.cpp44
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp198
-rw-r--r--src/widgets/kernel/qwidgetwindow_p.h47
-rw-r--r--src/widgets/kernel/qwindowcontainer.cpp135
-rw-r--r--src/widgets/kernel/qwindowcontainer_p.h45
62 files changed, 3845 insertions, 3481 deletions
diff --git a/src/widgets/kernel/qaction.h b/src/widgets/kernel/qaction.h
index 7c9496f638..4311d503d7 100644
--- a/src/widgets/kernel/qaction.h
+++ b/src/widgets/kernel/qaction.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/QAction>
diff --git a/src/widgets/kernel/qaction_widgets.cpp b/src/widgets/kernel/qaction_widgets.cpp
index dcecb32b06..ad282ab104 100644
--- a/src/widgets/kernel/qaction_widgets.cpp
+++ b/src/widgets/kernel/qaction_widgets.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qaction.h"
@@ -64,8 +28,9 @@ void QtWidgetsActionPrivate::destroy()
{
Q_Q(QAction);
const auto objects = associatedObjects;
- for (int i = objects.size()-1; i >= 0; --i) {
- QObject *object = objects.at(i);
+ const auto end = objects.crend();
+ for (auto it = objects.crbegin(); it != end; ++it) {
+ QObject *object = *it;
if (QWidget *widget = qobject_cast<QWidget*>(object))
widget->removeAction(q);
#if QT_CONFIG(graphicsview)
diff --git a/src/widgets/kernel/qaction_widgets_p.h b/src/widgets/kernel/qaction_widgets_p.h
index c301aeb926..77c3d8a680 100644
--- a/src/widgets/kernel/qaction_widgets_p.h
+++ b/src/widgets/kernel/qaction_widgets_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui 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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QACTION_WIDGETS_P_H
#define QACTION_WIDGETS_P_H
@@ -56,6 +20,8 @@
#include <QtWidgets/qmenu.h>
#endif
+#include <QtCore/qpointer.h>
+
QT_REQUIRE_CONFIG(action);
QT_BEGIN_NAMESPACE
diff --git a/src/widgets/kernel/qactiongroup.h b/src/widgets/kernel/qactiongroup.h
index 74c6c44a00..2592eb17b4 100644
--- a/src/widgets/kernel/qactiongroup.h
+++ b/src/widgets/kernel/qactiongroup.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/QActionGroup>
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 0fa3c6a3d7..de7d93ce20 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qabstracteventdispatcher.h"
@@ -84,14 +48,18 @@
#if QT_CONFIG(whatsthis)
#include <QtWidgets/QWhatsThis>
#endif
+#if QT_CONFIG(accessibility)
+#include <QtGui/qaccessible_base.h>
+#include "private/qaccessiblewidgetfactory_p.h"
+#endif
#include "private/qkeymapper_p.h"
-#include "private/qaccessiblewidgetfactory_p.h"
#include <qthread.h>
#include <private/qthread_p.h>
#include <QtGui/private/qevent_p.h>
+#include <QtGui/private/qeventpoint_p.h>
#include <private/qfont_p.h>
#if QT_CONFIG(action)
#include <private/qaction_p.h>
@@ -112,11 +80,13 @@
#include <qtwidgets_tracepoints_p.h>
+#ifdef Q_OS_MACOS
+#include <QtCore/private/qcore_mac_p.h>
+#endif
+
#include <algorithm>
#include <iterator>
-//#define ALIEN_DEBUG
-
static void initResources()
{
Q_INIT_RESOURCE(qstyle);
@@ -128,6 +98,15 @@ static void initResources()
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+Q_TRACE_PREFIX(qtwidgets,
+ "#include <qcoreevent.h>"
+);
+Q_TRACE_METADATA(qtwidgets, "ENUM { AUTO, RANGE User ... MaxUser } QEvent::Type;");
+Q_TRACE_POINT(qtwidgets, QApplication_notify_entry, QObject *receiver, QEvent *event, QEvent::Type type);
+Q_TRACE_POINT(qtwidgets, QApplication_notify_exit, bool consumed, bool filtered);
+
// Helper macro for static functions to check on the existence of the application class.
#define CHECK_QAPP_INSTANCE(...) \
if (Q_LIKELY(QCoreApplication::instance())) { \
@@ -143,8 +122,8 @@ QApplicationPrivate *QApplicationPrivate::self = nullptr;
bool QApplicationPrivate::autoSipEnabled = true;
-QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, int flags)
- : QApplicationPrivateBase(argc, argv, flags)
+QApplicationPrivate::QApplicationPrivate(int &argc, char **argv)
+ : QGuiApplicationPrivate(argc, argv)
{
application_type = QApplicationPrivate::Gui;
@@ -331,7 +310,6 @@ QWidget *QApplication::topLevelAt(const QPoint &pos)
*/
void qt_init_tooltip_palette();
-void qt_cleanup();
QStyle *QApplicationPrivate::app_style = nullptr; // default application style
#ifndef QT_NO_STYLE_STYLESHEET
@@ -387,7 +365,7 @@ void QApplicationPrivate::process_cmdline()
styleOverride = QString::fromLocal8Bit(qgetenv("QT_STYLE_OVERRIDE"));
// process platform-indep command line
- if (!qt_is_gui_used || !argc)
+ if (qt_is_tty_app || !argc)
return;
int i, j;
@@ -407,10 +385,10 @@ void QApplicationPrivate::process_cmdline()
// obsolete argument
#ifndef QT_NO_STYLE_STYLESHEET
} else if (strcmp(arg, "-stylesheet") == 0 && i < argc -1) {
- styleSheet = QLatin1String("file:///");
+ styleSheet = "file:///"_L1;
styleSheet.append(QString::fromLocal8Bit(argv[++i]));
} else if (strncmp(arg, "-stylesheet=", 12) == 0) {
- styleSheet = QLatin1String("file:///");
+ styleSheet = "file:///"_L1;
styleSheet.append(QString::fromLocal8Bit(arg + 12));
#endif
} else if (qstrcmp(arg, "-widgetcount") == 0) {
@@ -474,9 +452,9 @@ void QApplicationPrivate::process_cmdline()
#ifdef Q_QDOC
QApplication::QApplication(int &argc, char **argv)
#else
-QApplication::QApplication(int &argc, char **argv, int _internal)
+QApplication::QApplication(int &argc, char **argv, int)
#endif
- : QGuiApplication(*new QApplicationPrivate(argc, argv, _internal))
+ : QGuiApplication(*new QApplicationPrivate(argc, argv))
{
Q_D(QApplication);
d->init();
@@ -495,7 +473,7 @@ void QApplicationPrivate::init()
initResources();
- qt_is_gui_used = (application_type != QApplicationPrivate::Tty);
+ qt_is_tty_app = (application_type == QApplicationPrivate::Tty);
process_cmdline();
// Must be called before initialize()
@@ -507,7 +485,7 @@ void QApplicationPrivate::init()
initialize();
eventDispatcher->startingUp();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
// factory for accessible interfaces for widgets shipped with Qt
QAccessible::installFactory(&qAccessibleFactory);
#endif
@@ -517,8 +495,11 @@ void QApplicationPrivate::init()
void qt_init_tooltip_palette()
{
#if QT_CONFIG(tooltip)
- if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette))
- QToolTip::setPalette(*toolTipPalette);
+ if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette)) {
+ QPalette toolTipPal = *toolTipPalette;
+ toolTipPal.setResolveMask(0);
+ QToolTip::setPalette(toolTipPal);
+ }
#endif
}
@@ -547,7 +528,9 @@ void QApplicationPrivate::initialize()
} else {
qWarning("QApplication: invalid style override '%s' passed, ignoring it.\n"
"\tAvailable styles: %s", qPrintable(styleOverride),
- qPrintable(QStyleFactory::keys().join(QLatin1String(", "))));
+ qPrintable(QStyleFactory::keys().join(", "_L1)));
+ // Clear styleOverride so it is not picked by Qt Quick Controls (QTBUG-100563)
+ styleOverride.clear();
}
}
@@ -558,7 +541,7 @@ void QApplicationPrivate::initialize()
if (qEnvironmentVariableIntValue("QT_USE_NATIVE_WINDOWS") > 0)
QCoreApplication::setAttribute(Qt::AA_NativeWindows);
- if (qt_is_gui_used)
+ if (!qt_is_tty_app)
initializeMultitouch();
if (QGuiApplication::desktopSettingsAware())
@@ -718,13 +701,16 @@ QApplication::~QApplication()
QApplicationPrivate::app_style = nullptr;
#if QT_CONFIG(draganddrop)
- if (qt_is_gui_used)
+ if (!qt_is_tty_app)
delete QDragManager::self();
#endif
d->cleanupMultitouch();
- qt_cleanup();
+ QPixmapCache::clear();
+ QColormap::cleanup();
+
+ QApplicationPrivate::active_window = nullptr; //### this should not be necessary
if (QApplicationPrivate::widgetCount)
qDebug("Widgets left: %i Max widgets: %i \n", QWidgetPrivate::instanceCounter, QWidgetPrivate::maxInstances);
@@ -735,14 +721,6 @@ QApplication::~QApplication()
QApplicationPrivate::widgetCount = false;
}
-void qt_cleanup()
-{
- QPixmapCache::clear();
- QColormap::cleanup();
-
- QApplicationPrivate::active_window = nullptr; //### this should not be necessary
-}
-
/*!
\fn QWidget *QApplication::widgetAt(const QPoint &point)
@@ -804,35 +782,54 @@ QWidget *QApplication::widgetAt(const QPoint &p)
*/
bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
{
- if ((event->type() == QEvent::UpdateRequest
- || event->type() == QEvent::LayoutRequest
- || event->type() == QEvent::Resize
- || event->type() == QEvent::Move
- || event->type() == QEvent::LanguageChange)) {
- for (QPostEventList::const_iterator it = postedEvents->constBegin(); it != postedEvents->constEnd(); ++it) {
- const QPostEvent &cur = *it;
- if (cur.receiver != receiver || cur.event == nullptr || cur.event->type() != event->type())
- continue;
- if (cur.event->type() == QEvent::LayoutRequest
- || cur.event->type() == QEvent::UpdateRequest) {
- ;
- } else if (cur.event->type() == QEvent::Resize) {
- static_cast<QResizeEvent *>(cur.event)->m_size =
- static_cast<const QResizeEvent *>(event)->size();
- } else if (cur.event->type() == QEvent::Move) {
- static_cast<QMoveEvent *>(cur.event)->m_pos =
- static_cast<const QMoveEvent *>(event)->pos();
- } else if (cur.event->type() == QEvent::LanguageChange) {
- ;
- } else {
- continue;
- }
- delete event;
- return true;
+ // Only compress the following events:
+ const QEvent::Type type = event->type();
+ switch (type) {
+ case QEvent::UpdateRequest:
+ case QEvent::UpdateLater:
+ case QEvent::LayoutRequest:
+ case QEvent::Resize:
+ case QEvent::Move:
+ case QEvent::LanguageChange:
+ break;
+ default:
+ return QGuiApplication::compressEvent(event, receiver, postedEvents);
+ }
+
+ for (const auto &postedEvent : std::as_const(*postedEvents)) {
+
+ // Continue, unless a valid event of the same type exists for the same receiver
+ if (postedEvent.receiver != receiver
+ || !postedEvent.event
+ || postedEvent.event->type() != type) {
+ continue;
}
- return false;
+
+ // Handle type specific compression
+ switch (type) {
+ case QEvent::Resize:
+ static_cast<QResizeEvent *>(postedEvent.event)->m_size =
+ static_cast<const QResizeEvent *>(event)->size();
+ break;
+ case QEvent::Move:
+ static_cast<QMoveEvent *>(postedEvent.event)->m_pos =
+ static_cast<const QMoveEvent *>(event)->pos();
+ break;
+ case QEvent::UpdateLater:
+ static_cast<QUpdateLaterEvent *>(postedEvent.event)->m_region +=
+ static_cast<const QUpdateLaterEvent *>(event)->region();
+ break;
+ case QEvent::UpdateRequest:
+ case QEvent::LanguageChange:
+ case QEvent::LayoutRequest:
+ break;
+ default:
+ continue;
+ }
+ delete event;
+ return true;
}
- return QGuiApplication::compressEvent(event, receiver, postedEvents);
+ return false;
}
/*!
@@ -1213,7 +1210,7 @@ void QApplicationPrivate::handlePaletteChanged(const char *className)
}
#if QT_CONFIG(graphicsview)
- for (auto scene : qAsConst(scene_list))
+ for (auto scene : std::as_const(scene_list))
QCoreApplication::sendEvent(scene, &event);
#endif
@@ -1663,7 +1660,8 @@ void QApplication::aboutQt()
bool QApplication::event(QEvent *e)
{
Q_D(QApplication);
- if (e->type() == QEvent::Quit) {
+ switch (e->type()) {
+ case QEvent::Quit:
// FIXME: This logic first tries to close all windows, and then
// checks whether it was successful, but the conditions used in
// closeAllWindows() differ from the verification logic below.
@@ -1683,7 +1681,7 @@ bool QApplication::event(QEvent *e)
// closeAllWindows(). FIXME: Unify all this close magic through closeAllWindows.
return QCoreApplication::event(e);
#ifndef Q_OS_WIN
- } else if (e->type() == QEvent::LocaleChange) {
+ case QEvent::LocaleChange: {
// on Windows the event propagation is taken care by the
// WM_SETTINGCHANGE event handler.
const QWidgetList list = topLevelWidgets();
@@ -1693,8 +1691,10 @@ bool QApplication::event(QEvent *e)
w->d_func()->setLocale_helper(QLocale(), true);
}
}
+ break;
+ }
#endif
- } else if (e->type() == QEvent::Timer) {
+ case QEvent::Timer: {
QTimerEvent *te = static_cast<QTimerEvent*>(e);
Q_ASSERT(te != nullptr);
if (te->timerId() == d->toolTipWakeUp.timerId()) {
@@ -1723,15 +1723,16 @@ bool QApplication::event(QEvent *e)
} else if (te->timerId() == d->toolTipFallAsleep.timerId()) {
d->toolTipFallAsleep.stop();
}
+ break;
+ }
#if QT_CONFIG(whatsthis)
- } else if (e->type() == QEvent::EnterWhatsThisMode) {
+ case QEvent::EnterWhatsThisMode:
QWhatsThis::enterWhatsThisMode();
return true;
#endif
- }
-
- if (e->type() == QEvent::LanguageChange || e->type() == QEvent::ApplicationFontChange ||
- e->type() == QEvent::ApplicationPaletteChange) {
+ case QEvent::LanguageChange:
+ case QEvent::ApplicationFontChange:
+ case QEvent::ApplicationPaletteChange: {
// QGuiApplication::event does not account for the cases where
// there is a top level widget without a window handle. So they
// need to have the event posted here
@@ -1740,6 +1741,10 @@ bool QApplication::event(QEvent *e)
if (!w->windowHandle() && (w->windowType() != Qt::Desktop))
postEvent(w, new QEvent(e->type()));
}
+ break;
+ }
+ default:
+ break;
}
return QGuiApplication::event(e);
@@ -1771,6 +1776,7 @@ void QApplicationPrivate::notifyLayoutDirectionChange()
/*!
\fn void QApplication::setActiveWindow(QWidget* active)
+ \deprecated [6.5] Use QWidget::activateWindow() instead.
Sets the active window to the \a active widget in response to a system
event. The function is called from the platform specific event handlers.
@@ -1787,8 +1793,15 @@ void QApplicationPrivate::notifyLayoutDirectionChange()
\sa activeWindow(), QWidget::activateWindow()
*/
+#if QT_DEPRECATED_SINCE(6,5)
void QApplication::setActiveWindow(QWidget* act)
{
+ QApplicationPrivate::setActiveWindow(act);
+}
+#endif
+
+void QApplicationPrivate::setActiveWindow(QWidget* act)
+{
QWidget* window = act?act->window():nullptr;
if (QApplicationPrivate::active_window == window)
@@ -1805,8 +1818,8 @@ void QApplication::setActiveWindow(QWidget* act)
QWidgetList toBeDeactivated;
if (QApplicationPrivate::active_window) {
- if (style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, QApplicationPrivate::active_window)) {
- const QWidgetList list = topLevelWidgets();
+ if (QApplication::style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, QApplicationPrivate::active_window)) {
+ const QWidgetList list = QApplication::topLevelWidgets();
for (auto *w : list) {
if (w->isVisible() && w->isActiveWindow())
toBeDeactivated.append(w);
@@ -1827,8 +1840,8 @@ void QApplication::setActiveWindow(QWidget* act)
QApplicationPrivate::active_window = window;
if (QApplicationPrivate::active_window) {
- if (style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, QApplicationPrivate::active_window)) {
- const QWidgetList list = topLevelWidgets();
+ if (QApplication::style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, QApplicationPrivate::active_window)) {
+ const QWidgetList list = QApplication::topLevelWidgets();
for (auto *w : list) {
if (w->isVisible() && w->isActiveWindow())
toBeActivated.append(w);
@@ -1846,14 +1859,14 @@ void QApplication::setActiveWindow(QWidget* act)
for (int i = 0; i < toBeActivated.size(); ++i) {
QWidget *w = toBeActivated.at(i);
- sendSpontaneousEvent(w, &windowActivate);
- sendSpontaneousEvent(w, &activationChange);
+ QApplication::sendSpontaneousEvent(w, &windowActivate);
+ QApplication::sendSpontaneousEvent(w, &activationChange);
}
for(int i = 0; i < toBeDeactivated.size(); ++i) {
QWidget *w = toBeDeactivated.at(i);
- sendSpontaneousEvent(w, &windowDeactivate);
- sendSpontaneousEvent(w, &activationChange);
+ QApplication::sendSpontaneousEvent(w, &windowDeactivate);
+ QApplication::sendSpontaneousEvent(w, &activationChange);
}
if (QApplicationPrivate::popupWidgets == nullptr) { // !inPopupMode()
@@ -1908,7 +1921,6 @@ QWidget *qt_tlw_for_window(QWindow *wnd)
void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
{
- Q_UNUSED(previous);
#ifndef Q_OS_MACOS
// Some delayed focus event to ignore, unless we are on cocoa where
// popups can be opened via right-click on inactive applications
@@ -1917,7 +1929,7 @@ void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
#endif
QWindow *focusWindow = QGuiApplicationPrivate::focus_window;
QWidget *focusWidget = qt_tlw_for_window(focusWindow);
- QApplication::setActiveWindow(focusWidget);
+ QApplicationPrivate::setActiveWindow(focusWidget);
// QTBUG-37126, Active X controls may set the focus on native child widgets.
if (focusWindow && focusWidget && focusWindow != focusWidget->windowHandle()) {
if (QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(focusWindow))
@@ -1925,6 +1937,20 @@ void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
if (widget->inherits("QAxHostWidget"))
widget->setFocus(Qt::ActiveWindowFocusReason);
}
+
+ // QApplication::setActiveWindow() will deliver window activation events for
+ // QWidgetWindows. But for other subclasses of QWindow (like QQuickWindow), we
+ // need to send them explicitly, like we do from the base class implementation.
+ if (previous && !qobject_cast<QWidgetWindow *>(previous)) {
+ QEvent de(QEvent::WindowDeactivate);
+ QCoreApplication::sendEvent(previous, &de);
+ }
+
+ if (focusWindow && !qobject_cast<QWidgetWindow *>(focusWindow)) {
+ QEvent ae(QEvent::WindowActivate);
+ QCoreApplication::sendEvent(focusWindow, &ae);
+ }
+
// don't call base class to avoid double delivery of WindowActivate/Deactivate events
}
@@ -1943,7 +1969,7 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool
f = toplevel;
QWidget *w = f;
- QWidget *test = f->d_func()->focus_next;
+ QWidget *test = f->nextInFocusChain();
bool seenWindow = false;
bool focusWidgetAfterWindow = false;
while (test && test != f) {
@@ -1974,7 +2000,7 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool
if (next)
break;
}
- test = test->d_func()->focus_next;
+ test = test->nextInFocusChain();
}
if (wrappingOccurred != nullptr)
@@ -1999,24 +2025,9 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool
*/
void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF)
{
-#if 0
- if (leave) {
- QEvent e(QEvent::Leave);
- QCoreApplication::sendEvent(leave, & e);
- }
- if (enter) {
- const QPoint windowPos = enter->window()->mapFromGlobal(globalPos);
- QEnterEvent e(enter->mapFromGlobal(globalPos), windowPos, globalPos);
- QCoreApplication::sendEvent(enter, & e);
- }
- return;
-#endif
-
if ((!enter && !leave) || (enter == leave))
return;
-#ifdef ALIEN_DEBUG
- qDebug() << "QApplicationPrivate::dispatchEnterLeave, ENTER:" << enter << "LEAVE:" << leave;
-#endif
+
QWidgetList leaveList;
QWidgetList enterList;
@@ -2072,7 +2083,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con
if (w->testAttribute(Qt::WA_Hover) &&
(!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
Q_ASSERT(instance());
- QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1), w->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos),
+ QHoverEvent he(QEvent::HoverLeave, QPointF(-1, -1), globalPosF, w->mapFromGlobal(globalPosF),
QGuiApplication::keyboardModifiers());
qApp->d_func()->notify_helper(w, &he);
}
@@ -2080,20 +2091,21 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con
}
if (!enterList.isEmpty()) {
// Guard against QGuiApplicationPrivate::lastCursorPosition initialized to qInf(), qInf().
- const QPoint globalPos = qIsInf(globalPosF.x())
- ? QPoint(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)
- : globalPosF.toPoint();
- const QPoint windowPos = qAsConst(enterList).back()->window()->mapFromGlobal(globalPos);
+ const QPointF globalPos = qIsInf(globalPosF.x())
+ ? QPointF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)
+ : globalPosF;
+ const QPointF windowPos = std::as_const(enterList).back()->window()->mapFromGlobal(globalPos);
for (auto it = enterList.crbegin(), end = enterList.crend(); it != end; ++it) {
auto *w = *it;
if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, nullptr)) {
const QPointF localPos = w->mapFromGlobal(globalPos);
- QEnterEvent enterEvent(localPos, windowPos, globalPosF);
+ QEnterEvent enterEvent(localPos, windowPos, globalPos);
QCoreApplication::sendEvent(w, &enterEvent);
if (w->testAttribute(Qt::WA_Hover) &&
(!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
- QHoverEvent he(QEvent::HoverEnter, localPos, QPoint(-1, -1),
+ QHoverEvent he(QEvent::HoverEnter, windowPos, QPointF(-1, -1), globalPos,
QGuiApplication::keyboardModifiers());
+ QMutableEventPoint::setPosition(he.point(0), localPos);
qApp->d_func()->notify_helper(w, &he);
}
}
@@ -2170,80 +2182,16 @@ bool QApplicationPrivate::isBlockedByModal(QWidget *widget)
return window && self->isWindowBlocked(window);
}
-bool QApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blockingWindow) const
+Qt::WindowModality QApplicationPrivate::defaultModality() const
{
- QWindow *unused = nullptr;
- if (Q_UNLIKELY(!window)) {
- qWarning().nospace() << "window == 0 passed.";
- return false;
- }
- if (!blockingWindow)
- blockingWindow = &unused;
+ return Qt::ApplicationModal;
+}
- if (modalWindowList.isEmpty()) {
- *blockingWindow = nullptr;
- return false;
- }
+bool QApplicationPrivate::windowNeverBlocked(QWindow *window) const
+{
QWidget *popupWidget = QApplication::activePopupWidget();
QWindow *popupWindow = popupWidget ? popupWidget->windowHandle() : nullptr;
- if (popupWindow == window || (!popupWindow && QWindowPrivate::get(window)->isPopup())) {
- *blockingWindow = nullptr;
- return false;
- }
-
- for (int i = 0; i < modalWindowList.count(); ++i) {
- QWindow *modalWindow = modalWindowList.at(i);
-
- // A window is not blocked by another modal window if the two are
- // the same, or if the window is a child of the modal window.
- if (window == modalWindow || modalWindow->isAncestorOf(window, QWindow::IncludeTransients)) {
- *blockingWindow = nullptr;
- return false;
- }
-
- Qt::WindowModality windowModality = modalWindow->modality();
- if (windowModality == Qt::NonModal) {
- // If modality type hasn't been set on the modalWindow's widget, as
- // when waiting for a native dialog, use ApplicationModal.
- windowModality = Qt::ApplicationModal;
- }
-
- switch (windowModality) {
- case Qt::ApplicationModal:
- if (modalWindow != window) {
- *blockingWindow = modalWindow;
- return true;
- }
- break;
- case Qt::WindowModal:
- {
- QWindow *w = window;
- do {
- QWindow *m = modalWindow;
- do {
- if (m == w) {
- *blockingWindow = m;
- return true;
- }
- QWindow *p = m->parent();
- if (!p)
- p = m->transientParent();
- m = p;
- } while (m);
- QWindow *p = w->parent();
- if (!p)
- p = w->transientParent();
- w = p;
- } while (w);
- break;
- }
- default:
- Q_ASSERT_X(false, "QApplication", "internal error, a modal window cannot be modeless");
- break;
- }
- }
- *blockingWindow = nullptr;
- return false;
+ return popupWindow == window || (!popupWindow && QWindowPrivate::get(window)->isPopup());
}
/*!\internal
@@ -2323,9 +2271,6 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint
if (mouseGrabber && mouseGrabber != candidate) {
receiver = mouseGrabber;
*pos = receiver->mapFromGlobal(candidate->mapToGlobal(windowPos));
-#ifdef ALIEN_DEBUG
- qDebug() << " ** receiver adjusted to:" << receiver << "pos:" << pos;
-#endif
}
return receiver;
@@ -2389,13 +2334,6 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
}
}
-#ifdef ALIEN_DEBUG
- qDebug() << "QApplicationPrivate::sendMouseEvent: receiver:" << receiver
- << "pos:" << event->position() << "alien" << alienWidget << "button down"
- << *buttonDown << "last" << lastMouseReceiver << "leave after release"
- << leaveAfterRelease;
-#endif
-
// We need this quard in case someone opens a modal dialog / popup. If that's the case
// leaveAfterRelease is set to null, but we shall not update lastMouseReceiver.
const bool wasLeaveAfterRelease = leaveAfterRelease != nullptr;
@@ -2536,7 +2474,7 @@ void QApplication::setStartDragTime(int ms)
The default value is 500 ms.
- \sa startDragDistance(), {Drag and Drop}
+ \sa startDragDistance(), {Drag and Drop in Qt}{Drag and Drop}
*/
int QApplication::startDragTime()
@@ -2575,7 +2513,7 @@ void QApplication::setStartDragDistance(int l)
The default value (if the platform doesn't provide a different default)
is 10 pixels.
- \sa startDragTime(), QPoint::manhattanLength(), {Drag and Drop}
+ \sa startDragTime(), QPoint::manhattanLength(), {Drag and Drop in Qt}{Drag and Drop}
*/
int QApplication::startDragDistance()
@@ -2597,8 +2535,9 @@ int QApplication::startDragDistance()
exec(), because modal widgets call exec() to start a local event loop.
To make your application perform idle processing, i.e., executing a special
- function whenever there are no pending events, use a QTimer with 0 timeout.
- More advanced idle processing schemes can be achieved using processEvents().
+ function whenever there are no pending events, use a QChronoTimer with 0ns
+ timeout. More advanced idle processing schemes can be achieved using
+ processEvents().
We recommend that you connect clean-up code to the
\l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in your
@@ -2707,6 +2646,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
Q_FALLTHROUGH();
case QEvent::Leave:
d->toolTipWakeUp.stop();
+ break;
default:
break;
}
@@ -2731,6 +2671,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
|| key == Qt::Key_Up
|| key == Qt::Key_Right
|| key == Qt::Key_Down);
+ break;
}
default:
break;
@@ -2842,11 +2783,12 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
w = static_cast<QWidget *>(receiver);
relpos = mouse->position().toPoint();
- QPoint diff = relpos - w->mapFromGlobal(d->hoverGlobalPos);
+ QPoint diff = relpos - w->mapFromGlobal(mouse->globalPosition().toPoint());
while (w) {
if (w->testAttribute(Qt::WA_Hover) &&
(!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
- QHoverEvent he(QEvent::HoverMove, relpos, relpos - diff, mouse->modifiers());
+ QHoverEvent he(QEvent::HoverMove, mouse->scenePosition(), mouse->globalPosition(), relpos - diff, mouse->modifiers());
+ QMutableEventPoint::setPosition(he.point(0), relpos);
d->notify_helper(w, &he);
}
if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
@@ -2947,7 +2889,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
break;
- QMutableSinglePointEvent::from(we).mutablePoint().setPosition(we.position() + w->pos());
+ QMutableEventPoint::setPosition(we.point(0), we.position() + w->pos());
w = w->parentWidget();
} while (w);
wheel->setAccepted(eventAccepted);
@@ -2991,6 +2933,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
tablet->tangentialPressure(), tablet->rotation(), tablet->z(),
tablet->modifiers(), tablet->button(), tablet->buttons());
te.m_spont = e->spontaneous();
+ te.setTimestamp(tablet->timestamp());
te.setAccepted(false);
res = d->notify_helper(w, w == receiver ? tablet : &te);
eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted();
@@ -3086,8 +3029,16 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
#endif
w = qobject_cast<QWidget *>(QDragManager::self()->currentTarget());
- if (!w)
- break;
+ if (!w) {
+ // The widget that received DragEnter didn't accept the event, so we have no
+ // current drag target in the QDragManager. But DragLeave still needs to be
+ // dispatched so that enter/leave events are in balance (and so that UnderMouse
+ // gets cleared).
+ if (e->type() == QEvent::DragLeave)
+ w = static_cast<QWidget *>(receiver);
+ else
+ break;
+ }
if (e->type() == QEvent::DragMove || e->type() == QEvent::Drop) {
QDropEvent *dragEvent = static_cast<QDropEvent *>(e);
QWidget *origReceiver = static_cast<QWidget *>(receiver);
@@ -3104,15 +3055,16 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
)
QDragManager::self()->setCurrentTarget(nullptr, e->type() == QEvent::Drop);
break;
-#endif
}
+#endif // QT_CONFIG(draganddrop)
case QEvent::TouchBegin: {
// Note: TouchUpdate and TouchEnd events are never propagated
QMutableTouchEvent *touchEvent = QMutableTouchEvent::from(static_cast<QTouchEvent *>(e));
bool eventAccepted = touchEvent->isAccepted();
bool acceptTouchEvents = w->testAttribute(Qt::WA_AcceptTouchEvents);
- if (acceptTouchEvents && e->spontaneous()) {
+ if (acceptTouchEvents && e->spontaneous()
+ && touchEvent->device()->type() != QInputDevice::DeviceType::TouchPad) {
const QPoint localPos = touchEvent->points()[0].position().toPoint();
QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, localPos);
}
@@ -3152,15 +3104,16 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
w = w->parentWidget();
touchEvent->setTarget(w);
for (int i = 0; i < touchEvent->pointCount(); ++i) {
- auto &pt = QMutableEventPoint::from(touchEvent->point(i));
- pt.setPosition(pt.position() + offset);
+ auto &pt = touchEvent->point(i);
+ QMutableEventPoint::setPosition(pt, pt.position() + offset);
}
}
#ifndef QT_NO_GESTURES
if (!eventAccepted && !gesturePendingWidget.isNull()) {
- // the first widget subscribed to a gesture gets an implicit grab
- d->activateImplicitTouchGrab(gesturePendingWidget, touchEvent);
+ // the first widget subscribed to a gesture gets an implicit grab for all
+ // points, also for events and event points that have not been accepted.
+ d->activateImplicitTouchGrab(gesturePendingWidget, touchEvent, QApplicationPrivate::GrabAllPoints);
}
#endif
@@ -3250,7 +3203,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
break;
w = w->parentWidget();
}
- for (QGesture *g : qAsConst(allGestures))
+ for (QGesture *g : std::as_const(allGestures))
gestureEvent->setAccepted(g, false);
gestureEvent->m_accept = false; // to make sure we check individual gestures
break;
@@ -3401,7 +3354,7 @@ void QApplicationPrivate::closePopup(QWidget *popup)
qt_popup_down = nullptr;
}
- if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup
+ if (QApplicationPrivate::popupWidgets->size() == 0) { // this was the last popup
delete QApplicationPrivate::popupWidgets;
QApplicationPrivate::popupWidgets = nullptr;
qt_popup_down_closed = false;
@@ -3446,7 +3399,7 @@ void QApplicationPrivate::closePopup(QWidget *popup)
// can become nullptr due to setFocus() above
if (QApplicationPrivate::popupWidgets &&
- QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
+ QApplicationPrivate::popupWidgets->size() == 1) // grab mouse/keyboard
grabForPopup(aw);
}
@@ -3461,7 +3414,7 @@ void QApplicationPrivate::openPopup(QWidget *popup)
popupWidgets = new QWidgetList;
popupWidgets->append(popup); // add to end of list
- if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
+ if (QApplicationPrivate::popupWidgets->size() == 1) // grab mouse/keyboard
grabForPopup(popup);
// popups are not focus-handled by the window system (the first
@@ -3469,7 +3422,7 @@ void QApplicationPrivate::openPopup(QWidget *popup)
// new popup gets the focus
if (popup->focusWidget()) {
popup->focusWidget()->setFocus(Qt::PopupFocusReason);
- } else if (popupWidgets->count() == 1) { // this was the first popup
+ } else if (popupWidgets->size() == 1) { // this was the first popup
if (QWidget *fw = QApplication::focusWidget()) {
QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
QCoreApplication::sendEvent(fw, &e);
@@ -3801,8 +3754,8 @@ bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven
bool containsPress = false;
for (int i = 0; i < touchEvent->pointCount(); ++i) {
- auto &pt = QMutableEventPoint::from(touchEvent->point(i));
- pt.setPosition(widget->mapFromGlobal(pt.globalPosition()));
+ auto &pt = touchEvent->point(i);
+ QMutableEventPoint::setPosition(pt, widget->mapFromGlobal(pt.globalPosition()));
if (pt.state() == QEventPoint::State::Pressed)
containsPress = true;
@@ -3844,24 +3797,26 @@ QWidget *QApplicationPrivate::findClosestTouchPointTarget(const QPointingDevice
if (closestTouchPointId == -1 || distance < closestDistance) {
closestTouchPointId = pt.id();
closestDistance = distance;
- closestTarget = static_cast<const QMutableEventPoint &>(pt).target();
+ closestTarget = QMutableEventPoint::target(pt);
}
}
}
return static_cast<QWidget *>(closestTarget);
}
-void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchEvent)
+void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchEvent,
+ ImplicitTouchGrabMode grabMode)
{
if (touchEvent->type() != QEvent::TouchBegin)
return;
// If the widget dispatched the event further (see QGraphicsProxyWidget), then
- // there might already be an implicit grabber. Don't override that.
+ // there might already be an implicit grabber. Don't override that. A widget that
+ // has partially recognized a gesture needs to grab all points.
for (int i = 0; i < touchEvent->pointCount(); ++i) {
- auto &mep = QMutableEventPoint::from(touchEvent->point(i));
- if (!mep.target() && mep.isAccepted())
- mep.setTarget(widget);
+ auto &ep = touchEvent->point(i);
+ if (!QMutableEventPoint::target(ep) && (ep.isAccepted() || grabMode == GrabAllPoints))
+ QMutableEventPoint::setTarget(ep, widget);
}
// TODO setExclusiveGrabber() to be consistent with Qt Quick?
}
@@ -3910,9 +3865,9 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, const QTouchEv
// on touch pads, implicitly grab all touch points
// on touch screens, grab touch points that are redirected to the closest widget
if (device->type() == QInputDevice::DeviceType::TouchPad || usingClosestWidget)
- QMutableEventPoint::from(touchPoint).setTarget(target);
+ QMutableEventPoint::setTarget(touchPoint, target);
} else {
- target = QMutableEventPoint::from(touchPoint).target();
+ target = QMutableEventPoint::target(touchPoint);
if (!target)
continue;
}
@@ -4013,7 +3968,7 @@ void QApplicationPrivate::translateTouchCancel(const QPointingDevice *device, ul
const QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(device);
for (auto &epd : devPriv->activePoints.values()) {
const auto &pt = epd.eventPoint;
- QObject *target = static_cast<const QMutableEventPoint &>(pt).target();
+ QObject *target = QMutableEventPoint::target(pt);
if (target && target->isWidgetType())
widgetsNeedingCancel.insert(static_cast<QWidget *>(target));
}
@@ -4025,9 +3980,9 @@ void QApplicationPrivate::translateTouchCancel(const QPointingDevice *device, ul
}
}
-void QApplicationPrivate::notifyThemeChanged()
+void QApplicationPrivate::handleThemeChanged()
{
- QGuiApplicationPrivate::notifyThemeChanged();
+ QGuiApplicationPrivate::handleThemeChanged();
qt_init_tooltip_palette();
}
diff --git a/src/widgets/kernel/qapplication.h b/src/widgets/kernel/qapplication.h
index 97e07bd17a..fd698fb69f 100644
--- a/src/widgets/kernel/qapplication.h
+++ b/src/widgets/kernel/qapplication.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QAPPLICATION_H
#define QAPPLICATION_H
@@ -114,7 +78,11 @@ public:
static QWidget *focusWidget();
static QWidget *activeWindow();
+
+#if QT_DEPRECATED_SINCE(6, 5)
+ QT_DEPRECATED_VERSION_X_6_5("Use QWidget::activateWindow() instead.")
static void setActiveWindow(QWidget* act);
+#endif
static QWidget *widgetAt(const QPoint &p);
static inline QWidget *widgetAt(int x, int y) { return widgetAt(QPoint(x, y)); }
@@ -161,12 +129,12 @@ Q_SIGNALS:
public:
QString styleSheet() const;
+ bool autoSipEnabled() const;
public Q_SLOTS:
#ifndef QT_NO_STYLE_STYLESHEET
void setStyleSheet(const QString& sheet);
#endif
void setAutoSipEnabled(const bool enabled);
- bool autoSipEnabled() const;
static void closeAllWindows();
static void aboutQt();
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 6bb1f35d1b..21b1605dfc 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QAPPLICATION_P_H
#define QAPPLICATION_P_H
@@ -86,7 +50,7 @@ class QPointingDevice;
class QGestureManager;
#endif
-extern Q_GUI_EXPORT bool qt_is_gui_used;
+extern Q_GUI_EXPORT bool qt_is_tty_app;
#ifndef QT_NO_CLIPBOARD
extern QClipboard *qt_clipboard;
#endif
@@ -94,13 +58,11 @@ extern QClipboard *qt_clipboard;
typedef QHash<QByteArray, QFont> FontHash;
Q_WIDGETS_EXPORT FontHash *qt_app_fonts_hash();
-#define QApplicationPrivateBase QGuiApplicationPrivate
-
-class Q_WIDGETS_EXPORT QApplicationPrivate : public QApplicationPrivateBase
+class Q_WIDGETS_EXPORT QApplicationPrivate : public QGuiApplicationPrivate
{
Q_DECLARE_PUBLIC(QApplication)
public:
- QApplicationPrivate(int &argc, char **argv, int flags);
+ QApplicationPrivate(int &argc, char **argv);
~QApplicationPrivate();
virtual void notifyLayoutDirectionChange() override;
@@ -122,7 +84,8 @@ public:
#endif
//modality
- bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = nullptr) const override;
+ Qt::WindowModality defaultModality() const override;
+ bool windowNeverBlocked(QWindow *window) const override;
static bool isBlockedByModal(QWidget *widget);
static bool modalState();
static bool tryModalHelper(QWidget *widget, QWidget **rettop = nullptr);
@@ -141,6 +104,8 @@ public:
void initialize();
void process_cmdline();
+ static void setActiveWindow(QWidget* act);
+
static bool inPopupMode();
bool popupActive() override { return inPopupMode(); }
bool closeAllPopups() override;
@@ -165,7 +130,7 @@ public:
static QStyle *app_style;
protected:
- void notifyThemeChanged() override;
+ void handleThemeChanged() override;
QPalette basePalette() const override;
void handlePaletteChanged(const char *className = nullptr) override;
@@ -180,9 +145,7 @@ public:
static QWidget *main_widget;
static QWidget *focus_widget;
static QWidget *hidden_focus_widget;
- static QWidget *active_window;
#if QT_CONFIG(wheelevent)
- static int wheel_scroll_lines;
static QPointer<QWidget> wheel_widget;
#endif
@@ -248,7 +211,9 @@ public:
QWidget *findClosestTouchPointTarget(const QPointingDevice *device, const QEventPoint &touchPoint);
void appendTouchPoint(const QEventPoint &touchPoint);
void removeTouchPoint(int touchPointId);
- void activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchBeginEvent);
+ enum ImplicitTouchGrabMode { GrabAcceptedPoints, GrabAllPoints };
+ void activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchBeginEvent,
+ ImplicitTouchGrabMode grabMode = GrabAcceptedPoints);
static bool translateRawTouchEvent(QWidget *widget, const QTouchEvent *touchEvent);
static void translateTouchCancel(const QPointingDevice *device, ulong timestamp);
@@ -261,6 +226,7 @@ private:
static void giveFocusAccordingToFocusPolicy(QWidget *w, QEvent *event, QPoint localPos);
static bool shouldSetFocus(QWidget *w, Qt::FocusPolicy policy);
+ static QWidget *active_window;
static bool isAlien(QWidget *);
};
diff --git a/src/widgets/kernel/qboxlayout.cpp b/src/widgets/kernel/qboxlayout.cpp
index 28e7302b83..501883e85a 100644
--- a/src/widgets/kernel/qboxlayout.cpp
+++ b/src/widgets/kernel/qboxlayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qapplication.h"
#include "qboxlayout.h"
@@ -124,6 +88,7 @@ public:
void effectiveMargins(int *left, int *top, int *right, int *bottom) const;
QLayoutItem* replaceAt(int index, QLayoutItem*) override;
+ int validateIndex(int index) const;
};
QBoxLayoutPrivate::~QBoxLayoutPrivate()
@@ -268,7 +233,7 @@ void QBoxLayoutPrivate::setupGeom()
hasHfw = false;
- int n = list.count();
+ int n = list.size();
geomArray.clear();
QList<QLayoutStruct> a(n);
@@ -400,7 +365,7 @@ void QBoxLayoutPrivate::setupGeom()
void QBoxLayoutPrivate::calcHfw(int w)
{
QList<QLayoutStruct> &a = geomArray;
- int n = a.count();
+ int n = a.size();
int h = 0;
int mh = 0;
@@ -443,6 +408,14 @@ QLayoutItem* QBoxLayoutPrivate::replaceAt(int index, QLayoutItem *item)
return r;
}
+int QBoxLayoutPrivate::validateIndex(int index) const
+{
+ if (index < 0)
+ return list.size(); // append
+
+ Q_ASSERT_X(index >= 0 && index <= list.size(), "QBoxLayout::insert", "index out of range");
+ return index;
+}
/*!
\class QBoxLayout
@@ -707,7 +680,7 @@ void QBoxLayout::invalidate()
int QBoxLayout::count() const
{
Q_D(const QBoxLayout);
- return d->list.count();
+ return d->list.size();
}
/*!
@@ -716,7 +689,7 @@ int QBoxLayout::count() const
QLayoutItem *QBoxLayout::itemAt(int index) const
{
Q_D(const QBoxLayout);
- return index >= 0 && index < d->list.count() ? d->list.at(index)->item : nullptr;
+ return index >= 0 && index < d->list.size() ? d->list.at(index)->item : nullptr;
}
/*!
@@ -725,7 +698,7 @@ QLayoutItem *QBoxLayout::itemAt(int index) const
QLayoutItem *QBoxLayout::takeAt(int index)
{
Q_D(QBoxLayout);
- if (index < 0 || index >= d->list.count())
+ if (index < 0 || index >= d->list.size())
return nullptr;
QBoxLayoutItem *b = d->list.takeAt(index);
QLayoutItem *item = b->item;
@@ -776,7 +749,7 @@ void QBoxLayout::setGeometry(const QRect &r)
QList<QLayoutStruct> a = d->geomArray;
int pos = horz(d->dir) ? s.x() : s.y();
int space = horz(d->dir) ? s.width() : s.height();
- int n = a.count();
+ int n = a.size();
if (d->hasHfw && !horz(d->dir)) {
for (int i = 0; i < n; i++) {
QBoxLayoutItem *box = d->list.at(i);
@@ -847,9 +820,7 @@ void QBoxLayout::addItem(QLayoutItem *item)
void QBoxLayout::insertItem(int index, QLayoutItem *item)
{
Q_D(QBoxLayout);
- if (index < 0) // append
- index = d->list.count();
-
+ index = d->validateIndex(index);
QBoxLayoutItem *it = new QBoxLayoutItem(item);
d->list.insert(index, it);
invalidate();
@@ -867,9 +838,7 @@ void QBoxLayout::insertItem(int index, QLayoutItem *item)
void QBoxLayout::insertSpacing(int index, int size)
{
Q_D(QBoxLayout);
- if (index < 0) // append
- index = d->list.count();
-
+ index = d->validateIndex(index);
QLayoutItem *b;
if (horz(d->dir))
b = QLayoutPrivate::createSpacerItem(this, size, 0, QSizePolicy::Fixed, QSizePolicy::Minimum);
@@ -892,9 +861,7 @@ void QBoxLayout::insertSpacing(int index, int size)
void QBoxLayout::insertStretch(int index, int stretch)
{
Q_D(QBoxLayout);
- if (index < 0) // append
- index = d->list.count();
-
+ index = d->validateIndex(index);
QLayoutItem *b;
if (horz(d->dir))
b = QLayoutPrivate::createSpacerItem(this, 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
@@ -919,9 +886,7 @@ void QBoxLayout::insertStretch(int index, int stretch)
void QBoxLayout::insertSpacerItem(int index, QSpacerItem *spacerItem)
{
Q_D(QBoxLayout);
- if (index < 0) // append
- index = d->list.count();
-
+ index = d->validateIndex(index);
QBoxLayoutItem *it = new QBoxLayoutItem(spacerItem);
it->magic = true;
d->list.insert(index, it);
@@ -943,8 +908,7 @@ void QBoxLayout::insertLayout(int index, QLayout *layout, int stretch)
return;
if (!adoptLayout(layout))
return;
- if (index < 0) // append
- index = d->list.count();
+ index = d->validateIndex(index);
QBoxLayoutItem *it = new QBoxLayoutItem(layout, stretch);
d->list.insert(index, it);
invalidate();
@@ -977,8 +941,7 @@ void QBoxLayout::insertWidget(int index, QWidget *widget, int stretch,
if (!d->checkWidget(widget))
return;
addChildWidget(widget);
- if (index < 0) // append
- index = d->list.count();
+ index = d->validateIndex(index);
QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget);
b->setAlignment(alignment);
diff --git a/src/widgets/kernel/qboxlayout.h b/src/widgets/kernel/qboxlayout.h
index ab0b2267f0..a1adb2809b 100644
--- a/src/widgets/kernel/qboxlayout.h
+++ b/src/widgets/kernel/qboxlayout.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBOXLAYOUT_H
#define QBOXLAYOUT_H
diff --git a/src/widgets/kernel/qformlayout.cpp b/src/widgets/kernel/qformlayout.cpp
index 8c3d3448ca..01097b6123 100644
--- a/src/widgets/kernel/qformlayout.cpp
+++ b/src/widgets/kernel/qformlayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qapplication.h"
#include "qdebug.h"
@@ -49,7 +13,7 @@
QT_BEGIN_NAMESPACE
-namespace {
+namespace QtPrivate {
// Fixed column matrix, stores items as [i11, i12, i21, i22...],
// with FORTRAN-style index operator(r, c).
template <class T, int NumColumns>
@@ -104,13 +68,11 @@ void FixedColumnMatrix<T, NumColumns>::storageIndexToPosition(int idx, int *rowP
const uint DefaultFieldGrowthPolicy = 255;
const uint DefaultRowWrapPolicy = 255;
-enum { ColumnCount = 2 };
-
// -- our data structure for our items
// This owns the QLayoutItem
struct QFormLayoutItem
{
- QFormLayoutItem(QLayoutItem* i) : item(i), fullRow(false), isHfw(false) { }
+ QFormLayoutItem(QLayoutItem* i) : item(i) { }
~QFormLayoutItem() { delete item; }
// Wrappers
@@ -127,37 +89,68 @@ struct QFormLayoutItem
void setGeometry(const QRect& r) { item->setGeometry(r); }
QRect geometry() const { return item->geometry(); }
+ void setVisible(bool on);
+ bool isHidden() const { return !isVisible || (widget() && widget()->isHidden()); }
+
// For use with FixedColumnMatrix
bool operator==(const QFormLayoutItem& other) { return item == other.item; }
- QLayoutItem *item;
- bool fullRow;
+ QLayoutItem *item = nullptr;
+ bool fullRow = false;
+ bool isVisible = true;
// set by updateSizes
- bool isHfw;
+ bool isHfw = false;
QSize minSize;
QSize sizeHint;
QSize maxSize;
// also set by updateSizes
- int sbsHSpace; // only used for side by side, for the field item only (not label)
- int vSpace; // This is the spacing to the item in the row above
+ int sbsHSpace = -1; // only used for side by side, for the field item only (not label)
+ int vSpace = -1; // This is the spacing to the item in the row above
// set by setupVerticalLayoutData
- bool sideBySide;
- int vLayoutIndex;
+ bool sideBySide = false;
+ int vLayoutIndex = -1;
// set by setupHorizontalLayoutData
- int layoutPos;
- int layoutWidth;
+ int layoutPos = -1;
+ int layoutWidth = -1;
};
+static void hideOrShowWidgetsInLayout(QLayout *layout, bool on)
+{
+ for (int i = 0; i < layout->count(); ++i) {
+ QLayoutItem *item = layout->itemAt(i);
+ if (QWidget *widget = item->widget())
+ widget->setVisible(on);
+ else if (item->layout())
+ hideOrShowWidgetsInLayout(item->layout(), on);
+ }
+}
+
+void QFormLayoutItem::setVisible(bool on)
+{
+ isVisible = on;
+ // Explicitly hide the widget so that it loses focus and
+ // doesn't automatically get shown again when this layout
+ // hides and shows.
+ if (widget()) {
+ widget()->setVisible(on);
+ return;
+ }
+ // Layouts can't be hidden, so we have to traverse the widgets
+ // inside and hide all of them so that they also lose focus.
+ if (layout())
+ hideOrShowWidgetsInLayout(layout(), on);
+}
+
class QFormLayoutPrivate : public QLayoutPrivate
{
Q_DECLARE_PUBLIC(QFormLayout)
public:
- typedef FixedColumnMatrix<QFormLayoutItem *, ColumnCount> ItemMatrix;
+ using ItemMatrix = QtPrivate::FixedColumnMatrix<QFormLayoutItem *, 2>;
QFormLayoutPrivate();
~QFormLayoutPrivate() { }
@@ -378,23 +371,25 @@ void QFormLayoutPrivate::updateSizes()
QSizePolicy::ControlTypes(fldtop ? fldtop->controlTypes() : QSizePolicy::DefaultType);
// To be compatible to QGridLayout, we have to compare solitary labels & fields with both predecessors
- if (label) {
+ if (label && !label->isHidden()) {
if (!field) {
int lblspacing = style->combinedLayoutSpacing(lbltoptypes, lbltypes, Qt::Vertical, nullptr, parent);
int fldspacing = style->combinedLayoutSpacing(fldtoptypes, lbltypes, Qt::Vertical, nullptr, parent);
label->vSpace = qMax(lblspacing, fldspacing);
- } else
+ } else {
label->vSpace = style->combinedLayoutSpacing(lbltoptypes, lbltypes, Qt::Vertical, nullptr, parent);
+ }
}
- if (field) {
+ if (field && !field->isHidden()) {
// check spacing against both the previous label and field
if (!label) {
int lblspacing = style->combinedLayoutSpacing(lbltoptypes, fldtypes, Qt::Vertical, nullptr, parent);
int fldspacing = style->combinedLayoutSpacing(fldtoptypes, fldtypes, Qt::Vertical, nullptr, parent);
field->vSpace = qMax(lblspacing, fldspacing);
- } else
+ } else {
field->vSpace = style->combinedLayoutSpacing(fldtoptypes, fldtypes, Qt::Vertical, nullptr, parent);
+ }
}
}
}
@@ -483,6 +478,7 @@ void QFormLayoutPrivate::recalcHFW(int w)
void QFormLayoutPrivate::setupHfwLayoutData()
{
+ Q_Q(QFormLayout);
// setupVerticalLayoutData must be called before this
// setupHorizontalLayoutData must also be called before this
// copies non hfw data into hfw
@@ -507,7 +503,11 @@ void QFormLayoutPrivate::setupHfwLayoutData()
QFormLayoutItem *label = m_matrix(i, 0);
QFormLayoutItem *field = m_matrix(i, 1);
- if (label) {
+ // ignore rows with only hidden items
+ if (!q->isRowVisible(i))
+ continue;
+
+ if (label && label->vLayoutIndex > -1) {
if (label->isHfw) {
// We don't check sideBySide here, since a label is only
// ever side by side with its field
@@ -522,7 +522,7 @@ void QFormLayoutPrivate::setupHfwLayoutData()
}
}
- if (field) {
+ if (field && field->vLayoutIndex > -1) {
int hfw = field->isHfw ? field->heightForWidth(field->layoutWidth) : 0;
int h = field->isHfw ? hfw : field->sizeHint.height();
int mh = field->isHfw ? hfw : field->minSize.height();
@@ -681,12 +681,18 @@ void QFormLayoutPrivate::setupVerticalLayoutData(int width)
bool prevRowSplit = false;
for (int i = 0; i < rr; ++i) {
- QFormLayoutItem *label = m_matrix(i, 0);
+ QFormLayoutItem *label = m_matrix(i, 0);
QFormLayoutItem *field = m_matrix(i, 1);
- // Totally ignore empty rows...
- if (!label && !field)
+ // Ignore empty rows or rows with only hidden items,
+ // and invalidate their position in the layout.
+ if (!q->isRowVisible(i)) {
+ if (label)
+ label->vLayoutIndex = -1;
+ if (field)
+ field->vLayoutIndex = -1;
continue;
+ }
QSize min1;
QSize min2;
@@ -1646,7 +1652,7 @@ void QFormLayout::addItem(QLayoutItem *item)
int QFormLayout::count() const
{
Q_D(const QFormLayout);
- return d->m_things.count();
+ return d->m_things.size();
}
/*!
@@ -2193,7 +2199,10 @@ void QFormLayoutPrivate::arrangeWidgets(const QList<QLayoutStruct> &layouts, QRe
QFormLayoutItem *label = m_matrix(i, 0);
QFormLayoutItem *field = m_matrix(i, 1);
- if (label) {
+ if (!q->isRowVisible(i))
+ continue;
+
+ if (label && label->vLayoutIndex > -1) {
int height = layouts.at(label->vLayoutIndex).size;
if ((label->expandingDirections() & Qt::Vertical) == 0) {
/*
@@ -2220,7 +2229,7 @@ void QFormLayoutPrivate::arrangeWidgets(const QList<QLayoutStruct> &layouts, QRe
label->setGeometry(QStyle::visualRect(layoutDirection, rect, QRect(p, sz)));
}
- if (field) {
+ if (field && field->vLayoutIndex > -1) {
QSize sz(field->layoutWidth, layouts.at(field->vLayoutIndex).size);
QPoint p(field->layoutPos + leftOffset + rect.x(), layouts.at(field->vLayoutIndex).pos);
/*
@@ -2300,6 +2309,158 @@ void QFormLayout::setItem(int row, ItemRole role, QLayoutItem *item)
}
/*!
+ \since 6.4
+
+ Shows the row \a row if \a on is true, otherwise hides the row.
+
+ \a row must be non-negative and less than rowCount().
+
+ \sa removeRow(), takeRow()
+*/
+void QFormLayout::setRowVisible(int row, bool on)
+{
+ Q_D(QFormLayout);
+ QFormLayoutItem *label = d->m_matrix(row, 0);
+ QFormLayoutItem *field = d->m_matrix(row, 1);
+ bool change = false;
+ if (label) {
+ change = label->isVisible != on;
+ label->setVisible(on);
+ }
+ if (field) {
+ change |= field->isVisible != on;
+ field->setVisible(on);
+ }
+ if (change)
+ invalidate();
+}
+
+/*!
+ \since 6.4
+
+ \overload
+
+ Shows the row corresponding to \a widget if \a on is true,
+ otherwise hides the row.
+
+ \sa removeRow(), takeRow()
+*/
+void QFormLayout::setRowVisible(QWidget *widget, bool on)
+{
+ Q_D(QFormLayout);
+ if (Q_UNLIKELY(!d->checkWidget(widget)))
+ return;
+
+ int row;
+ ItemRole role;
+ getWidgetPosition(widget, &row, &role);
+
+ if (Q_UNLIKELY(row < 0)) {
+ qWarning("QFormLayout::setRowVisible: Invalid widget");
+ return;
+ }
+
+ setRowVisible(row, on);
+}
+
+/*!
+ \since 6.4
+
+ \overload
+
+ Shows the row corresponding to \a layout if \a on is true,
+ otherwise hides the row.
+
+ \sa removeRow(), takeRow()
+*/
+void QFormLayout::setRowVisible(QLayout *layout, bool on)
+{
+ Q_D(QFormLayout);
+ if (Q_UNLIKELY(!d->checkLayout(layout)))
+ return;
+
+ int row;
+ ItemRole role;
+ getLayoutPosition(layout, &row, &role);
+
+ if (Q_UNLIKELY(row < 0)) {
+ qWarning("QFormLayout::setRowVisible: Invalid layout");
+ return;
+ }
+
+ setRowVisible(row, on);
+}
+
+/*!
+ \since 6.4
+
+ Returns true if some items in the row \a row are visible,
+ otherwise returns false.
+*/
+bool QFormLayout::isRowVisible(int row) const
+{
+ Q_D(const QFormLayout);
+ QFormLayoutItem *label = d->m_matrix(row, 0);
+ QFormLayoutItem *field = d->m_matrix(row, 1);
+
+ int visibleItemCount = 2;
+ if (!label || label->isHidden() || (label->widget() && label->widget()->isHidden()))
+ --visibleItemCount;
+ if (!field || field->isHidden() || (field->widget() && field->widget()->isHidden()))
+ --visibleItemCount;
+
+ return visibleItemCount > 0;
+}
+
+/*!
+ \since 6.4
+ \overload
+
+ Returns true if some items in the row corresponding to \a widget
+ are visible, otherwise returns false.
+*/
+bool QFormLayout::isRowVisible(QWidget *widget) const
+{
+ Q_D(const QFormLayout);
+ if (Q_UNLIKELY(!d->checkWidget(widget)))
+ return false;
+ int row;
+ ItemRole role;
+ getWidgetPosition(widget, &row, &role);
+
+ if (Q_UNLIKELY(row < 0)) {
+ qWarning("QFormLayout::takeRow: Invalid widget");
+ return false;
+ }
+
+ return isRowVisible(row);
+}
+
+/*!
+ \since 6.4
+ \overload
+
+ Returns true if some items in the row corresponding to \a layout
+ are visible, otherwise returns false.
+*/
+bool QFormLayout::isRowVisible(QLayout *layout) const
+{
+ Q_D(const QFormLayout);
+ if (Q_UNLIKELY(!d->checkLayout(layout)))
+ return false;
+ int row;
+ ItemRole role;
+ getLayoutPosition(layout, &row, &role);
+
+ if (Q_UNLIKELY(row < 0)) {
+ qWarning("QFormLayout::takeRow: Invalid layout");
+ return false;
+ }
+
+ return isRowVisible(row);
+}
+
+/*!
\internal
*/
diff --git a/src/widgets/kernel/qformlayout.h b/src/widgets/kernel/qformlayout.h
index c716a963e5..b24fe131a0 100644
--- a/src/widgets/kernel/qformlayout.h
+++ b/src/widgets/kernel/qformlayout.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFORMLAYOUT_H
#define QFORMLAYOUT_H
@@ -138,6 +102,14 @@ public:
void setWidget(int row, ItemRole role, QWidget *widget);
void setLayout(int row, ItemRole role, QLayout *layout);
+ void setRowVisible(int row, bool on);
+ void setRowVisible(QWidget *widget, bool on);
+ void setRowVisible(QLayout *layout, bool on);
+
+ bool isRowVisible(int row) const;
+ bool isRowVisible(QWidget *widget) const;
+ bool isRowVisible(QLayout *layout) const;
+
QLayoutItem *itemAt(int row, ItemRole role) const;
void getItemPosition(int index, int *rowPtr, ItemRole *rolePtr) const;
void getWidgetPosition(QWidget *widget, int *rowPtr, ItemRole *rolePtr) const;
diff --git a/src/widgets/kernel/qgesture.cpp b/src/widgets/kernel/qgesture.cpp
index bde5484771..82b4d9ced8 100644
--- a/src/widgets/kernel/qgesture.cpp
+++ b/src/widgets/kernel/qgesture.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qgesture.h"
#include "private/qgesture_p.h"
@@ -49,6 +13,13 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN_TAGGED(Qt::GestureState, Qt__GestureState)
+QT_IMPL_METATYPE_EXTERN_TAGGED(Qt::GestureType, Qt__GestureType)
+QT_IMPL_METATYPE_EXTERN_TAGGED(QPinchGesture::ChangeFlags,
+ QPinchGesture__ChangeFlags)
+QT_IMPL_METATYPE_EXTERN_TAGGED(QGesture::GestureCancelPolicy,
+ QGesture__GestureCancelPolicy)
+
/*!
\class QGesture
\since 4.6
diff --git a/src/widgets/kernel/qgesture.h b/src/widgets/kernel/qgesture.h
index 312962f9bf..7e7041ef76 100644
--- a/src/widgets/kernel/qgesture.h
+++ b/src/widgets/kernel/qgesture.h
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGESTURE_H
#define QGESTURE_H
#include <QtWidgets/qtwidgetsglobal.h>
#include <QtCore/qobject.h>
+#include <QtCore/qmap.h>
#include <QtCore/qlist.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qpoint.h>
@@ -51,8 +16,10 @@
#ifndef QT_NO_GESTURES
-Q_DECLARE_METATYPE(Qt::GestureState)
-Q_DECLARE_METATYPE(Qt::GestureType)
+// ### move to qnamespace.h
+QT_DECL_METATYPE_EXTERN_TAGGED(Qt::GestureState, Qt__GestureState, Q_WIDGETS_EXPORT)
+// ### move to qnamespace.h
+QT_DECL_METATYPE_EXTERN_TAGGED(Qt::GestureType, Qt__GestureType, Q_WIDGETS_EXPORT)
QT_BEGIN_NAMESPACE
@@ -143,7 +110,7 @@ public:
RotationAngleChanged = 0x2,
CenterPointChanged = 0x4
};
- Q_FLAG(ChangeFlag)
+ Q_ENUM(ChangeFlag)
Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag)
Q_FLAG(ChangeFlags)
@@ -200,7 +167,8 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QPinchGesture::ChangeFlags)
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QPinchGesture::ChangeFlags)
+QT_DECL_METATYPE_EXTERN_TAGGED(QPinchGesture::ChangeFlags,
+ QPinchGesture__ChangeFlags, Q_WIDGETS_EXPORT)
QT_BEGIN_NAMESPACE
@@ -323,7 +291,9 @@ Q_WIDGETS_EXPORT QDebug operator<<(QDebug, const QGestureEvent *);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QGesture::GestureCancelPolicy)
+QT_DECL_METATYPE_EXTERN_TAGGED(QGesture::GestureCancelPolicy,
+ QGesture__GestureCancelPolicy, Q_WIDGETS_EXPORT)
+
#endif // QT_NO_GESTURES
#endif // QGESTURE_H
diff --git a/src/widgets/kernel/qgesture_p.h b/src/widgets/kernel/qgesture_p.h
index 057302bda1..1e4292abf9 100644
--- a/src/widgets/kernel/qgesture_p.h
+++ b/src/widgets/kernel/qgesture_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGESTURE_P_H
#define QGESTURE_P_H
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index b725485948..edb159bbbf 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qgesturemanager_p.h"
#include "private/qstandardgestures_p.h"
@@ -57,6 +21,7 @@
#include "qdebug.h"
#include <QtCore/QLoggingCategory>
+#include <QtCore/QVarLengthArray>
#ifndef QT_NO_GESTURES
@@ -85,7 +50,7 @@ static inline int panTouchPoints()
#endif
QGestureManager::QGestureManager(QObject *parent)
- : QObject(parent), state(NotGesture), m_lastCustomGestureId(Qt::CustomGesture)
+ : QObject(parent), m_lastCustomGestureId(Qt::CustomGesture)
{
qRegisterMetaType<Qt::GestureState>();
@@ -133,25 +98,23 @@ void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type)
{
QList<QGestureRecognizer *> list = m_recognizers.values(type);
m_recognizers.remove(type);
- foreach (QGesture *g, m_gestureToRecognizer.keys()) {
- QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g);
+ for (const auto &[g, recognizer] : std::as_const(m_gestureToRecognizer).asKeyValueRange()) {
if (list.contains(recognizer)) {
m_deletedRecognizers.insert(g, recognizer);
}
}
- QMap<ObjectGesture, QList<QGesture *> >::const_iterator iter = m_objectGestures.constBegin();
- while (iter != m_objectGestures.constEnd()) {
- ObjectGesture objectGesture = iter.key();
+ for (const auto &[objectGesture, gestures] : std::as_const(m_objectGestures).asKeyValueRange()) {
if (objectGesture.gesture == type) {
- foreach (QGesture *g, iter.value()) {
- if (QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g)) {
- m_gestureToRecognizer.remove(g);
+ for (QGesture *g : gestures) {
+ auto it = m_gestureToRecognizer.constFind(g);
+ if (it != m_gestureToRecognizer.cend() && it.value()) {
+ QGestureRecognizer *recognizer = it.value();
+ m_gestureToRecognizer.erase(it);
m_obsoleteGestures[recognizer].insert(g);
}
}
}
- ++iter;
}
}
@@ -317,18 +280,18 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *,
}
if (!triggeredGestures.isEmpty() || !finishedGestures.isEmpty()
|| !newMaybeGestures.isEmpty() || !notGestures.isEmpty()) {
- QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures;
+ const QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures;
triggeredGestures &= m_activeGestures;
// check if a running gesture switched back to maybe state
- QSet<QGesture *> activeToMaybeGestures = m_activeGestures & newMaybeGestures;
+ const QSet<QGesture *> activeToMaybeGestures = m_activeGestures & newMaybeGestures;
// check if a maybe gesture switched to canceled - reset it but don't send an event
QSet<QGesture *> maybeToCanceledGestures = m_maybeGestures & notGestures;
// check if a running gesture switched back to not gesture state,
// i.e. were canceled
- QSet<QGesture *> canceledGestures = m_activeGestures & notGestures;
+ const QSet<QGesture *> canceledGestures = m_activeGestures & notGestures;
// new gestures in maybe state
m_maybeGestures += newMaybeGestures;
@@ -346,11 +309,11 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *,
Q_ASSERT((finishedGestures & canceledGestures).isEmpty());
Q_ASSERT((canceledGestures & newMaybeGestures).isEmpty());
- QSet<QGesture *> notStarted = finishedGestures - m_activeGestures;
+ const QSet<QGesture *> notStarted = finishedGestures - m_activeGestures;
if (!notStarted.isEmpty()) {
// there are some gestures that claim to be finished, but never started.
// probably those are "singleshot" gestures so we'll fake the started state.
- foreach (QGesture *gesture, notStarted)
+ for (QGesture *gesture : notStarted)
gesture->d_func()->state = Qt::GestureStarted;
QSet<QGesture *> undeliveredGestures;
deliverEvents(notStarted, &undeliveredGestures);
@@ -365,15 +328,15 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *,
m_activeGestures -= canceledGestures;
// set the proper gesture state on each gesture
- foreach (QGesture *gesture, startedGestures)
+ for (QGesture *gesture : startedGestures)
gesture->d_func()->state = Qt::GestureStarted;
- foreach (QGesture *gesture, triggeredGestures)
+ for (QGesture *gesture : std::as_const(triggeredGestures))
gesture->d_func()->state = Qt::GestureUpdated;
- foreach (QGesture *gesture, finishedGestures)
+ for (QGesture *gesture : std::as_const(finishedGestures))
gesture->d_func()->state = Qt::GestureFinished;
- foreach (QGesture *gesture, canceledGestures)
+ for (QGesture *gesture : canceledGestures)
gesture->d_func()->state = Qt::GestureCanceled;
- foreach (QGesture *gesture, activeToMaybeGestures)
+ for (QGesture *gesture : activeToMaybeGestures)
gesture->d_func()->state = Qt::GestureFinished;
if (!m_activeGestures.isEmpty() || !m_maybeGestures.isEmpty() ||
@@ -393,7 +356,7 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *,
deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures,
&undeliveredGestures);
- foreach (QGesture *g, startedGestures) {
+ for (QGesture *g : startedGestures) {
if (undeliveredGestures.contains(g))
continue;
if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
@@ -406,9 +369,9 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *,
m_activeGestures -= undeliveredGestures;
// reset gestures that ended
- QSet<QGesture *> endedGestures =
+ const QSet<QGesture *> endedGestures =
finishedGestures + canceledGestures + undeliveredGestures + maybeToCanceledGestures;
- foreach (QGesture *gesture, endedGestures) {
+ for (QGesture *gesture : endedGestures) {
recycle(gesture);
m_gestureTargets.remove(gesture);
}
@@ -585,7 +548,7 @@ void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures,
GestureByTypes gestureByTypes;
// sort gestures by types
- foreach (QGesture *gesture, gestures) {
+ for (QGesture *gesture : gestures) {
QWidget *receiver = m_gestureTargets.value(gesture, nullptr);
Q_ASSERT(receiver);
if (receiver)
@@ -647,7 +610,8 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures,
QWidget *child = topLevel->childAt(topLevel->mapFromGlobal(pt));
target = child ? child : topLevel;
}
- } else {
+ }
+ if (!target) {
// or use the context of the gesture
QObject *context = m_gestureOwners.value(gesture, 0);
if (context->isWidgetType())
@@ -686,7 +650,7 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures,
for (GesturesPerWidget::const_iterator it = conflictedGestures.constBegin(),
e = conflictedGestures.constEnd(); it != e; ++it) {
QWidget *receiver = it.key();
- QList<QGesture *> gestures = it.value();
+ const QList<QGesture *> &gestures = it.value();
qCDebug(lcGestureManager) << "QGestureManager::deliverEvents: sending GestureOverride to"
<< receiver
<< "gestures:" << gestures;
@@ -694,7 +658,7 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures,
event.t = QEvent::GestureOverride;
// mark event and individual gestures as ignored
event.ignore();
- foreach(QGesture *g, gestures)
+ for (QGesture *g : gestures)
event.setAccepted(g, false);
QCoreApplication::sendEvent(receiver, &event);
diff --git a/src/widgets/kernel/qgesturemanager_p.h b/src/widgets/kernel/qgesturemanager_p.h
index 3a5c9822eb..02beb024f9 100644
--- a/src/widgets/kernel/qgesturemanager_p.h
+++ b/src/widgets/kernel/qgesturemanager_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGESTUREMANAGER_P_H
#define QGESTUREMANAGER_P_H
@@ -57,6 +21,8 @@
#include "private/qwidget_p.h"
#include "qgesturerecognizer.h"
+#include <QtCore/qpointer.h>
+
#ifndef QT_NO_GESTURES
#include <functional>
@@ -100,14 +66,6 @@ private:
QSet<QGesture *> m_activeGestures;
QSet<QGesture *> m_maybeGestures;
- enum State {
- Gesture,
- NotGesture,
- MaybeGesture // this means timers are up and waiting for some
- // more events, and input events are handled by
- // gesture recognizer explicitly
- } state;
-
struct ObjectGesture
{
QObject* object;
diff --git a/src/widgets/kernel/qgesturerecognizer.cpp b/src/widgets/kernel/qgesturerecognizer.cpp
index 75d091ce4e..50c394e9b0 100644
--- a/src/widgets/kernel/qgesturerecognizer.cpp
+++ b/src/widgets/kernel/qgesturerecognizer.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qgesturerecognizer.h"
diff --git a/src/widgets/kernel/qgesturerecognizer.h b/src/widgets/kernel/qgesturerecognizer.h
index 04e85c46cc..de48fec399 100644
--- a/src/widgets/kernel/qgesturerecognizer.h
+++ b/src/widgets/kernel/qgesturerecognizer.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGESTURERECOGNIZER_H
#define QGESTURERECOGNIZER_H
diff --git a/src/widgets/kernel/qgridlayout.cpp b/src/widgets/kernel/qgridlayout.cpp
index 336a68cd80..7998567a21 100644
--- a/src/widgets/kernel/qgridlayout.cpp
+++ b/src/widgets/kernel/qgridlayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qapplication.h"
#include "qgridlayout.h"
@@ -145,18 +109,18 @@ public:
int minimumHeightForWidth(int width, int hSpacing, int vSpacing);
inline void getNextPos(int &row, int &col) { row = nextR; col = nextC; }
- inline int count() const { return things.count(); }
+ inline int count() const { return things.size(); }
QRect cellRect(int row, int col) const;
inline QLayoutItem *itemAt(int index) const {
- if (index >= 0 && index < things.count())
+ if (index >= 0 && index < things.size())
return things.at(index)->item();
else
return nullptr;
}
inline QLayoutItem *takeAt(int index) {
Q_Q(QGridLayout);
- if (index >= 0 && index < things.count()) {
+ if (index >= 0 && index < things.size()) {
if (QGridBox *b = things.takeAt(index)) {
QLayoutItem *item = b->takeItem();
if (QLayout *l = item->layout()) {
@@ -184,7 +148,7 @@ public:
}
void getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan) const {
- if (index >= 0 && index < things.count()) {
+ if (index >= 0 && index < things.size()) {
const QGridBox *b = things.at(index);
int toRow = b->toRow(rr);
int toCol = b->toCol(cc);
@@ -1330,7 +1294,7 @@ QLayoutItem *QGridLayout::itemAt(int index) const
QLayoutItem *QGridLayout::itemAtPosition(int row, int column) const
{
Q_D(const QGridLayout);
- int n = d->things.count();
+ int n = d->things.size();
for (int i = 0; i < n; ++i) {
QGridBox *box = d->things.at(i);
if (row >= box->row && row <= box->toRow(d->rr)
diff --git a/src/widgets/kernel/qgridlayout.h b/src/widgets/kernel/qgridlayout.h
index 1107d850eb..bb4887e2fd 100644
--- a/src/widgets/kernel/qgridlayout.h
+++ b/src/widgets/kernel/qgridlayout.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGRIDLAYOUT_H
#define QGRIDLAYOUT_H
diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp
index 044176d141..a826ea75bc 100644
--- a/src/widgets/kernel/qlayout.cpp
+++ b/src/widgets/kernel/qlayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlayout.h"
@@ -93,14 +57,13 @@ static int menuBarHeightForWidth(QWidget *menubar, int w)
resized to zero size if there is too little space. To support
children whose heights depend on their widths, implement
hasHeightForWidth() and heightForWidth(). See the
- \l{layouts/borderlayout}{Border Layout} and
- \l{layouts/flowlayout}{Flow Layout} examples for
+ \l{layouts/flowlayout}{Flow Layout} example for
more information about implementing custom layout managers.
Geometry management stops when the layout manager is deleted.
\sa QLayoutItem, {Layout Management}, {Basic Layouts Example},
- {Border Layout Example}, {Flow Layout Example}
+ {Flow Layout Example}
*/
@@ -557,10 +520,11 @@ void QLayoutPrivate::doResize()
void QLayout::widgetEvent(QEvent *e)
{
Q_D(QLayout);
- if (!d->enabled)
+ const QEvent::Type type = e->type();
+ if (!d->enabled && type != QEvent::ChildRemoved)
return;
- switch (e->type()) {
+ switch (type) {
case QEvent::Resize:
if (d->activated)
d->doResize();
@@ -570,12 +534,14 @@ void QLayout::widgetEvent(QEvent *e)
case QEvent::ChildRemoved:
{
QChildEvent *c = (QChildEvent *)e;
- if (c->child()->isWidgetType()) {
+ QObject *child = c->child();
+ QObjectPrivate *op = QObjectPrivate::get(child);
+ if (op->wasWidget) {
#if QT_CONFIG(menubar)
- if (c->child() == d->menubar)
+ if (child == d->menubar)
d->menubar = nullptr;
#endif
- removeWidgetRecursively(this, c->child());
+ removeWidgetRecursively(this, child);
}
}
break;
@@ -743,24 +709,24 @@ QLayout::~QLayout()
/*!
This function is called from \c addLayout() or \c insertLayout() functions in
- subclasses to add layout \a l as a sub-layout.
+ subclasses to add layout \a childLayout as a sub-layout.
The only scenario in which you need to call it directly is if you
implement a custom layout that supports nested layouts.
\sa QBoxLayout::addLayout(), QBoxLayout::insertLayout(), QGridLayout::addLayout()
*/
-void QLayout::addChildLayout(QLayout *l)
+void QLayout::addChildLayout(QLayout *childLayout)
{
- if (Q_UNLIKELY(l->parent())) {
- qWarning("QLayout::addChildLayout: layout \"%ls\" already has a parent",
- qUtf16Printable(l->objectName()));
+ if (Q_UNLIKELY(childLayout->parent())) {
+ qWarning("QLayout::addChildLayout: layout %s \"%ls\" already has a parent",
+ childLayout->metaObject()->className(), qUtf16Printable(childLayout->objectName()));
return;
}
- l->setParent(this);
+ childLayout->setParent(this);
if (QWidget *mw = parentWidget()) {
- l->d_func()->reparentChildWidgets(mw);
+ childLayout->d_func()->reparentChildWidgets(mw);
}
}
@@ -807,7 +773,7 @@ void QLayoutPrivate::reparentChildWidgets(QWidget *mw)
w->metaObject()->className(), qUtf16Printable(w->objectName()));
}
#endif
- bool needShow = mwVisible && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
+ bool needShow = mwVisible && !QWidgetPrivate::get(w)->isExplicitlyHidden();
if (pw != mw)
w->setParent(mw);
if (needShow)
@@ -863,9 +829,10 @@ bool QLayoutPrivate::checkLayout(QLayout *otherLayout) const
This function is called from \c addWidget() functions in
subclasses to add \a w as a managed widget of a layout.
- If \a w is already managed by a layout, this function will give a warning
- and remove \a w from that layout. This function must therefore be
- called before adding \a w to the layout's data structure.
+ If \a w is already managed by a layout, this function will produce
+ a warning, and remove \a w from that layout. This function must
+ therefore be called before adding \a w to the layout's data
+ structure.
*/
void QLayout::addChildWidget(QWidget *w)
{
@@ -892,7 +859,7 @@ void QLayout::addChildWidget(QWidget *w)
#endif
pw = nullptr;
}
- bool needShow = mw && mw->isVisible() && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
+ bool needShow = mw && mw->isVisible() && !QWidgetPrivate::get(w)->isExplicitlyHidden();
if (!pw && mw)
w->setParent(mw);
w->setAttribute(Qt::WA_LaidOut);
@@ -1292,7 +1259,7 @@ QLayout::SizeConstraint QLayout::sizeConstraint() const
this layout is set to \a r, provided that this layout supports
setAlignment().
- The result is derived from sizeHint() and expanding(). It is never
+ The result is derived from sizeHint() and expandingDirections(). It is never
larger than \a r.
*/
QRect QLayout::alignmentRect(const QRect &r) const
diff --git a/src/widgets/kernel/qlayout.h b/src/widgets/kernel/qlayout.h
index d37caeef25..ee7b5e047c 100644
--- a/src/widgets/kernel/qlayout.h
+++ b/src/widgets/kernel/qlayout.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLAYOUT_H
#define QLAYOUT_H
diff --git a/src/widgets/kernel/qlayout_p.h b/src/widgets/kernel/qlayout_p.h
index 437ab84fc3..cd40a98fb7 100644
--- a/src/widgets/kernel/qlayout_p.h
+++ b/src/widgets/kernel/qlayout_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLAYOUT_P_H
#define QLAYOUT_P_H
diff --git a/src/widgets/kernel/qlayoutengine.cpp b/src/widgets/kernel/qlayoutengine.cpp
index e318300f98..576678ad0a 100644
--- a/src/widgets/kernel/qlayoutengine.cpp
+++ b/src/widgets/kernel/qlayoutengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlayout.h"
#include "private/qlayoutengine_p.h"
diff --git a/src/widgets/kernel/qlayoutengine_p.h b/src/widgets/kernel/qlayoutengine_p.h
index 4eefb36c68..ff7b4107e1 100644
--- a/src/widgets/kernel/qlayoutengine_p.h
+++ b/src/widgets/kernel/qlayoutengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLAYOUTENGINE_P_H
#define QLAYOUTENGINE_P_H
diff --git a/src/widgets/kernel/qlayoutitem.cpp b/src/widgets/kernel/qlayoutitem.cpp
index b241821c82..246d090828 100644
--- a/src/widgets/kernel/qlayoutitem.cpp
+++ b/src/widgets/kernel/qlayoutitem.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlayout.h"
@@ -88,7 +52,7 @@ inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
Pure virtual functions are provided to return information about
the layout, including, sizeHint(), minimumSize(), maximumSize()
- and expanding().
+ and expandingDirections().
The layout's geometry can be set and retrieved with setGeometry()
and geometry(), and its alignment with setAlignment() and
diff --git a/src/widgets/kernel/qlayoutitem.h b/src/widgets/kernel/qlayoutitem.h
index ba11976f06..531498ea4b 100644
--- a/src/widgets/kernel/qlayoutitem.h
+++ b/src/widgets/kernel/qlayoutitem.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLAYOUTITEM_H
#define QLAYOUTITEM_H
diff --git a/src/widgets/kernel/qmacgesturerecognizer.cpp b/src/widgets/kernel/qmacgesturerecognizer.cpp
index 8e18132df8..8149bea30d 100644
--- a/src/widgets/kernel/qmacgesturerecognizer.cpp
+++ b/src/widgets/kernel/qmacgesturerecognizer.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmacgesturerecognizer_p.h"
#include "qgesture.h"
diff --git a/src/widgets/kernel/qmacgesturerecognizer_p.h b/src/widgets/kernel/qmacgesturerecognizer_p.h
index 739fc201b7..5c559c6cb9 100644
--- a/src/widgets/kernel/qmacgesturerecognizer_p.h
+++ b/src/widgets/kernel/qmacgesturerecognizer_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMACSWIPEGESTURERECOGNIZER_MAC_P_H
#define QMACSWIPEGESTURERECOGNIZER_MAC_P_H
diff --git a/src/widgets/kernel/qrhiwidget.cpp b/src/widgets/kernel/qrhiwidget.cpp
new file mode 100644
index 0000000000..bf56263113
--- /dev/null
+++ b/src/widgets/kernel/qrhiwidget.cpp
@@ -0,0 +1,1309 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qrhiwidget_p.h"
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+#include <private/qwidgetrepaintmanager_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QRhiWidget
+ \inmodule QtWidgets
+ \since 6.7
+
+ \brief The QRhiWidget class is a widget for rendering 3D graphics via an
+ accelerated grapics API, such as Vulkan, Metal, or Direct 3D.
+
+ \preliminary
+
+ \note QRhiWidget is in tech preview in Qt 6.7. \b {The API is under
+ development and subject to change.}
+
+ QRhiWidget provides functionality for displaying 3D content rendered
+ through the \l QRhi APIs within a QWidget-based application. In many ways
+ it is the portable equivalent of \l QOpenGLWidget that is not tied to a
+ single 3D graphics API, but rather can function with all the APIs QRhi
+ supports (such as, Direct 3D 11/12, Vulkan, Metal, and OpenGL).
+
+ QRhiWidget is expected to be subclassed. To render into the 2D texture that
+ is implicitly created and managed by the QRhiWidget, subclasses should
+ reimplement the virtual functions initialize() and render().
+
+ The size of the texture will by default adapt to the size of the widget. If
+ a fixed size is preferred, set a fixed size specified in pixels by calling
+ setFixedColorBufferSize().
+
+ In addition to the texture serving as the color buffer, a depth/stencil
+ buffer and a render target binding these together is maintained implicitly
+ as well.
+
+ The QRhi for the widget's top-level window is configured to use a
+ platform-specific backend and graphics API by default: Metal on macOS and
+ iOS, Direct 3D 11 on Windows, OpenGL otherwise. Call setApi() to override
+ this.
+
+ \note A single widget window can only use one QRhi backend, and so one
+ single 3D graphics API. If two QRhiWidget or QQuickWidget widgets in the
+ window's widget hierarchy request different APIs, only one of them will
+ function correctly.
+
+ \note While QRhiWidget is a public Qt API, the QRhi family of classes in
+ the Qt Gui module, including QRhi, QShader and QShaderDescription, offer
+ limited compatibility guarantees. There are no source or binary
+ compatibility guarantees for these classes, meaning the API is only
+ guaranteed to work with the Qt version the application was developed
+ against. Source incompatible changes are however aimed to be kept at a
+ minimum and will only be made in minor releases (6.7, 6.8, and so on).
+ \c{qrhiwidget.h} does not directly include any QRhi-related headers. To use
+ those classes when implementing a QRhiWidget subclass, link to
+ \c{Qt::GuiPrivate} (if using CMake), and include the appropriate headers
+ with the \c rhi prefix, for example \c{#include <rhi/qrhi.h>}.
+
+ An example of a simple QRhiWidget subclass rendering a triangle is the
+ following:
+
+ \snippet qrhiwidget/rhiwidgetintro.cpp 0
+
+ This is a widget that continuously requests updates, throttled by the
+ presentation rate (vsync, depending on the screen refresh rate). If
+ rendering continuously is not desired, the update() call in render() should
+ be removed, and rather issued only when updating the rendered content is
+ necessary. For example, if the rotation of the cube should be tied to the
+ value of a QSlider, then connecting the slider's value change signal to a
+ slot or lambda that forwards the new value and calls update() is
+ sufficient.
+
+ The vertex and fragment shaders are provided as Vulkan-style GLSL and must
+ be processed first by the Qt shader infrastructure first. This is achieved
+ either by running the \c qsb command-line tool manually, or by using the
+ \l{Qt Shader Tools Build System Integration}{qt_add_shaders()} function in
+ CMake. The QRhiWidget implementation loads these pre-processed \c{.qsb}
+ files that are shipped with the application. See \l{Qt Shader Tools} for
+ more information about Qt's shader translation infrastructure.
+
+ The source code for these shaders could be the following:
+
+ \c{color.vert}
+
+ \snippet qrhiwidget/rhiwidgetintro.vert 0
+
+ \c{color.frag}
+
+ \snippet qrhiwidget/rhiwidgetintro.frag 0
+
+ The result is a widget that shows the following:
+
+ \image qrhiwidget-intro.jpg
+
+ For a complete, minimal, introductory example check out the \l{Simple RHI
+ Widget Example}.
+
+ For an example with more functionality and demonstration of further
+ concepts, see the \l{Cube RHI Widget Example}.
+
+ QRhiWidget always involves rendering into a backing texture, not
+ directly to the window (the surface or layer provided by the windowing
+ system for the native window). This allows properly compositing the content
+ with the rest of the widget-based UI, and offering a simple and compact
+ API, making it easy to get started. All this comes at the expense of
+ additional resources and a potential effect on performance. This is often
+ perfectly acceptable in practice, but advanced users should keep in mind
+ the pros and cons of the different approaches. Refer to the \l{RHI Window
+ Example} and compare it with the \l{Simple RHI Widget Example} for details
+ about the two approaches.
+
+ Reparenting a QRhiWidget into a widget hierarchy that belongs to a
+ different window (top-level widget), or making the QRhiWidget itself a
+ top-level (by setting the parent to \nullptr), involves changing the
+ associated QRhi (and potentially destroying the old one) while the
+ QRhiWidget continues to stay alive and well. To support this, robust
+ QRhiWidget implementations are expected to reimplement the
+ releaseResources() virtual function as well, and drop their QRhi resources
+ just as they do in the destructor. The \l{Cube RHI Widget Example}
+ demonstrates this in practice.
+
+ While not a primary use case, QRhiWidget also allows incorporating
+ rendering code that directly uses a 3D graphics API such as Vulkan, Metal,
+ Direct 3D, or OpenGL. See \l QRhiCommandBuffer::beginExternal() for details
+ on recording native commands within a QRhi render pass, as well as
+ \l QRhiTexture::createFrom() for a way to wrap an existing native texture and
+ then use it with QRhi in a subsequent render pass. Note however that the
+ configurability of the underlying graphics API (its device or context
+ features, layers, extensions, etc.) is going to be limited since
+ QRhiWidget's primary goal is to provide an environment suitable for
+ QRhi-based rendering code, not to enable arbitrary, potentially complex,
+ foreign rendering engines.
+
+ \since 6.7
+
+ \sa QRhi, QShader, QOpenGLWidget, {Simple RHI Widget Example}, {Cube RHI Widget Example}
+ */
+
+/*!
+ \enum QRhiWidget::Api
+ Specifies the 3D API and QRhi backend to use
+
+ \value Null
+ \value OpenGL
+ \value Metal
+ \value Vulkan
+ \value Direct3D11
+ \value Direct3D12
+
+ \sa QRhi
+ */
+
+/*!
+ \enum QRhiWidget::TextureFormat
+ Specifies the format of the texture to which the QRhiWidget renders.
+
+ \value RGBA8 See QRhiTexture::RGBA8.
+ \value RGBA16F See QRhiTexture::RGBA16F.
+ \value RGBA32F See QRhiTexture::RGBA32F.
+ \value RGB10A2 See QRhiTexture::RGB10A2.
+
+ \sa QRhiTexture
+ */
+
+/*!
+ Constructs a widget which is a child of \a parent, with widget flags set to \a f.
+ */
+QRhiWidget::QRhiWidget(QWidget *parent, Qt::WindowFlags f)
+ : QWidget(*(new QRhiWidgetPrivate), parent, f)
+{
+ Q_D(QRhiWidget);
+ if (Q_UNLIKELY(!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RhiBasedRendering)))
+ qWarning("QRhiWidget: QRhi is not supported on this platform.");
+ else
+ d->setRenderToTexture();
+
+ d->config.setEnabled(true);
+#if defined(Q_OS_DARWIN)
+ d->config.setApi(QPlatformBackingStoreRhiConfig::Metal);
+#elif defined(Q_OS_WIN)
+ d->config.setApi(QPlatformBackingStoreRhiConfig::D3D11);
+#else
+ d->config.setApi(QPlatformBackingStoreRhiConfig::OpenGL);
+#endif
+}
+
+/*!
+ Destructor.
+ */
+QRhiWidget::~QRhiWidget()
+{
+ Q_D(QRhiWidget);
+
+ if (d->rhi) {
+ d->rhi->removeCleanupCallback(this);
+ // rhi resources must be destroyed here, due to how QWidget teardown works;
+ // it should not be left to the private object's destruction.
+ d->resetRenderTargetObjects();
+ d->resetColorBufferObjects();
+ qDeleteAll(d->pendingDeletes);
+ }
+
+ d->offscreenRenderer.reset();
+}
+
+/*!
+ Handles resize events that are passed in the \a e event parameter. Calls
+ the virtual function initialize().
+
+ \note Avoid overriding this function in derived classes. If that is not
+ feasible, make sure that QRhiWidget's implementation is invoked too.
+ Otherwise the underlying texture object and related resources will not get
+ resized properly and will lead to incorrect rendering.
+ */
+void QRhiWidget::resizeEvent(QResizeEvent *e)
+{
+ Q_D(QRhiWidget);
+
+ if (e->size().isEmpty()) {
+ d->noSize = true;
+ return;
+ }
+ d->noSize = false;
+
+ d->sendPaintEvent(QRect(QPoint(0, 0), size()));
+}
+
+/*!
+ Handles paint events.
+
+ Calling QWidget::update() will lead to sending a paint event \a e, and thus
+ invoking this function. The sending of the event is asynchronous and will
+ happen at some point after returning from update(). This function will
+ then, after some preparation, call the virtual render() to update the
+ contents of the QRhiWidget's associated texture. The widget's top-level
+ window will then composite the texture with the rest of the window.
+ */
+void QRhiWidget::paintEvent(QPaintEvent *)
+{
+ Q_D(QRhiWidget);
+ if (!updatesEnabled() || d->noSize)
+ return;
+
+ d->ensureRhi();
+ if (!d->rhi) {
+ qWarning("QRhiWidget: No QRhi");
+ emit renderFailed();
+ return;
+ }
+
+ QRhiCommandBuffer *cb = nullptr;
+ if (d->rhi->beginOffscreenFrame(&cb) != QRhi::FrameOpSuccess)
+ return;
+
+ bool needsInit = false;
+ d->ensureTexture(&needsInit);
+ if (d->colorTexture || d->msaaColorBuffer) {
+ bool canRender = true;
+ if (needsInit)
+ canRender = d->invokeInitialize(cb);
+ if (canRender)
+ render(cb);
+ }
+
+ d->rhi->endOffscreenFrame();
+}
+
+/*!
+ \reimp
+*/
+bool QRhiWidget::event(QEvent *e)
+{
+ Q_D(QRhiWidget);
+ switch (e->type()) {
+ case QEvent::WindowAboutToChangeInternal:
+ // The QRhi will almost certainly change, prevent texture() from
+ // returning the existing QRhiTexture in the meantime.
+ d->textureInvalid = true;
+
+ if (d->rhi && d->rhi != d->offscreenRenderer.rhi()) {
+ // Drop the cleanup callback registered to the toplevel's rhi and
+ // do the early-release, there may not be another chance to do
+ // this, and the QRhi we have currently set may be destroyed by the
+ // time we get to ensureRhi() again.
+ d->rhi->removeCleanupCallback(this);
+ releaseResources(); // notify the user code about the early-release
+ d->releaseResources();
+ // must _not_ null out d->rhi here, for proper interaction with ensureRhi()
+ }
+
+ break;
+
+ case QEvent::Show:
+ if (isVisible())
+ d->sendPaintEvent(QRect(QPoint(0, 0), size()));
+ break;
+ default:
+ break;
+ }
+ return QWidget::event(e);
+}
+
+QWidgetPrivate::TextureData QRhiWidgetPrivate::texture() const
+{
+ // This is the only safe place to clear pendingDeletes, due to the
+ // possibility of the texture returned in the previous invocation of this
+ // function having been added to pendingDeletes, meaning the object then
+ // needs to be valid until the next (this) invocation of this function.
+ // (the exact object lifetime requirements depend on the
+ // QWidget/RepaintManager internal implementation; for now avoid relying on
+ // such details by clearing pendingDeletes only here, not in endCompose())
+ qDeleteAll(pendingDeletes);
+ pendingDeletes.clear();
+
+ TextureData td;
+ if (!textureInvalid)
+ td.textureLeft = resolveTexture ? resolveTexture : colorTexture;
+ return td;
+}
+
+QPlatformTextureList::Flags QRhiWidgetPrivate::textureListFlags()
+{
+ QPlatformTextureList::Flags flags = QWidgetPrivate::textureListFlags();
+ if (mirrorVertically)
+ flags |= QPlatformTextureList::MirrorVertically;
+ return flags;
+}
+
+QPlatformBackingStoreRhiConfig QRhiWidgetPrivate::rhiConfig() const
+{
+ return config;
+}
+
+void QRhiWidgetPrivate::endCompose()
+{
+ // This function is called by QWidgetRepaintManager right after the
+ // backingstore's QRhi-based flush returns. In practice that means after
+ // the begin-endFrame() on the top-level window's swapchain.
+
+ if (rhi) {
+ Q_Q(QRhiWidget);
+ emit q->frameSubmitted();
+ }
+}
+
+// This is reimplemented to enable calling QWidget::grab() on the widget or an
+// ancestor of it. At the same time, QRhiWidget provides its own
+// grabFramebuffer() as well, mirroring QQuickWidget and QOpenGLWidget for
+// consistency. In both types of grabs we end up in here.
+QImage QRhiWidgetPrivate::grabFramebuffer()
+{
+ Q_Q(QRhiWidget);
+ if (noSize)
+ return QImage();
+
+ ensureRhi();
+ if (!rhi) {
+ // The widget (and its parent chain, if any) may not be shown at
+ // all, yet one may still want to use it for grabs. This is
+ // ridiculous of course because the rendering infrastructure is
+ // tied to the top-level widget that initializes upon expose, but
+ // it has to be supported.
+ offscreenRenderer.setConfig(config);
+ // no window passed in, so no swapchain, but we get a functional QRhi which we own
+ offscreenRenderer.create();
+ rhi = offscreenRenderer.rhi();
+ if (!rhi) {
+ qWarning("QRhiWidget: Failed to create dedicated QRhi for grabbing");
+ emit q->renderFailed();
+ return QImage();
+ }
+ }
+
+ QRhiCommandBuffer *cb = nullptr;
+ if (rhi->beginOffscreenFrame(&cb) != QRhi::FrameOpSuccess)
+ return QImage();
+
+ QRhiReadbackResult readResult;
+ bool readCompleted = false;
+ bool needsInit = false;
+ ensureTexture(&needsInit);
+
+ if (colorTexture || msaaColorBuffer) {
+ bool canRender = true;
+ if (needsInit)
+ canRender = invokeInitialize(cb);
+ if (canRender)
+ q->render(cb);
+
+ QRhiResourceUpdateBatch *readbackBatch = rhi->nextResourceUpdateBatch();
+ readResult.completed = [&readCompleted] { readCompleted = true; };
+ readbackBatch->readBackTexture(resolveTexture ? resolveTexture : colorTexture, &readResult);
+ cb->resourceUpdate(readbackBatch);
+ }
+
+ rhi->endOffscreenFrame();
+
+ if (readCompleted) {
+ QImage::Format imageFormat = QImage::Format_RGBA8888;
+ switch (widgetTextureFormat) {
+ case QRhiWidget::TextureFormat::RGBA8:
+ break;
+ case QRhiWidget::TextureFormat::RGBA16F:
+ imageFormat = QImage::Format_RGBA16FPx4;
+ break;
+ case QRhiWidget::TextureFormat::RGBA32F:
+ imageFormat = QImage::Format_RGBA32FPx4;
+ break;
+ case QRhiWidget::TextureFormat::RGB10A2:
+ imageFormat = QImage::Format_BGR30;
+ break;
+ }
+ QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()),
+ readResult.pixelSize.width(), readResult.pixelSize.height(),
+ imageFormat);
+ QImage result;
+ if (rhi->isYUpInFramebuffer())
+ result = wrapperImage.mirrored();
+ else
+ result = wrapperImage.copy();
+ result.setDevicePixelRatio(q->devicePixelRatio());
+ return result;
+ } else {
+ Q_UNREACHABLE();
+ }
+
+ return QImage();
+}
+
+void QRhiWidgetPrivate::resetColorBufferObjects()
+{
+ if (colorTexture) {
+ pendingDeletes.append(colorTexture);
+ colorTexture = nullptr;
+ }
+ if (msaaColorBuffer) {
+ pendingDeletes.append(msaaColorBuffer);
+ msaaColorBuffer = nullptr;
+ }
+ if (resolveTexture) {
+ pendingDeletes.append(resolveTexture);
+ resolveTexture = nullptr;
+ }
+}
+
+void QRhiWidgetPrivate::resetRenderTargetObjects()
+{
+ if (renderTarget) {
+ renderTarget->deleteLater();
+ renderTarget = nullptr;
+ }
+ if (renderPassDescriptor) {
+ renderPassDescriptor->deleteLater();
+ renderPassDescriptor = nullptr;
+ }
+ if (depthStencilBuffer) {
+ depthStencilBuffer->deleteLater();
+ depthStencilBuffer = nullptr;
+ }
+}
+
+void QRhiWidgetPrivate::releaseResources()
+{
+ resetRenderTargetObjects();
+ resetColorBufferObjects();
+ qDeleteAll(pendingDeletes);
+ pendingDeletes.clear();
+}
+
+void QRhiWidgetPrivate::ensureRhi()
+{
+ Q_Q(QRhiWidget);
+ QRhi *currentRhi = QWidgetPrivate::rhi();
+ if (currentRhi && currentRhi->backend() != QBackingStoreRhiSupport::apiToRhiBackend(config.api())) {
+ qWarning("The top-level window is already using another graphics API for composition, "
+ "'%s' is not compatible with this widget",
+ currentRhi->backendName());
+ return;
+ }
+
+ // NB the rhi member may be an invalid object, the pointer can be used, but no deref
+ if (currentRhi && rhi != currentRhi) {
+ if (rhi) {
+ // if previously we created our own but now get a QRhi from the
+ // top-level, then drop what we have and start using the top-level's
+ if (rhi == offscreenRenderer.rhi()) {
+ q->releaseResources(); // notify the user code about the early-release
+ releaseResources();
+ offscreenRenderer.reset();
+ } else {
+ // rhi resources created by us all belong to the old rhi, drop them;
+ // due to nulling out colorTexture this is also what ensures that
+ // initialize() is going to be called again eventually
+ resetRenderTargetObjects();
+ resetColorBufferObjects();
+ }
+ }
+
+ // Normally the widget gets destroyed before the QRhi (which is managed by
+ // the top-level's backingstore). When reparenting between top-levels is
+ // involved, that is not always the case. Therefore we use a per-widget rhi
+ // cleanup callback to get notified when the QRhi is about to be destroyed
+ // while the QRhiWidget is still around.
+ currentRhi->addCleanupCallback(q, [q, this](QRhi *regRhi) {
+ if (!QWidgetPrivate::get(q)->data.in_destructor && this->rhi == regRhi) {
+ q->releaseResources(); // notify the user code about the early-release
+ releaseResources();
+ // must null out our ref, the QRhi object is going to be invalid
+ this->rhi = nullptr;
+ }
+ });
+ }
+
+ rhi = currentRhi;
+}
+
+void QRhiWidgetPrivate::ensureTexture(bool *changed)
+{
+ Q_Q(QRhiWidget);
+
+ QSize newSize = fixedSize;
+ if (newSize.isEmpty())
+ newSize = q->size() * q->devicePixelRatio();
+
+ const int minTexSize = rhi->resourceLimit(QRhi::TextureSizeMin);
+ const int maxTexSize = rhi->resourceLimit(QRhi::TextureSizeMax);
+ newSize.setWidth(qMin(maxTexSize, qMax(minTexSize, newSize.width())));
+ newSize.setHeight(qMin(maxTexSize, qMax(minTexSize, newSize.height())));
+
+ if (colorTexture) {
+ if (colorTexture->format() != rhiTextureFormat || colorTexture->sampleCount() != samples) {
+ resetColorBufferObjects();
+ // sample count change needs new depth-stencil, possibly a new
+ // render target; format change needs new renderpassdescriptor;
+ // therefore must drop the rest too
+ resetRenderTargetObjects();
+ }
+ }
+
+ if (msaaColorBuffer) {
+ if (msaaColorBuffer->backingFormat() != rhiTextureFormat || msaaColorBuffer->sampleCount() != samples) {
+ resetColorBufferObjects();
+ // sample count change needs new depth-stencil, possibly a new
+ // render target; format change needs new renderpassdescriptor;
+ // therefore must drop the rest too
+ resetRenderTargetObjects();
+ }
+ }
+
+ if (!colorTexture && samples <= 1) {
+ if (changed)
+ *changed = true;
+ if (!rhi->isTextureFormatSupported(rhiTextureFormat)) {
+ qWarning("QRhiWidget: The requested texture format (%d) is not supported by the "
+ "underlying 3D graphics API implementation", int(rhiTextureFormat));
+ }
+ colorTexture = rhi->newTexture(rhiTextureFormat, newSize, samples, QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource);
+ if (!colorTexture->create()) {
+ qWarning("Failed to create backing texture for QRhiWidget");
+ delete colorTexture;
+ colorTexture = nullptr;
+ return;
+ }
+ }
+
+ if (samples > 1) {
+ if (!msaaColorBuffer) {
+ if (changed)
+ *changed = true;
+ if (!rhi->isFeatureSupported(QRhi::MultisampleRenderBuffer)) {
+ qWarning("QRhiWidget: Multisample renderbuffers are reported as unsupported; "
+ "sample count %d will not work as expected", samples);
+ }
+ if (!rhi->isTextureFormatSupported(rhiTextureFormat)) {
+ qWarning("QRhiWidget: The requested texture format (%d) is not supported by the "
+ "underlying 3D graphics API implementation", int(rhiTextureFormat));
+ }
+ msaaColorBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::Color, newSize, samples, {}, rhiTextureFormat);
+ if (!msaaColorBuffer->create()) {
+ qWarning("Failed to create multisample color buffer for QRhiWidget");
+ delete msaaColorBuffer;
+ msaaColorBuffer = nullptr;
+ return;
+ }
+ }
+ if (!resolveTexture) {
+ if (changed)
+ *changed = true;
+ resolveTexture = rhi->newTexture(rhiTextureFormat, newSize, 1, QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource);
+ if (!resolveTexture->create()) {
+ qWarning("Failed to create resolve texture for QRhiWidget");
+ delete resolveTexture;
+ resolveTexture = nullptr;
+ return;
+ }
+ }
+ } else if (resolveTexture) {
+ resolveTexture->deleteLater();
+ resolveTexture = nullptr;
+ }
+
+ if (colorTexture && colorTexture->pixelSize() != newSize) {
+ if (changed)
+ *changed = true;
+ colorTexture->setPixelSize(newSize);
+ if (!colorTexture->create())
+ qWarning("Failed to rebuild texture for QRhiWidget after resizing");
+ }
+
+ if (msaaColorBuffer && msaaColorBuffer->pixelSize() != newSize) {
+ if (changed)
+ *changed = true;
+ msaaColorBuffer->setPixelSize(newSize);
+ if (!msaaColorBuffer->create())
+ qWarning("Failed to rebuild multisample color buffer for QRhiWidget after resizing");
+ }
+
+ if (resolveTexture && resolveTexture->pixelSize() != newSize) {
+ if (changed)
+ *changed = true;
+ resolveTexture->setPixelSize(newSize);
+ if (!resolveTexture->create())
+ qWarning("Failed to rebuild resolve texture for QRhiWidget after resizing");
+ }
+
+ textureInvalid = false;
+}
+
+bool QRhiWidgetPrivate::invokeInitialize(QRhiCommandBuffer *cb)
+{
+ Q_Q(QRhiWidget);
+ if (!colorTexture && !msaaColorBuffer)
+ return false;
+
+ if (autoRenderTarget) {
+ const QSize pixelSize = colorTexture ? colorTexture->pixelSize() : msaaColorBuffer->pixelSize();
+ if (!depthStencilBuffer) {
+ depthStencilBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, pixelSize, samples);
+ if (!depthStencilBuffer->create()) {
+ qWarning("Failed to create depth-stencil buffer for QRhiWidget");
+ resetRenderTargetObjects();
+ return false;
+ }
+ } else if (depthStencilBuffer->pixelSize() != pixelSize) {
+ depthStencilBuffer->setPixelSize(pixelSize);
+ if (!depthStencilBuffer->create()) {
+ qWarning("Failed to rebuild depth-stencil buffer for QRhiWidget with new size");
+ return false;
+ }
+ }
+
+ if (!renderTarget) {
+ QRhiColorAttachment color0;
+ if (colorTexture)
+ color0.setTexture(colorTexture);
+ else
+ color0.setRenderBuffer(msaaColorBuffer);
+ if (samples > 1)
+ color0.setResolveTexture(resolveTexture);
+ QRhiTextureRenderTargetDescription rtDesc(color0, depthStencilBuffer);
+ renderTarget = rhi->newTextureRenderTarget(rtDesc);
+ renderPassDescriptor = renderTarget->newCompatibleRenderPassDescriptor();
+ renderTarget->setRenderPassDescriptor(renderPassDescriptor);
+ if (!renderTarget->create()) {
+ qWarning("Failed to create render target for QRhiWidget");
+ resetRenderTargetObjects();
+ return false;
+ }
+ }
+ } else {
+ resetRenderTargetObjects();
+ }
+
+ q->initialize(cb);
+
+ return true;
+}
+
+/*!
+ \return the currently set graphics API (QRhi backend).
+
+ \sa setApi()
+ */
+QRhiWidget::Api QRhiWidget::api() const
+{
+ Q_D(const QRhiWidget);
+ switch (d->config.api()) {
+ case QPlatformBackingStoreRhiConfig::OpenGL:
+ return Api::OpenGL;
+ case QPlatformBackingStoreRhiConfig::Metal:
+ return Api::Metal;
+ case QPlatformBackingStoreRhiConfig::Vulkan:
+ return Api::Vulkan;
+ case QPlatformBackingStoreRhiConfig::D3D11:
+ return Api::Direct3D11;
+ case QPlatformBackingStoreRhiConfig::D3D12:
+ return Api::Direct3D12;
+ case QPlatformBackingStoreRhiConfig::Null:
+ return Api::Null;
+ }
+ Q_UNREACHABLE_RETURN(Api::Null);
+}
+
+/*!
+ Sets the graphics API and QRhi backend to use to \a api.
+
+ \warning This function must be called early enough, before the widget is
+ added to a widget hierarchy and displayed on screen. For example, aim to
+ call the function for the subclass constructor. If called too late, the
+ function will have no effect.
+
+ The default value depends on the platform: Metal on macOS and iOS, Direct
+ 3D 11 on Windows, OpenGL otherwise.
+
+ The \a api can only be set once for the widget and its top-level window,
+ once it is done and takes effect, the window can only use that API and QRhi
+ backend to render. Attempting to set another value, or to add another
+ QRhiWidget with a different \a api will not function as expected.
+
+ \sa setColorBufferFormat(), setDebugLayerEnabled(), api()
+ */
+void QRhiWidget::setApi(Api api)
+{
+ Q_D(QRhiWidget);
+ switch (api) {
+ case Api::OpenGL:
+ d->config.setApi(QPlatformBackingStoreRhiConfig::OpenGL);
+ break;
+ case Api::Metal:
+ d->config.setApi(QPlatformBackingStoreRhiConfig::Metal);
+ break;
+ case Api::Vulkan:
+ d->config.setApi(QPlatformBackingStoreRhiConfig::Vulkan);
+ break;
+ case Api::Direct3D11:
+ d->config.setApi(QPlatformBackingStoreRhiConfig::D3D11);
+ break;
+ case Api::Direct3D12:
+ d->config.setApi(QPlatformBackingStoreRhiConfig::D3D12);
+ break;
+ case Api::Null:
+ d->config.setApi(QPlatformBackingStoreRhiConfig::Null);
+ break;
+ }
+}
+
+/*!
+ \return true if a debug or validation layer will be requested if applicable
+ to the graphics API in use.
+
+ \sa setDebugLayerEnabled()
+ */
+bool QRhiWidget::isDebugLayerEnabled() const
+{
+ Q_D(const QRhiWidget);
+ return d->config.isDebugLayerEnabled();
+}
+
+/*!
+ Requests the debug or validation layer of the underlying graphics API
+ when \a enable is true.
+
+ \warning This function must be called early enough, before the widget is added
+ to a widget hierarchy and displayed on screen. For example, aim to call the
+ function for the subclass constructor. If called too late, the function
+ will have no effect.
+
+ Applicable for Vulkan and Direct 3D.
+
+ By default this is disabled.
+
+ \sa setApi(), isDebugLayerEnabled()
+ */
+void QRhiWidget::setDebugLayerEnabled(bool enable)
+{
+ Q_D(QRhiWidget);
+ d->config.setDebugLayer(enable);
+}
+
+/*!
+ \property QRhiWidget::colorBufferFormat
+
+ This property controls the texture format of the texture (or renderbuffer)
+ used as the color buffer. The default value is TextureFormat::RGBA8.
+ QRhiWidget supports rendering to a subset of the formats supported by \l
+ QRhiTexture. Only formats that are reported as supported from \l
+ QRhi::isTextureFormatSupported() should be specified, rendering will not be
+ functional otherwise.
+
+ \note Setting a new format when the widget is already initialized and has
+ rendered implies that all QRhiGraphicsPipeline objects created by the
+ renderer may become unusable, if the associated QRhiRenderPassDescriptor is
+ now incompatible due to the different texture format. Similarly to changing
+ \l sampleCount dynamically, this means that initialize() or render()
+ implementations must then take care of releasing the existing pipelines and
+ creating new ones.
+ */
+
+QRhiWidget::TextureFormat QRhiWidget::colorBufferFormat() const
+{
+ Q_D(const QRhiWidget);
+ return d->widgetTextureFormat;
+}
+
+void QRhiWidget::setColorBufferFormat(TextureFormat format)
+{
+ Q_D(QRhiWidget);
+ if (d->widgetTextureFormat != format) {
+ d->widgetTextureFormat = format;
+ switch (format) {
+ case TextureFormat::RGBA8:
+ d->rhiTextureFormat = QRhiTexture::RGBA8;
+ break;
+ case TextureFormat::RGBA16F:
+ d->rhiTextureFormat = QRhiTexture::RGBA16F;
+ break;
+ case TextureFormat::RGBA32F:
+ d->rhiTextureFormat = QRhiTexture::RGBA32F;
+ break;
+ case TextureFormat::RGB10A2:
+ d->rhiTextureFormat = QRhiTexture::RGB10A2;
+ break;
+ }
+ emit colorBufferFormatChanged(format);
+ update();
+ }
+}
+
+/*!
+ \property QRhiWidget::sampleCount
+
+ This property controls for sample count for multisample antialiasing.
+ By default the value is \c 1 which means MSAA is disabled.
+
+ Valid values are 1, 4, 8, and sometimes 16 and 32.
+ \l QRhi::supportedSampleCounts() can be used to query the supported sample
+ counts at run time, but typically applications should request 1 (no MSAA),
+ 4x (normal MSAA) or 8x (high MSAA).
+
+ \note Setting a new value implies that all QRhiGraphicsPipeline objects
+ created by the renderer must use the same sample count from then on.
+ Existing QRhiGraphicsPipeline objects created with a different sample count
+ must not be used anymore. When the value changes, all color and
+ depth-stencil buffers are destroyed and recreated automatically, and
+ initialize() is invoked again. However, when
+ \l autoRenderTarget is \c false, it will be up to the application to
+ manage this with regards to the depth-stencil buffer or additional color
+ buffers.
+
+ Changing the sample count from the default 1 to a higher value implies that
+ colorTexture() becomes \nullptr and msaaColorBuffer() starts returning a
+ valid object. Switching back to 1 (or 0), implies the opposite: in the next
+ call to initialize() msaaColorBuffer() is going to return \nullptr, whereas
+ colorTexture() becomes once again valid. In addition, resolveTexture()
+ returns a valid (non-multisample) QRhiTexture whenever the sample count is
+ greater than 1 (i.e., MSAA is in use).
+
+ \sa msaaColorBuffer(), resolveTexture()
+ */
+
+int QRhiWidget::sampleCount() const
+{
+ Q_D(const QRhiWidget);
+ return d->samples;
+}
+
+void QRhiWidget::setSampleCount(int samples)
+{
+ Q_D(QRhiWidget);
+ if (d->samples != samples) {
+ d->samples = samples;
+ emit sampleCountChanged(samples);
+ update();
+ }
+}
+
+/*!
+ \property QRhiWidget::fixedColorBufferSize
+
+ The fixed size, in pixels, of the QRhiWidget's associated texture. Relevant
+ when a fixed texture size is desired that does not depend on the widget's
+ size. This size has no effect on the geometry of the widget (its size and
+ placement within the top-level window), which means the texture's content
+ will appear stretched (scaled up) or scaled down onto the widget's area.
+
+ For example, setting a size that is exactly twice the widget's (pixel) size
+ effectively performs 2x supersampling (rendering at twice the resolution
+ and then implicitly scaling down when texturing the quad corresponding to
+ the widget in the window).
+
+ By default the value is a null QSize. A null or empty QSize means that the
+ texture's size follows the QRhiWidget's size. (\c{texture size} = \c{widget
+ size} * \c{device pixel ratio}).
+ */
+
+QSize QRhiWidget::fixedColorBufferSize() const
+{
+ Q_D(const QRhiWidget);
+ return d->fixedSize;
+}
+
+void QRhiWidget::setFixedColorBufferSize(QSize pixelSize)
+{
+ Q_D(QRhiWidget);
+ if (d->fixedSize != pixelSize) {
+ d->fixedSize = pixelSize;
+ emit fixedColorBufferSizeChanged(pixelSize);
+ update();
+ }
+}
+
+/*!
+ \property QRhiWidget::mirrorVertically
+
+ When enabled, flips the image around the X axis when compositing the
+ QRhiWidget's backing texture with the rest of the widget content in the
+ top-level window.
+
+ The default value is \c false.
+ */
+
+bool QRhiWidget::isMirrorVerticallyEnabled() const
+{
+ Q_D(const QRhiWidget);
+ return d->mirrorVertically;
+}
+
+void QRhiWidget::setMirrorVertically(bool enabled)
+{
+ Q_D(QRhiWidget);
+ if (d->mirrorVertically != enabled) {
+ d->mirrorVertically = enabled;
+ emit mirrorVerticallyChanged(enabled);
+ update();
+ }
+}
+
+/*!
+ \property QRhiWidget::autoRenderTarget
+
+ The current setting for automatic depth-stencil buffer and render
+ target maintenance.
+
+ By default the value is \c true.
+ */
+bool QRhiWidget::isAutoRenderTargetEnabled() const
+{
+ Q_D(const QRhiWidget);
+ return d->autoRenderTarget;
+}
+
+/*!
+ Controls if a depth-stencil QRhiRenderBuffer and a QRhiTextureRenderTarget
+ is created and maintained automatically by the widget. The default value is
+ \c true.
+
+ In automatic mode, the size and sample count of the depth-stencil buffer
+ follows the color buffer texture's settings. In non-automatic mode,
+ renderTarget() and depthStencilBuffer() always return \nullptr and it is
+ then up to the application's implementation of initialize() to take care of
+ setting up and managing these objects.
+
+ Call this function with \a enabled set to \c false early on, for example in
+ the derived class' constructor, to disable the automatic mode.
+ */
+void QRhiWidget::setAutoRenderTarget(bool enabled)
+{
+ Q_D(QRhiWidget);
+ if (d->autoRenderTarget != enabled) {
+ d->autoRenderTarget = enabled;
+ update();
+ }
+}
+
+/*!
+ Renders a new frame, reads the contents of the texture back, and returns it
+ as a QImage.
+
+ When an error occurs, a null QImage is returned.
+
+ The returned QImage will have a format of QImage::Format_RGBA8888,
+ QImage::Format_RGBA16FPx4, QImage::Format_RGBA32FPx4, or
+ QImage::Format_BGR30, depending on colorBufferFormat().
+
+ QRhiWidget does not know the renderer's approach to blending and
+ composition, and therefore cannot know if the output has alpha
+ premultiplied in the RGB color values. Thus \c{_Premultiplied} QImage
+ formats are never used for the returned QImage, even when it would be
+ appropriate. It is up to the caller to reinterpret the resulting data as it
+ sees fit.
+
+ \note This function can also be called when the QRhiWidget is not added to
+ a widget hierarchy belonging to an on-screen top-level window. This allows
+ generating an image from a 3D rendering off-screen.
+
+ The function is named grabFramebuffer() for consistency with QOpenGLWidget
+ and QQuickWidget. It is not the only way to get CPU-side image data out of
+ the QRhiWidget's content: calling \l QWidget::grab() on a QRhiWidget, or an
+ ancestor of it, is functional as well (returning a QPixmap). Besides
+ working directly with QImage, another advantage of grabFramebuffer() is
+ that it may be slightly more performant, simply because it does not have to
+ go through the rest of QWidget infrastructure but can right away trigger
+ rendering a new frame and then do the readback.
+
+ \sa setColorBufferFormat()
+ */
+QImage QRhiWidget::grabFramebuffer() const
+{
+ return const_cast<QRhiWidgetPrivate *>(d_func())->grabFramebuffer();
+}
+
+/*!
+ Called when the widget is initialized for the first time, when the
+ associated texture's size, format, or sample count changes, or when the
+ QRhi and texture change for any reason. The function is expected to
+ maintain (create if not yet created, adjust and rebuild if the size has
+ changed) the graphics resources used by the rendering code in render().
+
+ To query the QRhi, QRhiTexture, and other related objects, call rhi(),
+ colorTexture(), depthStencilBuffer(), and renderTarget().
+
+ When the widget size changes, the QRhi object, the color buffer texture,
+ and the depth stencil buffer objects are all the same instances (so the
+ getters return the same pointers) as before, but the color and
+ depth/stencil buffers will likely have been rebuilt, meaning the
+ \l{QRhiTexture::pixelSize()}{size} and the underlying native texture
+ resource may be different than in the last invocation.
+
+ Reimplementations should also be prepared that the QRhi object and the
+ color buffer texture may change between invocations of this function. One
+ special case where the objects will be different is when performing a
+ grabFramebuffer() with a widget that is not yet shown, and then making the
+ widget visible on-screen within a top-level widget. There the grab will
+ happen with a dedicated QRhi that is then replaced with the top-level
+ window's associated QRhi in subsequent initialize() and render()
+ invocations. Another, more common case is when the widget is reparented so
+ that it belongs to a new top-level window. In this case the QRhi and all
+ related resources managed by the QRhiWidget will be different instances
+ than before in the subsequent call to this function. Is is then important
+ that all existing QRhi resources previously created by the subclass are
+ destroyed because they belong to the previous QRhi that should not be used
+ by the widget anymore.
+
+ When \l autoRenderTarget is \c true, which is the default, a
+ depth-stencil QRhiRenderBuffer and a QRhiTextureRenderTarget associated
+ with colorTexture() (or msaaColorBuffer()) and the depth-stencil buffer are
+ created and managed automatically. Reimplementations of initialize() and
+ render() can query those objects via depthStencilBuffer() and
+ renderTarget(). When \l autoRenderTarget is set to \c false, these
+ objects are no longer created and managed automatically. Rather, it will be
+ up the the initialize() implementation to create buffers and set up the
+ render target as it sees fit. When manually managing additional color or
+ depth-stencil attachments for the render target, their size and sample
+ count must always follow the size and sample count of colorTexture() /
+ msaaColorBuffer(), otherwise rendering or 3D API validation errors may
+ occur.
+
+ The subclass-created graphics resources are expected to be released in the
+ destructor implementation of the subclass.
+
+ \a cb is the QRhiCommandBuffer for the current frame of the widget. The
+ function is called with a frame being recorded, but without an active
+ render pass. The command buffer is provided primarily to allow enqueuing
+ \l{QRhiCommandBuffer::resourceUpdate()}{resource updates} without deferring
+ to render().
+
+ \sa render()
+ */
+void QRhiWidget::initialize(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+}
+
+/*!
+ Called when the widget contents (i.e. the contents of the texture) need
+ updating.
+
+ There is always at least one call to initialize() before this function is
+ called.
+
+ To request updates, call QWidget::update(). Calling update() from within
+ render() will lead to updating continuously, throttled by vsync.
+
+ \a cb is the QRhiCommandBuffer for the current frame of the widget. The
+ function is called with a frame being recorded, but without an active
+ render pass.
+
+ \sa initialize()
+ */
+void QRhiWidget::render(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+}
+
+/*!
+ Called when the need to early-release the graphics resources arises.
+
+ This normally does not happen for a QRhiWidget that is added to a top-level
+ widget's child hierarchy and it then stays there for the rest of its and
+ the top-level's lifetime. Thus in many cases there is no need to
+ reimplement this function, e.g. because the application only ever has a
+ single top-level widget (native window). However, when reparenting of the
+ widget (or an ancestor of it) is involved, reimplementing this function
+ will become necessary in robust, well-written QRhiWidget subclasses.
+
+ When this function is called, the implementation is expected to destroy all
+ QRhi resources (QRhiBuffer, QRhiTexture, etc. objects), similarly to how it
+ is expected to do this in the destructor. Nulling out, using a smart
+ pointer, or setting a \c{resources-invalid} flag is going to be required as
+ well, because initialize() will eventually get called afterwards. Note
+ however that deferring the releasing of resources to the subsequent
+ initialize() is wrong. If this function is called, the resource must be
+ dropped before returning. Also note that implementing this function does
+ not replace the class destructor (or smart pointers): the graphics
+ resources must still be released in both.
+
+ See the \l{Cube RHI Widget Example} for an example of this in action. There
+ the button that toggles the QRhiWidget between being a child widget (due to
+ having a parent widget) and being a top-level widget (due to having no
+ parent widget), will trigger invoking this function since the associated
+ top-level widget, native window, and QRhi all change during the lifetime of
+ the QRhiWidget, with the previously used QRhi getting destroyed which
+ implies an early-release of the associated resources managed by the
+ still-alive QRhiWidget.
+
+ Another case when this function is called is when grabFramebuffer() is used
+ with a QRhiWidget that is not added to a visible window, i.e. the rendering
+ is performed offscreen. If later on this QRhiWidget is made visible, or
+ added to a visible widget hierarchy, the associated QRhi will change from
+ the temporary one used for offscreen rendering to the window's dedicated
+ one, thus triggering this function as well.
+
+ \sa initialize()
+ */
+void QRhiWidget::releaseResources()
+{
+}
+
+/*!
+ \return the current QRhi object.
+
+ Must only be called from initialize() and render().
+ */
+QRhi *QRhiWidget::rhi() const
+{
+ Q_D(const QRhiWidget);
+ return d->rhi;
+}
+
+/*!
+ \return the texture serving as the color buffer for the widget.
+
+ Must only be called from initialize() and render().
+
+ Unlike the depth-stencil buffer and the QRhiRenderTarget, this texture is
+ always available and is managed by the QRhiWidget, independent of the value
+ of \l autoRenderTarget.
+
+ \note When \l sampleCount is larger than 1, and so multisample antialiasing
+ is enabled, the return value is \nullptr. Instead, query the
+ \l QRhiRenderBuffer by calling msaaColorBuffer().
+
+ \note The backing texture size and sample count can also be queried via the
+ QRhiRenderTarget returned from renderTarget(). This can be more convenient
+ and compact than querying from the QRhiTexture or QRhiRenderBuffer, because
+ it works regardless of multisampling is in use or not.
+
+ \sa msaaColorBuffer(), depthStencilBuffer(), renderTarget(), resolveTexture()
+ */
+QRhiTexture *QRhiWidget::colorTexture() const
+{
+ Q_D(const QRhiWidget);
+ return d->colorTexture;
+}
+
+/*!
+ \return the renderbuffer serving as the multisample color buffer for the widget.
+
+ Must only be called from initialize() and render().
+
+ When \l sampleCount is larger than 1, and so multisample antialising is
+ enabled, the returned QRhiRenderBuffer has a matching sample count and
+ serves as the color buffer. Graphics pipelines used to render into this
+ buffer must be created with the same sample count, and the depth-stencil
+ buffer's sample count must match as well. The multisample content is
+ expected to be resolved into the texture returned from resolveTexture().
+ When \l autoRenderTarget is
+ \c true, renderTarget() is set up automatically to do this, by setting up
+ msaaColorBuffer() as the \l{QRhiColorAttachment::renderBuffer()}{renderbuffer} of
+ color attachment 0 and resolveTexture() as its
+ \l{QRhiColorAttachment::resolveTexture()}{resolveTexture}.
+
+ When MSAA is not in use, the return value is \nullptr. Use colorTexture()
+ instead then.
+
+ Depending on the underlying 3D graphics API, there may be no practical
+ difference between multisample textures and color renderbuffers with a
+ sample count larger than 1 (QRhi may just map both to the same native
+ resource type). Some older APIs however may differentiate between textures
+ and renderbuffers. In order to support OpenGL ES 3.0, where multisample
+ renderbuffers are available, but multisample textures are not, QRhiWidget
+ always performs MSAA by using a multisample QRhiRenderBuffer as the color
+ attachment (and never a multisample QRhiTexture).
+
+ \note The backing texture size and sample count can also be queried via the
+ QRhiRenderTarget returned from renderTarget(). This can be more convenient
+ and compact than querying from the QRhiTexture or QRhiRenderBuffer, because
+ it works regardless of multisampling is in use or not.
+
+ \sa colorTexture(), depthStencilBuffer(), renderTarget(), resolveTexture()
+ */
+QRhiRenderBuffer *QRhiWidget::msaaColorBuffer() const
+{
+ Q_D(const QRhiWidget);
+ return d->msaaColorBuffer;
+}
+
+/*!
+ \return the non-multisample texture to which the multisample content is resolved.
+
+ The result is \nullptr when multisample antialiasing is not enabled.
+
+ Must only be called from initialize() and render().
+
+ With MSAA enabled, this is the texture that gets composited with the rest
+ of the QWidget content on-screen. However, the QRhiWidget's rendering must
+ target the (multisample) QRhiRenderBuffer returned from
+ msaaColorBuffer(). When
+ \l autoRenderTarget is \c true, this is taken care of by the
+ QRhiRenderTarget returned from renderTarget(). Otherwise, it is up to the
+ subclass code to correctly configure a render target object with both the
+ color buffer and resolve textures.
+
+ \sa colorTexture()
+ */
+QRhiTexture *QRhiWidget::resolveTexture() const
+{
+ Q_D(const QRhiWidget);
+ return d->resolveTexture;
+}
+
+/*!
+ \return the depth-stencil buffer used by the widget's rendering.
+
+ Must only be called from initialize() and render().
+
+ Available only when \l autoRenderTarget is \c true. Otherwise the
+ returned value is \nullptr and it is up the reimplementation of
+ initialize() to create and manage a depth-stencil buffer and a
+ QRhiTextureRenderTarget.
+
+ \sa colorTexture(), renderTarget()
+ */
+QRhiRenderBuffer *QRhiWidget::depthStencilBuffer() const
+{
+ Q_D(const QRhiWidget);
+ return d->depthStencilBuffer;
+}
+
+/*!
+ \return the render target object that must be used with
+ \l QRhiCommandBuffer::beginPass() in reimplementations of render().
+
+ Must only be called from initialize() and render().
+
+ Available only when \l autoRenderTarget is \c true. Otherwise the
+ returned value is \nullptr and it is up the reimplementation of
+ initialize() to create and manage a depth-stencil buffer and a
+ QRhiTextureRenderTarget.
+
+ When creating \l{QRhiGraphicsPipeline}{graphics pipelines}, a
+ QRhiRenderPassDescriptor is needed. This can be queried from the returned
+ QRhiTextureRenderTarget by calling
+ \l{QRhiTextureRenderTarget::renderPassDescriptor()}{renderPassDescriptor()}.
+
+ \sa colorTexture(), depthStencilBuffer()
+ */
+QRhiRenderTarget *QRhiWidget::renderTarget() const
+{
+ Q_D(const QRhiWidget);
+ return d->renderTarget;
+}
+
+/*!
+ \fn void QRhiWidget::frameSubmitted()
+
+ This signal is emitted after the widget's top-level window has finished
+ composition and has \l{QRhi::endFrame()}{submitted a frame}.
+*/
+
+/*!
+ \fn void QRhiWidget::renderFailed()
+
+ This signal is emitted whenever the widget is supposed to render to its
+ backing texture (either due to a \l{QWidget::update()}{widget update} or
+ due to a call to grabFramebuffer()), but there is no \l QRhi for the widget to
+ use, likely due to issues related to graphics configuration.
+
+ This signal may be emitted multiple times when a problem arises. Do not
+ assume it is emitted only once. Connect with Qt::SingleShotConnection if
+ the error handling code is to be notified only once.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qrhiwidget.h b/src/widgets/kernel/qrhiwidget.h
new file mode 100644
index 0000000000..45fe7b7482
--- /dev/null
+++ b/src/widgets/kernel/qrhiwidget.h
@@ -0,0 +1,101 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHIWIDGET_H
+#define QRHIWIDGET_H
+
+#include <QtWidgets/qwidget.h>
+
+QT_BEGIN_NAMESPACE
+
+class QRhiWidgetPrivate;
+class QRhi;
+class QRhiTexture;
+class QRhiRenderBuffer;
+class QRhiRenderTarget;
+class QRhiCommandBuffer;
+
+class Q_WIDGETS_EXPORT QRhiWidget : public QWidget
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QRhiWidget)
+ Q_PROPERTY(int sampleCount READ sampleCount WRITE setSampleCount NOTIFY sampleCountChanged)
+ Q_PROPERTY(TextureFormat colorBufferFormat READ colorBufferFormat WRITE setColorBufferFormat NOTIFY colorBufferFormatChanged)
+ Q_PROPERTY(QSize fixedColorBufferSize READ fixedColorBufferSize WRITE setFixedColorBufferSize NOTIFY fixedColorBufferSizeChanged)
+ Q_PROPERTY(bool mirrorVertically READ isMirrorVerticallyEnabled WRITE setMirrorVertically NOTIFY mirrorVerticallyChanged)
+ QDOC_PROPERTY(bool autoRenderTarget READ isAutoRenderTargetEnabled WRITE setAutoRenderTarget)
+
+public:
+ explicit QRhiWidget(QWidget *parent = nullptr, Qt::WindowFlags f = {});
+ ~QRhiWidget() override;
+
+ enum class Api {
+ Null,
+ OpenGL,
+ Metal,
+ Vulkan,
+ Direct3D11,
+ Direct3D12,
+ };
+ Q_ENUM(Api)
+
+ enum class TextureFormat {
+ RGBA8,
+ RGBA16F,
+ RGBA32F,
+ RGB10A2,
+ };
+ Q_ENUM(TextureFormat)
+
+ Api api() const;
+ void setApi(Api api);
+
+ bool isDebugLayerEnabled() const;
+ void setDebugLayerEnabled(bool enable);
+
+ int sampleCount() const;
+ void setSampleCount(int samples);
+
+ TextureFormat colorBufferFormat() const;
+ void setColorBufferFormat(TextureFormat format);
+
+ QSize fixedColorBufferSize() const;
+ void setFixedColorBufferSize(QSize pixelSize);
+ void setFixedColorBufferSize(int w, int h) { setFixedColorBufferSize(QSize(w, h)); }
+
+ bool isMirrorVerticallyEnabled() const;
+ void setMirrorVertically(bool enabled);
+
+ QImage grabFramebuffer() const;
+
+protected:
+ bool isAutoRenderTargetEnabled() const;
+ void setAutoRenderTarget(bool enabled);
+
+ virtual void initialize(QRhiCommandBuffer *cb);
+ virtual void render(QRhiCommandBuffer *cb);
+ virtual void releaseResources();
+
+ QRhi *rhi() const;
+ QRhiTexture *colorTexture() const;
+ QRhiRenderBuffer *msaaColorBuffer() const;
+ QRhiTexture *resolveTexture() const;
+ QRhiRenderBuffer *depthStencilBuffer() const;
+ QRhiRenderTarget *renderTarget() const;
+
+ void resizeEvent(QResizeEvent *e) override;
+ void paintEvent(QPaintEvent *e) override;
+ bool event(QEvent *e) override;
+
+Q_SIGNALS:
+ void frameSubmitted();
+ void renderFailed();
+ void sampleCountChanged(int samples);
+ void colorBufferFormatChanged(TextureFormat format);
+ void fixedColorBufferSizeChanged(const QSize &pixelSize);
+ void mirrorVerticallyChanged(bool enabled);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/widgets/kernel/qrhiwidget_p.h b/src/widgets/kernel/qrhiwidget_p.h
new file mode 100644
index 0000000000..b594b67ec8
--- /dev/null
+++ b/src/widgets/kernel/qrhiwidget_p.h
@@ -0,0 +1,64 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHIWIDGET_P_H
+#define QRHIWIDGET_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrhiwidget.h"
+#include <rhi/qrhi.h>
+#include <private/qwidget_p.h>
+#include <private/qbackingstorerhisupport_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QRhiWidgetPrivate : public QWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(QRhiWidget)
+public:
+ TextureData texture() const override;
+ QPlatformTextureList::Flags textureListFlags() override;
+ QPlatformBackingStoreRhiConfig rhiConfig() const override;
+ void endCompose() override;
+ QImage grabFramebuffer() override;
+
+ void ensureRhi();
+ void ensureTexture(bool *changed);
+ bool invokeInitialize(QRhiCommandBuffer *cb);
+ void resetColorBufferObjects();
+ void resetRenderTargetObjects();
+ void releaseResources();
+
+ QRhi *rhi = nullptr;
+ bool noSize = false;
+ QPlatformBackingStoreRhiConfig config;
+ QRhiWidget::TextureFormat widgetTextureFormat = QRhiWidget::TextureFormat::RGBA8;
+ QRhiTexture::Format rhiTextureFormat = QRhiTexture::RGBA8;
+ int samples = 1;
+ QSize fixedSize;
+ bool autoRenderTarget = true;
+ bool mirrorVertically = false;
+ QBackingStoreRhiSupport offscreenRenderer;
+ bool textureInvalid = false;
+ QRhiTexture *colorTexture = nullptr;
+ QRhiRenderBuffer *msaaColorBuffer = nullptr;
+ QRhiTexture *resolveTexture = nullptr;
+ QRhiRenderBuffer *depthStencilBuffer = nullptr;
+ QRhiTextureRenderTarget *renderTarget = nullptr;
+ QRhiRenderPassDescriptor *renderPassDescriptor = nullptr;
+ mutable QVector<QRhiResource *> pendingDeletes;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/widgets/kernel/qshortcut.h b/src/widgets/kernel/qshortcut.h
index c09cf23ca4..6cec8d45ea 100644
--- a/src/widgets/kernel/qshortcut.h
+++ b/src/widgets/kernel/qshortcut.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/QShortcut>
diff --git a/src/widgets/kernel/qshortcut_widgets.cpp b/src/widgets/kernel/qshortcut_widgets.cpp
index 8beb4ce5d6..6e25d79bd6 100644
--- a/src/widgets/kernel/qshortcut_widgets.cpp
+++ b/src/widgets/kernel/qshortcut_widgets.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qshortcut.h"
#include "private/qshortcut_p.h"
@@ -101,9 +65,6 @@ bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context)
}
}
- if (!active_window)
- return false;
-
#if QT_CONFIG(action)
if (auto a = qobject_cast<QAction *>(object))
return correctActionContext(context, a, active_window);
@@ -117,7 +78,7 @@ bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context)
auto w = qobject_cast<QWidget *>(object);
if (!w) {
if (auto s = qobject_cast<QShortcut *>(object))
- w = s->parentWidget();
+ w = qobject_cast<QWidget *>(s->parent());
}
if (!w) {
@@ -131,14 +92,17 @@ bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context)
}
}
- if (!w)
- return false;
+ if (w)
+ return correctWidgetContext(context, w, active_window);
- return correctWidgetContext(context, w, active_window);
+ return QShortcutPrivate::simpleContextMatcher(object, context);
}
static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidget *active_window)
{
+ if (!active_window)
+ return false;
+
bool visible = w->isVisible();
#if QT_CONFIG(menubar)
if (auto menuBar = qobject_cast<QMenuBar *>(w)) {
@@ -224,6 +188,9 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge
#if QT_CONFIG(graphicsview)
static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsWidget *w, QWidget *active_window)
{
+ if (!active_window)
+ return false;
+
bool visible = w->isVisible();
#if defined(Q_OS_DARWIN) && QT_CONFIG(menubar)
if (!QCoreApplication::testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w))
@@ -283,6 +250,9 @@ static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsW
#if QT_CONFIG(action)
static bool correctActionContext(Qt::ShortcutContext context, QAction *a, QWidget *active_window)
{
+ if (!active_window)
+ return false;
+
const QObjectList associatedObjects = a->associatedObjects();
#if defined(DEBUG_QSHORTCUTMAP)
if (associatedObjects.isEmpty())
diff --git a/src/widgets/kernel/qsizepolicy.cpp b/src/widgets/kernel/qsizepolicy.cpp
index fe34ef5982..b883c1ed6f 100644
--- a/src/widgets/kernel/qsizepolicy.cpp
+++ b/src/widgets/kernel/qsizepolicy.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsizepolicy.h"
diff --git a/src/widgets/kernel/qsizepolicy.h b/src/widgets/kernel/qsizepolicy.h
index 53c7afc906..af964bf6af 100644
--- a/src/widgets/kernel/qsizepolicy.h
+++ b/src/widgets/kernel/qsizepolicy.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSIZEPOLICY_H
#define QSIZEPOLICY_H
@@ -198,6 +162,7 @@ private:
Q_DECLARE_TYPEINFO(QSizePolicy, Q_PRIMITIVE_TYPE);
Q_DECLARE_OPERATORS_FOR_FLAGS(QSizePolicy::ControlTypes)
+Q_DECLARE_MIXED_ENUM_OPERATORS(int, QSizePolicy::Policy, QSizePolicy::PolicyFlag)
#ifndef QT_NO_DATASTREAM
Q_WIDGETS_EXPORT QDataStream &operator<<(QDataStream &, const QSizePolicy &);
diff --git a/src/widgets/kernel/qstackedlayout.cpp b/src/widgets/kernel/qstackedlayout.cpp
index 2f3d6f39cb..04eacf1d41 100644
--- a/src/widgets/kernel/qstackedlayout.cpp
+++ b/src/widgets/kernel/qstackedlayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstackedlayout.h"
#include "qlayout_p.h"
@@ -44,6 +8,8 @@
#include "private/qwidget_p.h"
#include "private/qlayoutengine_p.h"
+#include <QtCore/qpointer.h>
+
#include <memory>
QT_BEGIN_NAMESPACE
@@ -202,7 +168,7 @@ QStackedLayout::~QStackedLayout()
int QStackedLayout::addWidget(QWidget *widget)
{
Q_D(QStackedLayout);
- return insertWidget(d->list.count(), widget);
+ return insertWidget(d->list.size(), widget);
}
/*!
@@ -223,9 +189,9 @@ int QStackedLayout::insertWidget(int index, QWidget *widget)
{
Q_D(QStackedLayout);
addChildWidget(widget);
- index = qMin(index, d->list.count());
+ index = qMin(index, d->list.size());
if (index < 0)
- index = d->list.count();
+ index = d->list.size();
QWidgetItem *wi = QLayoutPrivate::createWidgetItem(this, widget);
d->list.insert(index, wi);
invalidate();
@@ -270,8 +236,8 @@ QLayoutItem *QStackedLayout::takeAt(int index)
QLayoutItem *item = d->list.takeAt(index);
if (index == d->index) {
d->index = -1;
- if ( d->list.count() > 0 ) {
- int newIndex = (index == d->list.count()) ? index-1 : index;
+ if ( d->list.size() > 0 ) {
+ int newIndex = (index == d->list.size()) ? index-1 : index;
setCurrentIndex(newIndex);
} else {
emit currentChanged(-1);
@@ -439,7 +405,7 @@ QSize QStackedLayout::sizeHint() const
{
Q_D(const QStackedLayout);
QSize s(0, 0);
- int n = d->list.count();
+ int n = d->list.size();
for (int i = 0; i < n; ++i)
if (QWidget *widget = d->list.at(i)->widget()) {
@@ -460,7 +426,7 @@ QSize QStackedLayout::minimumSize() const
{
Q_D(const QStackedLayout);
QSize s(0, 0);
- int n = d->list.count();
+ int n = d->list.size();
for (int i = 0; i < n; ++i)
if (QWidget *widget = d->list.at(i)->widget())
@@ -480,7 +446,7 @@ void QStackedLayout::setGeometry(const QRect &rect)
widget->setGeometry(rect);
break;
case StackAll:
- if (const int n = d->list.count())
+ if (const int n = d->list.size())
for (int i = 0; i < n; ++i)
if (QWidget *widget = d->list.at(i)->widget())
widget->setGeometry(rect);
@@ -567,7 +533,7 @@ void QStackedLayout::setStackingMode(StackingMode stackingMode)
return;
d->stackingMode = stackingMode;
- const int n = d->list.count();
+ const int n = d->list.size();
if (n == 0)
return;
diff --git a/src/widgets/kernel/qstackedlayout.h b/src/widgets/kernel/qstackedlayout.h
index 966ee2aae4..91d7d1e9f5 100644
--- a/src/widgets/kernel/qstackedlayout.h
+++ b/src/widgets/kernel/qstackedlayout.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTACKEDLAYOUT_H
#define QSTACKEDLAYOUT_H
diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp
index 32faa7d1d4..4effc1a2d1 100644
--- a/src/widgets/kernel/qstandardgestures.cpp
+++ b/src/widgets/kernel/qstandardgestures.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstandardgestures_p.h"
#include "qgesture.h"
diff --git a/src/widgets/kernel/qstandardgestures_p.h b/src/widgets/kernel/qstandardgestures_p.h
index 6de09361fe..ef1c1cb97c 100644
--- a/src/widgets/kernel/qstandardgestures_p.h
+++ b/src/widgets/kernel/qstandardgestures_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTANDARDGESTURES_P_H
#define QSTANDARDGESTURES_P_H
diff --git a/src/widgets/kernel/qt_widgets_pch.h b/src/widgets/kernel/qt_widgets_pch.h
index 954e50f7a3..213e2c23e0 100644
--- a/src/widgets/kernel/qt_widgets_pch.h
+++ b/src/widgets/kernel/qt_widgets_pch.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
* This is a precompiled header file for use in Xcode / Mac GCC /
diff --git a/src/widgets/kernel/qtestsupport_widgets.cpp b/src/widgets/kernel/qtestsupport_widgets.cpp
index c9116fcef6..f7b25b6643 100644
--- a/src/widgets/kernel/qtestsupport_widgets.cpp
+++ b/src/widgets/kernel/qtestsupport_widgets.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtTest 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$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtestsupport_widgets.h"
@@ -46,48 +10,101 @@
#include <QtCore/qthread.h>
#include <QtGui/qtestsupport_gui.h>
#include <QtGui/private/qevent_p.h>
+#include <QtGui/private/qeventpoint_p.h>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
QT_BEGIN_NAMESPACE
+template <typename FunctorWindowGetter, typename FunctorPredicate, typename Timeout>
+static bool qWaitForWidgetWindow(FunctorWindowGetter windowGetter, FunctorPredicate predicate, Timeout timeout)
+{
+ if (!windowGetter())
+ return false;
+
+ return QTest::qWaitFor([&]() {
+ if (QWindow *window = windowGetter())
+ return predicate(window);
+ return false;
+ }, timeout);
+}
+
/*!
\since 5.0
- Waits for \a timeout milliseconds or until the \a widget's window is active.
+ Returns \c true if \a widget is active within \a timeout milliseconds. Otherwise returns \c false.
+
+ The method is useful in tests that call QWidget::show() and rely on the widget actually being
+ active (i.e. being visible and having focus) before proceeding.
+
+ \note The method will time out and return \c false if another window prevents \a widget from
+ becoming active.
- Returns \c true if \c widget's window is active within \a timeout milliseconds, otherwise returns \c false.
+ \note Since focus is an exclusive property, \a widget may loose its focus to another window at
+ any time - even after the method has returned \c true.
\sa qWaitForWindowExposed(), QWidget::isActiveWindow()
*/
Q_WIDGETS_EXPORT bool QTest::qWaitForWindowActive(QWidget *widget, int timeout)
{
- if (QWindow *window = widget->window()->windowHandle())
- return QTest::qWaitForWindowActive(window, timeout);
- return false;
+ if (Q_UNLIKELY(!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))) {
+ qWarning() << "qWaitForWindowActive was called on a platform that doesn't support window"
+ << "activation. This means there is an error in the test and it should either"
+ << "check for the WindowActivation platform capability before calling"
+ << "qWaitForWindowActivate, use qWaitForWindowExposed instead, or skip the test."
+ << "Falling back to qWaitForWindowExposed.";
+ return qWaitForWindowExposed(widget, timeout);
+ }
+ return qWaitForWidgetWindow([&]() { return widget->window()->windowHandle(); },
+ [&](QWindow *window) { return window->isActive(); },
+ timeout);
}
+
/*!
- \since 5.0
+ \since 6.7
+
+ Returns \c true, if \a widget is the focus window within \a timeout. Otherwise returns \c false.
- Waits for \a timeout milliseconds or until the \a widget's window is exposed.
- Returns \c true if \c widget's window is exposed within \a timeout milliseconds, otherwise returns \c false.
+ The method is useful in tests that call QWidget::show() and rely on the widget
+ having focus (for receiving keyboard events e.g.) before proceeding.
+
+ \note The method will time out and return \c false if another window prevents \a widget from
+ becoming focused.
+
+ \note Since focus is an exclusive property, \a widget may loose its focus to another window at
+ any time - even after the method has returned \c true.
+
+ \sa qWaitForWindowExposed(), qWaitForWindowActive(), QGuiApplication::focusWindow()
+*/
+Q_WIDGETS_EXPORT bool QTest::qWaitForWindowFocused(QWidget *widget, QDeadlineTimer timeout)
+{
+ return qWaitForWidgetWindow([&]() {
+ return widget->window()->windowHandle();
+ }, [&](QWindow *window) {
+ return qGuiApp->focusWindow() == window;
+ }, timeout);
+}
+
+/*!
+ \since 5.0
- This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
- time after being asked to show itself on the screen.
+ Returns \c true if \a widget is exposed within \a timeout milliseconds. Otherwise returns \c false.
- Note that a window that is mapped to screen may still not be considered exposed if the window client
- area is completely covered by other windows, or if the window is otherwise not visible. This function
- will then time out when waiting for such a window.
+ The method is useful in tests that call QWidget::show() and rely on the widget actually being
+ being visible before proceeding.
- A specific configuration where this happens is when using QGLWidget as a viewport widget on macOS:
- The viewport widget gets the expose event, not the parent widget.
+ \note A window mapped to screen may still not be considered exposed, if the window client area is
+ not visible, e.g. because it is completely covered by other windows.
+ In such cases, the method will time out and return \c false.
- \sa qWaitForWindowActive()
+ \sa qWaitForWindowActive(), QWidget::isVisible(), QWindow::isExposed()
*/
Q_WIDGETS_EXPORT bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout)
{
- if (QWindow *window = widget->window()->windowHandle())
- return QTest::qWaitForWindowExposed(window, timeout);
- return false;
+ return qWaitForWidgetWindow([&]() { return widget->window()->windowHandle(); },
+ [&](QWindow *window) { return window->isExposed(); },
+ timeout);
}
namespace QTest {
@@ -95,52 +112,54 @@ namespace QTest {
QTouchEventWidgetSequence::~QTouchEventWidgetSequence()
{
if (commitWhenDestroyed)
- commit();
+ QTouchEventWidgetSequence::commit();
}
QTouchEventWidgetSequence& QTouchEventWidgetSequence::press(int touchId, const QPoint &pt, QWidget *widget)
{
- auto &p = QMutableEventPoint::from(point(touchId));
- p.setGlobalPosition(mapToScreen(widget, pt));
- p.setState(QEventPoint::State::Pressed);
+ auto &p = point(touchId);
+ QMutableEventPoint::setGlobalPosition(p, mapToScreen(widget, pt));
+ QMutableEventPoint::setState(p, QEventPoint::State::Pressed);
return *this;
}
QTouchEventWidgetSequence& QTouchEventWidgetSequence::move(int touchId, const QPoint &pt, QWidget *widget)
{
- auto &p = QMutableEventPoint::from(point(touchId));
- p.setGlobalPosition(mapToScreen(widget, pt));
- p.setState(QEventPoint::State::Updated);
+ auto &p = point(touchId);
+ QMutableEventPoint::setGlobalPosition(p, mapToScreen(widget, pt));
+ QMutableEventPoint::setState(p, QEventPoint::State::Updated);
return *this;
}
QTouchEventWidgetSequence& QTouchEventWidgetSequence::release(int touchId, const QPoint &pt, QWidget *widget)
{
- auto &p = QMutableEventPoint::from(point(touchId));
- p.setGlobalPosition(mapToScreen(widget, pt));
- p.setState(QEventPoint::State::Released);
+ auto &p = point(touchId);
+ QMutableEventPoint::setGlobalPosition(p, mapToScreen(widget, pt));
+ QMutableEventPoint::setState(p, QEventPoint::State::Released);
return *this;
}
QTouchEventWidgetSequence& QTouchEventWidgetSequence::stationary(int touchId)
{
- auto &p = QMutableEventPoint::from(pointOrPreviousPoint(touchId));
- p.setState(QEventPoint::State::Stationary);
+ auto &p = pointOrPreviousPoint(touchId);
+ QMutableEventPoint::setState(p, QEventPoint::State::Stationary);
return *this;
}
-void QTouchEventWidgetSequence::commit(bool processEvents)
+bool QTouchEventWidgetSequence::commit(bool processEvents)
{
+ bool ret = false;
if (points.isEmpty())
- return;
- QThread::msleep(1);
+ return ret;
+ QThread::sleep(std::chrono::milliseconds{1});
if (targetWindow) {
- qt_handleTouchEvent(targetWindow, device, points.values());
+ ret = qt_handleTouchEventv2(targetWindow, device, points.values());
} else if (targetWidget) {
- qt_handleTouchEvent(targetWidget->windowHandle(), device, points.values());
+ ret = qt_handleTouchEventv2(targetWidget->windowHandle(), device, points.values());
}
if (processEvents)
QCoreApplication::processEvents();
previousPoints = points;
points.clear();
+ return ret;
}
QTest::QTouchEventWidgetSequence::QTouchEventWidgetSequence(QWidget *widget, QPointingDevice *aDevice, bool autoCommit)
diff --git a/src/widgets/kernel/qtestsupport_widgets.h b/src/widgets/kernel/qtestsupport_widgets.h
index b375b7264b..b49e68db65 100644
--- a/src/widgets/kernel/qtestsupport_widgets.h
+++ b/src/widgets/kernel/qtestsupport_widgets.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtTest 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$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTESTSUPPORT_WIDGETS_H
#define QTESTSUPPORT_WIDGETS_H
@@ -51,6 +15,7 @@ class QWidget;
namespace QTest {
[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowActive(QWidget *widget, int timeout = 5000);
+[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowFocused(QWidget *widget, QDeadlineTimer timeout = std::chrono::seconds{5});
[[nodiscard]] Q_WIDGETS_EXPORT bool qWaitForWindowExposed(QWidget *widget, int timeout = 5000);
class Q_WIDGETS_EXPORT QTouchEventWidgetSequence : public QTouchEventSequence
@@ -62,7 +27,7 @@ public:
QTouchEventWidgetSequence& release(int touchId, const QPoint &pt, QWidget *widget = nullptr);
QTouchEventWidgetSequence& stationary(int touchId) override;
- void commit(bool processEvents = true) override;
+ bool commit(bool processEvents = true) override;
private:
QTouchEventWidgetSequence(QWidget *widget, QPointingDevice *aDevice, bool autoCommit);
diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp
index 49de9e0c6a..35eaa8042a 100644
--- a/src/widgets/kernel/qtooltip.cpp
+++ b/src/widgets/kernel/qtooltip.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtWidgets/private/qtwidgetsglobal_p.h>
@@ -62,6 +26,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QToolTip
@@ -79,15 +45,24 @@ QT_BEGIN_NAMESPACE
Rich text displayed in a tool tip is implicitly word-wrapped unless
specified differently with \c{<p style='white-space:pre'>}.
- The simplest and most common way to set a widget's tool tip is by
- calling its QWidget::setToolTip() function.
+ UI elements that are created via \l{QAction} use the tooltip property
+ of the QAction, so for most interactive UI elements, setting that
+ property is the easiest way to provide tool tips.
+
+ \snippet tooltips/main.cpp action_tooltip
+
+ For any other widgets, the simplest and most common way to set
+ a widget's tool tip is by calling its QWidget::setToolTip() function.
+
+ \snippet tooltips/main.cpp static_tooltip
It is also possible to show different tool tips for different
regions of a widget, by using a QHelpEvent of type
QEvent::ToolTip. Intercept the help event in your widget's \l
{QWidget::}{event()} function and call QToolTip::showText() with
- the text you want to display. The \l{widgets/tooltips}{Tooltips}
- example illustrates this technique.
+ the text you want to display.
+
+ \snippet tooltips/main.cpp dynamic_tooltip
If you are calling QToolTip::hideText(), or QToolTip::showText()
with an empty string, as a result of a \l{QEvent::}{ToolTip}-event you
@@ -109,7 +84,7 @@ QT_BEGIN_NAMESPACE
\note Tool tips use the inactive color group of QPalette, because tool
tips are not active windows.
- \sa QWidget::toolTip, QAction::toolTip, {Tool Tips Example}
+ \sa QWidget::toolTip, QAction::toolTip
*/
class QTipLabel : public QLabel
@@ -147,7 +122,7 @@ protected:
#ifndef QT_NO_STYLE_STYLESHEET
public slots:
/** \internal
- Cleanup the _q_stylesheet_parent propery.
+ Cleanup the _q_stylesheet_parent property.
*/
void styleSheetParentDestroyed() {
setProperty("_q_stylesheet_parent", QVariant());
@@ -191,7 +166,9 @@ QTipLabel::QTipLabel(const QString &text, const QPoint &pos, QWidget *w, int mse
void QTipLabel::restartExpireTimer(int msecDisplayTime)
{
- int time = 10000 + 40 * qMax(0, text().length()-100);
+ Q_D(const QLabel);
+ const qsizetype textLength = d->needTextControl() ? d->control->toPlainText().size() : text().size();
+ qsizetype time = 10000 + 40 * qMax(0, textLength - 100);
if (msecDisplayTime > 0)
time = msecDisplayTime;
expireTimer.start(time, this);
@@ -202,8 +179,8 @@ void QTipLabel::reuseTip(const QString &text, int msecDisplayTime, const QPoint
{
#ifndef QT_NO_STYLE_STYLESHEET
if (styleSheetParent){
- disconnect(styleSheetParent, SIGNAL(destroyed()),
- QTipLabel::instance, SLOT(styleSheetParentDestroyed()));
+ disconnect(styleSheetParent, &QWidget::destroyed,
+ this, &QTipLabel::styleSheetParentDestroyed);
styleSheetParent = nullptr;
}
#endif
@@ -352,6 +329,7 @@ bool QTipLabel::eventFilter(QObject *o, QEvent *e)
case QEvent::MouseMove:
if (o == widget && !rect.isNull() && !rect.contains(static_cast<QMouseEvent*>(e)->position().toPoint()))
hideTip();
+ break;
default:
break;
}
@@ -372,17 +350,19 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
//the stylesheet need to know the real parent
QTipLabel::instance->setProperty("_q_stylesheet_parent", QVariant::fromValue(w));
//we force the style to be the QStyleSheetStyle, and force to clear the cache as well.
- QTipLabel::instance->setStyleSheet(QLatin1String("/* */"));
+ QTipLabel::instance->setStyleSheet("/* */"_L1);
// Set up for cleaning up this later...
QTipLabel::instance->styleSheetParent = w;
if (w) {
- connect(w, SIGNAL(destroyed()),
- QTipLabel::instance, SLOT(styleSheetParentDestroyed()));
- // QTBUG-64550: A font inherited by the style sheet might change the size,
- // particular on Windows, where the tip is not parented on a window.
- QTipLabel::instance->updateSize(pos);
+ connect(w, &QWidget::destroyed,
+ QTipLabel::instance, &QTipLabel::styleSheetParentDestroyed);
}
+ // QTBUG-64550: A font inherited by the style sheet might change the size,
+ // particular on Windows, where the tip is not parented on a window.
+ // The updatesSize() also makes sure that the content size be updated with
+ // correct content margin.
+ QTipLabel::instance->updateSize(pos);
}
#endif //QT_NO_STYLE_STYLESHEET
@@ -492,7 +472,7 @@ void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, cons
QWidgetPrivate::get(QTipLabel::instance)->setScreen(QTipLabel::getTipScreen(pos, w));
QTipLabel::instance->setTipRect(w, rect);
QTipLabel::instance->placeTip(pos, w);
- QTipLabel::instance->setObjectName(QLatin1String("qtooltip_label"));
+ QTipLabel::instance->setObjectName("qtooltip_label"_L1);
#if QT_CONFIG(effects)
if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip))
diff --git a/src/widgets/kernel/qtooltip.h b/src/widgets/kernel/qtooltip.h
index c78e4c3251..863162e15b 100644
--- a/src/widgets/kernel/qtooltip.h
+++ b/src/widgets/kernel/qtooltip.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTOOLTIP_H
#define QTOOLTIP_H
diff --git a/src/widgets/kernel/qtwidgetsglobal.h b/src/widgets/kernel/qtwidgetsglobal.h
index 4b990c6e2a..bfa7272f19 100644
--- a/src/widgets/kernel/qtwidgetsglobal.h
+++ b/src/widgets/kernel/qtwidgetsglobal.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTWIDGETSGLOBAL_H
#define QTWIDGETSGLOBAL_H
diff --git a/src/widgets/kernel/qtwidgetsglobal_p.h b/src/widgets/kernel/qtwidgetsglobal_p.h
index 22ba876022..535071891e 100644
--- a/src/widgets/kernel/qtwidgetsglobal_p.h
+++ b/src/widgets/kernel/qtwidgetsglobal_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTWIDGETSGLOBAL_P_H
#define QTWIDGETSGLOBAL_P_H
diff --git a/src/widgets/kernel/qwhatsthis.cpp b/src/widgets/kernel/qwhatsthis.cpp
index d264dfc4b2..c80f37267f 100644
--- a/src/widgets/kernel/qwhatsthis.cpp
+++ b/src/widgets/kernel/qwhatsthis.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwhatsthis.h"
#include "qpointer.h"
@@ -56,7 +20,7 @@
#include <qpa/qplatformtheme.h>
#include "private/qtextdocumentlayout_p.h"
#include "qdebug.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
@@ -133,8 +97,6 @@ QT_BEGIN_NAMESPACE
\sa QToolTip
*/
-Q_CORE_EXPORT void qDeleteInEventHandler(QObject *o);
-
class QWhatsThat : public QWidget
{
Q_OBJECT
@@ -146,7 +108,6 @@ public:
static QWhatsThat *instance;
protected:
- void showEvent(QShowEvent *e) override;
void mousePressEvent(QMouseEvent*) override;
void mouseReleaseEvent(QMouseEvent*) override;
void mouseMoveEvent(QMouseEvent*) override;
@@ -159,7 +120,6 @@ private:
QString text;
QTextDocument* doc;
QString anchor;
- QPixmap background;
};
QWhatsThat *QWhatsThat::instance = nullptr;
@@ -233,11 +193,6 @@ QWhatsThat::~QWhatsThat()
delete doc;
}
-void QWhatsThat::showEvent(QShowEvent *)
-{
- background = QGuiApplication::primaryScreen()->grabWindow(0, x(), y(), width(), height());
-}
-
void QWhatsThat::mousePressEvent(QMouseEvent* e)
{
pressed = true;
@@ -297,7 +252,6 @@ void QWhatsThat::paintEvent(QPaintEvent*)
if (drawShadow)
r.adjust(0, 0, -shadowWidth, -shadowWidth);
QPainter p(this);
- p.drawPixmap(0, 0, background);
p.setPen(QPen(palette().toolTipText(), 0));
p.setBrush(palette().toolTipBase());
p.drawRect(r);
@@ -402,7 +356,7 @@ QWhatsThisPrivate::QWhatsThisPrivate()
QGuiApplication::setOverrideCursor(Qt::WhatsThisCursor);
#endif
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleEvent event(this, QAccessible::ContextHelpStart);
QAccessible::updateAccessibility(&event);
#endif
@@ -417,7 +371,7 @@ QWhatsThisPrivate::~QWhatsThisPrivate()
#ifndef QT_NO_CURSOR
QGuiApplication::restoreOverrideCursor();
#endif
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleEvent event(this, QAccessible::ContextHelpEnd);
QAccessible::updateAccessibility(&event);
#endif
@@ -464,7 +418,7 @@ bool QWhatsThisPrivate::eventFilter(QObject *o, QEvent *e)
break;
case QEvent::KeyPress:
{
- QKeyEvent* kev = (QKeyEvent*)e;
+ QKeyEvent *kev = static_cast<QKeyEvent *>(e);
#if QT_CONFIG(shortcut)
if (kev->matches(QKeySequence::Cancel)) {
QWhatsThis::leaveWhatsThisMode();
@@ -508,7 +462,7 @@ QWhatsThisAction::QWhatsThisAction(QObject *parent) : QAction(tr("What's This?")
setIcon(p);
#endif
setCheckable(true);
- connect(this, SIGNAL(triggered()), this, SLOT(actionTriggered()));
+ connect(this, &QWhatsThisAction::triggered, this, &QWhatsThisAction::actionTriggered);
#ifndef QT_NO_SHORTCUT
setShortcut(Qt::ShiftModifier | Qt::Key_F1);
#endif
@@ -654,7 +608,7 @@ void QWhatsThis::showText(const QPoint &pos, const QString &text, QWidget *w)
*/
void QWhatsThis::hideText()
{
- qDeleteInEventHandler(QWhatsThat::instance);
+ delete QWhatsThat::instance;
}
/*!
diff --git a/src/widgets/kernel/qwhatsthis.h b/src/widgets/kernel/qwhatsthis.h
index fa5b97d98a..0ab32d8bd6 100644
--- a/src/widgets/kernel/qwhatsthis.h
+++ b/src/widgets/kernel/qwhatsthis.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWHATSTHIS_H
#define QWHATSTHIS_H
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 7c48df9799..e8342a4788 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qapplication.h"
#include "qapplication_p.h"
#include "qbrush.h"
#include "qcursor.h"
+#include "private/qduplicatetracker_p.h"
#include "qevent.h"
#include "qlayout.h"
#if QT_CONFIG(menu)
@@ -57,7 +22,7 @@
#include "qwidget.h"
#include "qstyleoption.h"
#include "qstylehints.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
# include "qaccessible.h"
#endif
#include <qpa/qplatformwindow.h>
@@ -77,9 +42,6 @@
#include "qscopeguard.h"
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/qinputmethod.h>
-#include <QtGui/qopenglcontext.h>
-#include <QtGui/private/qopenglcontext_p.h>
-#include <QtGui/qoffscreensurface.h>
#if QT_CONFIG(graphicseffect)
#include <private/qgraphicseffect_p.h>
@@ -113,15 +75,24 @@
#include "qwindowcontainer_p.h"
-// widget/widget data creation count
-//#define QWIDGET_EXTRA_DEBUG
-//#define ALIEN_DEBUG
+#include <sstream>
QT_BEGIN_NAMESPACE
using namespace QNativeInterface::Private;
+using namespace Qt::StringLiterals;
Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg);
+Q_LOGGING_CATEGORY(lcWidgetShowHide, "qt.widgets.showhide", QtWarningMsg);
+Q_LOGGING_CATEGORY(lcWidgetWindow, "qt.widgets.window", QtWarningMsg);
+Q_LOGGING_CATEGORY(lcWidgetFocus, "qt.widgets.focus")
+
+#ifndef QT_NO_DEBUG_STREAM
+namespace {
+ struct WidgetAttributes { const QWidget *widget; };
+ QDebug operator<<(QDebug debug, const WidgetAttributes &attributes);
+}
+#endif
static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
{
@@ -178,10 +149,8 @@ QWidgetPrivate::QWidgetPrivate(int version)
#ifndef QT_NO_IM
, inheritsInputMethodHints(0)
#endif
-#ifndef QT_NO_OPENGL
, renderToTextureReallyDirty(1)
- , renderToTextureComposeActive(0)
-#endif
+ , usesRhiFlush(0)
, childrenHiddenByWState(0)
, childrenShownByExpose(0)
#if defined(Q_OS_WIN)
@@ -203,7 +172,7 @@ QWidgetPrivate::QWidgetPrivate(int version)
version, QObjectPrivateVersion);
#endif
- isWidget = true;
+ willBeWidget = true; // used in QObject's ctor
memset(high_attributes, 0, sizeof(high_attributes));
#ifdef QWIDGET_EXTRA_DEBUG
@@ -399,14 +368,14 @@ void QWidget::setAutoFillBackground(bool enabled)
If not, it will be a child of \e parent, and be constrained by
\e parent's geometry (unless you specify Qt::Window as window flag).
\li \c{Qt::WindowFlags f = { }} (where available) sets the window flags;
- the default is suitable for almost all widgets, but to get, for
+ the default is suitable for most widgets, but to get, for
example, a window without a window system frame, you must use
special flags.
\endlist
QWidget has many member functions, but some of them have little direct
functionality; for example, QWidget has a font property, but never uses
- this itself. There are many subclasses which provide real functionality,
+ this itself. There are many subclasses that provide real functionality,
such as QLabel, QPushButton, QListWidget, and QTabWidget.
@@ -414,7 +383,7 @@ void QWidget::setAutoFillBackground(bool enabled)
A widget without a parent widget is always an independent window (top-level
widget). For these widgets, setWindowTitle() and setWindowIcon() set the
- title bar and icon respectively.
+ title bar and icon, respectively.
Non-window widgets are child widgets, displayed within their parent
widgets. Most widgets in Qt are mainly useful as child widgets. For
@@ -427,7 +396,7 @@ void QWidget::setAutoFillBackground(bool enabled)
widgets in a layout provided by QGridLayout. The QLabel child widgets have
been outlined to indicate their full sizes.
- If you want to use a QWidget to hold child widgets you will usually want to
+ If you want to use a QWidget to hold child widgets, you will usually want to
add a layout to the parent QWidget. See \l{Layout Management} for more
information.
@@ -437,14 +406,13 @@ void QWidget::setAutoFillBackground(bool enabled)
When a widget is used as a container to group a number of child widgets, it
is known as a composite widget. These can be created by constructing a
widget with the required visual properties - a QFrame, for example - and
- adding child widgets to it, usually managed by a layout. The above diagram
- shows such a composite widget that was created using Qt Designer.
+ adding child widgets to it, usually managed by a layout.
Composite widgets can also be created by subclassing a standard widget,
such as QWidget or QFrame, and adding the necessary layout and child
widgets in the constructor of the subclass. Many of the \l{Qt Widgets Examples}
{examples provided with Qt} use this approach, and it is also covered in
- the Qt \l{Tutorials}.
+ the Qt \l{Widgets Tutorial}.
\section1 Custom Widgets and Painting
@@ -458,7 +426,7 @@ void QWidget::setAutoFillBackground(bool enabled)
Each widget performs all painting operations from within its paintEvent()
function. This is called whenever the widget needs to be redrawn, either
- as a result of some external change or when requested by the application.
+ because of some external change or when requested by the application.
The \l{widgets/analogclock}{Analog Clock example} shows how a simple widget
can handle paint events.
@@ -470,7 +438,7 @@ void QWidget::setAutoFillBackground(bool enabled)
sizeHint() to provide a reasonable default size for the widget and to set
the correct size policy with setSizePolicy().
- By default, composite widgets which do not provide a size hint will be
+ By default, composite widgets that do not provide a size hint will be
sized according to the space requirements of their child widgets.
The size policy lets you supply good default behavior for the layout
@@ -490,9 +458,9 @@ void QWidget::setAutoFillBackground(bool enabled)
delivers events to widgets by calling specific event handler functions with
instances of QEvent subclasses containing information about each event.
- If your widget only contains child widgets, you probably do not need to
+ If your widget only contains child widgets, you probably don't need to
implement any event handlers. If you want to detect a mouse click in a
- child widget call the child's underMouse() function inside the widget's
+ child widget, call the child's underMouse() function inside the widget's
mousePressEvent().
The \l{widgets/scribble}{Scribble example} implements a wider set of
@@ -557,7 +525,7 @@ void QWidget::setAutoFillBackground(bool enabled)
button is held down. This can be useful during drag and drop
operations. If you call \l{setMouseTracking()}{setMouseTracking}(true),
you get mouse move events even when no buttons are held down.
- (See also the \l{Drag and Drop} guide.)
+ (See also the \l{Drag and Drop in Qt}{Drag and Drop} guide.)
\li keyReleaseEvent() is called whenever a key is released and while it
is held down (if the key is auto-repeating). In that case, the
widget will receive a pair of key release and key press event for
@@ -571,7 +539,7 @@ void QWidget::setAutoFillBackground(bool enabled)
space. (This excludes screen space owned by any of the widget's
children.)
\li leaveEvent() is called when the mouse leaves the widget's screen
- space. If the mouse enters a child widget it will not cause a
+ space. If the mouse enters a child widget, it will not cause a
leaveEvent().
\li moveEvent() is called when the widget has been moved relative to
its parent.
@@ -709,11 +677,11 @@ void QWidget::setAutoFillBackground(bool enabled)
\section1 Transparency and Double Buffering
- Since Qt 4.0, QWidget automatically double-buffers its painting, so there
+ QWidget automatically double-buffers its painting, so there
is no need to write double-buffering code in paintEvent() to avoid
flicker.
- Since Qt 4.1, the contents of parent widgets are propagated by
+ The contents of parent widgets are propagated by
default to each of their children as long as Qt::WA_PaintOnScreen is not
set. Custom widgets can be written to take advantage of this feature by
updating irregular regions (to create non-rectangular child widgets), or
@@ -730,7 +698,7 @@ void QWidget::setAutoFillBackground(bool enabled)
\list
\li The left widget has no additional properties or widget attributes
- set. This default state suits most custom widgets using
+ set. This default state suits most custom widgets that have
transparency, are irregularly-shaped, or do not paint over their
entire area with an opaque brush.
\li The center widget has the \l autoFillBackground property set. This
@@ -741,10 +709,7 @@ void QWidget::setAutoFillBackground(bool enabled)
set. This indicates that the widget will paint over its entire area
with opaque colors. The widget's area will initially be
\e{uninitialized}, represented in the diagram with a red diagonal
- grid pattern that shines through the overpainted area. The
- Qt::WA_OpaquePaintArea attribute is useful for widgets that need to
- paint their own specialized contents quickly and do not need a
- default filled background.
+ grid pattern that shines through the overpainted area.
\endlist
To rapidly update custom widgets with simple background colors, such as
@@ -754,19 +719,18 @@ void QWidget::setAutoFillBackground(bool enabled)
implement the necessary drawing functionality in the widget's paintEvent().
To rapidly update custom widgets that constantly paint over their entire
- areas with opaque content, e.g., video streaming widgets, it is better to
- set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary overhead
- associated with repainting the widget's background.
+ areas with opaque content, for example, video streaming widgets, it is
+ better to set the widget's Qt::WA_OpaquePaintEvent, avoiding any unnecessary
+ overhead associated with repainting the widget's background.
If a widget has both the Qt::WA_OpaquePaintEvent widget attribute \e{and}
the \l autoFillBackground property set, the Qt::WA_OpaquePaintEvent
attribute takes precedence. Depending on your requirements, you should
choose either one of them.
- Since Qt 4.1, the contents of parent widgets are also propagated to
- standard Qt widgets. This can lead to some unexpected results if the
- parent widget is decorated in a non-standard way, as shown in the diagram
- below.
+ The contents of parent widgets are also propagated to standard Qt widgets.
+ This can lead to some unexpected results if the parent widget is decorated
+ in a non-standard way, as shown in the diagram below.
\image propagation-standard.png
@@ -778,8 +742,8 @@ void QWidget::setAutoFillBackground(bool enabled)
\section1 Creating Translucent Windows
- Since Qt 4.5, it has been possible to create windows with translucent regions
- on window systems that support compositing.
+ You can create windows with translucent regions on window systems that
+ support compositing.
To enable this feature in a top-level widget, set its Qt::WA_TranslucentBackground
attribute with setAttribute() and ensure that its background is painted with
@@ -799,19 +763,19 @@ void QWidget::setAutoFillBackground(bool enabled)
\section1 Native Widgets vs Alien Widgets
- Introduced in Qt 4.4, alien widgets are widgets unknown to the windowing
- system. They do not have a native window handle associated with them. This
- feature significantly speeds up widget painting, resizing, and removes flicker.
+ Alien widgets are widgets unknown to the windowing system. They do not have
+ a native window handle associated with them. This feature significantly
+ speeds up widget painting, resizing, and removes flicker.
- Should you require the old behavior with native windows, you can choose
- one of the following options:
+ Should you require the old behavior with native windows, choose one of the
+ following options:
\list 1
\li Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment.
\li Set the Qt::AA_NativeWindows attribute on your application. All
widgets will be native widgets.
\li Set the Qt::WA_NativeWindow attribute on widgets: The widget itself
- and all of its ancestors will become native (unless
+ and all its ancestors will become native (unless
Qt::WA_DontCreateNativeAncestors is set).
\li Call QWidget::winId to enforce a native window (this implies 3).
\li Set the Qt::WA_PaintOnScreen attribute to enforce a native window
@@ -856,12 +820,7 @@ struct QWidgetExceptionCleaner
Q_UNUSED(d);
#else
QWidgetPrivate::allWidgets->remove(that);
- if (d->focus_next != that) {
- if (d->focus_next)
- d->focus_next->d_func()->focus_prev = d->focus_prev;
- if (d->focus_prev)
- d->focus_prev->d_func()->focus_next = d->focus_next;
- }
+ d->removeFromFocusChain();
#endif
}
};
@@ -978,6 +937,9 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
{
Q_Q(QWidget);
+ isWidget = true;
+ wasWidget = true;
+
Q_ASSERT_X(q != parentWidget, Q_FUNC_INFO, "Cannot parent a QWidget to itself");
if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
@@ -1026,7 +988,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
//give potential windows a bigger "pre-initial" size; create() will give them a new size later
data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
- focus_next = focus_prev = q;
+ initFocusChain();
if ((f & Qt::WindowType_Mask) == Qt::Desktop)
q->create();
@@ -1065,6 +1027,31 @@ void QWidgetPrivate::createRecursively()
}
}
+QRhi *QWidgetPrivate::rhi() const
+{
+ if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
+ return repaintManager->rhi();
+ else
+ return nullptr;
+}
+
+/*!
+ \internal
+ Returns the closest parent widget that has a QWindow window handle
+
+ \note This behavior is different from nativeParentWidget(), which
+ returns the closest parent that has a QWindow window handle with
+ a created QPlatformWindow, and hence native window (winId).
+*/
+QWidget *QWidgetPrivate::closestParentWidgetWithWindowHandle() const
+{
+ Q_Q(const QWidget);
+ QWidget *parent = q->parentWidget();
+ while (parent && !parent->windowHandle())
+ parent = parent->parentWidget();
+ return parent;
+}
+
QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
{
if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
@@ -1074,6 +1061,7 @@ QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
}
}
if (mode == WindowHandleMode::Closest) {
+ // FIXME: Use closestParentWidgetWithWindowHandle instead
if (auto nativeParent = q_func()->nativeParentWidget()) {
if (auto window = nativeParent->windowHandle())
return window;
@@ -1101,11 +1089,57 @@ QWindow *QWidgetPrivate::_q_closestWindowHandle() const
QScreen *QWidgetPrivate::associatedScreen() const
{
+#if QT_CONFIG(graphicsview)
+ // embedded widgets never have a screen associated, let QWidget::screen fall back to toplevel
+ if (nearestGraphicsProxyWidget(q_func()))
+ return nullptr;
+#endif
if (auto window = windowHandle(WindowHandleMode::Closest))
return window->screen();
return nullptr;
}
+// finds the first rhiconfig in the hierarchy that has enable==true
+static bool q_evaluateRhiConfigRecursive(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
+{
+ QPlatformBackingStoreRhiConfig config = QWidgetPrivate::get(w)->rhiConfig();
+ if (config.isEnabled()) {
+ if (outConfig)
+ *outConfig = config;
+ if (outType)
+ *outType = QBackingStoreRhiSupport::surfaceTypeForConfig(config);
+ return true;
+ }
+ for (const QObject *child : w->children()) {
+ if (const QWidget *childWidget = qobject_cast<const QWidget *>(child)) {
+ if (q_evaluateRhiConfigRecursive(childWidget, outConfig, outType))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
+{
+ // First, check env.vars. or other means that force the usage of rhi-based
+ // flushing with a specific graphics API. This takes precedence over what
+ // the widgets themselves declare. This is global, applying to all
+ // top-levels.
+ if (QBackingStoreRhiSupport::checkForceRhi(outConfig, outType)) {
+ qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluated to forced flushing with QRhi";
+ return true;
+ }
+
+ // Otherwise, check the widget hierarchy to see if there is a child (or
+ // ourselves) that declare the need for rhi-based composition.
+ if (q_evaluateRhiConfigRecursive(w, outConfig, outType)) {
+ qCDebug(lcWidgetPainting) << "Tree with root" << w << "evaluates to flushing with QRhi";
+ return true;
+ }
+
+ return false;
+}
+
// ### fixme: Qt 6: Remove parameter window from QWidget::create()
/*!
@@ -1166,11 +1200,6 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
if (QApplicationPrivate::testAttribute(Qt::AA_NativeWindows))
setAttribute(Qt::WA_NativeWindow);
-#ifdef ALIEN_DEBUG
- qDebug() << "QWidget::create:" << this << "parent:" << parentWidget()
- << "Alien?" << !testAttribute(Qt::WA_NativeWindow);
-#endif
-
d->updateIsOpaque();
setAttribute(Qt::WA_WState_Created); // set created flag
@@ -1260,7 +1289,7 @@ void QWidgetPrivate::create()
Qt::WindowFlags &flags = data.window_flags;
-#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
+#if defined(QT_PLATFORM_UIKIT)
if (q->testAttribute(Qt::WA_ContentsMarginsRespectsSafeArea))
flags |= Qt::MaximizeUsingFullscreenGeometryHint;
#endif
@@ -1269,7 +1298,6 @@ void QWidgetPrivate::create()
win->setProperty("_q_showWithoutActivating", QVariant(true));
if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
win->setProperty("_q_macAlwaysShowToolWindow", QVariant(true));
- setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
win->setFlags(flags);
fixPosIncludesFrame();
if (q->testAttribute(Qt::WA_Moved)
@@ -1317,8 +1345,6 @@ void QWidgetPrivate::create()
}
data.window_flags = win->flags();
- if (!win->isTopLevel()) // In a Widget world foreign windows can only be top level
- data.window_flags &= ~Qt::ForeignWindow;
#if QT_CONFIG(xcb)
if (!topData()->role.isNull()) {
@@ -1328,14 +1354,21 @@ void QWidgetPrivate::create()
#endif
QBackingStore *store = q->backingStore();
+ usesRhiFlush = false;
if (!store) {
if (q->windowType() != Qt::Desktop) {
- if (q->isWindow())
+ if (q->isWindow()) {
q->setBackingStore(new QBackingStore(win));
+ QPlatformBackingStoreRhiConfig rhiConfig;
+ usesRhiFlush = q_evaluateRhiConfig(q, &rhiConfig, nullptr);
+ topData()->backingStore->handle()->setRhiConfig(rhiConfig);
+ }
} else {
q->setAttribute(Qt::WA_PaintOnScreen, true);
}
+ } else if (win->handle()) {
+ usesRhiFlush = q_evaluateRhiConfig(q, nullptr, nullptr);
}
setWindowModified_helper();
@@ -1346,6 +1379,7 @@ void QWidgetPrivate::create()
Q_ASSERT(id != WId(0));
setWinId(id);
}
+ setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
// Check children and create windows for them if necessary
q_createNativeChildrenAndSetParent(q);
@@ -1389,6 +1423,8 @@ void QWidgetPrivate::createTLSysExtra()
#endif
if (isTipLabel || isAlphaWidget || q->inherits("QRollEffect"))
qt_window_private(extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
+
+ updateIsTranslucent();
}
}
@@ -1421,7 +1457,7 @@ QWidget::~QWidget()
#ifndef QT_NO_ACTION
// remove all actions from this widget
- for (auto action : qAsConst(d->actions)) {
+ for (auto action : std::as_const(d->actions)) {
QActionPrivate *apriv = action->d_func();
apriv->associatedObjects.removeAll(this);
}
@@ -1438,17 +1474,9 @@ QWidget::~QWidget()
// delete layout while we still are a valid widget
delete d->layout;
d->layout = nullptr;
- // Remove myself from focus list
-
- Q_ASSERT(d->focus_next->d_func()->focus_prev == this);
- Q_ASSERT(d->focus_prev->d_func()->focus_next == this);
-
- if (d->focus_next != this) {
- d->focus_next->d_func()->focus_prev = d->focus_prev;
- d->focus_prev->d_func()->focus_next = d->focus_next;
- d->focus_next = d->focus_prev = nullptr;
- }
+ // Remove this from focus list
+ d->removeFromFocusChain(QWidgetPrivate::FocusChainRemovalRule::AssertConsistency);
QT_TRY {
#if QT_CONFIG(graphicsview)
@@ -1541,6 +1569,8 @@ QWidget::~QWidget()
#if QT_CONFIG(graphicseffect)
delete d->graphicsEffect;
#endif
+
+ d->isWidget = false;
}
int QWidgetPrivate::instanceCounter = 0; // Current number of widget instances
@@ -1646,10 +1676,9 @@ void QWidgetPrivate::deleteExtra()
if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style))
proxy->deref();
#endif
- if (extra->topextra) {
+ if (extra->topextra)
deleteTLSysExtra();
- // extra->topextra->backingStore destroyed in QWidgetPrivate::deleteTLSysExtra()
- }
+
// extra->xic destroyed in QWidget::destroy()
extra.reset();
}
@@ -1659,37 +1688,11 @@ void QWidgetPrivate::deleteSysExtra()
{
}
-static void deleteBackingStore(QWidgetPrivate *d)
-{
- QTLWExtra *topData = d->topData();
-
- delete topData->backingStore;
- topData->backingStore = nullptr;
-}
-
void QWidgetPrivate::deleteTLSysExtra()
{
if (extra && extra->topextra) {
- //the qplatformbackingstore may hold a reference to the window, so the backingstore
- //needs to be deleted first.
-
- extra->topextra->repaintManager.reset(nullptr);
- deleteBackingStore(this);
-#ifndef QT_NO_OPENGL
- extra->topextra->widgetTextures.clear();
- extra->topextra->shareContext.reset();
-#endif
-
- //the toplevel might have a context with a "qglcontext associated with it. We need to
- //delete the qglcontext before we delete the qplatformopenglcontext.
- //One unfortunate thing about this is that we potentially create a glContext just to
- //delete it straight afterwards.
- if (extra->topextra->window) {
- extra->topextra->window->destroy();
- }
delete extra->topextra->window;
extra->topextra->window = nullptr;
-
}
}
@@ -2191,7 +2194,7 @@ void QWidgetPrivate::updateIsTranslucent()
if (QWindow *window = q->windowHandle()) {
QSurfaceFormat format = window->format();
const int oldAlpha = format.alphaBufferSize();
- const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground)? 8 : 0;
+ const int newAlpha = q->testAttribute(Qt::WA_TranslucentBackground) ? 8 : -1;
if (oldAlpha != newAlpha) {
// QTBUG-85714: Do this only when the QWindow has not yet been create()'ed yet.
//
@@ -2305,7 +2308,7 @@ void QWidgetPrivate::deactivateWidgetCleanup()
Q_Q(QWidget);
// If this was the active application window, reset it
if (QApplication::activeWindow() == q)
- QApplication::setActiveWindow(nullptr);
+ QApplicationPrivate::setActiveWindow(nullptr);
// If the is the active mouse press widget, reset it
if (q == qt_button_down)
qt_button_down = nullptr;
@@ -2356,9 +2359,6 @@ WId QWidget::winId() const
if (!data->in_destructor
&& (!testAttribute(Qt::WA_WState_Created) || !internalWinId()))
{
-#ifdef ALIEN_DEBUG
- qDebug() << "QWidget::winId: creating native window for" << this;
-#endif
QWidget *that = const_cast<QWidget*>(this);
that->setAttribute(Qt::WA_NativeWindow);
that->d_func()->createWinId();
@@ -2371,9 +2371,6 @@ void QWidgetPrivate::createWinId()
{
Q_Q(QWidget);
-#ifdef ALIEN_DEBUG
- qDebug() << "QWidgetPrivate::createWinId for" << q;
-#endif
const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow);
if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) {
if (!q->isWindow()) {
@@ -2444,10 +2441,6 @@ Ensures that the widget has a window system identifier, i.e. that it is known to
void QWidget::createWinId()
{
Q_D(QWidget);
-#ifdef ALIEN_DEBUG
- qDebug() << "QWidget::createWinId" << this;
-#endif
-// qWarning("QWidget::createWinId is obsolete, please fix your code.");
d->createWinId();
}
@@ -2925,7 +2918,7 @@ void QWidget::overrideWindowState(Qt::WindowStates newstate)
\snippet code/src_gui_kernel_qwidget.cpp 0
- In order to restore and activate a minimized window (while
+ To restore and activate a minimized window (while
preserving its maximized and/or full-screen state), use the following:
\snippet code/src_gui_kernel_qwidget.cpp 1
@@ -3001,7 +2994,7 @@ bool QWidget::isFullScreen() const
ICCCM protocol that specifies the communication between X11
clients and the window manager. ICCCM simply does not understand
the concept of non-decorated full-screen windows. Therefore, the
- best we can do is to request a borderless window and place and
+ best you can do is to request a borderless window and place and
resize it to fill the entire screen. Depending on the window
manager, this may or may not work. The borderless window is
requested using MOTIF hints, which are at least partially
@@ -3009,7 +3002,7 @@ bool QWidget::isFullScreen() const
An alternative would be to bypass the window manager entirely and
create a window with the Qt::X11BypassWindowManagerHint flag. This
- has other severe problems though, like totally broken keyboard focus
+ has other severe problems though, like broken keyboard focus
and very strange effects on desktop changes or when the user raises
other windows.
@@ -3109,7 +3102,7 @@ bool QWidget::isEnabledTo(const QWidget *ancestor) const
/*!
Appends the action \a action to this widget's list of actions.
- All QWidgets have a list of \l{QAction}s, however they can be
+ All QWidgets have a list of \l{QAction}s. However, they can be
represented graphically in many different ways. The default use of
the QAction list (as returned by actions()) is to create a context
QMenu.
@@ -3133,7 +3126,7 @@ void QWidget::addAction(QAction *action)
*/
void QWidget::addActions(const QList<QAction *> &actions)
{
- for(int i = 0; i < actions.count(); i++)
+ for(int i = 0; i < actions.size(); i++)
insertAction(nullptr, actions.at(i));
}
@@ -3182,7 +3175,7 @@ void QWidget::insertAction(QAction *before, QAction *action)
*/
void QWidget::insertActions(QAction *before, const QList<QAction*> &actions)
{
- for(int i = 0; i < actions.count(); ++i)
+ for(int i = 0; i < actions.size(); ++i)
insertAction(before, actions.at(i));
}
@@ -3247,6 +3240,7 @@ QAction *QWidget::addAction(const QIcon &icon, const QString &text)
return ret;
}
+#if QT_CONFIG(shortcut)
QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut)
{
QAction *ret = addAction(text);
@@ -3260,6 +3254,7 @@ QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySe
ret->setShortcut(shortcut);
return ret;
}
+#endif
/*!
\fn QAction *QWidget::addAction(const QString &text, const QObject *receiver, const char* member, Qt::ConnectionType type)
@@ -3317,10 +3312,10 @@ QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySe
#endif // QT_CONFIG(shortcut)
/*!
- \fn template<typename...Args> QAction *QWidget::addAction(const QString &text, Args&&...args)
- \fn template<typename...Args> QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, Args&&...args)
- \fn template<typename...Args> QAction *QWidget::addAction(const QIcon &icon, const QString &text, Args&&...args)
- \fn template<typename...Args> QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, Args&&...args)
+ \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, Args&&...args)
+ \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QString &text, const QKeySequence &shortcut, Args&&...args)
+ \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, Args&&...args)
+ \fn template<typename...Args, typename = compatible_action_slot_args<Args...>> QAction *QWidget::addAction(const QIcon &icon, const QString &text, const QKeySequence &shortcut, Args&&...args)
\since 6.3
\overload
@@ -3431,7 +3426,7 @@ void QWidgetPrivate::setEnabled_helper(bool enable)
By default, this property is \c false.
- \sa {Drag and Drop}
+ \sa {Drag and Drop in Qt}{Drag and Drop}
*/
bool QWidget::acceptDrops() const
{
@@ -3545,6 +3540,10 @@ int QWidget::y() const
See the \l{Window Geometry} documentation for an overview of geometry
issues with windows.
+ \note Not all windowing systems support setting or querying top level window positions.
+ On such a system, programmatically moving windows may not have any effect, and artificial
+ values may be returned for the current positions, such as \c QPoint(0, 0).
+
\sa frameGeometry, size, x(), y()
*/
QPoint QWidget::pos() const
@@ -3742,7 +3741,7 @@ QRegion QWidget::childrenRegion() const
the current size is smaller.
The minimum size set by this function will override the minimum size
- defined by QLayout. In order to unset the minimum size, use a
+ defined by QLayout. To unset the minimum size, use a
value of \c{QSize(0, 0)}.
By default, this property contains a size with zero width and height.
@@ -4353,7 +4352,7 @@ QWidget *QWidget::nativeParentWidget() const
The background role defines the brush from the widget's \l palette that
is used to render the background.
- If no explicit background role is set, the widget inherts its parent
+ If no explicit background role is set, the widget inherits its parent
widget's background role.
\sa setBackgroundRole(), foregroundRole()
@@ -4497,7 +4496,7 @@ void QWidget::setForegroundRole(QPalette::ColorRole role)
QWidget's palette propagation is similar to its font propagation.
The current style, which is used to render the content of all standard Qt
- widgets, is free to choose colors and brushes from the widget palette, or
+ widgets, is free to choose colors and brushes from the widget palette, or,
in some cases, to ignore the palette (partially, or completely). In
particular, certain styles like GTK style, Mac style, and Windows Vista
style, depend on third party APIs to render the content of widgets,
@@ -5463,7 +5462,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *>
(source->d_func());
if (!sourced->context) {
- const QRegion effectRgn(rgn.boundingRect());
+ const QRegion effectRgn((flags & UseEffectRegionBounds) ? rgn.boundingRect() : rgn);
QWidgetPaintContext context(pdev, effectRgn, offset, flags, sharedPainter, repaintManager);
sourced->context = &context;
if (!sharedPainter) {
@@ -5495,6 +5494,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
}
#endif // QT_CONFIG(graphicseffect)
+ flags = flags & ~UseEffectRegionBounds;
const bool alsoOnScreen = flags & DrawPaintOnScreen;
const bool recursive = flags & DrawRecursive;
@@ -5528,30 +5528,23 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
//paint the background
if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground))
&& !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
-#ifndef QT_NO_OPENGL
beginBackingStorePainting();
-#endif
QPainter p(q);
+ p.setRenderHint(QPainter::SmoothPixmapTransform);
paintBackground(&p, toBePainted, (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags());
-#ifndef QT_NO_OPENGL
endBackingStorePainting();
-#endif
}
if (!sharedPainter)
setSystemClip(pdev->paintEngine(), pdev->devicePixelRatio(), toBePainted.translated(offset));
if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
-#ifndef QT_NO_OPENGL
beginBackingStorePainting();
-#endif
QPainter p(q);
QColor tint = q->palette().window().color();
tint.setAlphaF(.6f);
p.fillRect(toBePainted.boundingRect(), tint);
-#ifndef QT_NO_OPENGL
endBackingStorePainting();
-#endif
}
}
@@ -5562,7 +5555,6 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
#endif
bool skipPaintEvent = false;
-#ifndef QT_NO_OPENGL
if (renderToTexture) {
// This widget renders into a texture which is composed later. We just need to
// punch a hole in the backingstore, so the texture will be visible.
@@ -5588,7 +5580,6 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
else
skipPaintEvent = true;
}
-#endif // QT_NO_OPENGL
if (!skipPaintEvent) {
//actually send the paint event
@@ -5644,10 +5635,8 @@ void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
QPaintEvent e(toBePainted);
QCoreApplication::sendSpontaneousEvent(q, &e);
-#ifndef QT_NO_OPENGL
if (renderToTexture)
resolveSamples();
-#endif // QT_NO_OPENGL
}
void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
@@ -5981,7 +5970,7 @@ QString QWidget::windowTitle() const
if (!d->extra->topextra->caption.isEmpty())
return d->extra->topextra->caption;
if (!d->extra->topextra->filePath.isEmpty())
- return QFileInfo(d->extra->topextra->filePath).fileName() + QLatin1String("[*]");
+ return QFileInfo(d->extra->topextra->filePath).fileName() + "[*]"_L1;
}
return QString();
}
@@ -6005,7 +5994,7 @@ QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widg
if (cap.isEmpty())
return cap;
- QLatin1String placeHolder("[*]");
+ const auto placeHolder = "[*]"_L1;
int index = cap.indexOf(placeHolder);
// here the magic begins
@@ -6029,7 +6018,7 @@ QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widg
index = cap.indexOf(placeHolder, index);
}
- cap.replace(QLatin1String("[*][*]"), placeHolder);
+ cap.replace("[*][*]"_L1, placeHolder);
return cap;
}
@@ -6391,6 +6380,36 @@ void QWidget::setFocusProxy(QWidget * w)
d->createExtra();
d->extra->focus_proxy = w;
+ if (w && isAncestorOf(w)) {
+ // If the focus proxy is a child of this (so this is a compound widget), then
+ // we need to make sure that this widget is immediately in front of its own children
+ // in the focus chain. Otherwise focusNextPrev_helper might jump over unrelated
+ // widgets that are positioned between this compound widget, and its proxy in
+ // the focus chain.
+ const QWidget *parentOfW = w->parentWidget();
+ Q_ASSERT(parentOfW); // can't be nullptr since we are an ancestor of w
+ QWidget *firstChild = nullptr;
+ const auto childList = children();
+ for (QObject *child : childList) {
+ if ((firstChild = qobject_cast<QWidget *>(child)))
+ break;
+ }
+ Q_ASSERT(firstChild); // can't be nullptr since w is a child
+ d->insertIntoFocusChainBefore(firstChild);
+ } else if (w && w->isAncestorOf(this)) {
+ // If the focus proxy is a parent, 'this' has to be inserted directly after its parent in the focus chain
+ // remove it from the chain and insert this into the focus chain after its parent
+
+ // is this the case already?
+ QWidget *parentsNext = w->nextInFocusChain();
+ if (parentsNext == this) {
+ // nothing to do.
+ Q_ASSERT(previousInFocusChain() == w);
+ } else {
+ d->QWidgetPrivate::insertIntoFocusChainAfter(w);
+ }
+ }
+
if (moveFocusToProxy)
setFocus(Qt::OtherFocusReason);
}
@@ -6525,7 +6544,7 @@ void QWidget::setFocus(Qt::FocusReason reason)
f->d_func()->updateFocusChild();
QApplicationPrivate::setFocusWidget(f, reason);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
// menus update the focus manually and this would create bogus events
if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem")))
{
@@ -6597,7 +6616,9 @@ void QWidgetPrivate::setFocus_sys()
{
Q_Q(QWidget);
// Embedded native widget may have taken the focus; get it back to toplevel
- // if that is the case (QTBUG-25852)
+ // if that is the case (QTBUG-25852), unless widget is a window container.
+ if (extra && extra->hasWindowContainer)
+ return;
// Do not activate in case the popup menu opens another application (QTBUG-70810)
// unless the application is embedded (QTBUG-71991).
if (QWindow *nativeWindow = q->testAttribute(Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) {
@@ -6649,8 +6670,8 @@ void QWidgetPrivate::updateFocusChild()
If the widget has active focus, a \l{focusOutEvent()}{focus out event} is sent to this widget to tell it that it has
lost the focus.
- This widget must enable focus setting in order to get the keyboard
- input focus, i.e. it must call setFocusPolicy().
+ This widget must enable focus setting to get the keyboard
+ input focus; that is, it must call setFocusPolicy().
\sa hasFocus(), setFocus(), focusInEvent(), focusOutEvent(),
setFocusPolicy(), QApplication::focusWidget()
@@ -6667,7 +6688,14 @@ void QWidget::clearFocus()
}
QTLWExtra *extra = window()->d_func()->maybeTopData();
- QObject *originalFocusObject = (extra && extra->window) ? extra->window->focusObject() : nullptr;
+ QObject *originalFocusObject = nullptr;
+ if (extra && extra->window) {
+ originalFocusObject = extra->window->focusObject();
+ // the window's focus object might already be nullptr if we are in the destructor, but we still
+ // need to update QGuiApplication and input context if we have a focus widget.
+ if (!originalFocusObject)
+ originalFocusObject = focusWidget();
+ }
QWidget *w = this;
while (w) {
@@ -6693,7 +6721,7 @@ void QWidget::clearFocus()
if (hasFocus()) {
// Update proxy state
QApplicationPrivate::setFocusWidget(nullptr, Qt::OtherFocusReason);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleEvent event(this, QAccessible::Focus);
QAccessible::updateAccessibility(&event);
#endif
@@ -6799,6 +6827,13 @@ QWidget *QWidget::focusWidget() const
return const_cast<QWidget *>(d_func()->focus_child);
}
+QObject *QWidgetPrivate::focusObject()
+{
+ Q_Q(QWidget);
+ QWidget *proxy = deepestFocusProxy();
+ return proxy ? proxy : q;
+}
+
/*!
Returns the next widget in this widget's focus chain.
@@ -6806,7 +6841,8 @@ QWidget *QWidget::focusWidget() const
*/
QWidget *QWidget::nextInFocusChain() const
{
- return const_cast<QWidget *>(d_func()->focus_next);
+ Q_D(const QWidget);
+ return d->nextPrevElementInFocusChain(QWidgetPrivate::FocusDirection::Next);
}
/*!
@@ -6819,7 +6855,8 @@ QWidget *QWidget::nextInFocusChain() const
*/
QWidget *QWidget::previousInFocusChain() const
{
- return const_cast<QWidget *>(d_func()->focus_prev);
+ Q_D(const QWidget);
+ return d->nextPrevElementInFocusChain(QWidgetPrivate::FocusDirection::Previous);
}
/*!
@@ -6889,6 +6926,30 @@ bool QWidget::isActiveWindow() const
}
/*!
+ \fn void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
+ \overload
+ \since 6.6
+
+ Sets the tab order for the widgets in the \a widgets list by calling
+ \l{QWidget::setTabOrder(QWidget *, QWidget *)} for each consecutive
+ pair of widgets.
+
+ Instead of setting up each pair manually like this:
+
+ \snippet code/src_gui_kernel_qwidget.cpp 9
+
+ you can call:
+
+ \snippet code/src_gui_kernel_qwidget.cpp 9.list
+
+ The call does not create a closed tab focus loop. If there are more widgets
+ with \l{Qt::TabFocus} focus policy, tabbing on \c{d} will move focus to one
+ of those widgets, not back to \c{a}.
+
+ \sa setFocusPolicy(), setFocusProxy(), {Keyboard Focus in Widgets}
+*/
+
+/*!
Puts the \a second widget after the \a first widget in the focus order.
It effectively removes the \a second widget from its focus chain and
@@ -6926,16 +6987,16 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
return;
}
- auto determineLastFocusChild = [](QWidget *target, QWidget *&lastFocusChild)
+ const auto determineLastFocusChild = [](QWidget *target, QWidget *noFurtherThan)
{
// Since we need to repeat the same logic for both 'first' and 'second', we add a function that
// determines the last focus child for a widget, taking proxies and compound widgets into account.
// If the target is not a compound widget (it doesn't have a focus proxy that points to a child),
// 'lastFocusChild' will be set to the target itself.
- lastFocusChild = target;
+ QWidget *lastFocusChild = target;
QWidget *focusProxy = target->d_func()->deepestFocusProxy();
- if (!focusProxy || !target->isAncestorOf(focusProxy)) {
+ if (!focusProxy) {
// QTBUG-81097: Another case is possible here. We can have a child
// widget, that sets its focusProxy() to the parent (target).
// An example of such widget is a QLineEdit, nested into
@@ -6948,55 +7009,52 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
break;
}
}
- return;
- }
-
- lastFocusChild = focusProxy;
-
- for (QWidget *focusNext = lastFocusChild->d_func()->focus_next;
- focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window();
- focusNext = focusNext->d_func()->focus_next) {
- if (focusNext->focusPolicy() != Qt::NoFocus)
- lastFocusChild = focusNext;
+ } else if (target->isAncestorOf(focusProxy)) {
+ lastFocusChild = focusProxy;
+ for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
+ focusNext != focusProxy && target->isAncestorOf(focusNext) && focusNext->window() == focusProxy->window();
+ focusNext = focusNext->nextInFocusChain()) {
+ if (focusNext == noFurtherThan)
+ break;
+ if (focusNext->focusPolicy() != Qt::NoFocus)
+ lastFocusChild = focusNext;
+ }
}
+ return lastFocusChild;
};
- auto setPrev = [](QWidget *w, QWidget *prev)
- {
- w->d_func()->focus_prev = prev;
- };
- auto setNext = [](QWidget *w, QWidget *next)
- {
- w->d_func()->focus_next = next;
- };
-
- // remove the second widget from the chain
- QWidget *lastFocusChildOfSecond;
- determineLastFocusChild(second, lastFocusChildOfSecond);
- {
- QWidget *oldPrev = second->d_func()->focus_prev;
- QWidget *prevWithFocus = oldPrev;
- while (prevWithFocus->focusPolicy() == Qt::NoFocus)
- prevWithFocus = prevWithFocus->d_func()->focus_prev;
- // only widgets between first and second -> all is fine
- if (prevWithFocus == first)
- return;
- QWidget *oldNext = lastFocusChildOfSecond->d_func()->focus_next;
- setPrev(oldNext, oldPrev);
- setNext(oldPrev, oldNext);
- }
+ // detect inflection in case we have compound widgets
+ QWidget *lastFocusChildOfFirst = determineLastFocusChild(first, second);
+ if (lastFocusChildOfFirst == second)
+ lastFocusChildOfFirst = first;
+ QWidget *lastFocusChildOfSecond = determineLastFocusChild(second, first);
+ if (lastFocusChildOfSecond == first)
+ lastFocusChildOfSecond = second;
+
+ // Return if only NoFocus widgets are between first and second
+ QWidget *oldPrev = second->previousInFocusChain();
+ QWidget *prevWithFocus = oldPrev;
+ while (prevWithFocus->focusPolicy() == Qt::NoFocus)
+ prevWithFocus = prevWithFocus->previousInFocusChain();
+ if (prevWithFocus == first)
+ return;
+ const QWidgetList chain = QWidgetPrivate::takeFromFocusChain(second, lastFocusChildOfSecond);
+ QWidgetPrivate::insertIntoFocusChain(chain, QWidgetPrivate::FocusDirection::Next, lastFocusChildOfFirst);
+}
- // insert the second widget into the chain
- QWidget *lastFocusChildOfFirst;
- determineLastFocusChild(first, lastFocusChildOfFirst);
- {
- QWidget *oldNext = lastFocusChildOfFirst->d_func()->focus_next;
- setPrev(second, lastFocusChildOfFirst);
- setNext(lastFocusChildOfFirst, second);
- setPrev(oldNext, lastFocusChildOfSecond);
- setNext(lastFocusChildOfSecond, oldNext);
+void QWidget::setTabOrder(std::initializer_list<QWidget *> widgets)
+{
+ QWidget *prev = nullptr;
+ for (const auto &widget : widgets) {
+ if (!prev) {
+ prev = widget;
+ } else {
+ QWidget::setTabOrder(prev, widget);
+ prev = widget;
+ }
}
}
+
/*!\internal
Moves the relevant subwidgets of this widget from the \a oldtlw's
@@ -7018,67 +7076,8 @@ void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
if (focus_child)
focus_child->clearFocus();
- // separate the focus chain into new (children of myself) and old (the rest)
- QWidget *firstOld = nullptr;
- //QWidget *firstNew = q; //invariant
- QWidget *o = nullptr; // last in the old list
- QWidget *n = q; // last in the new list
-
- bool prevWasNew = true;
- QWidget *w = focus_next;
-
- //Note: for efficiency, we do not maintain the list invariant inside the loop
- //we append items to the relevant list, and we optimize by not changing pointers
- //when subsequent items are going into the same list.
- while (w != q) {
- bool currentIsNew = q->isAncestorOf(w);
- if (currentIsNew) {
- if (!prevWasNew) {
- //prev was old -- append to new list
- n->d_func()->focus_next = w;
- w->d_func()->focus_prev = n;
- }
- n = w;
- } else {
- if (prevWasNew) {
- //prev was new -- append to old list, if there is one
- if (o) {
- o->d_func()->focus_next = w;
- w->d_func()->focus_prev = o;
- } else {
- // "create" the old list
- firstOld = w;
- }
- }
- o = w;
- }
- w = w->d_func()->focus_next;
- prevWasNew = currentIsNew;
- }
-
- //repair the old list:
- if (firstOld) {
- o->d_func()->focus_next = firstOld;
- firstOld->d_func()->focus_prev = o;
- }
-
- if (!q->isWindow()) {
- QWidget *topLevel = q->window();
- //insert new chain into toplevel's chain
-
- QWidget *prev = topLevel->d_func()->focus_prev;
-
- topLevel->d_func()->focus_prev = n;
- prev->d_func()->focus_next = q;
-
- focus_prev = prev;
- n->d_func()->focus_next = topLevel;
- } else {
- //repair the new list
- n->d_func()->focus_next = q;
- focus_prev = n;
- }
-
+ insertIntoFocusChain(QWidgetPrivate::FocusDirection::Previous, q->window());
+ reparentFocusChildren(QWidgetPrivate::FocusDirection::Next);
}
/*!
@@ -7358,15 +7357,67 @@ QByteArray QWidget::saveGeometry() const
return array;
}
-static void checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
+/*!
+ \internal
+
+ Check a if \a restoredGeometry fits into \a availableGeometry
+ This method is used to verify that a widget is restored to a geometry, which
+ fits into the target screen.
+
+ \param frameHeight represents the height of the widget's title bar, which is expected
+ to be on its top.
+
+ If the size of \a restoredGeometry exceeds \a availableGeometry, its height and width
+ will be resized to be two pixels smaller than \a availableGeometry. An exact match would
+ be full screen.
+
+ If at least one edge of \a restoredGeometry is outside \a availableGeometry,
+ \a restoredGeometry will be moved
+ \list
+ \li down if its top is off screen
+ \li up if its bottom is off screen
+ \li right if its left edge is off screen
+ \li left if its right edge is off screen
+ \endlist
+ */
+void QWidgetPrivate::checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
int frameHeight)
{
- if (!restoredGeometry->intersects(availableGeometry)) {
- restoredGeometry->moveBottom(qMin(restoredGeometry->bottom(), availableGeometry.bottom()));
- restoredGeometry->moveLeft(qMax(restoredGeometry->left(), availableGeometry.left()));
- restoredGeometry->moveRight(qMin(restoredGeometry->right(), availableGeometry.right()));
+ // compare with restored geometry's height increased by frameHeight
+ const int height = restoredGeometry->height() + frameHeight;
+
+ // Step 1: Resize if necessary:
+ // make height / width 2px smaller than screen, because an exact match would be fullscreen
+ if (availableGeometry.height() <= height)
+ restoredGeometry->setHeight(availableGeometry.height() - 2 - frameHeight);
+ if (availableGeometry.width() <= restoredGeometry->width())
+ restoredGeometry->setWidth(availableGeometry.width() - 2);
+
+ // Step 2: Move if necessary:
+ // Construct a rectangle from restored Geometry adjusted by frameHeight
+ const QRect restored = restoredGeometry->adjusted(0, -frameHeight, 0, 0);
+
+ // Return if restoredGeometry (including frame) fits into screen
+ if (availableGeometry.contains(restored))
+ return;
+
+ // (size is correct, but at least one edge is off screen)
+
+ // Top out of bounds => move down
+ if (restored.top() <= availableGeometry.top()) {
+ restoredGeometry->moveTop(availableGeometry.top() + 1 + frameHeight);
+ } else if (restored.bottom() >= availableGeometry.bottom()) {
+ // Bottom out of bounds => move up
+ restoredGeometry->moveBottom(availableGeometry.bottom() - 1);
+ }
+
+ // Left edge out of bounds => move right
+ if (restored.left() <= availableGeometry.left()) {
+ restoredGeometry->moveLeft(availableGeometry.left() + 1);
+ } else if (restored.right() >= availableGeometry.right()) {
+ // Right edge out of bounds => move left
+ restoredGeometry->moveRight(availableGeometry.right() - 1);
}
- restoredGeometry->moveTop(qMax(restoredGeometry->top(), availableGeometry.top() + frameHeight));
}
/*!
@@ -7453,7 +7504,9 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
return false;
}
- const int frameHeight = 20;
+ const int frameHeight = QApplication::style()
+ ? QApplication::style()->pixelMetric(QStyle::PM_TitleBarHeight, nullptr, this)
+ : 20;
if (!restoredNormalGeometry.isValid())
restoredNormalGeometry = QRect(QPoint(0, frameHeight), sizeHint());
@@ -7469,11 +7522,11 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
// Modify the restored geometry if we are about to restore to coordinates
// that would make the window "lost". This happens if:
- // - The restored geometry is completely oustside the available geometry
+ // - The restored geometry is completely or partly oustside the available geometry
// - The title bar is outside the available geometry.
- checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight);
- checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight);
+ QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight);
+ QWidgetPrivate::checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight);
if (maximized || fullScreen) {
// set geometry before setting the window state to make
@@ -7505,6 +7558,8 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
d_func()->topData()->normalGeometry = restoredNormalGeometry;
} else {
setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
+
+ // FIXME: Why fall back to restoredNormalGeometry if majorVersion <= 2?
if (majorVersion > 2)
setGeometry(restoredGeometry);
else
@@ -7803,21 +7858,29 @@ void QWidget::setUpdatesEnabled(bool enable)
/*!
Shows the widget and its child widgets.
- This is equivalent to calling showFullScreen(), showMaximized(), or setVisible(true),
- depending on the platform's default behavior for the window flags.
+ For child windows, this is equivalent to calling setVisible(true).
+ Otherwise, it is equivalent to calling showFullScreen(), showMaximized(),
+ or setVisible(true), depending on the platform's default behavior for the window flags.
- \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
+ \sa raise(), showEvent(), hide(), setVisible(), showMinimized(), showMaximized(),
showNormal(), isVisible(), windowFlags()
*/
void QWidget::show()
{
- Qt::WindowState defaultState = QGuiApplicationPrivate::platformIntegration()->defaultWindowState(data->window_flags);
- if (defaultState == Qt::WindowFullScreen)
- showFullScreen();
- else if (defaultState == Qt::WindowMaximized)
- showMaximized();
- else
- setVisible(true); // Don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
+ // Note: We don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
+
+ if (!isWindow()) {
+ setVisible(true);
+ } else {
+ const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
+ Qt::WindowState defaultState = platformIntegration->defaultWindowState(data->window_flags);
+ if (defaultState == Qt::WindowFullScreen)
+ showFullScreen();
+ else if (defaultState == Qt::WindowMaximized)
+ showMaximized();
+ else
+ setVisible(true);
+ }
}
/*! \internal
@@ -7968,7 +8031,7 @@ void QWidgetPrivate::show_helper()
if (!isEmbedded && q->windowType() == Qt::Popup)
qApp->d_func()->openPopup(q);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (q->windowType() != Qt::ToolTip) { // Tooltips are read aloud twice in MS narrator.
QAccessibleEvent event(q, QAccessible::ObjectShow);
QAccessible::updateAccessibility(&event);
@@ -8114,7 +8177,7 @@ void QWidgetPrivate::hide_helper()
if (QWidgetRepaintManager *repaintManager = maybeRepaintManager())
repaintManager->removeDirtyWidget(q);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (wasVisible) {
QAccessibleEvent event(q, QAccessible::ObjectHide);
QAccessible::updateAccessibility(&event);
@@ -8184,13 +8247,17 @@ void QWidgetPrivate::hide_sys()
void QWidget::setVisible(bool visible)
{
+ Q_D(QWidget);
+ qCDebug(lcWidgetShowHide) << "Setting visibility of" << this
+ << "with attributes" << WidgetAttributes{this}
+ << "to" << visible << "via QWidget";
+
if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible)
return;
// Remember that setVisible was called explicitly
setAttribute(Qt::WA_WState_ExplicitShowHide);
- Q_D(QWidget);
d->setVisible(visible);
}
@@ -8200,6 +8267,10 @@ void QWidget::setVisible(bool visible)
void QWidgetPrivate::setVisible(bool visible)
{
Q_Q(QWidget);
+ qCDebug(lcWidgetShowHide) << "Setting visibility of" << q
+ << "with attributes" << WidgetAttributes{q}
+ << "to" << visible << "via QWidgetPrivate";
+
if (visible) { // show
// Designer uses a trick to make grabWidget work without showing
if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible()
@@ -8279,8 +8350,7 @@ void QWidgetPrivate::setVisible(bool visible)
if (!q->testAttribute(Qt::WA_WState_Hidden)) {
q->setAttribute(Qt::WA_WState_Hidden);
- if (q->testAttribute(Qt::WA_WState_Created))
- hide_helper();
+ hide_helper();
}
// invalidate layout similar to updateGeometry()
@@ -8304,23 +8374,35 @@ void QWidget::setHidden(bool hidden)
setVisible(!hidden);
}
+bool QWidgetPrivate::isExplicitlyHidden() const
+{
+ Q_Q(const QWidget);
+ return q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
+}
+
void QWidgetPrivate::_q_showIfNotHidden()
{
Q_Q(QWidget);
- if ( !(q->isHidden() && q->testAttribute(Qt::WA_WState_ExplicitShowHide)) )
+ if (!isExplicitlyHidden())
q->setVisible(true);
}
void QWidgetPrivate::showChildren(bool spontaneous)
{
+ Q_Q(QWidget);
+ qCDebug(lcWidgetShowHide) << "Showing children of" << q
+ << "spontaneously" << spontaneous;
+
QList<QObject*> childList = children;
for (int i = 0; i < childList.size(); ++i) {
QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
- if (widget && widget->windowHandle() && !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
+ if (!widget)
+ continue;
+ qCDebug(lcWidgetShowHide) << "Considering" << widget
+ << "with attributes" << WidgetAttributes{widget};
+ if (widget->windowHandle() && !widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
widget->setAttribute(Qt::WA_WState_Hidden, false);
- if (!widget
- || widget->isWindow()
- || widget->testAttribute(Qt::WA_WState_Hidden))
+ if (widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
continue;
if (spontaneous) {
widget->setAttribute(Qt::WA_Mapped);
@@ -8331,17 +8413,25 @@ void QWidgetPrivate::showChildren(bool spontaneous)
if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide))
widget->d_func()->show_recursive();
else
- widget->show();
+ widget->d_func()->setVisible(true);
}
}
}
void QWidgetPrivate::hideChildren(bool spontaneous)
{
+ Q_Q(QWidget);
+ qCDebug(lcWidgetShowHide) << "Hiding children of" << q
+ << "spontaneously" << spontaneous;
+
QList<QObject*> childList = children;
for (int i = 0; i < childList.size(); ++i) {
QWidget *widget = qobject_cast<QWidget*>(childList.at(i));
- if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
+ if (!widget)
+ continue;
+ qCDebug(lcWidgetShowHide) << "Considering" << widget
+ << "with attributes" << WidgetAttributes{widget};
+ if (widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden))
continue;
if (spontaneous)
@@ -8362,13 +8452,21 @@ void QWidgetPrivate::hideChildren(bool spontaneous)
}
}
qApp->d_func()->sendSyntheticEnterLeave(widget);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (!spontaneous) {
QAccessibleEvent event(widget, QAccessible::ObjectHide);
QAccessible::updateAccessibility(&event);
}
#endif
}
+
+ // If the window of this widget is not closed, then the leave event
+ // will eventually handle the widget under mouse use case.
+ // Otherwise, we need to explicitly handle it here.
+ if (QWidget* widgetWindow = q->window();
+ widgetWindow && widgetWindow->data->is_closing) {
+ q->setAttribute(Qt::WA_UnderMouse, false);
+ }
}
/*!
@@ -8391,13 +8489,15 @@ void QWidgetPrivate::hideChildren(bool spontaneous)
*/
bool QWidgetPrivate::handleClose(CloseMode mode)
{
+ Q_Q(QWidget);
+ qCDebug(lcWidgetShowHide) << "Handling close event for" << q;
+
if (data.is_closing)
return true;
// We might not have initiated the close, so update the state now that we know
data.is_closing = true;
- Q_Q(QWidget);
QPointer<QWidget> that = q;
if (data.in_destructor)
@@ -8507,7 +8607,7 @@ bool QWidgetPrivate::close()
when the user minimizes the window, and a spontaneous show event
when the window is restored again.
- You almost never have to reimplement the setVisible() function. If
+ You seldom have to reimplement the setVisible() function. If
you need to change some settings before a widget is shown, use
showEvent() instead. If you need to do some delayed initialization
use the Polish event delivered to the event() function.
@@ -8834,7 +8934,7 @@ bool QWidget::event(QEvent *event)
break;
#endif
case QEvent::KeyPress: {
- QKeyEvent *k = (QKeyEvent *)event;
+ QKeyEvent *k = static_cast<QKeyEvent *>(event);
bool res = false;
if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) { //### Add MetaModifier?
if (k->key() == Qt::Key_Backtab
@@ -8898,8 +8998,15 @@ bool QWidget::event(QEvent *event)
Qt::InputMethodQuery q = (Qt::InputMethodQuery)(int)(queries & (1<<i));
if (q) {
QVariant v = inputMethodQuery(q);
- if (q == Qt::ImEnabled && !v.isValid() && isEnabled())
- v = QVariant(true); // special case for Qt4 compatibility
+ if (q == Qt::ImEnabled && !v.isValid() && isEnabled()) {
+ // Qt:ImEnabled was added in Qt 5.3. So not all widgets support it, even
+ // if they implement IM otherwise (by overriding inputMethodQuery()). Instead
+ // they set the widget attribute Qt::WA_InputMethodEnabled. But this attribute
+ // will only be set if the widget supports IM _and_ is not read-only. So for
+ // read-only widgets, not all IM features will be supported when ImEnabled is
+ // not implemented explicitly (e.g selection handles for read-only widgets on iOS).
+ v = QVariant(testAttribute(Qt::WA_InputMethodEnabled));
+ }
query->setValue(q, v);
}
}
@@ -8996,7 +9103,7 @@ bool QWidget::event(QEvent *event)
break;
#if QT_CONFIG(menu)
case Qt::ActionsContextMenu:
- if (d->actions.count()) {
+ if (d->actions.size()) {
QMenu::exec(d->actions, static_cast<QContextMenuEvent *>(event)->globalPos(),
nullptr, this);
break;
@@ -9220,16 +9327,15 @@ bool QWidget::event(QEvent *event)
const QWindow *win = te->window;
d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
}
+ break;
+ case QEvent::DevicePixelRatioChange:
if (d->data.fnt.d->dpi != logicalDpiY())
d->updateFont(d->data.fnt);
-#ifndef QT_NO_OPENGL
d->renderToTextureReallyDirty = 1;
-#endif
break;
-#ifndef QT_NO_PROPERTIES
case QEvent::DynamicPropertyChange: {
const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
- if (propName.length() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
+ if (propName.size() == 13 && !qstrncmp(propName, "_q_customDpi", 12)) {
uint value = property(propName.constData()).toUInt();
if (!d->extra)
d->createExtra();
@@ -9244,7 +9350,6 @@ bool QWidget::event(QEvent *event)
windowHandle()->setProperty(propName, property(propName));
Q_FALLTHROUGH();
}
-#endif
default:
return QObject::event(event);
}
@@ -9272,7 +9377,7 @@ void QWidget::changeEvent(QEvent * event)
switch(event->type()) {
case QEvent::EnabledChange: {
update();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::State s;
s.disabled = true;
QAccessibleStateChangeEvent event(this, s);
@@ -9488,7 +9593,7 @@ void QWidget::tabletEvent(QTabletEvent *event)
implementation if you act upon the key.
\sa keyReleaseEvent(), setFocusPolicy(),
- focusInEvent(), focusOutEvent(), event(), QKeyEvent, {Tetrix Example}
+ focusInEvent(), focusOutEvent(), event(), QKeyEvent
*/
void QWidget::keyPressEvent(QKeyEvent *event)
@@ -9539,7 +9644,7 @@ void QWidget::keyReleaseEvent(QKeyEvent *event)
is passed in the \a event parameter
A widget normally must setFocusPolicy() to something other than
- Qt::NoFocus in order to receive focus events. (Note that the
+ Qt::NoFocus to receive focus events. (Note that the
application programmer can call setFocus() on any widget, even
those that do not normally accept focus.)
@@ -9565,7 +9670,7 @@ void QWidget::focusInEvent(QFocusEvent *)
passed in the \a event parameter.
A widget normally must setFocusPolicy() to something other than
- Qt::NoFocus in order to receive focus events. (Note that the
+ Qt::NoFocus to receive focus events. (Note that the
application programmer can call setFocus() on any widget, even
those that do not normally accept focus.)
@@ -9665,7 +9770,7 @@ void QWidget::leaveEvent(QEvent *)
never be called; the backingstore will be used instead.
\sa event(), repaint(), update(), QPainter, QPixmap, QPaintEvent,
- {Analog Clock Example}
+ {Analog Clock}
*/
void QWidget::paintEvent(QPaintEvent *)
@@ -9737,13 +9842,8 @@ void QWidget::actionEvent(QActionEvent *)
Main window applications typically use reimplementations of this function to check
whether the user's work has been saved and ask for permission before closing.
- For example, the \l{Qt Widgets - Application Example} uses a helper function to
- determine whether or not to close the window:
-
- \snippet mainwindows/application/mainwindow.cpp 3
- \snippet mainwindows/application/mainwindow.cpp 4
- \sa event(), hide(), close(), QCloseEvent, {Qt Widgets - Application Example}
+ \sa event(), hide(), close(), QCloseEvent
*/
void QWidget::closeEvent(QCloseEvent *event)
@@ -9832,7 +9932,7 @@ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
is set, the input method may change its visual components to reflect
that only numbers can be entered.
- \warning Some widgets require certain flags in order to work as
+ \warning Some widgets require certain flags to work as
intended. To set a flag, do \c{w->setInputMethodHints(w->inputMethodHints()|f)}
instead of \c{w->setInputMethodHints(f)}.
@@ -10082,7 +10182,7 @@ void QWidget::ensurePolished() const
Returns the mask currently set on a widget. If no mask is set the
return value will be an empty region.
- \sa setMask(), clearMask(), QRegion::isEmpty(), {Shaped Clock Example}
+ \sa setMask(), clearMask(), QRegion::isEmpty()
*/
QRegion QWidget::mask() const
{
@@ -10503,22 +10603,26 @@ void QWidget::setParent(QWidget *parent)
setParent((QWidget*)parent, windowFlags() & ~Qt::WindowType_Mask);
}
-#ifndef QT_NO_OPENGL
-static void sendWindowChangeToTextureChildrenRecursively(QWidget *widget)
+void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType)
{
QWidgetPrivate *d = QWidgetPrivate::get(widget);
if (d->renderToTexture) {
- QEvent e(QEvent::WindowChangeInternal);
+ QEvent e(eventType);
QCoreApplication::sendEvent(widget, &e);
}
for (int i = 0; i < d->children.size(); ++i) {
QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
- if (w && !w->isWindow() && QWidgetPrivate::get(w)->textureChildSeen)
- sendWindowChangeToTextureChildrenRecursively(w);
+ if (w && !w->isWindow())
+ qSendWindowChangeToTextureChildrenRecursively(w, eventType);
+ }
+
+ // Notify QWidgetWindow after we've notified all child QWidgets
+ if (auto *window = d->windowHandle(QWidgetPrivate::WindowHandleMode::Direct)) {
+ QEvent e(eventType);
+ QCoreApplication::sendEvent(window, &e);
}
}
-#endif
/*!
\overload
@@ -10548,6 +10652,7 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
const bool resized = testAttribute(Qt::WA_Resized);
const bool wasCreated = testAttribute(Qt::WA_WState_Created);
QWidget *oldtlw = window();
+ Q_ASSERT(oldtlw);
if (f & Qt::Window) // Frame geometry likely changes, refresh.
d->data.fstrut_dirty = true;
@@ -10566,7 +10671,20 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
if (wasCreated) {
if (!testAttribute(Qt::WA_WState_Hidden)) {
+ // Hiding the widget will set WA_WState_Hidden as well, which would
+ // normally require the widget to be explicitly shown again to become
+ // visible, even as a child widget. But we refine this value later in
+ // setParent_sys(), applying WA_WState_Hidden based on whether the
+ // widget is a top level or not.
hide();
+
+ // We reset WA_WState_ExplicitShowHide here, likely as a remnant of
+ // when we only had QWidget::setVisible(), which is treated as an
+ // explicit show/hide. Nowadays we have QWidgetPrivate::setVisible(),
+ // that allows us to hide a widget without affecting ExplicitShowHide.
+ // Though it can be argued that ExplicitShowHide should reflect the
+ // last update of the widget's state, so if we hide the widget as a
+ // side effect of changing parent, perhaps we _should_ reset it?
setAttribute(Qt::WA_WState_ExplicitShowHide, false);
}
if (newParent) {
@@ -10574,6 +10692,12 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
QCoreApplication::sendEvent(this, &e);
}
}
+
+ // texture-based widgets need a pre-notification when their associated top-level window changes
+ // This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget.
+ if (oldtlw->d_func()->usesRhiFlush && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
+ qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowAboutToChangeInternal);
+
// If we get parented into another window, children will be folded
// into the new parent's focus chain, so clear focus now.
if (newParent && isAncestorOf(focusWidget()) && !(f & Qt::Window))
@@ -10584,12 +10708,10 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
if (desktopWidget)
parent = nullptr;
-#ifndef QT_NO_OPENGL
if (d->textureChildSeen && parent) {
// set the textureChildSeen flag up the whole parent chain
QWidgetPrivate::get(parent)->setTextureChildSeen();
}
-#endif
if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) {
if (newParent)
@@ -10651,12 +10773,11 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
QEvent e(QEvent::ParentChange);
QCoreApplication::sendEvent(this, &e);
}
-#ifndef QT_NO_OPENGL
- //renderToTexture widgets also need to know when their top-level window changes
- if (d->textureChildSeen && oldtlw != window()) {
- sendWindowChangeToTextureChildrenRecursively(this);
- }
-#endif
+
+ // texture-based widgets need another event when their top-level window
+ // changes (more precisely, has already changed at this point)
+ if (oldtlw->d_func()->usesRhiFlush && oldtlw != window())
+ qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowChangeInternal);
if (!wasCreated) {
if (isWindow() || parentWidget()->isVisible())
@@ -10682,6 +10803,37 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
if (d->extra && d->extra->hasWindowContainer)
QWindowContainer::parentWasChanged(this);
+
+ QWidget *newtlw = window();
+ if (oldtlw != newtlw) {
+ QSurface::SurfaceType surfaceType = QSurface::RasterSurface;
+ // Only evaluate the reparented subtree. While it might be tempting to
+ // do it on newtlw instead, the performance implications of that are
+ // problematic when it comes to large widget trees.
+ if (q_evaluateRhiConfig(this, nullptr, &surfaceType)) {
+ const bool wasUsingRhiFlush = newtlw->d_func()->usesRhiFlush;
+ newtlw->d_func()->usesRhiFlush = true;
+ bool recreate = false;
+ if (QWindow *w = newtlw->windowHandle()) {
+ if (w->surfaceType() != surfaceType || !wasUsingRhiFlush)
+ recreate = true;
+ }
+ // QTBUG-115652: Besides the toplevel the nativeParentWidget()'s QWindow must be checked as well.
+ if (QWindow *w = d->windowHandle(QWidgetPrivate::WindowHandleMode::Closest)) {
+ if (w->surfaceType() != surfaceType)
+ recreate = true;
+ }
+ if (recreate) {
+ const auto windowStateBeforeDestroy = newtlw->windowState();
+ const auto visibilityBeforeDestroy = newtlw->isVisible();
+ newtlw->destroy();
+ newtlw->create();
+ Q_ASSERT(newtlw->windowHandle());
+ newtlw->windowHandle()->setWindowStates(windowStateBeforeDestroy);
+ QWidgetPrivate::get(newtlw)->setVisible(visibilityBeforeDestroy);
+ }
+ }
+ }
}
void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
@@ -10702,57 +10854,61 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
setWinId(0);
- if (parent != newparent) {
- QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
- if (q->windowHandle()) {
- q->windowHandle()->setFlags(f);
- QWidget *parentWithWindow =
- newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : nullptr;
- if (parentWithWindow) {
- QWidget *topLevel = parentWithWindow->window();
- if ((f & Qt::Window) && topLevel && topLevel->windowHandle()) {
- q->windowHandle()->setTransientParent(topLevel->windowHandle());
- q->windowHandle()->setParent(nullptr);
- } else {
- q->windowHandle()->setTransientParent(nullptr);
- q->windowHandle()->setParent(parentWithWindow->windowHandle());
- }
- } else {
- q->windowHandle()->setTransientParent(nullptr);
- q->windowHandle()->setParent(nullptr);
- }
- }
- }
-
if (!newparent) {
f |= Qt::Window;
if (parent)
targetScreen = q->parentWidget()->window()->screen();
}
- bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
+ const bool destroyWindow = (
+ // Reparenting top level to child
+ (oldFlags & Qt::Window) && !(f & Qt::Window)
+ // And we can dispose of the window
+ && wasCreated && !q->testAttribute(Qt::WA_NativeWindow)
+ );
- // Reparenting toplevel to child
- if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
- if (extra && extra->hasWindowContainer)
- QWindowContainer::toplevelAboutToBeDestroyed(q);
+ if (parent != newparent) {
+ // Update object parent now, so we can resolve new parent window below
+ QObjectPrivate::setParent_helper(newparent);
+
+ if (q->windowHandle())
+ q->windowHandle()->setFlags(f);
- QWindow *newParentWindow = newparent->windowHandle();
- if (!newParentWindow)
- if (QWidget *npw = newparent->nativeParentWidget())
- newParentWindow = npw->windowHandle();
+ // If the widget itself or any of its children have been created,
+ // we need to reparent their QWindows as well.
+ QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
+ // But if the widget is about to be destroyed we must skip the
+ // widget itself, and only reparent children.
+ if (destroyWindow)
+ reparentWidgetWindowChildren(parentWithWindow);
+ else
+ reparentWidgetWindows(parentWithWindow, f);
+ }
- for (QObject *child : q->windowHandle()->children()) {
- QWindow *childWindow = qobject_cast<QWindow *>(child);
- if (!childWindow)
- continue;
+ bool explicitlyHidden = isExplicitlyHidden();
- QWidgetWindow *childWW = qobject_cast<QWidgetWindow *>(childWindow);
- QWidget *childWidget = childWW ? childWW->widget() : nullptr;
- if (!childWW || (childWidget && childWidget->testAttribute(Qt::WA_NativeWindow)))
- childWindow->setParent(newParentWindow);
+ if (destroyWindow) {
+ if (extra && extra->hasWindowContainer)
+ QWindowContainer::toplevelAboutToBeDestroyed(q);
+
+ // There shouldn't be any QWindow children left, but if there
+ // are, re-parent them now, before we destroy.
+ if (!q->windowHandle()->children().isEmpty()) {
+ QWidget *parentWithWindow = closestParentWidgetWithWindowHandle();
+ QWindow *newParentWindow = parentWithWindow ? parentWithWindow->windowHandle() : nullptr;
+ for (QObject *child : q->windowHandle()->children()) {
+ if (QWindow *childWindow = qobject_cast<QWindow *>(child)) {
+ qCWarning(lcWidgetWindow) << "Reparenting" << childWindow
+ << "before destroying" << this;
+ childWindow->setParent(newParentWindow);
+ }
+ }
}
- q->destroy();
+
+ // We have reparented any child windows of the widget we are
+ // about to destroy to the new parent window handle, so we can
+ // safely destroy this widget without destroying sub windows.
+ q->destroy(true, false);
}
adjustFlags(f, q);
@@ -10778,6 +10934,53 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
}
}
+void QWidgetPrivate::reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags)
+{
+ if (QWindow *window = windowHandle()) {
+ // Reparent this QWindow, and all QWindow children will follow
+ if (parentWithWindow) {
+ // The reparented widget has not updated its window flags yet,
+ // so we can't ask the widget directly. And we can't use the
+ // QWindow flags, as unlike QWidgets the QWindow flags always
+ // reflect Qt::Window, even for child windows. And we can't use
+ // QWindow::isTopLevel() either, as that depends on the parent,
+ // which we are in the process of updating. So we propagate the
+ // new flags of the reparented window from setParent_sys().
+ if (windowFlags & Qt::Window) {
+ // Top level windows can only have transient parents,
+ // and the transient parent must be another top level.
+ QWidget *topLevel = parentWithWindow->window();
+ auto *transientParent = topLevel->windowHandle();
+ Q_ASSERT(transientParent);
+ qCDebug(lcWidgetWindow) << "Setting" << window << "transient parent to" << transientParent;
+ window->setTransientParent(transientParent);
+ window->setParent(nullptr);
+ } else {
+ auto *parentWindow = parentWithWindow->windowHandle();
+ qCDebug(lcWidgetWindow) << "Reparenting" << window << "into" << parentWindow;
+ window->setTransientParent(nullptr);
+ window->setParent(parentWindow);
+ }
+ } else {
+ qCDebug(lcWidgetWindow) << "Making" << window << "top level window";
+ window->setTransientParent(nullptr);
+ window->setParent(nullptr);
+ }
+ } else {
+ reparentWidgetWindowChildren(parentWithWindow);
+ }
+}
+
+void QWidgetPrivate::reparentWidgetWindowChildren(QWidget *parentWithWindow)
+{
+ for (auto *child : std::as_const(children)) {
+ if (auto *childWidget = qobject_cast<QWidget*>(child)) {
+ auto *childPrivate = QWidgetPrivate::get(childWidget);
+ childPrivate->reparentWidgetWindows(parentWithWindow);
+ }
+ }
+}
+
/*!
Scrolls the widget including its children \a dx pixels to the
right and \a dy downward. Both \a dx and \a dy may be negative.
@@ -10872,7 +11075,7 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
unless updates are disabled or the widget is hidden.
We suggest only using repaint() if you need an immediate repaint,
- for example during animation. In almost all circumstances update()
+ for example during animation. In most circumstances update()
is better, as it permits Qt to optimize for speed and minimize
flicker.
@@ -10939,7 +11142,7 @@ void QWidgetPrivate::repaint(T r)
return;
QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
- if (tlwExtra && tlwExtra->backingStore)
+ if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow);
}
@@ -10959,7 +11162,7 @@ void QWidgetPrivate::repaint(T r)
If the Qt::WA_OpaquePaintEvent widget attribute is set, the widget is
responsible for painting all its pixels with an opaque color.
- \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock Example}
+ \sa repaint(), paintEvent(), setUpdatesEnabled(), {Analog Clock}
*/
void QWidget::update()
{
@@ -11000,6 +11203,11 @@ void QWidgetPrivate::update(T r)
{
Q_Q(QWidget);
+ if (renderToTexture && !q->isVisible()) {
+ renderToTextureReallyDirty = 1;
+ return;
+ }
+
if (!q->isVisible() || !q->updatesEnabled())
return;
@@ -11014,7 +11222,7 @@ void QWidgetPrivate::update(T r)
}
QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
- if (tlwExtra && tlwExtra->backingStore)
+ if (tlwExtra && tlwExtra->backingStore && tlwExtra->repaintManager)
tlwExtra->repaintManager->markDirty(clipped, q);
}
@@ -11363,8 +11571,7 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level)
its parent because other children of the parent might have been
modified.
- \sa windowTitle, {Qt Widgets - Application Example}, {SDI Example},
- {MDI Example}
+ \sa windowTitle
*/
bool QWidget::isWindowModified() const
{
@@ -11393,7 +11600,7 @@ void QWidgetPrivate::setWindowModified_helper()
return;
bool on = q->testAttribute(Qt::WA_WindowModified);
if (!platformWindow->setWindowModified(on)) {
- if (Q_UNLIKELY(on && !q->windowTitle().contains(QLatin1String("[*]"))))
+ if (Q_UNLIKELY(on && !q->windowTitle().contains("[*]"_L1)))
qWarning("QWidget::setWindowModified: The window title does not contain a '[*]' placeholder");
setWindowTitle_helper(q->windowTitle());
setWindowIconText_helper(q->windowIconText());
@@ -11505,7 +11712,7 @@ QString QWidget::whatsThis() const
}
#endif // QT_CONFIG(whatsthis)
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
/*!
\property QWidget::accessibleName
@@ -11570,7 +11777,7 @@ QString QWidget::accessibleDescription() const
Q_D(const QWidget);
return d->accessibleDescription;
}
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#ifndef QT_NO_SHORTCUT
/*!
@@ -12055,7 +12262,7 @@ void QWidget::setBackingStore(QBackingStore *store)
return;
QBackingStore *oldStore = topData->backingStore;
- deleteBackingStore(d);
+ delete topData->backingStore;
topData->backingStore = store;
QWidgetRepaintManager *repaintManager = d->maybeRepaintManager();
@@ -12150,27 +12357,6 @@ void QWidgetPrivate::adjustQuitOnCloseAttribute()
}
}
-QOpenGLContext *QWidgetPrivate::shareContext() const
-{
-#ifdef QT_NO_OPENGL
- return nullptr;
-#else
- if (!extra || !extra->topextra || !extra->topextra->window)
- return nullptr;
-
- if (!extra->topextra->shareContext) {
- auto ctx = std::make_unique<QOpenGLContext>();
- ctx->setShareContext(qt_gl_global_share_context());
- ctx->setFormat(extra->topextra->window->format());
- ctx->setScreen(extra->topextra->window->screen());
- ctx->create();
- extra->topextra->shareContext = std::move(ctx);
- }
- return extra->topextra->shareContext.get();
-#endif // QT_NO_OPENGL
-}
-
-#ifndef QT_NO_OPENGL
void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
{
QWidgetPrivate *wd = QWidgetPrivate::get(w);
@@ -12186,7 +12372,6 @@ void QWidgetPrivate::sendComposeStatus(QWidget *w, bool end)
sendComposeStatus(w, end);
}
}
-#endif // QT_NO_OPENGL
Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
{
@@ -12275,8 +12460,8 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
if ((windowType() == Qt::Popup) && qApp)
qApp->d_func()->closePopup(this);
- if (this == QApplicationPrivate::active_window)
- QApplication::setActiveWindow(nullptr);
+ if (this == qApp->activeWindow())
+ QApplicationPrivate::setActiveWindow(nullptr);
if (QWidget::mouseGrabber() == this)
releaseMouse();
if (QWidget::keyboardGrabber() == this)
@@ -12513,7 +12698,7 @@ static void releaseMouseGrabOfWidget(QWidget *widget)
terminal. Use this function with extreme caution, and consider
using the \c -nograb command line option while debugging.
- It is almost never necessary to grab the mouse when using Qt, as
+ It is seldom necessary to grab the mouse when using Qt, as
Qt grabs and releases it sensibly. In particular, Qt grabs the
mouse when a mouse button is pressed and keeps it until the last
button is released.
@@ -12702,57 +12887,59 @@ void QWidget::activateWindow()
*/
int QWidget::metric(PaintDeviceMetric m) const
{
- QWindow *topLevelWindow = nullptr;
- QScreen *screen = nullptr;
- if (QWidget *topLevel = window()) {
- topLevelWindow = topLevel->windowHandle();
- if (topLevelWindow)
- screen = topLevelWindow->screen();
- }
- if (!screen && QGuiApplication::primaryScreen())
- screen = QGuiApplication::primaryScreen();
+ QScreen *screen = this->screen();
if (!screen) {
if (m == PdmDpiX || m == PdmDpiY)
return 72;
return QPaintDevice::metric(m);
}
- int val;
- if (m == PdmWidth) {
- val = data->crect.width();
- } else if (m == PdmWidthMM) {
- val = data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
- } else if (m == PdmHeight) {
- val = data->crect.height();
- } else if (m == PdmHeightMM) {
- val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
- } else if (m == PdmDepth) {
+
+ auto resolveDevicePixelRatio = [this, screen]() -> qreal {
+
+ // Note: keep in sync with QBackingStorePrivate::backingStoreDevicePixelRatio()!
+ static bool downscale = qEnvironmentVariableIntValue("QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
+ QWindow *window = this->window()->windowHandle();
+ if (window)
+ return downscale ? std::ceil(window->devicePixelRatio()) : window->devicePixelRatio();
+ return screen->devicePixelRatio();
+ };
+
+ switch (m) {
+ case PdmWidth:
+ return data->crect.width();
+ case PdmWidthMM:
+ return data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
+ case PdmHeight:
+ return data->crect.height();
+ case PdmHeightMM:
+ return data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
+ case PdmDepth:
return screen->depth();
- } else if (m == PdmDpiX) {
+ case PdmDpiX:
for (const QWidget *p = this; p; p = p->parentWidget()) {
if (p->d_func()->extra && p->d_func()->extra->customDpiX)
return p->d_func()->extra->customDpiX;
}
return qRound(screen->logicalDotsPerInchX());
- } else if (m == PdmDpiY) {
+ case PdmDpiY:
for (const QWidget *p = this; p; p = p->parentWidget()) {
if (p->d_func()->extra && p->d_func()->extra->customDpiY)
return p->d_func()->extra->customDpiY;
}
return qRound(screen->logicalDotsPerInchY());
- } else if (m == PdmPhysicalDpiX) {
+ case PdmPhysicalDpiX:
return qRound(screen->physicalDotsPerInchX());
- } else if (m == PdmPhysicalDpiY) {
+ case PdmPhysicalDpiY:
return qRound(screen->physicalDotsPerInchY());
- } else if (m == PdmDevicePixelRatio) {
- return topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio();
- } else if (m == PdmDevicePixelRatioScaled) {
- return (QPaintDevice::devicePixelRatioFScale() *
- (topLevelWindow ? topLevelWindow->devicePixelRatio() : qApp->devicePixelRatio()));
- } else {
- val = QPaintDevice::metric(m);// XXX
+ case PdmDevicePixelRatio:
+ return resolveDevicePixelRatio();
+ case PdmDevicePixelRatioScaled:
+ return QPaintDevice::devicePixelRatioFScale() * resolveDevicePixelRatio();
+ default:
+ break;
}
- return val;
+ return QPaintDevice::metric(m);
}
/*!
@@ -12810,8 +12997,16 @@ QPainter *QWidget::sharedPainter() const
widget, window system controls in that area may or may not be
visible, depending on the platform.
- Note that this effect can be slow if the region is particularly
- complex.
+ Since QRegion allows arbitrarily complex regions to be created, widget
+ masks can be made to suit the most unconventionally-shaped windows, and
+ even allow widgets to be displayed with holes in them. Note that this
+ effect can be slow if the region is particularly complex.
+
+ Widget masks are used to hint to the window system that the application
+ does not want mouse events for areas outside the mask. On most systems,
+ they also result in coarse visual clipping. To get smooth window edges, use
+ translucent background and anti-aliased painting instead, as shown in the
+ \l{Translucent Background} example.
\sa windowOpacity
*/
@@ -12897,7 +13092,7 @@ void QWidgetPrivate::setMask_sys(const QRegion &region)
Masked widgets receive mouse events only on their visible
portions.
- \sa clearMask(), windowOpacity(), {Shaped Clock Example}
+ \sa clearMask(), windowOpacity()
*/
void QWidget::setMask(const QBitmap &bitmap)
{
@@ -12927,6 +13122,25 @@ void QWidgetPrivate::setWidgetParentHelper(QObject *widgetAsObject, QObject *new
widget->setParent(static_cast<QWidget*>(newParent));
}
+std::string QWidgetPrivate::flagsForDumping() const
+{
+ Q_Q(const QWidget);
+ std::string flags = QObjectPrivate::flagsForDumping();
+ if (QApplication::focusWidget() == q)
+ flags += 'F';
+ if (q->isVisible()) {
+ std::stringstream s;
+ s << '<'
+ << q->width() << 'x' << q->height()
+ << std::showpos << q->x() << q->y()
+ << '>';
+ flags += s.str();
+ } else {
+ flags += 'I';
+ }
+ return flags;
+}
+
void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
{
#if QT_CONFIG(xcb)
@@ -12973,22 +13187,47 @@ void QWidgetPrivate::setNetWmWindowTypes(bool skipIfMissing)
#endif
}
+/*!
+ \internal
+ \return \c true, if a child with \param policy exists and isn't a child of \param excludeChildrenOf.
+ Return false otherwise.
+ */
+bool QWidgetPrivate::hasChildWithFocusPolicy(Qt::FocusPolicy policy, const QWidget *excludeChildrenOf) const
+{
+ Q_Q(const QWidget);
+ const QWidgetList &children = q->findChildren<QWidget *>(Qt::FindChildrenRecursively);
+ for (const auto *child : children) {
+ if (child->focusPolicy() == policy && child->isEnabled()
+ && (!excludeChildrenOf || !excludeChildrenOf->isAncestorOf(child))) {
+ return true;
+ }
+ }
+ return false;
+}
+
#ifndef QT_NO_DEBUG_STREAM
-static inline void formatWidgetAttributes(QDebug debug, const QWidget *widget)
+namespace {
+QDebug operator<<(QDebug debug, const WidgetAttributes &attributes)
{
- const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
- const QMetaEnum me = qtMo->enumerator(qtMo->indexOfEnumerator("WidgetAttribute"));
- debug << ", attributes=[";
- int count = 0;
- for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
- if (widget->testAttribute(static_cast<Qt::WidgetAttribute>(a))) {
- if (count++)
- debug << ',';
- debug << me.valueToKey(a);
+ const QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug << '[';
+ if (const QWidget *widget = attributes.widget) {
+ const QMetaObject *qtMo = qt_getEnumMetaObject(Qt::WA_AttributeCount);
+ const QMetaEnum me = qtMo->enumerator(qtMo->indexOfEnumerator("WidgetAttribute"));
+ int count = 0;
+ for (int a = 0; a < Qt::WA_AttributeCount; ++a) {
+ if (widget->testAttribute(static_cast<Qt::WidgetAttribute>(a))) {
+ if (count++)
+ debug << ',';
+ debug << me.valueToKey(a);
+ }
}
}
debug << ']';
+ return debug;
+}
}
QDebug operator<<(QDebug debug, const QWidget *widget)
@@ -13008,7 +13247,7 @@ QDebug operator<<(QDebug debug, const QWidget *widget)
debug << ", disabled";
debug << ", states=" << widget->windowState()
<< ", type=" << widget->windowType() << ", flags=" << widget->windowFlags();
- formatWidgetAttributes(debug, widget);
+ debug << ", attributes=" << WidgetAttributes{widget};
if (widget->isWindow())
debug << ", window";
debug << ", " << geometry.width() << 'x' << geometry.height()
@@ -13032,7 +13271,405 @@ QDebug operator<<(QDebug debug, const QWidget *widget)
}
#endif // !QT_NO_DEBUG_STREAM
+
+// *************************** Focus abstraction ************************************
+
+#define FOCUS_NEXT(w) w->d_func()->focus_next
+#define FOCUS_PREV(w) w->d_func()->focus_prev
+
+/*!
+ \internal
+ \return next or previous element in the focus chain, depending on
+ \param direction, irrespective of focus proxies or widgets with Qt::NoFocus.
+ */
+QWidget *QWidgetPrivate::nextPrevElementInFocusChain(FocusDirection direction) const
+{
+ Q_Q(const QWidget);
+ return direction == FocusDirection::Next ? FOCUS_NEXT(q) : FOCUS_PREV(q);
+}
+
+/*!
+ \internal
+ Removes a widget from the focus chain, respecting the flags set in \param rules.
+ \list
+ \li EnsureFocusOut: If the widget has input focus, transfer focus to the next or previous widget
+ in the focus chain, depending on \param direction.
+ \li RemoveInconsistent: Remove the widget, even if its focus chain is inconsistent.
+ \li AssertConsistency: qFatal, if the focus chain is inconsistent. This is used in the QWidget destructor.
+ \endlist
+ \return \c true if the widget has been removed, otherwise \c false.
+ */
+bool QWidgetPrivate::removeFromFocusChain(FocusChainRemovalRules rules, FocusDirection direction)
+{
+ Q_Q(QWidget);
+ if (!isFocusChainConsistent()) {
+#ifdef QT_DEBUG
+ if (rules.testFlag(FocusChainRemovalRule::AssertConsistency))
+ qFatal() << q << "has inconsistent focus chain.";
+#endif
+ qCDebug(lcWidgetFocus) << q << "wasn't removed, because of inconsistent focus chain.";
+ return false;
+ }
+
+ if (!isInFocusChain()) {
+ qCDebug(lcWidgetFocus) << q << "wasn't removed, because it is not part of a focus chain.";
+ return false;
+ }
+
+ if (rules.testFlag(FocusChainRemovalRule::EnsureFocusOut))
+ q->focusNextPrevChild(direction == FocusDirection::Next);
+
+ FOCUS_NEXT(FOCUS_PREV(q)) = FOCUS_NEXT(q);
+ FOCUS_PREV(FOCUS_NEXT(q)) = FOCUS_PREV(q);
+ initFocusChain();
+ qCDebug(lcWidgetFocus) << q << "removed from focus chain.";
+ return true;
+}
+
+/*!
+ \internal
+ Initialises the focus chain by making the widget point to itself.
+ */
+void QWidgetPrivate::initFocusChain()
+{
+ Q_Q(QWidget);
+ qCDebug(lcWidgetFocus) << "Initializing focus chain of" << q;
+ FOCUS_PREV(q) = q;
+ FOCUS_NEXT(q) = q;
+}
+
+/*!
+ \internal
+ Reads QWidget children, which are not part of a focus chain yet.
+ Inserts them into the focus chain before or after the widget,
+ depending on \param direction and in the order of their creation.
+ This is used, when QWidget::setParent() causes a widget to change toplevel windows.
+ */
+void QWidgetPrivate::reparentFocusChildren(FocusDirection direction)
+{
+ Q_Q(QWidget);
+ QWidgetList focusChildrenInsideChain;
+ QDuplicateTracker<QWidget *> seen;
+ QWidget *widget = q->nextInFocusChain();
+ while (q->isAncestorOf(widget)
+ && !seen.hasSeen(widget)
+ && widget != q->window()) {
+ if (widget->focusPolicy() != Qt::NoFocus)
+ focusChildrenInsideChain << widget;
+
+ widget = direction == FocusDirection::Next ? widget->nextInFocusChain()
+ : widget->previousInFocusChain();
+ }
+
+ const QWidgetList children = q->findChildren<QWidget *>(Qt::FindDirectChildrenOnly);
+ QWidgetList focusChildrenOutsideChain;
+ for (auto *child : children) {
+ if (!focusChildrenInsideChain.contains(child))
+ focusChildrenOutsideChain << child;
+ }
+ if (focusChildrenOutsideChain.isEmpty())
+ return;
+
+ QWidget *previous = q;
+ for (auto *child : focusChildrenOutsideChain) {
+ child->d_func()->insertIntoFocusChain(direction, previous);
+ previous = child;
+ }
+}
+
+/*!
+ \internal
+ Inserts a widget into the focus chain before or after \param position, depending on
+ \param direction.
+ \return \c true, if the insertion has changed the focus chain, otherwise \c false.
+ */
+bool QWidgetPrivate::insertIntoFocusChain(FocusDirection direction, QWidget *position)
+{
+ Q_Q(QWidget);
+ Q_ASSERT(position);
+ QWidget *next = FOCUS_NEXT(q);
+ QWidget *previous = FOCUS_PREV(q);
+
+ switch (direction) {
+ case FocusDirection::Next:
+ if (previous == position) {
+ qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already before" << position;
+ return false;
+ }
+
+ removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
+
+ FOCUS_NEXT(q) = FOCUS_NEXT(position);
+ FOCUS_PREV(FOCUS_NEXT(position)) = q;
+ FOCUS_NEXT(position) = q;
+ FOCUS_PREV(q) = position;
+ qCDebug(lcWidgetFocus) << q << "inserted after" << position;
+ break;
+
+ case FocusDirection::Previous:
+ if (next == position) {
+ qCDebug(lcWidgetFocus) << "No-op insertion." << q << "is already after" << position;
+ return false;
+ }
+
+ removeFromFocusChain(FocusChainRemovalRule::AssertConsistency);
+
+ FOCUS_PREV(q) = FOCUS_PREV(position);
+ FOCUS_NEXT(FOCUS_PREV(position)) = q;
+ FOCUS_PREV(position) = q;
+ FOCUS_NEXT(q) = position;
+ qCDebug(lcWidgetFocus) << q << "inserted before" << position;
+ break;
+ }
+
+ Q_ASSERT(isFocusChainConsistent());
+ return true;
+}
+
+/*!
+ \internal
+ Convenience override to insert a QWidgetList \param toBeInserted into the focus chain
+ before or after \param position, depending on \param direction.
+ \return \c true, if the insertion has changed the focus chain, otherwise \c false.
+ \note
+ \param toBeInserted must be a consistent focus chain.
+ */
+bool QWidgetPrivate::insertIntoFocusChain(const QWidgetList &toBeInserted,
+ FocusDirection direction, QWidget *position)
+{
+ if (toBeInserted.isEmpty()) {
+ qCDebug(lcWidgetFocus) << "No-op insertion of an empty list";
+ return false;
+ }
+
+ Q_ASSERT_X(!toBeInserted.contains(position),
+ Q_FUNC_INFO,
+ "Coding error: toBeInserted contains position");
+
+ QWidget *first = toBeInserted.constFirst();
+ QWidget *last = toBeInserted.constLast();
+
+ // Call QWidget override to log accordingly
+ if (toBeInserted.count() == 1)
+ return first->d_func()->insertIntoFocusChain(direction, position);
+
+ Q_ASSERT(first != last);
+ switch (direction) {
+ case FocusDirection::Previous:
+ if (FOCUS_PREV(position) == last) {
+ qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already before"
+ << position;
+ return false;
+ }
+ FOCUS_NEXT(FOCUS_PREV(position)) = first;
+ FOCUS_PREV(first) = FOCUS_PREV(position);
+ FOCUS_NEXT(last) = position;
+ FOCUS_PREV(position) = last;
+ qCDebug(lcWidgetFocus) << toBeInserted << "inserted before" << position;
+ break;
+ case FocusDirection::Next:
+ if (FOCUS_PREV(position) == last) {
+ qCDebug(lcWidgetFocus) << "No-op insertion." << toBeInserted << "is already after"
+ << position;
+ return false;
+ }
+ FOCUS_PREV(FOCUS_NEXT(position)) = last;
+ FOCUS_NEXT(last) = FOCUS_NEXT(position);
+ FOCUS_PREV(first) = position;
+ FOCUS_NEXT(position) = first;
+ qCDebug(lcWidgetFocus) << toBeInserted << "inserted after" << position;
+ break;
+ }
+
+ Q_ASSERT(position->d_func()->isFocusChainConsistent());
+ return true;
+}
+
+/*!
+ \internal
+ \return a QWidgetList, representing the part of the focus chain,
+ starting with \param from and ending with \param to, in \param direction.
+ */
+QWidgetList focusPath(QWidget *from, QWidget *to, QWidgetPrivate::FocusDirection direction)
+{
+ QWidgetList path({from});
+ if (from == to)
+ return path;
+
+ QWidget *current = from;
+ do {
+ switch (direction) {
+ case QWidgetPrivate::FocusDirection::Previous:
+ current = current->previousInFocusChain();
+ break;
+ case QWidgetPrivate::FocusDirection::Next:
+ current = current->nextInFocusChain();
+ break;
+ }
+ if (path.contains(current))
+ return QWidgetList();
+ path << current;
+ } while (current != to);
+
+ return path;
+}
+
+/*!
+ \internal
+ Removes the part from the focus chain starting with \param from and ending with \param to,
+ in \param direction.
+ \return removed part as a QWidgetList.
+ */
+QWidgetList QWidgetPrivate::takeFromFocusChain(QWidget *from,
+ QWidget *to,
+ FocusDirection direction)
+{
+ // Check if there is a path from->to in direction
+ const QWidgetList path = focusPath(from, to , direction);
+ if (path.isEmpty()) {
+ qCDebug(lcWidgetFocus) << "No-op removal. Focus chain from" << from << "doesn't lead to " << to;
+ return QWidgetList();
+ }
+
+ QWidget *first = path.constFirst();
+ QWidget *last = path.constLast();
+ if (first == last) {
+ first->d_func()->removeFromFocusChain();
+ return QWidgetList({first});
+ }
+
+ FOCUS_NEXT(FOCUS_PREV(first)) = FOCUS_NEXT(last);
+ FOCUS_PREV(FOCUS_NEXT(last)) = FOCUS_PREV(first);
+ FOCUS_PREV(first) = last;
+ FOCUS_NEXT(last) = first;
+ qCDebug(lcWidgetFocus) << path << "removed from focus chain";
+ return path;
+}
+
+/*!
+ \internal
+ \return The last focus child of the widget, traversing the focus chain no further than
+ \param noFurtherThan.
+ */
+QWidget *QWidgetPrivate::determineLastFocusChild(QWidget *noFurtherThan)
+{
+ Q_Q(QWidget);
+ // Since we need to repeat the same logic for both 'first' and 'second', we add a function
+ // that determines the last focus child for a widget, taking proxies and compound widgets into
+ // account. If the target is not a compound widget (it doesn't have a focus proxy that points
+ // to a child), 'lastFocusChild' will be set to the target itself.
+ QWidget *lastFocusChild = q;
+
+ QWidget *focusProxy = deepestFocusProxy();
+ if (!focusProxy) {
+ // QTBUG-81097: Another case is possible here. We can have a child
+ // widget, that sets its focusProxy() to the parent (target).
+ // An example of such widget is a QLineEdit, nested into
+ // a QAbstractSpinBox. In this case such widget should be considered
+ // the last focus child.
+ for (auto *object : std::as_const(q->children())) {
+ QWidget *w = qobject_cast<QWidget *>(object);
+ if (w && w->focusProxy() == q) {
+ lastFocusChild = w;
+ break;
+ }
+ }
+ } else if (q->isAncestorOf(focusProxy)) {
+ lastFocusChild = focusProxy;
+ for (QWidget *focusNext = lastFocusChild->nextInFocusChain();
+ focusNext != focusProxy && q->isAncestorOf(focusNext)
+ && focusNext->window() == focusProxy->window();
+ focusNext = focusNext->nextInFocusChain()) {
+ if (focusNext == noFurtherThan)
+ break;
+ if (focusNext->focusPolicy() != Qt::NoFocus)
+ lastFocusChild = focusNext;
+ }
+ }
+ return lastFocusChild;
+};
+
+/*!
+ \internal
+ \return \c true, if the widget is part of a focus chain and \c false otherwise.
+ A widget is considered to be part of a focus chain, neither FOCUS_NEXT, nor FOCUS_PREV
+ are pointing to the widget itself.
+
+ \note
+ This method doesn't check the consistency of the focus chain.
+ If multiple widgets have been removed from the focus chain by takeFromFocusChain(),
+ isInFocusChain() will return \c true for all of those widgets, even if they represent
+ an inconsistent focus chain.
+ */
+bool QWidgetPrivate::isInFocusChain() const
+{
+ Q_Q(const QWidget);
+ return !(FOCUS_NEXT(q) == q && FOCUS_PREV(q) == q);
+}
+
+/*!
+ \internal
+ A focus chain is consistent, when it is circular: Following the chain in either direction
+ has to return to the beginning. This is why a newly constructed widget points to itself,
+ when the focus chain has been initialized. A newly constructed widget is considered to have
+ a consistent focus chain, while not being part of a focus chain.
+
+ The method always returns \c true, when the logging category "qt.widgets.focus" is disabled.
+ When it is enabled, the method returns \c true early, if a widget is pointing to itself.
+ It returns \c false, if one of the following is detected:
+ \list
+ \li nullptr found in a previous/next pointer.
+ \li broken chain: widget A is B's previous, but B isn't A's next.
+ \li chain isn't closed: starting at A doesn't lead back to A.
+ \endlist
+ It return \c true, if none of the above is observed.
+
+ \note
+ The focus chain is checked only in forward direction.
+ This is sufficient, because the check for a broken chain asserts consistent paths
+ in both directions.
+ */
+bool QWidgetPrivate::isFocusChainConsistent() const
+{
+ Q_Q(const QWidget);
+ const bool skip = !QLoggingCategory("qt.widgets.focus").isDebugEnabled();
+ if (skip)
+ return true;
+
+ if (!isInFocusChain())
+ return true;
+
+ const QWidget *position = q;
+
+ for (int i = 0; i < QApplication::allWidgets().count(); ++i) {
+ if (!FOCUS_PREV(position) || !FOCUS_NEXT(position)) {
+ qCDebug(lcWidgetFocus) << "Nullptr found at:" << position
+ << "Previous pointing to" << FOCUS_PREV(position)
+ << "Next pointing to" << FOCUS_NEXT(position);
+ return false;
+ }
+ if (!(FOCUS_PREV(FOCUS_NEXT(position)) == position
+ && FOCUS_NEXT(FOCUS_PREV(position)) == position)) {
+ qCDebug(lcWidgetFocus) << "Inconsistent focus chain at:" << position
+ << "Previous pointing to" << FOCUS_PREV(FOCUS_NEXT(position))
+ << "Next pointing to" << FOCUS_NEXT(FOCUS_PREV(position));
+ return false;
+ }
+ position = FOCUS_NEXT(position);
+ if (position == q)
+ return true;
+
+ }
+
+ qCDebug(lcWidgetFocus) << "Focus chain leading from" << q << "to" << position << "is not closed.";
+ return false;
+}
+
+#undef FOCUS_NEXT
+#undef FOCUS_PREV
+
+
QT_END_NAMESPACE
#include "moc_qwidget.cpp"
-
+#include "moc_qwidget_p.cpp"
diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h
index 6c30e018df..e5e83a43f2 100644
--- a/src/widgets/kernel/qwidget.h
+++ b/src/widgets/kernel/qwidget.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWIDGET_H
#define QWIDGET_H
@@ -44,7 +8,9 @@
#include <QtGui/qwindowdefs.h>
#include <QtCore/qobject.h>
#include <QtCore/qmargins.h>
+#if QT_CONFIG(action)
#include <QtGui/qaction.h>
+#endif
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpalette.h>
#include <QtGui/qfont.h>
@@ -197,7 +163,7 @@ class Q_WIDGETS_EXPORT QWidget : public QObject, public QPaintDevice
#if QT_CONFIG(whatsthis)
Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis)
#endif
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
Q_PROPERTY(QString accessibleName READ accessibleName WRITE setAccessibleName)
Q_PROPERTY(QString accessibleDescription READ accessibleDescription WRITE setAccessibleDescription)
#endif
@@ -211,6 +177,7 @@ class Q_WIDGETS_EXPORT QWidget : public QObject, public QPaintDevice
Q_PROPERTY(QString windowFilePath READ windowFilePath WRITE setWindowFilePath)
Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints)
+#if QT_CONFIG(action)
#if 0
// ### TODO: make this work (requires SFINAE-friendly connect())
template <typename...Args>
@@ -233,6 +200,8 @@ class Q_WIDGETS_EXPORT QWidget : public QObject, public QPaintDevice
std::negation<std::is_convertible<Args, QString>>...
>>;
#endif
+#endif // QT_CONFIG(action)
+
public:
enum RenderFlag {
DrawWindowBackground = 0x1,
@@ -432,7 +401,7 @@ public:
void setWhatsThis(const QString &);
QString whatsThis() const;
#endif
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QString accessibleName() const;
void setAccessibleName(const QString &name);
QString accessibleDescription() const;
@@ -463,6 +432,7 @@ public:
void setFocusPolicy(Qt::FocusPolicy policy);
bool hasFocus() const;
static void setTabOrder(QWidget *, QWidget *);
+ static void setTabOrder(std::initializer_list<QWidget *> widgets);
void setFocusProxy(QWidget *);
QWidget *focusProxy() const;
Qt::ContextMenuPolicy contextMenuPolicy() const;
@@ -799,9 +769,6 @@ private:
#endif // QT_NO_GESTURES
friend class QWidgetEffectSourcePrivate;
-#ifdef Q_OS_MAC
- friend bool qt_mac_is_metal(const QWidget *w);
-#endif
friend Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget);
friend Q_WIDGETS_EXPORT QWidgetPrivate *qt_widget_private(QWidget *widget);
@@ -832,17 +799,17 @@ inline QWidget *QWidget::childAt(int ax, int ay) const
{ return childAt(QPoint(ax, ay)); }
inline Qt::WindowType QWidget::windowType() const
-{ return static_cast<Qt::WindowType>(int(data->window_flags & Qt::WindowType_Mask)); }
+{ return static_cast<Qt::WindowType>((data->window_flags & Qt::WindowType_Mask).toInt()); }
inline Qt::WindowFlags QWidget::windowFlags() const
{ return data->window_flags; }
#if QT_DEPRECATED_SINCE(6, 1)
inline bool QWidget::isTopLevel() const
-{ return (windowType() & Qt::Window); }
+{ return bool(windowType() & Qt::Window); }
#endif
inline bool QWidget::isWindow() const
-{ return (windowType() & Qt::Window); }
+{ return bool(windowType() & Qt::Window); }
inline bool QWidget::isEnabled() const
{ return !testAttribute(Qt::WA_Disabled); }
@@ -947,7 +914,6 @@ inline bool QWidget::testAttribute(Qt::WidgetAttribute attribute) const
return testAttribute_helper(attribute);
}
-
#define QWIDGETSIZE_MAX ((1<<24)-1)
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index db458be7f1..9fab9efa62 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWIDGET_P_H
#define QWIDGET_P_H
@@ -61,7 +25,6 @@
#include "QtCore/qset.h"
#include "QtGui/qregion.h"
#include "QtGui/qinputmethod.h"
-#include "QtGui/qopengl.h"
#include "QtGui/qsurfaceformat.h"
#include "QtGui/qscreen.h"
#include "QtWidgets/qsizepolicy.h"
@@ -77,6 +40,10 @@
#endif
#include <private/qgesture_p.h>
#include <qpa/qplatformbackingstore.h>
+#include <QtGui/private/qbackingstorerhisupport_p.h>
+#include <private/qapplication_p.h>
+
+#include <QtCore/qpointer.h>
#include <vector>
#include <memory>
@@ -84,6 +51,7 @@
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcWidgetPainting);
+Q_DECLARE_LOGGING_CATEGORY(lcWidgetShowHide);
// Extra QWidget data
// - to minimize memory usage for members that are seldom used.
@@ -94,7 +62,6 @@ class QPixmap;
class QWidgetRepaintManager;
class QGraphicsProxyWidget;
class QWidgetItemV2;
-class QOpenGLContext;
class QStyle;
@@ -102,6 +69,7 @@ class QUnifiedToolbarSurface;
// implemented in qshortcut.cpp
bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context);
+void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type eventType);
class QUpdateLaterEvent : public QEvent
{
@@ -111,13 +79,10 @@ public:
{
}
- ~QUpdateLaterEvent()
- {
- }
-
inline const QRegion &region() const { return m_region; }
protected:
+ friend class QApplication;
QRegion m_region;
};
@@ -130,9 +95,6 @@ struct QTLWExtra {
QBackingStore *backingStore;
QPainter *sharedPainter;
QWidgetWindow *window;
-#ifndef QT_NO_OPENGL
- mutable std::unique_ptr<QOpenGLContext> shareContext;
-#endif
// Implicit pointers (shared_null).
QString caption; // widget caption
@@ -149,9 +111,7 @@ struct QTLWExtra {
Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen
QScreen *initialScreen; // Screen when passing a QDesktop[Screen]Widget as parent.
-#ifndef QT_NO_OPENGL
std::vector<std::unique_ptr<QPlatformTextureList>> widgetTextures;
-#endif
// *************************** Cross-platform bit fields ****************************
uint opacity : 8;
@@ -231,7 +191,8 @@ public:
DontSubtractOpaqueChildren = 0x10,
DontDrawOpaqueChildren = 0x20,
DontDrawNativeChildren = 0x40,
- DontSetCompositionMode = 0x80
+ DontSetCompositionMode = 0x80,
+ UseEffectRegionBounds = 0x100
};
Q_DECLARE_FLAGS(DrawWidgetFlags, DrawWidgetFlag)
Q_FLAG(DrawWidgetFlags)
@@ -251,6 +212,9 @@ public:
static QWidgetPrivate *get(QWidget *w) { return w->d_func(); }
static const QWidgetPrivate *get(const QWidget *w) { return w->d_func(); }
+ static void checkRestoredGeometry(const QRect &availableGeometry, QRect *restoredGeometry,
+ int frameHeight);
+
QWExtra *extraData() const;
QTLWExtra *topData() const;
QTLWExtra *maybeTopData() const;
@@ -258,6 +222,8 @@ public:
void setSharedPainter(QPainter *painter);
QWidgetRepaintManager *maybeRepaintManager() const;
+ QRhi *rhi() const;
+
enum class WindowHandleMode {
Direct,
Closest,
@@ -390,6 +356,7 @@ public:
void invalidateBackingStore(const T &);
QRegion overlappedRegion(const QRect &rect, bool breakAfterFirst = false) const;
+ bool isOverlapped(const QRect &rect) const { return !overlappedRegion(rect, true).isEmpty(); }
void syncBackingStore();
void syncBackingStore(const QRegion &region);
@@ -404,6 +371,8 @@ public:
void showChildren(bool spontaneous);
void hideChildren(bool spontaneous);
void setParent_sys(QWidget *parent, Qt::WindowFlags);
+ void reparentWidgetWindows(QWidget *parentWithWindow, Qt::WindowFlags windowFlags = {});
+ void reparentWidgetWindowChildren(QWidget *parentWithWindow);
void scroll_sys(int dx, int dy);
void scroll_sys(int dx, int dy, const QRect &r);
void deactivateWidgetCleanup();
@@ -416,6 +385,7 @@ public:
void show_sys();
void hide_sys();
void hide_helper();
+ bool isExplicitlyHidden() const;
void _q_showIfNotHidden();
void setVisible(bool);
@@ -478,27 +448,22 @@ public:
// 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)
+ static QWidget *parentGraphicsView(const QWidget *widget)
{
- QRect rect;
#if QT_CONFIG(graphicsview)
QGraphicsProxyWidget *ancestorProxy = widget->d_func()->nearestGraphicsProxyWidget(widget);
//It's embedded if it has an ancestor
if (ancestorProxy) {
if (!bypassGraphicsProxyWidget(widget) && ancestorProxy->scene() != nullptr) {
- // 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);
- rect = view->mapToScene(view->viewport()->rect()).boundingRect().toRect();
- } else {
- rect = ancestorProxy->scene()->sceneRect().toRect();
+ if (!ancestorProxy->scene()->views().empty()) {
+ return ancestorProxy->scene()->views().at(0);
}
}
}
#else
Q_UNUSED(widget);
#endif
- return rect;
+ return nullptr;
}
static QRect screenGeometry(const QWidget *widget)
@@ -511,11 +476,10 @@ public:
return availableScreenGeometry(widget, QPoint(), false);
}
- static QRect screenGeometry(const QWidget *widget, const QPoint &globalPosition, bool hasPosition = true)
+ static QScreen *screen(const QWidget *widget, const QPoint &globalPosition, bool hasPosition = true)
{
- QRect rect = graphicsViewParentRect(widget);
- if (!rect.isNull())
- return rect;
+ while (QWidget *view = parentGraphicsView(widget))
+ widget = view;
QScreen *screen = nullptr;
if (hasPosition)
@@ -523,22 +487,17 @@ public:
if (!screen)
screen = widget->screen();
- return screen->geometry();
+ return screen;
}
- static QRect availableScreenGeometry(const QWidget *widget, const QPoint &globalPosition, bool hasPosition = true)
+ static QRect screenGeometry(const QWidget *widget, const QPoint &globalPosition, bool hasPosition = true)
{
- QRect rect = graphicsViewParentRect(widget);
- if (!rect.isNull())
- return rect;
-
- QScreen *screen = nullptr;
- if (hasPosition)
- screen = widget->screen()->virtualSiblingAt(globalPosition);
- if (!screen)
- screen = widget->screen();
+ return screen(widget, globalPosition, hasPosition)->geometry();
+ }
- return screen->availableGeometry();
+ static QRect availableScreenGeometry(const QWidget *widget, const QPoint &globalPosition, bool hasPosition = true)
+ {
+ return screen(widget, globalPosition, hasPosition)->availableGeometry();
}
inline void setRedirected(QPaintDevice *replacement, const QPoint &offset)
@@ -626,12 +585,17 @@ public:
inline QRect mapFromWS(const QRect &r) const
{ return r.translated(data.wrect.topLeft()); }
- QOpenGLContext *shareContext() const;
+ virtual QObject *focusObject();
+
+ virtual QPlatformBackingStoreRhiConfig rhiConfig() const { return {}; }
- virtual QObject *focusObject() { return nullptr; }
+ // Note that textureRight may be null, as it's only used in stereoscopic rendering
+ struct TextureData {
+ QRhiTexture *textureLeft = nullptr;
+ QRhiTexture *textureRight = nullptr;
+ };
-#ifndef QT_NO_OPENGL
- virtual GLuint textureId() const { return 0; }
+ virtual TextureData texture() const { return {}; }
virtual QPlatformTextureList::Flags textureListFlags() {
Q_Q(QWidget);
return q->testAttribute(Qt::WA_AlwaysStackOnTop)
@@ -666,10 +630,18 @@ public:
virtual void resizeViewportFramebuffer() { }
// Called after each paint event.
virtual void resolveSamples() { }
-#endif
+
+ // These two are used in QGraphicsView for supporting stereoscopic rendering with a
+ // QOpenGLWidget viewport.
+ virtual bool isStereoEnabled() { return false; } // Called in QGraphicsView::setupViewport
+ virtual bool toggleStereoTargetBuffer() { return false; } // Called in QGraphicsView::paintEvent
static void setWidgetParentHelper(QObject *widgetAsObject, QObject *newParent);
+ std::string flagsForDumping() const override;
+
+ QWidget *closestParentWidgetWithWindowHandle() const;
+
// Variables.
// Regular pointers (keep them together to avoid gaps on 64 bit architectures).
std::unique_ptr<QWExtra> extra;
@@ -708,7 +680,7 @@ public:
#if QT_CONFIG(whatsthis)
QString whatsThis;
#endif
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QString accessibleName;
QString accessibleDescription;
#endif
@@ -757,13 +729,45 @@ public:
#ifndef QT_NO_IM
uint inheritsInputMethodHints : 1;
#endif
-#ifndef QT_NO_OPENGL
uint renderToTextureReallyDirty : 1;
- uint renderToTextureComposeActive : 1;
-#endif
+ uint usesRhiFlush : 1;
uint childrenHiddenByWState : 1;
uint childrenShownByExpose : 1;
+ // *************************** Focus abstraction ************************************
+ enum class FocusDirection {
+ Previous,
+ Next,
+ };
+
+ enum class FocusChainRemovalRule {
+ EnsureFocusOut = 0x01,
+ AssertConsistency = 0x02,
+ };
+ Q_DECLARE_FLAGS(FocusChainRemovalRules, FocusChainRemovalRule)
+
+ // Getters
+ QWidget *nextPrevElementInFocusChain(FocusDirection direction) const;
+
+ // manipulators
+ bool removeFromFocusChain(FocusChainRemovalRules rules = FocusChainRemovalRules(),
+ FocusDirection direction = FocusDirection::Next);
+ bool insertIntoFocusChain(FocusDirection direction, QWidget *position);
+ static bool insertIntoFocusChain(const QWidgetList &toBeInserted, FocusDirection direction, QWidget *position);
+ bool insertIntoFocusChainBefore(QWidget *position)
+ { return insertIntoFocusChain(FocusDirection::Previous, position); }
+ bool insertIntoFocusChainAfter(QWidget *position)
+ { return insertIntoFocusChain(FocusDirection::Next, position); }
+ static QWidgetList takeFromFocusChain(QWidget *from, QWidget *to,
+ FocusDirection direction = FocusDirection::Next);
+ void reparentFocusChildren(FocusDirection direction);
+ QWidget *determineLastFocusChild(QWidget *noFurtherThan);
+
+ // Initialization and tests
+ void initFocusChain();
+ bool isInFocusChain() const;
+ bool isFocusChainConsistent() const;
+
// *************************** Platform specific ************************************
#if defined(Q_OS_WIN)
uint noPaintOnScreen : 1; // see qwidget.cpp ::paintEngine()
@@ -774,6 +778,7 @@ public:
bool stealKeyboardGrab(bool grab);
bool stealMouseGrab(bool grab);
+ bool hasChildWithFocusPolicy(Qt::FocusPolicy policy, const QWidget *excludeChildrenOf = nullptr) const;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QWidgetPrivate::DrawWidgetFlags)
diff --git a/src/widgets/kernel/qwidgetaction.cpp b/src/widgets/kernel/qwidgetaction.cpp
index f9cd82f788..13f386d3ec 100644
--- a/src/widgets/kernel/qwidgetaction.cpp
+++ b/src/widgets/kernel/qwidgetaction.cpp
@@ -1,46 +1,12 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwidgetaction.h"
#include "qwidget.h"
#include "qdebug.h"
+#include <QtWidgets/private/qwidget_p.h>
+
#include "qwidgetaction_p.h"
QT_BEGIN_NAMESPACE
@@ -118,9 +84,9 @@ QWidgetAction::QWidgetAction(QObject *parent)
QWidgetAction::~QWidgetAction()
{
Q_D(QWidgetAction);
- for (int i = 0; i < d->createdWidgets.count(); ++i)
- disconnect(d->createdWidgets.at(i), SIGNAL(destroyed(QObject*)),
- this, SLOT(_q_widgetDestroyed(QObject*)));
+ for (QWidget *w : std::as_const(d->createdWidgets))
+ QObjectPrivate::disconnect(w, &QWidget::destroyed,
+ d, &QWidgetActionPrivate::widgetDestroyed);
QList<QWidget *> widgetsToDelete = d->createdWidgets;
d->createdWidgets.clear();
qDeleteAll(widgetsToDelete);
@@ -144,7 +110,7 @@ void QWidgetAction::setDefaultWidget(QWidget *widget)
if (!widget)
return;
- setVisible(!(widget->isHidden() && widget->testAttribute(Qt::WA_WState_ExplicitShowHide)));
+ setVisible(!QWidgetPrivate::get(widget)->isExplicitlyHidden());
d->defaultWidget->hide();
d->defaultWidget->setParent(nullptr);
d->defaultWidgetInUse = false;
@@ -183,8 +149,8 @@ QWidget *QWidgetAction::requestWidget(QWidget *parent)
return d->defaultWidget;
}
- connect(w, SIGNAL(destroyed(QObject*)),
- this, SLOT(_q_widgetDestroyed(QObject*)));
+ QObjectPrivate::connect(w, &QWidget::destroyed,
+ d, &QWidgetActionPrivate::widgetDestroyed);
d->createdWidgets.append(w);
return w;
}
@@ -211,8 +177,8 @@ void QWidgetAction::releaseWidget(QWidget *widget)
if (!d->createdWidgets.contains(widget))
return;
- disconnect(widget, SIGNAL(destroyed(QObject*)),
- this, SLOT(_q_widgetDestroyed(QObject*)));
+ QObjectPrivate::disconnect(widget, &QWidget::destroyed,
+ d, &QWidgetActionPrivate::widgetDestroyed);
d->createdWidgets.removeAll(widget);
deleteWidget(widget);
}
@@ -226,7 +192,7 @@ bool QWidgetAction::event(QEvent *event)
if (event->type() == QEvent::ActionChanged) {
if (d->defaultWidget)
d->defaultWidget->setEnabled(isEnabled());
- for (int i = 0; i < d->createdWidgets.count(); ++i)
+ for (int i = 0; i < d->createdWidgets.size(); ++i)
d->createdWidgets.at(i)->setEnabled(isEnabled());
}
return QAction::event(event);
diff --git a/src/widgets/kernel/qwidgetaction.h b/src/widgets/kernel/qwidgetaction.h
index e3bfc62ca7..296ff52d1e 100644
--- a/src/widgets/kernel/qwidgetaction.h
+++ b/src/widgets/kernel/qwidgetaction.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWIDGETACTION_H
#define QWIDGETACTION_H
@@ -73,7 +37,6 @@ protected:
private:
Q_DISABLE_COPY(QWidgetAction)
- Q_PRIVATE_SLOT(d_func(), void _q_widgetDestroyed(QObject *))
friend class QToolBar;
};
diff --git a/src/widgets/kernel/qwidgetaction_p.h b/src/widgets/kernel/qwidgetaction_p.h
index 4b118c45c5..6a1cd8c186 100644
--- a/src/widgets/kernel/qwidgetaction_p.h
+++ b/src/widgets/kernel/qwidgetaction_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWIDGETACTION_P_H
#define QWIDGETACTION_P_H
@@ -54,6 +18,8 @@
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include "private/qaction_widgets_p.h"
+#include <QtCore/qpointer.h>
+
QT_REQUIRE_CONFIG(action);
QT_BEGIN_NAMESPACE
@@ -68,7 +34,7 @@ public:
uint defaultWidgetInUse : 1;
uint autoCreated : 1; // created by QToolBar::addWidget and the like
- inline void _q_widgetDestroyed(QObject *o) {
+ inline void widgetDestroyed(QObject *o) {
createdWidgets.removeAll(static_cast<QWidget *>(o));
}
};
diff --git a/src/widgets/kernel/qwidgetrepaintmanager.cpp b/src/widgets/kernel/qwidgetrepaintmanager.cpp
index d9375c7281..607a767a20 100644
--- a/src/widgets/kernel/qwidgetrepaintmanager.cpp
+++ b/src/widgets/kernel/qwidgetrepaintmanager.cpp
@@ -1,42 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
-
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
@@ -65,12 +28,11 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_OPENGL
Q_GLOBAL_STATIC(QPlatformTextureList, qt_dummy_platformTextureList)
// Watches one or more QPlatformTextureLists for changes in the lock state and
// triggers a backingstore sync when all the registered lists turn into
-// unlocked state. This is essential when a custom composeAndFlush()
+// unlocked state. This is essential when a custom rhiFlush()
// implementation in a platform plugin is not synchronous and keeps
// holding on to the textures for some time even after returning from there.
class QPlatformTextureListWatcher : public QObject
@@ -86,7 +48,7 @@ public:
}
bool isLocked() const {
- foreach (bool v, m_locked) {
+ for (const auto &[_, v] : m_locked.asKeyValueRange()) {
if (v)
return true;
}
@@ -105,7 +67,6 @@ private:
QHash<QPlatformTextureList *, bool> m_locked;
QWidgetRepaintManager *m_repaintManager;
};
-#endif
// ---------------------------------------------------------------------------
@@ -164,7 +125,7 @@ void QWidgetPrivate::invalidateBackingStore(const T &r)
return;
QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
- if (!tlwExtra || !tlwExtra->backingStore)
+ if (!tlwExtra || !tlwExtra->backingStore || !tlwExtra->repaintManager)
return;
T clipped(r);
@@ -340,7 +301,7 @@ void QWidgetRepaintManager::removeDirtyWidget(QWidget *w)
needsFlushWidgets.removeAll(w);
QWidgetPrivate *wd = w->d_func();
- const int n = wd->children.count();
+ const int n = wd->children.size();
for (int i = 0; i < n; ++i) {
if (QWidget *child = qobject_cast<QWidget*>(wd->children.at(i)))
removeDirtyWidget(child);
@@ -374,14 +335,13 @@ void QWidgetRepaintManager::sendUpdateRequest(QWidget *widget, UpdateTime update
qCInfo(lcWidgetPainting) << "Sending update request to" << widget << "with" << updateTime;
-#ifndef QT_NO_OPENGL
// Having every repaint() leading to a sync/flush is bad as it causes
// compositing and waiting for vsync each and every time. Change to
// UpdateLater, except for approx. once per frame to prevent starvation in
// case the control does not get back to the event loop.
- QWidget *w = widget->window();
- if (updateTime == UpdateNow && w && w->windowHandle() && QWindowPrivate::get(w->windowHandle())->compositing) {
+ if (updateTime == UpdateNow && QWidgetPrivate::get(widget)->textureChildSeen) {
int refresh = 60;
+ QWidget *w = widget->window();
QScreen *ws = w->windowHandle()->screen();
if (ws)
refresh = ws->refreshRate();
@@ -390,13 +350,16 @@ void QWidgetRepaintManager::sendUpdateRequest(QWidget *widget, UpdateTime update
const qint64 elapsed = wd->lastComposeTime.elapsed();
if (elapsed <= qint64(1000.0f / refresh))
updateTime = UpdateLater;
- }
+ }
}
-#endif
switch (updateTime) {
case UpdateLater:
- updateRequestSent = true;
+ // Prevent redundant update request events, unless it's a
+ // paint on screen widget, as these don't go through the
+ // normal backingstore sync machinery.
+ if (!widget->d_func()->shouldPaintOnScreen())
+ updateRequestSent = true;
QCoreApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
break;
case UpdateNow: {
@@ -414,25 +377,6 @@ static bool hasPlatformWindow(QWidget *widget)
return widget && widget->windowHandle() && widget->windowHandle()->handle();
}
-static QList<QRect> getSortedRectsToScroll(const QRegion &region, int dx, int dy)
-{
- QList<QRect> rects;
- std::copy(region.begin(), region.end(), std::back_inserter(rects));
- if (rects.count() > 1) {
- std::sort(rects.begin(), rects.end(), [=](const QRect &r1, const QRect &r2) {
- if (r1.y() == r2.y()) {
- if (dx > 0)
- return r1.x() > r2.x();
- return r1.x() < r2.x();
- }
- if (dy > 0)
- return r1.y() > r2.y();
- return r1.y() < r2.y();
- });
- }
- return rects;
-}
-
//parent's coordinates; move whole rect; update parent and widget
//assume the screen blt has already been done, so we don't need to refresh that part
void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
@@ -442,80 +386,55 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
return;
QWidget *tlw = q->window();
- QTLWExtra* x = tlw->d_func()->topData();
static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_MOVE") == 0;
- QWidget *pw = q->parentWidget();
- QPoint toplevelOffset = pw->mapTo(tlw, QPoint());
- QWidgetPrivate *pd = pw->d_func();
- const QRect clipR(pd->clipRect());
+ QWidget *parentWidget = q->parentWidget();
+ QPoint toplevelOffset = parentWidget->mapTo(tlw, QPoint());
+ QWidgetPrivate *parentPrivate = parentWidget->d_func();
+ const QRect clipR(parentPrivate->clipRect());
const QRect newRect(rect.translated(dx, dy));
+ QRect destRect = rect.intersected(clipR);
+ if (destRect.isValid())
+ destRect = destRect.translated(dx, dy).intersected(clipR);
+ const QRect sourceRect(destRect.translated(-dx, -dy));
const QRect parentRect(rect & clipR);
const bool nativeWithTextureChild = textureChildSeen && hasPlatformWindow(q);
- const bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild
+ bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild && sourceRect.isValid()
#if QT_CONFIG(graphicsview)
// No accelerate move for proxy widgets.
&& !tlw->d_func()->extra->proxyWidget
#endif
- ;
+ && !isOverlapped(sourceRect) && !isOverlapped(destRect);
if (!accelerateMove) {
- QRegion parentR(effectiveRectFor(parentRect));
+ QRegion parentRegion(effectiveRectFor(parentRect));
if (!extra || !extra->hasMask) {
- parentR -= newRect;
+ parentRegion -= newRect;
} else {
// invalidateBackingStore() excludes anything outside the mask
- parentR += newRect & clipR;
+ parentRegion += newRect & clipR;
}
- pd->invalidateBackingStore(parentR);
+ parentPrivate->invalidateBackingStore(parentRegion);
invalidateBackingStore((newRect & clipR).translated(-data.crect.topLeft()));
} else {
- QRect destRect = rect.intersected(clipR);
- if (destRect.isValid())
- destRect = destRect.translated(dx, dy).intersected(clipR);
- const QRect sourceRect(destRect.translated(-dx, -dy));
+ QWidgetRepaintManager *repaintManager = QWidgetPrivate::get(tlw)->maybeRepaintManager();
+ Q_ASSERT(repaintManager);
+ QRegion childExpose(newRect & clipR);
- QWidgetRepaintManager *repaintManager = x->repaintManager.get();
- QRegion childExpose = QRegion(newRect) & clipR;
- QRegion overlappedExpose;
+ if (repaintManager->bltRect(sourceRect, dx, dy, parentWidget))
+ childExpose -= destRect;
- if (sourceRect.isValid()) {
- overlappedExpose = (overlappedRegion(sourceRect) | overlappedRegion(destRect)) & clipR;
-
- const qreal factor = QHighDpiScaling::factor(q->windowHandle());
- if (overlappedExpose.isEmpty() || qFloor(factor) == factor) {
- const QList<QRect> rectsToScroll =
- getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy);
- for (QRect r : rectsToScroll) {
- if (repaintManager->bltRect(r, dx, dy, pw)) {
- childExpose -= r.translated(dx, dy);
- }
- }
- isMoved = true;
- }
-
- childExpose -= overlappedExpose;
- }
-
- if (!pw->updatesEnabled())
+ if (!parentWidget->updatesEnabled())
return;
const bool childUpdatesEnabled = q->updatesEnabled();
- if (childUpdatesEnabled) {
- // As per paintAndFlush, reset isMoved if we have overlapping
- // or child regions that need to be painted.
- if (!overlappedExpose.isEmpty()) {
- overlappedExpose.translate(-data.crect.topLeft());
- invalidateBackingStore(overlappedExpose);
- isMoved = false;
- }
- if (!childExpose.isEmpty()) {
- childExpose.translate(-data.crect.topLeft());
- repaintManager->markDirty(childExpose, q);
- isMoved = false;
- }
+
+ if (childUpdatesEnabled && !childExpose.isEmpty()) {
+ childExpose.translate(-data.crect.topLeft());
+ repaintManager->markDirty(childExpose, q);
+ isMoved = true;
}
QRegion parentExpose(parentRect);
@@ -523,13 +442,15 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
if (extra && extra->hasMask)
parentExpose += QRegion(newRect) - extra->mask.translated(data.crect.topLeft());
- if (!parentExpose.isEmpty())
- repaintManager->markDirty(parentExpose, pw);
+ if (!parentExpose.isEmpty()) {
+ repaintManager->markDirty(parentExpose, parentWidget);
+ parentPrivate->isMoved = true;
+ }
- if (childUpdatesEnabled && sourceRect.isValid()) {
+ if (childUpdatesEnabled) {
QRegion needsFlush(sourceRect);
needsFlush += destRect;
- repaintManager->markNeedsFlush(pw, needsFlush, toplevelOffset);
+ repaintManager->markNeedsFlush(parentWidget, needsFlush, toplevelOffset);
}
}
}
@@ -539,20 +460,20 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
{
Q_Q(QWidget);
QWidget *tlw = q->window();
- QTLWExtra* x = tlw->d_func()->topData();
- QWidgetRepaintManager *repaintManager = x->repaintManager.get();
+ QWidgetRepaintManager *repaintManager = QWidgetPrivate::get(tlw)->maybeRepaintManager();
if (!repaintManager)
return;
static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_SCROLL") == 0;
- const QRect clipR = clipRect();
- const QRect scrollRect = rect & clipR;
- const bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent);
+ const QRect scrollRect = rect & clipRect();
+ bool overlapped = false;
+ bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent)
+ && !(overlapped = isOverlapped(scrollRect.translated(data.crect.topLeft())));
if (!accelerateScroll) {
- if (!overlappedRegion(scrollRect.translated(data.crect.topLeft()), true).isEmpty()) {
+ if (overlapped) {
QRegion region(scrollRect);
subtractOpaqueSiblings(region);
invalidateBackingStore(region);
@@ -564,23 +485,12 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
const QRect destRect = scrollRect.translated(dx, dy) & scrollRect;
const QRect sourceRect = destRect.translated(-dx, -dy);
- const QRegion overlappedExpose = (overlappedRegion(scrollRect.translated(data.crect.topLeft())))
- .translated(-data.crect.topLeft()) & clipR;
QRegion childExpose(scrollRect);
-
- const qreal factor = QHighDpiScaling::factor(q->windowHandle());
- if (overlappedExpose.isEmpty() || qFloor(factor) == factor) {
- const QList<QRect> rectsToScroll =
- getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy);
- for (const QRect &r : rectsToScroll) {
- if (repaintManager->bltRect(r, dx, dy, q)) {
- childExpose -= r.translated(dx, dy);
- }
- }
+ if (sourceRect.isValid()) {
+ if (repaintManager->bltRect(sourceRect, dx, dy, q))
+ childExpose -= destRect;
}
- childExpose -= overlappedExpose;
-
if (inDirtyList) {
if (rect == q->rect()) {
dirty.translate(dx, dy);
@@ -597,8 +507,6 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
if (!q->updatesEnabled())
return;
- if (!overlappedExpose.isEmpty())
- invalidateBackingStore(overlappedExpose);
if (!childExpose.isEmpty()) {
repaintManager->markDirty(childExpose, q);
isScrolled = true;
@@ -626,7 +534,6 @@ bool QWidgetRepaintManager::bltRect(const QRect &rect, int dx, int dy, QWidget *
// ---------------------------------------------------------------------------
-#ifndef QT_NO_OPENGL
static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget,
QPlatformTextureList *widgetTextures,
QList<QWidget *> *nativeChildren)
@@ -635,7 +542,8 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget,
if (wd->renderToTexture) {
QPlatformTextureList::Flags flags = wd->textureListFlags();
const QRect rect(widget->mapTo(tlw, QPoint()), widget->size());
- widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags);
+ QWidgetPrivate::TextureData data = wd->texture();
+ widgetTextures->appendTexture(widget, data.textureLeft, data.textureRight, rect, wd->clipRect(), flags);
}
for (int i = 0; i < wd->children.size(); ++i) {
@@ -661,7 +569,7 @@ static void findAllTextureWidgetsRecursively(QWidget *tlw, QWidget *widget)
if (!tl->isEmpty())
QWidgetPrivate::get(tlw)->topData()->widgetTextures.push_back(std::move(tl));
// Native child widgets, if there was any, get their own separate QPlatformTextureList.
- for (QWidget *ncw : qAsConst(nativeChildren)) {
+ for (QWidget *ncw : std::as_const(nativeChildren)) {
if (QWidgetPrivate::get(ncw)->textureChildSeen)
findAllTextureWidgetsRecursively(tlw, ncw);
}
@@ -679,33 +587,12 @@ static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget)
}
}
- if (QWidgetPrivate::get(widget)->textureChildSeen) {
- // No render-to-texture widgets in the (sub-)tree due to hidden or native
- // children. Returning null results in using the normal backingstore flush path
- // without OpenGL-based compositing. This is very desirable normally. However,
- // some platforms cannot handle switching between the non-GL and GL paths for
- // their windows so it has to be opt-in.
- static bool switchableWidgetComposition =
- QGuiApplicationPrivate::instance()->platformIntegration()
- ->hasCapability(QPlatformIntegration::SwitchableWidgetComposition);
- if (!switchableWidgetComposition)
- return qt_dummy_platformTextureList();
- }
+ if (QWidgetPrivate::get(widget)->textureChildSeen)
+ return qt_dummy_platformTextureList();
return nullptr;
}
-#else
-
-static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget)
-{
- Q_UNUSED(tlw);
- Q_UNUSED(widget);
- return nullptr;
-}
-
-#endif // QT_NO_OPENGL
-
// ---------------------------------------------------------------------------
/*!
@@ -780,7 +667,6 @@ bool QWidgetPrivate::shouldDiscardSyncRequest() const
bool QWidgetRepaintManager::syncAllowed()
{
-#ifndef QT_NO_OPENGL
QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
if (textureListWatcher && !textureListWatcher->isLocked()) {
textureListWatcher->deleteLater();
@@ -799,7 +685,6 @@ bool QWidgetRepaintManager::syncAllowed()
if (skipSync) // cannot compose due to widget textures being in use
return false;
}
-#endif
return true;
}
@@ -825,7 +710,9 @@ void QWidgetRepaintManager::paintAndFlush()
const QRect tlwRect = tlw->data->crect;
if (!updatesDisabled && store->size() != tlwRect.size()) {
- if (hasStaticContents() && !store->size().isEmpty() ) {
+ QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
+ if (hasStaticContents() && !store->size().isEmpty()
+ && integration->hasCapability(QPlatformIntegration::BackingStoreStaticContents)) {
// Repaint existing dirty area and newly visible area.
const QRect clipRect(QPoint(0, 0), store->size());
const QRegion staticRegion(staticContents(nullptr, clipRect));
@@ -912,24 +799,21 @@ void QWidgetRepaintManager::paintAndFlush()
}
dirtyWidgets.clear();
-#ifndef QT_NO_OPENGL
// Find all render-to-texture child widgets (including self).
// The search is cut at native widget boundaries, meaning that each native child widget
// has its own list for the subtree below it.
QTLWExtra *tlwExtra = tlw->d_func()->topData();
tlwExtra->widgetTextures.clear();
findAllTextureWidgetsRecursively(tlw, tlw);
- qt_window_private(tlw->windowHandle())->compositing = false; // will get updated in flush()
-#endif
if (toClean.isEmpty()) {
// Nothing to repaint. However renderToTexture widgets are handled
// specially, they are not in the regular dirty list, in order to
// prevent triggering unnecessary backingstore painting when only the
- // OpenGL content changes. Check if we have such widgets in the special
+ // texture content changes. Check if we have such widgets in the special
// dirty list.
QVarLengthArray<QWidget *, 16> paintPending;
- const int numPaintPending = dirtyRenderToTextureWidgets.count();
+ const int numPaintPending = dirtyRenderToTextureWidgets.size();
paintPending.reserve(numPaintPending);
for (int i = 0; i < numPaintPending; ++i) {
QWidget *w = dirtyRenderToTextureWidgets.at(i);
@@ -958,7 +842,6 @@ void QWidgetRepaintManager::paintAndFlush()
return;
}
-#ifndef QT_NO_OPENGL
for (const auto &tl : tlwExtra->widgetTextures) {
for (int i = 0; i < tl->count(); ++i) {
QWidget *w = static_cast<QWidget *>(tl->source(i));
@@ -972,10 +855,9 @@ void QWidgetRepaintManager::paintAndFlush()
}
}
}
- for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i)
+ for (int i = 0; i < dirtyRenderToTextureWidgets.size(); ++i)
resetWidget(dirtyRenderToTextureWidgets.at(i));
dirtyRenderToTextureWidgets.clear();
-#endif
#if QT_CONFIG(graphicsview)
if (tlw->d_func()->extra->proxyWidget) {
@@ -1020,7 +902,8 @@ void QWidgetRepaintManager::paintAndFlush()
// Paint the rest with composition.
if (repaintAllWidgets || !dirtyCopy.isEmpty()) {
- QWidgetPrivate::DrawWidgetFlags flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive;
+ QWidgetPrivate::DrawWidgetFlags flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive
+ | QWidgetPrivate::UseEffectRegionBounds;
tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, QPoint(), flags, nullptr, this);
}
@@ -1101,18 +984,16 @@ void QWidgetRepaintManager::flush()
// Render-to-texture widgets are not in topLevelNeedsFlush so flush if we have not done it above.
if (!flushed && !hasNeedsFlushWidgets) {
-#ifndef QT_NO_OPENGL
if (!tlw->d_func()->topData()->widgetTextures.empty()) {
if (QPlatformTextureList *widgetTextures = widgetTexturesFor(tlw, tlw))
flush(tlw, QRegion(), widgetTextures);
}
-#endif
}
if (!hasNeedsFlushWidgets)
return;
- for (QWidget *w : qExchange(needsFlushWidgets, {})) {
+ for (QWidget *w : std::exchange(needsFlushWidgets, {})) {
QWidgetPrivate *wd = w->d_func();
Q_ASSERT(wd->needsFlush);
QPlatformTextureList *widgetTexturesForNative = wd->textureChildSeen ? widgetTexturesFor(tlw, w) : nullptr;
@@ -1128,12 +1009,7 @@ void QWidgetRepaintManager::flush()
*/
void QWidgetRepaintManager::flush(QWidget *widget, const QRegion &region, QPlatformTextureList *widgetTextures)
{
-#ifdef QT_NO_OPENGL
- Q_UNUSED(widgetTextures);
- Q_ASSERT(!region.isEmpty());
-#else
Q_ASSERT(!region.isEmpty() || widgetTextures);
-#endif
Q_ASSERT(widget);
Q_ASSERT(tlw);
@@ -1146,8 +1022,6 @@ void QWidgetRepaintManager::flush(QWidget *widget, const QRegion &region, QPlatf
return;
}
- qCInfo(lcWidgetPainting) << "Flushing" << region << "of" << widget;
-
static bool fpsDebug = qEnvironmentVariableIntValue("QT_DEBUG_FPS");
if (fpsDebug) {
if (!perfFrames++)
@@ -1163,40 +1037,70 @@ void QWidgetRepaintManager::flush(QWidget *widget, const QRegion &region, QPlatf
if (widget != tlw)
offset += widget->mapTo(tlw, QPoint());
- QRegion effectiveRegion = region;
-#ifndef QT_NO_OPENGL
- const bool compositionWasActive = widget->d_func()->renderToTextureComposeActive;
- if (!widgetTextures) {
- widget->d_func()->renderToTextureComposeActive = false;
- // Detect the case of falling back to the normal flush path when no
- // render-to-texture widgets are visible anymore. We will force one
- // last flush to go through the OpenGL-based composition to prevent
- // artifacts. The next flush after this one will use the normal path.
- if (compositionWasActive)
+ // Use a condition that tries to keep both QTBUG-108344 and QTBUG-113557
+ // happy, i.e. support both (A) "native rhi-based child in a rhi-based
+ // toplevel" and (B) "native raster child in a rhi-based toplevel".
+ //
+ // If the tlw and the backingstore are RHI-based, then there are two cases
+ // to consider:
+ //
+ // (1) widget is not a native child, i.e. the QWindow for widget and tlw are
+ // the same,
+ //
+ // (2) widget is a native child which we now attempt to flush with tlw's
+ // backingstore to widget's native window. This is the interesting one.
+ //
+ // Using the condition tlw->usesRhiFlush on its own is insufficient since
+ // it fails to capture the case of a raster-based native child widget
+ // within tlw. (which must hit the non-rhi flush path)
+ //
+ // Extending the condition with tlw->windowHandle() == widget->windowHandle()
+ // would be logical but wrong, when it comes to (A) since flushing a
+ // RHI-based native child with a given 3D API using a RHI-based
+ // tlw/backingstore with the same 3D API needs to be supported still. (this
+ // happens when e.g. someone calls winId() on a QOpenGLWidget)
+ //
+ // Different 3D APIs do not need to be supported since we do not allow to
+ // do things like having a QQuickWidget with Vulkan and a QOpenGLWidget in
+ // the same toplevel, regardless of the widgets being native children or
+ // not. Hence comparing the surfaceType() instead. This satisfies both (A)
+ // and (B) given that an RHI-based toplevel cannot be RasterSurface.
+ //
+ if (tlw->d_func()->usesRhiFlush && tlw->windowHandle()->surfaceType() == widget->windowHandle()->surfaceType()) {
+ QRhi *rhi = store->handle()->rhi();
+ qCDebug(lcWidgetPainting) << "Flushing" << region << "of" << widget
+ << "with QRhi" << rhi
+ << "to window" << widget->windowHandle();
+ if (!widgetTextures)
widgetTextures = qt_dummy_platformTextureList;
- } else {
- widget->d_func()->renderToTextureComposeActive = true;
- }
- // When changing the composition status, make sure the dirty region covers
- // the entire widget. Just having e.g. the shown/hidden render-to-texture
- // widget's area marked as dirty is incorrect when changing flush paths.
- if (compositionWasActive != widget->d_func()->renderToTextureComposeActive)
- effectiveRegion = widget->rect();
-
- // re-test since we may have been forced to this path via the dummy texture list above
- if (widgetTextures) {
- qt_window_private(tlw->windowHandle())->compositing = true;
- widget->window()->d_func()->sendComposeStatus(widget->window(), false);
+
+ QWidgetPrivate *widgetWindowPrivate = widget->window()->d_func();
+ widgetWindowPrivate->sendComposeStatus(widget->window(), false);
// A window may have alpha even when the app did not request
// WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends
// to rely on translucency, in order to decide if it should clear to transparent or opaque.
const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground);
- store->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset,
- widgetTextures, translucentBackground);
- widget->window()->d_func()->sendComposeStatus(widget->window(), true);
- } else
-#endif
- store->flush(effectiveRegion, widget->windowHandle(), offset);
+
+ QPlatformBackingStore::FlushResult flushResult;
+ flushResult = store->handle()->rhiFlush(widget->windowHandle(),
+ widget->devicePixelRatio(),
+ region,
+ offset,
+ widgetTextures,
+ translucentBackground);
+ widgetWindowPrivate->sendComposeStatus(widget->window(), true);
+ if (flushResult == QPlatformBackingStore::FlushFailedDueToLostDevice) {
+ qSendWindowChangeToTextureChildrenRecursively(widget->window(),
+ QEvent::WindowAboutToChangeInternal);
+ store->handle()->graphicsDeviceReportedLost();
+ qSendWindowChangeToTextureChildrenRecursively(widget->window(),
+ QEvent::WindowChangeInternal);
+ widget->update();
+ }
+ } else {
+ qCInfo(lcWidgetPainting) << "Flushing" << region << "of" << widget;
+ store->flush(region, widget->windowHandle(), offset);
+ }
}
// ---------------------------------------------------------------------------
@@ -1240,11 +1144,7 @@ void QWidgetRepaintManager::removeStaticWidget(QWidget *widget)
bool QWidgetRepaintManager::hasStaticContents() const
{
-#if defined(Q_OS_WIN)
return !staticWidgets.isEmpty();
-#else
- return !staticWidgets.isEmpty() && false;
-#endif
}
/*!
@@ -1266,7 +1166,7 @@ QRegion QWidgetRepaintManager::staticContents(QWidget *parent, const QRect &with
return region;
const bool clipToRect = !withinClipRect.isEmpty();
- const int count = staticWidgets.count();
+ const int count = staticWidgets.size();
for (int i = 0; i < count; ++i) {
QWidget *w = staticWidgets.at(i);
QWidgetPrivate *wd = w->d_func();
@@ -1408,6 +1308,12 @@ void QWidgetPrivate::invalidateBackingStore_resizeHelper(const QPoint &oldPos, c
}
}
+QRhi *QWidgetRepaintManager::rhi() const
+{
+ return store->handle()->rhi();
+}
+
QT_END_NAMESPACE
#include "qwidgetrepaintmanager.moc"
+#include "moc_qwidgetrepaintmanager_p.cpp"
diff --git a/src/widgets/kernel/qwidgetrepaintmanager_p.h b/src/widgets/kernel/qwidgetrepaintmanager_p.h
index 8b792617ec..4378974610 100644
--- a/src/widgets/kernel/qwidgetrepaintmanager_p.h
+++ b/src/widgets/kernel/qwidgetrepaintmanager_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWIDGETREPAINTMANAGER_P_H
#define QWIDGETREPAINTMANAGER_P_H
@@ -62,8 +26,10 @@ QT_BEGIN_NAMESPACE
class QPlatformTextureList;
class QPlatformTextureListWatcher;
class QWidgetRepaintManager;
+class QRhi;
+class QRhiSwapChain;
-class Q_AUTOTEST_EXPORT QWidgetRepaintManager
+class Q_WIDGETS_EXPORT QWidgetRepaintManager
{
Q_GADGET
public:
@@ -100,9 +66,14 @@ public:
void moveStaticWidgets(QWidget *reparented);
void removeStaticWidget(QWidget *widget);
QRegion staticContents(QWidget *widget = nullptr, const QRect &withinClipRect = QRect()) const;
+ QRegion dirtyRegion() const { return dirty; }
+ QList<QWidget *> dirtyWidgetList() const { return dirtyWidgets; }
+ bool isDirty() const;
bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget);
+ QRhi *rhi() const;
+
private:
void updateLists(QWidget *widget);
@@ -121,8 +92,6 @@ private:
void flush();
void flush(QWidget *widget, const QRegion &region, QPlatformTextureList *widgetTextures);
- bool isDirty() const;
-
bool hasStaticContents() const;
void updateStaticContentsSize();
diff --git a/src/widgets/kernel/qwidgetsvariant.cpp b/src/widgets/kernel/qwidgetsvariant.cpp
index e27c26cd05..17a19aa780 100644
--- a/src/widgets/kernel/qwidgetsvariant.cpp
+++ b/src/widgets/kernel/qwidgetsvariant.cpp
@@ -1,55 +1,19 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qvariant.h"
#include "qsizepolicy.h"
#include "qwidget.h"
-#include "private/qvariant_p.h"
#include <private/qmetatype_p.h>
QT_BEGIN_NAMESPACE
namespace {
-static const struct : QMetaTypeModuleHelper
+// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor): this is not a base class
+static constexpr struct : QMetaTypeModuleHelper
{
const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
switch (type) {
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index c750d9f730..f51baba88b 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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.
-**
-** $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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qwindow_p.h"
#include "qwidgetwindow_p.h"
@@ -43,7 +7,7 @@
#include "private/qwidget_p.h"
#include "private/qapplication_p.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtGui/qaccessible.h>
#endif
#include <private/qwidgetrepaintmanager_p.h>
@@ -55,6 +19,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets();
Q_WIDGETS_EXPORT QWidget *qt_button_down = nullptr; // widget got last button-down
@@ -73,21 +39,25 @@ public:
void setVisible(bool visible) override
{
Q_Q(QWidgetWindow);
+ qCDebug(lcWidgetShowHide) << "Setting visibility of" << q->widget()
+ << "to" << visible << "via QWidgetWindowPrivate";
+
if (QWidget *widget = q->widget()) {
- // Check if the widget was already hidden, as this indicates it was done
- // explicitly and not because the parent window in this case made it hidden.
- // In which case do not automatically show the widget when the parent
- // window is shown.
- const bool wasExplicitShowHide = widget->testAttribute(Qt::WA_WState_ExplicitShowHide);
- const bool wasHidden = widget->testAttribute(Qt::WA_WState_Hidden);
- QWidgetPrivate::get(widget)->setVisible(visible);
- if (wasExplicitShowHide) {
- widget->setAttribute(Qt::WA_WState_ExplicitShowHide, wasExplicitShowHide);
- widget->setAttribute(Qt::WA_WState_Hidden, wasHidden);
- }
- } else {
- QWindowPrivate::setVisible(visible);
+ // If the widget's visible state is already matching the new QWindow
+ // visible state we assume the widget has already synced up.
+ if (visible != widget->isVisible())
+ QWidgetPrivate::get(widget)->setVisible(visible);
}
+
+ // If we end up calling QWidgetPrivate::setVisible() above, we will
+ // in most cases recurse back into setNativeWindowVisibility() to
+ // update the QWindow state. But during QWidget::destroy() this is
+ // not the case, as Qt::WA_WState_Created has been unset by the time
+ // we check if we should call hide_helper(). We handle this case, as
+ // well as the cases where we don't call QWidgetPrivate::setVisible(),
+ // by syncing up the QWindow state here if needed.
+ if (q->isVisible() != visible)
+ QWindowPrivate::setVisible(visible);
}
QWindow *eventReceiver() override {
@@ -108,9 +78,6 @@ public:
}
QRectF closestAcceptableGeometry(const QRectF &rect) const override;
-#if QT_CONFIG(opengl)
- QOpenGLContext *shareContext() const override;
-#endif
void processSafeAreaMarginsChanged() override
{
@@ -152,35 +119,43 @@ QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const
return result;
}
-#if QT_CONFIG(opengl)
-QOpenGLContext *QWidgetWindowPrivate::shareContext() const
-{
- Q_Q(const QWidgetWindow);
- const QWidgetPrivate *widgetPrivate = QWidgetPrivate::get(q->widget());
- return widgetPrivate->shareContext();
-}
-#endif // opengl
+bool q_evaluateRhiConfig(const QWidget *w, QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType);
QWidgetWindow::QWidgetWindow(QWidget *widget)
: QWindow(*new QWidgetWindowPrivate(), nullptr)
, m_widget(widget)
{
updateObjectName();
- // Enable QOpenGLWidget/QQuickWidget children if the platform plugin supports it,
- // and the application developer has not explicitly disabled it.
- if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RasterGLSurface)
- && !QCoreApplication::testAttribute(Qt::AA_ForceRasterWidgets)) {
- setSurfaceType(QSurface::RasterGLSurface);
+ if (!QCoreApplication::testAttribute(Qt::AA_ForceRasterWidgets)) {
+ QSurface::SurfaceType type = QSurface::RasterSurface;
+ q_evaluateRhiConfig(m_widget, nullptr, &type);
+ setSurfaceType(type);
}
+
connect(widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName);
- connect(this, SIGNAL(screenChanged(QScreen*)), this, SLOT(handleScreenChange()));
+ connect(this, &QWidgetWindow::screenChanged, this, &QWidgetWindow::handleScreenChange);
}
QWidgetWindow::~QWidgetWindow()
{
+ if (!m_widget)
+ return;
+
+ QTLWExtra *topData = QWidgetPrivate::get(m_widget)->topData();
+ Q_ASSERT(topData);
+
+ // The QPlaformBackingStore may hold a reference to the window,
+ // so the backingstore needs to be deleted first.
+ topData->repaintManager.reset(nullptr);
+ delete topData->backingStore;
+ topData->backingStore = nullptr;
+ topData->widgetTextures.clear();
+
+ // Too late to do anything beyond this point
+ topData->window = nullptr;
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleInterface *QWidgetWindow::accessibleRoot() const
{
if (m_widget)
@@ -214,6 +189,9 @@ QObject *QWidgetWindow::focusObject() const
void QWidgetWindow::setNativeWindowVisibility(bool visible)
{
Q_D(QWidgetWindow);
+ qCDebug(lcWidgetShowHide) << "Setting visibility of" << this
+ << "to" << visible << "via QWidgetWindow::setNativeWindowVisibility";
+
// Call base class setVisible() implementation to run the QWindow
// visibility logic. Don't call QWidgetWindowPrivate::setVisible()
// since that will recurse back into QWidget code.
@@ -255,7 +233,7 @@ bool QWidgetWindow::event(QEvent *event)
handleFocusInEvent(static_cast<QFocusEvent *>(event));
Q_FALLTHROUGH();
case QEvent::FocusOut: {
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::State state;
state.active = true;
QAccessibleStateChangeEvent ev(m_widget, state);
@@ -373,6 +351,10 @@ bool QWidgetWindow::event(QEvent *event)
m_widget->repaint();
return true;
+ case QEvent::DevicePixelRatioChange:
+ handleDevicePixelRatioChange();
+ break;
+
default:
break;
}
@@ -402,7 +384,7 @@ void QWidgetWindow::handleEnterLeaveEvent(QEvent *event)
QWindowSystemInterfacePrivate::EnterEvent *systemEvent =
static_cast<QWindowSystemInterfacePrivate::EnterEvent *>
(QWindowSystemInterfacePrivate::peekWindowSystemEvent(QWindowSystemInterfacePrivate::Enter));
- const QPointF globalPosF = systemEvent ? systemEvent->globalPos : QGuiApplicationPrivate::lastCursorPosition;
+ const QPointF globalPosF = systemEvent ? systemEvent->globalPos : QPointF(QGuiApplicationPrivate::lastCursorPosition);
if (systemEvent) {
if (QWidgetWindow *enterWindow = qobject_cast<QWidgetWindow *>(systemEvent->enter))
{
@@ -495,11 +477,11 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
QEvent::MouseButtonRelease : QEvent::MouseButtonPress;
if (QApplicationPrivate::inPopupMode()) {
QPointer<QWidget> activePopupWidget = QApplication::activePopupWidget();
- QPoint mapped = event->position().toPoint();
+ QPointF mapped = event->position();
if (activePopupWidget != m_widget)
- mapped = activePopupWidget->mapFromGlobal(event->globalPosition().toPoint());
+ mapped = activePopupWidget->mapFromGlobal(event->globalPosition());
bool releaseAfter = false;
- QWidget *popupChild = activePopupWidget->childAt(mapped);
+ QWidget *popupChild = activePopupWidget->childAt(mapped.toPoint());
if (activePopupWidget != qt_popup_down) {
qt_button_down = nullptr;
@@ -526,15 +508,15 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
// deliver event
qt_replay_popup_mouse_event = false;
QPointer<QWidget> receiver = activePopupWidget;
- QPoint widgetPos = mapped;
+ QPointF widgetPos = mapped;
if (qt_button_down)
receiver = qt_button_down;
else if (popupChild)
receiver = popupChild;
if (receiver != activePopupWidget)
- widgetPos = receiver->mapFromGlobal(event->globalPosition().toPoint());
+ widgetPos = receiver->mapFromGlobal(event->globalPosition());
- const bool reallyUnderMouse = activePopupWidget->rect().contains(mapped);
+ const bool reallyUnderMouse = activePopupWidget->rect().contains(mapped.toPoint());
const bool underMouse = activePopupWidget->underMouse();
if (underMouse != reallyUnderMouse) {
if (reallyUnderMouse) {
@@ -617,7 +599,8 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
receiver = qt_button_down;
else if (popupChild)
receiver = popupChild;
- QContextMenuEvent e(QContextMenuEvent::Mouse, mapped, event->globalPosition().toPoint(), event->modifiers());
+ const QPoint localPos = receiver->mapFromGlobal(event->globalPosition().toPoint());
+ QContextMenuEvent e(QContextMenuEvent::Mouse, localPos, event->globalPosition().toPoint(), event->modifiers());
QApplication::forwardEvent(receiver, &e, event);
}
#else
@@ -672,6 +655,8 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
&& m_widget->rect().contains(event->position().toPoint())) {
QContextMenuEvent e(QContextMenuEvent::Mouse, mapped, event->globalPosition().toPoint(), event->modifiers());
QGuiApplication::forwardEvent(receiver, &e, event);
+ if (e.isAccepted())
+ event->accept();
}
#endif
}
@@ -736,22 +721,32 @@ void QWidgetWindow::updateMargins()
m_widget->data->fstrut_dirty = false;
}
-static void sendScreenChangeRecursively(QWidget *widget)
+static void sendChangeRecursively(QWidget *widget, QEvent::Type type)
{
- QEvent e(QEvent::ScreenChangeInternal);
+ QEvent e(type);
QCoreApplication::sendEvent(widget, &e);
QWidgetPrivate *d = QWidgetPrivate::get(widget);
for (int i = 0; i < d->children.size(); ++i) {
QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
if (w)
- sendScreenChangeRecursively(w);
+ sendChangeRecursively(w, type);
}
}
void QWidgetWindow::handleScreenChange()
{
// Send an event recursively to the widget and its children.
- sendScreenChangeRecursively(m_widget);
+ sendChangeRecursively(m_widget, QEvent::ScreenChangeInternal);
+
+ // Invalidate the backing store buffer and repaint immediately.
+ if (screen())
+ repaintWindow();
+}
+
+void QWidgetWindow::handleDevicePixelRatioChange()
+{
+ // Send an event recursively to the widget and its children.
+ sendChangeRecursively(m_widget, QEvent::DevicePixelRatioChange);
// Invalidate the backing store buffer and repaint immediately.
if (screen())
@@ -940,8 +935,9 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
event->ignore();
if (m_dragTarget) { // Send DragLeave to previous
QDragLeaveEvent leaveEvent;
- QGuiApplication::forwardEvent(m_dragTarget, &leaveEvent, event);
+ QWidget *dragTarget = m_dragTarget;
m_dragTarget = nullptr;
+ QGuiApplication::forwardEvent(dragTarget, &leaveEvent, event);
}
} else {
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->position().toPoint()));
@@ -955,8 +951,9 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
} else {
if (m_dragTarget) { // Send DragLeave to previous
QDragLeaveEvent leaveEvent;
- QGuiApplication::forwardEvent(m_dragTarget, &leaveEvent, event);
+ QWidget *dragTarget = m_dragTarget;
m_dragTarget = nullptr;
+ QGuiApplication::forwardEvent(dragTarget, &leaveEvent, event);
}
// widget might have been deleted when handling the leaveEvent
if (widget) {
@@ -978,9 +975,11 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
void QWidgetWindow::handleDragLeaveEvent(QDragLeaveEvent *event)
{
- if (m_dragTarget)
- QGuiApplication::forwardEvent(m_dragTarget, event);
- m_dragTarget = nullptr;
+ if (m_dragTarget) {
+ QWidget *dragTarget = m_dragTarget;
+ m_dragTarget = nullptr;
+ QGuiApplication::forwardEvent(dragTarget, event);
+ }
}
void QWidgetWindow::handleDropEvent(QDropEvent *event)
@@ -992,10 +991,11 @@ void QWidgetWindow::handleDropEvent(QDropEvent *event)
}
const QPoint mapped = m_dragTarget->mapFromGlobal(m_widget->mapToGlobal(event->position().toPoint()));
QDropEvent translated(mapped, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
- QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
+ QWidget *dragTarget = m_dragTarget;
+ m_dragTarget = nullptr;
+ QGuiApplication::forwardEvent(dragTarget, &translated, event);
event->setAccepted(translated.isAccepted());
event->setDropAction(translated.dropAction());
- m_dragTarget = nullptr;
}
#endif // QT_CONFIG(draganddrop)
@@ -1040,11 +1040,8 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
m_widget->setAttribute(Qt::WA_Mapped);
for (QWidget *p = m_widget->parentWidget(); p && !p->testAttribute(Qt::WA_Mapped); p = p->parentWidget())
p->setAttribute(Qt::WA_Mapped);
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- if (!event->region().isNull())
- wPriv->syncBackingStore(event->region());
-QT_WARNING_POP
+ if (!event->m_region.isNull())
+ wPriv->syncBackingStore(event->m_region);
} else {
m_widget->setAttribute(Qt::WA_Mapped, false);
}
@@ -1092,11 +1089,10 @@ void QWidgetWindow::handleTabletEvent(QTabletEvent *event)
if (!widget) {
widget = m_widget->childAt(event->position().toPoint());
- if (event->type() == QEvent::TabletPress) {
- if (!widget)
- widget = m_widget;
+ if (!widget)
+ widget = m_widget;
+ if (event->type() == QEvent::TabletPress)
qt_tablet_target = widget;
- }
}
if (widget) {
@@ -1168,8 +1164,8 @@ void QWidgetWindow::updateObjectName()
{
QString name = m_widget->objectName();
if (name.isEmpty())
- name = QString::fromUtf8(m_widget->metaObject()->className()) + QLatin1String("Class");
- name += QLatin1String("Window");
+ name = QString::fromUtf8(m_widget->metaObject()->className()) + "Class"_L1;
+ name += "Window"_L1;
setObjectName(name);
}
diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h
index 0ad3ec5062..0ee6b71a79 100644
--- a/src/widgets/kernel/qwidgetwindow_p.h
+++ b/src/widgets/kernel/qwidgetwindow_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWIDGETWINDOW_P_H
#define QWIDGETWINDOW_P_H
@@ -58,6 +22,8 @@
#include <QtGui/private/qevent_p.h>
#include <QtWidgets/qwidget.h>
+#include <QtCore/qpointer.h>
+
QT_BEGIN_NAMESPACE
@@ -74,7 +40,7 @@ public:
~QWidgetWindow();
QWidget *widget() const { return m_widget; }
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessibleInterface *accessibleRoot() const override;
#endif
@@ -117,9 +83,10 @@ protected:
private slots:
void updateObjectName();
- void handleScreenChange();
private:
+ void handleScreenChange();
+ void handleDevicePixelRatioChange();
void repaintWindow();
bool updateSize();
void updateMargins();
diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp
index 5484544444..2c374ac408 100644
--- a/src/widgets/kernel/qwindowcontainer.cpp
+++ b/src/widgets/kernel/qwindowcontainer.cpp
@@ -1,44 +1,9 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowcontainer_p.h"
#include "qwidget_p.h"
+#include "qwidgetwindow_p.h"
#include <QtGui/qwindow.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
@@ -50,8 +15,12 @@
#include <QAbstractScrollArea>
#include <QPainter>
+#include <QtCore/qpointer.h>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
class QWindowContainerPrivate : public QWidgetPrivate
{
public:
@@ -59,7 +28,6 @@ public:
QWindowContainerPrivate()
: window(nullptr)
- , oldFocusWindow(nullptr)
, usesNativeWidgets(false)
{
}
@@ -134,7 +102,6 @@ public:
}
QPointer<QWindow> window;
- QWindow *oldFocusWindow;
QWindow fakeParent;
uint usesNativeWidgets : 1;
@@ -196,16 +163,34 @@ public:
application can greatly hurt the overall performance of the
application.
+ \li Since 6.7, if \a window belongs to a widget (that is, \a window
+ was received from calling \l windowHandle()), no container will be
+ created. Instead, this function will return the widget itself, after
+ being reparented to \l parent. Since no container will be created,
+ \a flags will be ignored. In other words, if \a window belongs to
+ a widget, consider just reparenting that widget to \a parent instead
+ of using this function.
+
\endlist
*/
QWidget *QWidget::createWindowContainer(QWindow *window, QWidget *parent, Qt::WindowFlags flags)
{
+ // Embedding a QWidget in a window container doesn't make sense,
+ // and has various issues in practice, so just return the widget
+ // itself.
+ if (auto *widgetWindow = qobject_cast<QWidgetWindow *>(window)) {
+ QWidget *widget = widgetWindow->widget();
+ if (flags != Qt::WindowFlags()) {
+ qWarning() << window << "refers to a widget:" << widget
+ << "WindowFlags" << flags << "will be ignored.";
+ }
+ widget->setParent(parent);
+ return widget;
+ }
return new QWindowContainer(window, parent, flags);
}
-
-
/*!
\internal
*/
@@ -219,26 +204,22 @@ QWindowContainer::QWindowContainer(QWindow *embeddedWindow, QWidget *parent, Qt:
return;
}
- // The embedded QWindow must use the same logic as QWidget when it comes to the surface type.
- // Otherwise we may end up with BadMatch failures on X11.
- if (embeddedWindow->surfaceType() == QSurface::RasterSurface
- && QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RasterGLSurface)
- && !QCoreApplication::testAttribute(Qt::AA_ForceRasterWidgets))
- embeddedWindow->setSurfaceType(QSurface::RasterGLSurface);
-
d->window = embeddedWindow;
+ d->window->installEventFilter(this);
QString windowName = d->window->objectName();
if (windowName.isEmpty())
windowName = QString::fromUtf8(d->window->metaObject()->className());
- d->fakeParent.setObjectName(windowName + QLatin1String("ContainerFakeParent"));
+ d->fakeParent.setObjectName(windowName + "ContainerFakeParent"_L1);
d->window->setParent(&d->fakeParent);
+ d->window->parent()->installEventFilter(this);
d->window->setFlag(Qt::SubWindow);
setAcceptDrops(true);
- connect(QGuiApplication::instance(), SIGNAL(focusWindowChanged(QWindow*)), this, SLOT(focusWindowChanged(QWindow*)));
+ connect(containedWindow(), &QWindow::minimumHeightChanged, this, &QWindowContainer::updateGeometry);
+ connect(containedWindow(), &QWindow::minimumWidthChanged, this, &QWindowContainer::updateGeometry);
}
QWindow *QWindowContainer::containedWindow() const
@@ -259,27 +240,36 @@ QWindowContainer::~QWindowContainer()
// QEvent::PlatformSurface delivery relies on virtuals. Getting
// SurfaceAboutToBeDestroyed can be essential for OpenGL, Vulkan, etc.
// QWindow subclasses in particular. Keep these working.
- if (d->window)
+ if (d->window) {
+ d->window->removeEventFilter(this);
d->window->destroy();
+ }
delete d->window;
}
-
-
/*!
\internal
*/
-void QWindowContainer::focusWindowChanged(QWindow *focusWindow)
+bool QWindowContainer::eventFilter(QObject *o, QEvent *e)
{
Q_D(QWindowContainer);
- d->oldFocusWindow = focusWindow;
- if (focusWindow == d->window) {
- QWidget *widget = QApplication::focusWidget();
- if (widget)
- widget->clearFocus();
+ if (!d->window)
+ return false;
+
+ if (e->type() == QEvent::ChildRemoved) {
+ QChildEvent *ce = static_cast<QChildEvent *>(e);
+ if (ce->child() == d->window) {
+ o->removeEventFilter(this);
+ d->window->removeEventFilter(this);
+ d->window = nullptr;
+ }
+ } else if (e->type() == QEvent::FocusIn) {
+ if (o == d->window)
+ setFocus(Qt::ActiveWindowFocusReason);
}
+ return false;
}
/*!
@@ -294,12 +284,6 @@ bool QWindowContainer::event(QEvent *e)
QEvent::Type type = e->type();
switch (type) {
- case QEvent::ChildRemoved: {
- QChildEvent *ce = static_cast<QChildEvent *>(e);
- if (ce->child() == d->window)
- d->window = nullptr;
- break;
- }
// The only thing we are interested in is making sure our sizes stay
// in sync, so do a catch-all case.
case QEvent::Resize:
@@ -314,10 +298,13 @@ bool QWindowContainer::event(QEvent *e)
case QEvent::Show:
d->updateUsesNativeWidgets();
if (d->isStillAnOrphan()) {
+ d->window->parent()->removeEventFilter(this);
d->window->setParent(d->usesNativeWidgets
? windowHandle()
: window()->windowHandle());
d->fakeParent.destroy();
+ if (d->window->parent())
+ d->window->parent()->installEventFilter(this);
}
if (d->window->parent()) {
d->markParentChain();
@@ -330,12 +317,8 @@ bool QWindowContainer::event(QEvent *e)
break;
case QEvent::FocusIn:
if (d->window->parent()) {
- if (d->oldFocusWindow != d->window) {
+ if (QGuiApplication::focusWindow() != d->window)
d->window->requestActivate();
- } else {
- QWidget *next = nextInFocusChain();
- next->setFocus();
- }
}
break;
#if QT_CONFIG(draganddrop)
@@ -371,6 +354,11 @@ bool QWindowContainer::event(QEvent *e)
return QWidget::event(e);
}
+QSize QWindowContainer::minimumSizeHint() const
+{
+ return containedWindow() ? containedWindow()->minimumSize() : QSize(0, 0);
+}
+
typedef void (*qwindowcontainer_traverse_callback)(QWidget *parent);
static void qwindowcontainer_traverse(QWidget *parent, qwindowcontainer_traverse_callback callback)
{
@@ -388,7 +376,10 @@ static void qwindowcontainer_traverse(QWidget *parent, qwindowcontainer_traverse
void QWindowContainer::toplevelAboutToBeDestroyed(QWidget *parent)
{
if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) {
+ if (d->window->parent())
+ d->window->parent()->removeEventFilter(parent);
d->window->setParent(&d->fakeParent);
+ d->window->parent()->installEventFilter(parent);
}
qwindowcontainer_traverse(parent, toplevelAboutToBeDestroyed);
}
@@ -406,7 +397,9 @@ void QWindowContainer::parentWasChanged(QWidget *parent)
tld->createTLSysExtra();
Q_ASSERT(toplevel->windowHandle());
}
+ d->window->parent()->removeEventFilter(parent);
d->window->setParent(toplevel->windowHandle());
+ toplevel->windowHandle()->installEventFilter(parent);
d->fakeParent.destroy();
d->updateGeometry();
}
diff --git a/src/widgets/kernel/qwindowcontainer_p.h b/src/widgets/kernel/qwindowcontainer_p.h
index 72474077aa..0cbcc5321d 100644
--- a/src/widgets/kernel/qwindowcontainer_p.h
+++ b/src/widgets/kernel/qwindowcontainer_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWCONTAINER_H
#define QWINDOWCONTAINER_H
@@ -67,6 +31,7 @@ public:
explicit QWindowContainer(QWindow *embeddedWindow, QWidget *parent = nullptr, Qt::WindowFlags f = { });
~QWindowContainer();
QWindow *containedWindow() const;
+ QSize minimumSizeHint() const override;
static void toplevelAboutToBeDestroyed(QWidget *parent);
static void parentWasChanged(QWidget *parent);
@@ -76,9 +41,7 @@ public:
protected:
bool event(QEvent *ev) override;
-
-private slots:
- void focusWindowChanged(QWindow *focusWindow);
+ bool eventFilter(QObject *, QEvent *ev) override;
};
QT_END_NAMESPACE