summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/syncqt.pl2
-rw-r--r--config_help.txt4
-rw-r--r--configure.json26
-rw-r--r--configure.pri13
-rw-r--r--dist/changes-5.12.382
-rw-r--r--mkspecs/common/clang.conf2
-rw-r--r--mkspecs/common/g++-base.conf2
-rw-r--r--mkspecs/common/msvc-version.conf2
-rw-r--r--mkspecs/features/create_cmake.prf25
-rw-r--r--mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in10
-rw-r--r--mkspecs/features/default_post.prf7
-rw-r--r--mkspecs/features/qt.prf31
-rw-r--r--mkspecs/features/qt_common.prf1
-rw-r--r--mkspecs/features/qt_configure.prf14
-rw-r--r--mkspecs/features/qt_module_headers.prf2
-rw-r--r--mkspecs/features/win32/opengl.prf16
-rw-r--r--mkspecs/features/win32/windows.prf7
-rw-r--r--mkspecs/linux-lsb-g++/qmake.conf1
-rw-r--r--qmake/doc/src/qmake-manual.qdoc58
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.cpp2
-rw-r--r--qmake/generators/win32/msvc_objectmodel.cpp8
-rw-r--r--qmake/generators/win32/msvc_objectmodel.h1
-rw-r--r--src/3rdparty/angle/src/libANGLE/Display.cpp17
-rw-r--r--src/3rdparty/angle/src/libANGLE/Display.h1
-rw-r--r--src/3rdparty/angle/src/libGLESv2/global_state.cpp2
-rw-r--r--src/angle/patches/0013-ANGLE-clean-up-displays-on-dll-unload.patch78
-rw-r--r--src/corelib/global/qglobal_p.h3
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp13
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp2
-rw-r--r--src/corelib/kernel/qobjectdefs.h4
-rw-r--r--src/corelib/tools/qdatetime.cpp3
-rw-r--r--src/corelib/tools/qdatetime.h2
-rw-r--r--src/corelib/tools/qlocale.cpp11
-rw-r--r--src/corelib/tools/qlocale.qdoc2
-rw-r--r--src/gui/kernel/qoffscreensurface.cpp8
-rw-r--r--src/gui/painting/qcoregraphics.mm158
-rw-r--r--src/gui/painting/qcoregraphics_p.h36
-rw-r--r--src/gui/util/qshaderformat.cpp17
-rw-r--r--src/gui/util/qshaderformat_p.h13
-rw-r--r--src/gui/util/qshadergenerator.cpp67
-rw-r--r--src/gui/util/qshadernodesloader.cpp11
-rw-r--r--src/network/kernel/qhostaddress.cpp4
-rw-r--r--src/platformsupport/eglconvenience/qeglconvenience.cpp2
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp8
-rw-r--r--src/platformsupport/glxconvenience/glxconvenience.pro2
-rw-r--r--src/platformsupport/input/tslib/qtslib.cpp4
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice.cpp8
-rw-r--r--src/platformsupport/platformcompositor/qopenglcompositor.cpp13
-rw-r--r--src/plugins/bearer/generic/qgenericengine.cpp2
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm23
-rw-r--r--src/plugins/platforms/cocoa/qnsview_drawing.mm1
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsintegration.cpp4
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfswindow.cpp3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsdropdataobject.cpp22
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp20
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp35
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp3
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp37
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h1
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp4
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm71
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp11
-rw-r--r--src/widgets/graphicsview/qgraphicsitem_p.h2
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.cpp2
-rw-r--r--src/widgets/itemviews/qheaderview.cpp16
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp8
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp3
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp5
-rw-r--r--src/widgets/util/qsystemtrayicon_p.h4
-rw-r--r--src/widgets/util/qsystemtrayicon_x11.cpp75
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp16
-rw-r--r--src/widgets/widgets/qtextedit.cpp23
-rw-r--r--tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp12
-rw-r--r--tests/auto/corelib/kernel/qmetaobject/qmetaobject.pro1
-rw-r--r--tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp18
-rw-r--r--tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp19
-rw-r--r--tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp383
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp17
-rw-r--r--tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp10
-rw-r--r--tests/auto/widgets/kernel/qwidget/BLACKLIST3
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp21
-rw-r--r--util/corelib/qurl-generateTLDs/main.cpp14
87 files changed, 1259 insertions, 449 deletions
diff --git a/bin/syncqt.pl b/bin/syncqt.pl
index 972717efcf..7793811c9f 100755
--- a/bin/syncqt.pl
+++ b/bin/syncqt.pl
@@ -1111,7 +1111,7 @@ foreach my $lib (@modules_to_sync) {
elsif (!$shadow) {
$pri_install_pfiles.= "$pri_install_iheader ";;
}
- $pri_injections .= fixPaths($iheader, $out_basedir)
+ $pri_injections .= fixPaths($iheader, $build_basedir)
.":".($no_stamp ? "^" : "").fixPaths($oheader, "$out_basedir/include/$lib")
.$injection." " if ($shadow);
}
diff --git a/config_help.txt b/config_help.txt
index 77a333c89a..5334f9618d 100644
--- a/config_help.txt
+++ b/config_help.txt
@@ -139,8 +139,8 @@ Build options:
-coverage {trace-pc-guard}
Add code coverage instrumentation (Clang only)
- -c++std <edition> .... Select C++ standard <edition> [c++1z/c++14/c++11]
- (Not supported with MSVC)
+ -c++std <edition> .... Select C++ standard <edition> [c++2a/c++17/c++14/c++11]
+ (Not supported with MSVC 2015)
-sse2 ................ Use SSE2 instructions [auto]
-sse3/-ssse3/-sse4.1/-sse4.2/-avx/-avx2/-avx512
diff --git a/configure.json b/configure.json
index f7449ec068..7f3018ed23 100644
--- a/configure.json
+++ b/configure.json
@@ -319,7 +319,7 @@
}
},
"c++1z": {
- "label": "C++1z support",
+ "label": "C++17 support",
"type": "compile",
"test": {
"head": [
@@ -339,6 +339,20 @@
"qmake": "CONFIG += c++11 c++14 c++1z"
}
},
+ "c++2a": {
+ "label": "C++2a support",
+ "type": "compile",
+ "test": {
+ "head": [
+ "#if __cplusplus > 201703L",
+ "// Compiler claims to support experimental C++2a, trust it",
+ "#else",
+ "# error __cplusplus must be > 201703L (the value for C++17)",
+ "#endif"
+ ],
+ "qmake": "CONFIG += c++11 c++14 c++1z c++2a"
+ }
+ },
"precompile_header": {
"label": "precompiled header support",
"type": "compile",
@@ -907,10 +921,16 @@
"output": [ "publicFeature", "publicQtConfig" ]
},
"c++1z": {
- "label": "C++1z",
+ "label": "C++17",
"condition": "features.c++14 && tests.c++1z",
"output": [ "publicFeature", "publicQtConfig" ]
},
+ "c++2a": {
+ "label": "C++2a",
+ "autoDetect": false,
+ "condition": "features.c++1z && tests.c++2a",
+ "output": [ "publicFeature", "publicQtConfig" ]
+ },
"c89": {
"label": "C89"
},
@@ -1413,7 +1433,7 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
{
"message": "Using C++ standard",
"type": "firstAvailableFeature",
- "args": "c++1z c++14 c++11"
+ "args": "c++2a c++1z c++14 c++11"
},
{
"type": "feature",
diff --git a/configure.pri b/configure.pri
index d8d0260fa0..81133da3d7 100644
--- a/configure.pri
+++ b/configure.pri
@@ -14,21 +14,26 @@ defineTest(qtConfCommandline_qmakeArgs) {
}
defineTest(qtConfCommandline_cxxstd) {
- msvc: \
- qtConfAddError("Command line option -c++std is not supported with MSVC compilers.")
-
arg = $${1}
val = $${2}
isEmpty(val): val = $$qtConfGetNextCommandlineArg()
!contains(val, "^-.*"):!isEmpty(val) {
contains(val, "(c\+\+)?11") {
qtConfCommandlineSetInput("c++14", "no")
+ qtConfCommandlineSetInput("c++1z", "no")
+ qtConfCommandlineSetInput("c++2a", "no")
} else: contains(val, "(c\+\+)?(14|1y)") {
qtConfCommandlineSetInput("c++14", "yes")
qtConfCommandlineSetInput("c++1z", "no")
- } else: contains(val, "(c\+\+)?(1z)") {
+ qtConfCommandlineSetInput("c++2a", "no")
+ } else: contains(val, "(c\+\+)?(17|1z)") {
+ qtConfCommandlineSetInput("c++14", "yes")
+ qtConfCommandlineSetInput("c++1z", "yes")
+ qtConfCommandlineSetInput("c++2a", "no")
+ } else: contains(val, "(c\+\+)?(2a)") {
qtConfCommandlineSetInput("c++14", "yes")
qtConfCommandlineSetInput("c++1z", "yes")
+ qtConfCommandlineSetInput("c++2a", "yes")
} else {
qtConfAddError("Invalid argument $$val to command line parameter $$arg")
}
diff --git a/dist/changes-5.12.3 b/dist/changes-5.12.3
new file mode 100644
index 0000000000..e6636fc153
--- /dev/null
+++ b/dist/changes-5.12.3
@@ -0,0 +1,82 @@
+Qt 5.12.3 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.0 through 5.12.2.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Third-Party Code *
+****************************************************************************
+
+ - Changed classification of the wintab license from Public Domain to
+ Custom.
+
+****************************************************************************
+* QtCore *
+****************************************************************************
+
+ - Event system:
+ * [QTBUG-72438] Fixed a possible race condition on Windows that would
+ cause an interrupted event loop to be stuck until more events were
+ posted.
+
+ - Logging system:
+ * [QTBUG-74359] Fixed the compilation of qCDebug("", ...) when debug
+ output was disabled.
+
+ - QCollator:
+ * [QTBUG-74209] Fixed a bug that caused QCompare to incorrect return a
+ sorting order on Windows if the Win32 API failed.
+
+ - QDateTime / QTimeZone:
+ * [QTBUG-74614] Fixed handling of timezones that contain no DST
+ transitions.
+
+ - QProcess:
+ * [QTBUG-73778] Fixed a crash when calling closeWriteChannel() on Windows.
+
+****************************************************************************
+* QtSql *
+****************************************************************************
+
+ - When cross-compiling pg_config, mysql_config are not looked up in PATH
+ anymore. Pass -psql_config path/to/pg_config or -mysql_config
+ path/to/mysql_config to explicitly enable PSQL or MySQL in this setup.
+
+****************************************************************************
+* Platform Specific Changes *
+****************************************************************************
+
+ - Android:
+ * Text fields with ImhNoPredictiveText set are no longer working around
+ keyboards that disregard this setting. To enforce the workaround, the
+ environment variable
+ QT_ANDROID_ENABLE_WORKAROUND_TO_DISABLE_PREDICTIVE_TEXT should be set.
+
+ * [QTBUG-74029] Added entries in the AndroidManifest.xml for specific
+ portrait and landscape splash screens. If one is present for the current
+ orientation, it will be preferred over the generic one.
+
+ - Linux:
+ * [QTBUG-74526] Changed the way we use the statx() system call to use a
+ fallback mechanism provided by the GNU C library. This should allow Qt
+ applications that are compiled with glibc >= 2.28 to run even on kernels
+ older than 4.11.
+
+ - Windows:
+ * [QTBUG-74062] Fixed QToolTip pop-ups and QComboBox animation pop-ups
+ being off by a few pixels on Windows 10.
+
diff --git a/mkspecs/common/clang.conf b/mkspecs/common/clang.conf
index 1666843136..aead581478 100644
--- a/mkspecs/common/clang.conf
+++ b/mkspecs/common/clang.conf
@@ -35,9 +35,11 @@ QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_CXXFLAGS_CXX14 = -std=c++1y
QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
+QMAKE_CXXFLAGS_CXX2A = -std=c++2a
QMAKE_CXXFLAGS_GNUCXX11 = -std=gnu++11
QMAKE_CXXFLAGS_GNUCXX14 = -std=gnu++1y
QMAKE_CXXFLAGS_GNUCXX1Z = -std=gnu++1z
+QMAKE_CXXFLAGS_GNUCXX2A = -std=gnu++2a
QMAKE_LFLAGS_CXX11 =
QMAKE_LFLAGS_CXX14 =
diff --git a/mkspecs/common/g++-base.conf b/mkspecs/common/g++-base.conf
index fa0f0c391d..8053feb876 100644
--- a/mkspecs/common/g++-base.conf
+++ b/mkspecs/common/g++-base.conf
@@ -32,9 +32,11 @@ QMAKE_CFLAGS_GNUC11 = -std=gnu11
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_CXXFLAGS_CXX14 = -std=c++1y
QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
+QMAKE_CXXFLAGS_CXX2A = -std=c++2a
QMAKE_CXXFLAGS_GNUCXX11 = -std=gnu++11
QMAKE_CXXFLAGS_GNUCXX14 = -std=gnu++1y
QMAKE_CXXFLAGS_GNUCXX1Z = -std=gnu++1z
+QMAKE_CXXFLAGS_GNUCXX2A = -std=gnu++2a
QMAKE_LFLAGS_CXX11 =
QMAKE_LFLAGS_CXX14 =
QMAKE_LFLAGS_CXX1Z =
diff --git a/mkspecs/common/msvc-version.conf b/mkspecs/common/msvc-version.conf
index 06af6abf13..af33132077 100644
--- a/mkspecs/common/msvc-version.conf
+++ b/mkspecs/common/msvc-version.conf
@@ -116,6 +116,8 @@ greaterThan(QMAKE_MSC_VER, 1910) {
greaterThan(QMAKE_MSC_VER, 1919) {
# Visual Studio 2019 (16.0) / Visual C++ 19.20 and up
MSVC_VER = 16.0
+ QMAKE_CXXFLAGS_CXX2A = -std:c++latest
+
}
!isEmpty(COMPAT_MKSPEC):!$$COMPAT_MKSPEC: CONFIG += $$COMPAT_MKSPEC
diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf
index 6bf1380716..2ab7775fea 100644
--- a/mkspecs/features/create_cmake.prf
+++ b/mkspecs/features/create_cmake.prf
@@ -26,20 +26,29 @@ contains(CMAKE_INSTALL_LIBS_DIR, ^(/usr)?/lib(64)?.*): CMAKE_USR_MOVE_WORKAROUND
CMAKE_OUT_DIR = $$MODULE_BASE_OUTDIR/lib/cmake
+# Core, Network, an external module named Foo
CMAKE_MODULE_NAME = $$cmakeModuleName($${MODULE})
+# QtCore, QtNetwork, still Foo
+CMAKE_INCLUDE_NAME = $$eval(QT.$${MODULE}.name)
+
+# TARGET here is the one changed at the end of qt_module.prf,
+# which already contains the Qt5 prefix and QT_LIBINFIX suffix :
+# Qt5Core_suffix, Qt5Network_suffix, Foo_suffix
+# (or QtCore_suffix, Foo_suffix on macos with -framework)
+CMAKE_QT_STEM = $${TARGET}
+
!generated_privates {
isEmpty(SYNCQT.INJECTED_PRIVATE_HEADER_FILES):isEmpty(SYNCQT.PRIVATE_HEADER_FILES): \
CMAKE_NO_PRIVATE_INCLUDES = true
}
-
split_incpath {
CMAKE_ADD_SOURCE_INCLUDE_DIRS = true
CMAKE_SOURCE_INCLUDES = \
- $$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME})
+ $$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/$${CMAKE_INCLUDE_NAME})
CMAKE_SOURCE_PRIVATE_INCLUDES = \
- $$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION) \
- $$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION)/Qt$${CMAKE_MODULE_NAME})
+ $$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE/$${CMAKE_INCLUDE_NAME}/$$eval(QT.$${MODULE}.VERSION) \
+ $$QT_MODULE_INCLUDE_BASE/$${CMAKE_INCLUDE_NAME}/$$eval(QT.$${MODULE}.VERSION)/$${CMAKE_INCLUDE_NAME})
cmake_extra_source_includes.input = $$PWD/data/cmake/ExtraSourceIncludes.cmake.in
cmake_extra_source_includes.output = $$CMAKE_OUT_DIR/Qt5$${CMAKE_MODULE_NAME}/ExtraSourceIncludes.cmake
@@ -200,10 +209,6 @@ CMAKE_QT5_MODULE_DEPS = $$join(lib_deps, ";")
CMAKE_INTERFACE_MODULE_DEPS = $$join(aux_mod_deps, ";")
CMAKE_INTERFACE_QT5_MODULE_DEPS = $$join(aux_lib_deps, ";")
-# TARGET here is the one changed at the end of qt_module.prf,
-# which already contains the Qt5 prefix and QT_LIBINFIX suffix
-CMAKE_QT_STEM = $${TARGET}
-
mac {
!isEmpty(CMAKE_STATIC_TYPE) {
CMAKE_LIB_FILE_LOCATION_DEBUG = lib$${CMAKE_QT_STEM}_debug.a
@@ -213,8 +218,8 @@ mac {
CMAKE_PRL_FILE_LOCATION_RELEASE = lib$${CMAKE_QT_STEM}.prl
} else {
qt_framework {
- CMAKE_LIB_FILE_LOCATION_DEBUG = Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}.framework/Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}
- CMAKE_LIB_FILE_LOCATION_RELEASE = Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}.framework/Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}
+ CMAKE_LIB_FILE_LOCATION_DEBUG = $${CMAKE_QT_STEM}.framework/$${CMAKE_QT_STEM}
+ CMAKE_LIB_FILE_LOCATION_RELEASE = $${CMAKE_QT_STEM}.framework/$${CMAKE_QT_STEM}
CMAKE_BUILD_IS_FRAMEWORK = "true"
} else {
CMAKE_LIB_FILE_LOCATION_DEBUG = lib$${CMAKE_QT_STEM}_debug.$$eval(QT.$${MODULE}.VERSION).dylib
diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
index b643e5edf9..aca8703238 100644
--- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
+++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
@@ -157,13 +157,13 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
!!IF !no_module_headers
!!IF !isEmpty(CMAKE_BUILD_IS_FRAMEWORK)
set(_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS
- \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}Qt$${CMAKE_MODULE_NAME}.framework\"
- \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}Qt$${CMAKE_MODULE_NAME}.framework/Headers\"
+ \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_QT_STEM}.framework\"
+ \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_QT_STEM}.framework/Headers\"
)
!!IF isEmpty(CMAKE_NO_PRIVATE_INCLUDES)
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS
- \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}Qt$${CMAKE_MODULE_NAME}.framework/Versions/$$section(VERSION, ., 0, 0)/Headers/$$VERSION/\"
- \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}Qt$${CMAKE_MODULE_NAME}.framework/Versions/$$section(VERSION, ., 0, 0)/Headers/$$VERSION/$${MODULE_INCNAME}\"
+ \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_QT_STEM}.framework/Versions/$$section(VERSION, ., 0, 0)/Headers/$$VERSION/\"
+ \"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_QT_STEM}.framework/Versions/$$section(VERSION, ., 0, 0)/Headers/$$VERSION/$${MODULE_INCNAME}\"
)
!!ELSE
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS \"\")
@@ -180,7 +180,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS \"\")
!!ENDIF
!!ELSE
- set(_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS \"$$CMAKE_INCLUDE_DIR\" \"$${CMAKE_INCLUDE_DIR}Qt$${CMAKE_MODULE_NAME}\")
+ set(_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS \"$$CMAKE_INCLUDE_DIR\" \"$${CMAKE_INCLUDE_DIR}$${CMAKE_INCLUDE_NAME}\")
!!IF isEmpty(CMAKE_NO_PRIVATE_INCLUDES)
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS
\"$${CMAKE_INCLUDE_DIR}$${MODULE_INCNAME}/$$VERSION\"
diff --git a/mkspecs/features/default_post.prf b/mkspecs/features/default_post.prf
index 69da78c5b7..9df99b8648 100644
--- a/mkspecs/features/default_post.prf
+++ b/mkspecs/features/default_post.prf
@@ -121,15 +121,16 @@ breakpad {
c++17: CONFIG += c++1z
-!c++11:!c++14:!c++1z {
+!c++11:!c++14:!c++1z:!c++2a {
# Qt requires C++11 since 5.7, check if we need to force a compiler option
QT_COMPILER_STDCXX_no_L = $$replace(QT_COMPILER_STDCXX, "L$", "")
!greaterThan(QT_COMPILER_STDCXX_no_L, 199711): CONFIG += c++11
}
-c++11|c++14|c++1z {
+c++11|c++14|c++1z|c++2a {
# Disable special compiler flags for host builds
!host_build|!cross_compile {
- c++1z: cxxstd = CXX1Z
+ c++2a: cxxstd = CXX2A
+ else: c++1z: cxxstd = CXX1Z
else: c++14: cxxstd = CXX14
else: cxxstd = CXX11
} else {
diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf
index 5ac640190a..3a71376029 100644
--- a/mkspecs/features/qt.prf
+++ b/mkspecs/features/qt.prf
@@ -145,12 +145,14 @@ import_plugins:qtConfig(static) {
# the plugin path. Unknown plugins must rely on the default link path.
plug_type = $$eval(QT_PLUGIN.$${plug}.TYPE)
!isEmpty(plug_type) {
+ plug_name = $$QMAKE_PREFIX_STATICLIB$${plug}$$qtPlatformTargetSuffix().$$QMAKE_EXTENSION_STATICLIB
plug_path = $$eval(QT_PLUGIN.$${plug}.PATH)
isEmpty(plug_path): \
plug_path = $$[QT_INSTALL_PLUGINS/get]
- LIBS += -L$$plug_path/$$plug_type
+ LIBS += $$plug_path/$$plug_type/$$plug_name
+ } else {
+ LIBS += -l$${plug}$$qtPlatformTargetSuffix()
}
- LIBS += -l$${plug}$$qtPlatformTargetSuffix()
}
}
@@ -195,8 +197,6 @@ for(ever) {
qtProcessModuleFlags(DEFINES, QT.$${QTLIB}.DEFINES)
MODULE_INCLUDES -= $$QMAKE_DEFAULT_INCDIRS
- MODULE_LIBS_ADD = $$MODULE_LIBS
- MODULE_LIBS_ADD -= $$QMAKE_DEFAULT_LIBDIRS
# Frameworks shouldn't need include paths, but much code does not use
# module-qualified #includes, so by default we add paths which point
@@ -209,23 +209,17 @@ for(ever) {
!isEmpty(MODULE_MODULE) {
contains(MODULE_CONFIG, lib_bundle) {
framework = $$MODULE_MODULE
+ # Linking frameworks by absolute path does not work.
LIBS$$var_sfx += -framework $$framework
} else {
- !isEmpty(MODULE_LIBS_ADD): \
- LIBS$$var_sfx += -L$$MODULE_LIBS_ADD
-
lib = $$MODULE_MODULE$$qtPlatformTargetSuffix()
- LIBS$$var_sfx += -l$$lib
-
- contains(MODULE_CONFIG, staticlib): \
- PRE_TARGETDEPS *= $$MODULE_LIBS/$${QMAKE_PREFIX_STATICLIB}$${lib}.$${QMAKE_EXTENSION_STATICLIB}
-
- !isEmpty(QMAKE_LSB) {
- !isEmpty(MODULE_LIBS_ADD): \
- QMAKE_LFLAGS *= --lsb-libpath=$$MODULE_LIBS_ADD
- QMAKE_LFLAGS *= --lsb-shared-libs=$$lib
- QMAKE_LIBDIR *= /opt/lsb/lib
+ win32|contains(MODULE_CONFIG, staticlib) {
+ lib = $$MODULE_LIBS/$$QMAKE_PREFIX_STATICLIB$${lib}.$$QMAKE_EXTENSION_STATICLIB
+ PRE_TARGETDEPS += $$lib
+ } else {
+ lib = $$MODULE_LIBS/$$QMAKE_PREFIX_SHLIB$${lib}.$$QMAKE_EXTENSION_SHLIB
}
+ LIBS$$var_sfx += $$lib
}
}
QMAKE_USE$$var_sfx += $$MODULE_USES
@@ -295,7 +289,8 @@ contains(all_qt_module_deps, qml): \
for (key, IMPORTS._KEYS_) {
PATH = $$eval(IMPORTS.$${key}.path)
PLUGIN = $$eval(IMPORTS.$${key}.plugin)
- !isEmpty(PATH):!isEmpty(PLUGIN): LIBS *= -L$$PATH -l$${PLUGIN}$$qtPlatformTargetSuffix()
+ !isEmpty(PATH):!isEmpty(PLUGIN): \
+ LIBS += $$PATH/$$QMAKE_PREFIX_STATICLIB$${PLUGIN}$$qtPlatformTargetSuffix().$$QMAKE_EXTENSION_STATICLIB
}
# create qml_plugin_import.cpp
diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf
index ae859a81ff..004b32fd22 100644
--- a/mkspecs/features/qt_common.prf
+++ b/mkspecs/features/qt_common.prf
@@ -17,6 +17,7 @@ DEFINES *= QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
qtConfig(c++11): CONFIG += c++11 strict_c++
qtConfig(c++14): CONFIG += c++14
qtConfig(c++1z): CONFIG += c++1z
+qtConfig(c++2a): CONFIG += c++2a
qtConfig(c99): CONFIG += c99
qtConfig(c11): CONFIG += c11
qtConfig(stack-protector-strong): CONFIG += stack_protector_strong
diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf
index 168a8e64f2..fc8ea4d203 100644
--- a/mkspecs/features/qt_configure.prf
+++ b/mkspecs/features/qt_configure.prf
@@ -526,6 +526,17 @@ defineTest(qtConfSetupLibraries) {
}
}
+defineReplace(qtGccSysrootifiedPath) {
+ return($$replace(1, ^=, $$[QT_SYSROOT]))
+}
+
+defineReplace(qtGccSysrootifiedPaths) {
+ sysrootified =
+ for (path, 1): \
+ sysrootified += $$qtGccSysrootifiedPath($$path)
+ return($$sysrootified)
+}
+
# libs-var, libs, in-paths, out-paths-var
defineTest(qtConfResolveLibs) {
ret = true
@@ -542,6 +553,7 @@ defineTest(qtConfResolveLibs) {
out += $$l
} else: contains(l, "^-L.*") {
lp = $$replace(l, "^-L", )
+ gcc: lp = $$qtGccSysrootifiedPath($$lp)
!exists($$lp/.) {
qtLog("Library path $$val_escape(lp) is invalid.")
ret = false
@@ -615,6 +627,7 @@ defineTest(qtConfResolveAllLibs) {
# libs-var, in-paths, libs
defineTest(qtConfResolvePathLibs) {
ret = true
+ gcc: 2 = $$qtGccSysrootifiedPaths($$2)
for (libdir, 2) {
!exists($$libdir/.) {
qtLog("Library path $$val_escape(libdir) is invalid.")
@@ -665,6 +678,7 @@ defineReplace(qtConfGetTestIncludes) {
# includes-var, in-paths, test-object-var
defineTest(qtConfResolvePathIncs) {
ret = true
+ gcc: 2 = $$qtGccSysrootifiedPaths($$2)
for (incdir, 2) {
!exists($$incdir/.) {
qtLog("Include path $$val_escape(incdir) is invalid.")
diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf
index 6b4b9143fa..37b69e31c8 100644
--- a/mkspecs/features/qt_module_headers.prf
+++ b/mkspecs/features/qt_module_headers.prf
@@ -23,7 +23,7 @@ load(qt_build_paths)
QMAKE_SYNCQT += -module $$mod
QMAKE_SYNCQT += \
-version $$VERSION -outdir $$system_quote($$MODULE_BASE_OUTDIR) \
- -builddir $$system_quote($$shadowed($$MODULE_BASE_INDIR)) $$MODULE_SYNCQT_DIR
+ -builddir $$system_quote($$REAL_MODULE_BASE_OUTDIR) $$MODULE_SYNCQT_DIR
!silent: message($$QMAKE_SYNCQT)
system($$QMAKE_SYNCQT)|error("Failed to run: $$QMAKE_SYNCQT")
diff --git a/mkspecs/features/win32/opengl.prf b/mkspecs/features/win32/opengl.prf
index c6fba7770f..f21848f941 100644
--- a/mkspecs/features/win32/opengl.prf
+++ b/mkspecs/features/win32/opengl.prf
@@ -1,13 +1,21 @@
QT_FOR_CONFIG += gui
+defineTest(prependOpenGlLib) {
+ path = $$QT.core.libs/$$QMAKE_PREFIX_STATICLIB$$1
+ ext = .$$QMAKE_EXTENSION_STATICLIB
+ QMAKE_LIBS_OPENGL_ES2 = $${path}$${ext} $$QMAKE_LIBS_OPENGL_ES2
+ QMAKE_LIBS_OPENGL_ES2_DEBUG = $${path}d$${ext} $$QMAKE_LIBS_OPENGL_ES2_DEBUG
+ export(QMAKE_LIBS_OPENGL_ES2)
+ export(QMAKE_LIBS_OPENGL_ES2_DEBUG)
+}
+
qtConfig(opengles2) {
# Depending on the configuration we use libQtANGLE or libEGL and libGLESv2
qtConfig(combined-angle-lib) {
- QMAKE_LIBS_OPENGL_ES2 = -l$${LIBQTANGLE_NAME} $$QMAKE_LIBS_OPENGL_ES2
- QMAKE_LIBS_OPENGL_ES2_DEBUG = -l$${LIBQTANGLE_NAME}d $$QMAKE_LIBS_OPENGL_ES2_DEBUG
+ prependOpenGlLib($$LIBQTANGLE_NAME)
} else {
- QMAKE_LIBS_OPENGL_ES2 = -l$${LIBEGL_NAME} -l$${LIBGLESV2_NAME} $$QMAKE_LIBS_OPENGL_ES2
- QMAKE_LIBS_OPENGL_ES2_DEBUG = -l$${LIBEGL_NAME}d -l$${LIBGLESV2_NAME}d $$QMAKE_LIBS_OPENGL_ES2_DEBUG
+ prependOpenGlLib($$LIBGLESV2_NAME)
+ prependOpenGlLib($$LIBEGL_NAME)
}
# For Desktop, use the ANGLE library location passed on from configure.
INCLUDEPATH += $$QMAKE_INCDIR_OPENGL_ES2
diff --git a/mkspecs/features/win32/windows.prf b/mkspecs/features/win32/windows.prf
index ecb167bf18..272170d428 100644
--- a/mkspecs/features/win32/windows.prf
+++ b/mkspecs/features/win32/windows.prf
@@ -6,10 +6,9 @@ contains(TEMPLATE, ".*app") {
qt:for(entryLib, $$list($$unique(QMAKE_LIBS_QT_ENTRY))) {
isEqual(entryLib, -lqtmain) {
- !contains(QMAKE_DEFAULT_LIBDIRS, $$QT.core.libs): \
- QMAKE_LIBS += -L$$QT.core.libs
- CONFIG(debug, debug|release): QMAKE_LIBS += $${entryLib}$${QT_LIBINFIX}d
- else: QMAKE_LIBS += $${entryLib}$${QT_LIBINFIX}
+ lib = $$QT.core.libs/$${QMAKE_PREFIX_STATICLIB}qtmain$$QT_LIBINFIX$$qtPlatformTargetSuffix().$$QMAKE_EXTENSION_STATICLIB
+ PRE_TARGETDEPS += $$lib
+ QMAKE_LIBS += $$lib
} else {
QMAKE_LIBS += $${entryLib}
}
diff --git a/mkspecs/linux-lsb-g++/qmake.conf b/mkspecs/linux-lsb-g++/qmake.conf
index 80353cd5f6..eb7b87b57b 100644
--- a/mkspecs/linux-lsb-g++/qmake.conf
+++ b/mkspecs/linux-lsb-g++/qmake.conf
@@ -13,7 +13,6 @@ load(qt_config)
QMAKE_LIBS_THREAD += -lrt
-QMAKE_LSB = 1
QMAKE_CC = lsbcc
QMAKE_CXX = lsbc++
diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc
index aba5be61dd..b293792bd1 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -1271,6 +1271,41 @@
\snippet code/doc_src_qmake-manual.pro 36
+ \c INSTALLS has a \c{.CONFIG} member that can take several values:
+
+ \table
+ \header
+ \li Value
+ \li Description
+ \row
+ \li no_check_exists
+ \li If not set, qmake looks to see if the files to install actually
+ exist. If these files don't exist, qmake doesn’t create the
+ install rule. Use this config value if you need to install
+ files that are generated as part of your build process, like
+ HTML files created by qdoc.
+ \row
+ \li nostrip
+ \li If set, the typical Unix strip functionality is turned off and
+ the debug information will remain in the binary.
+ \row
+ \li executable
+ \li On Unix, this sets the executable flag.
+ \row
+ \li no_build
+ \li When you do a \c{make install}, and you don't have a build of
+ the project yet, the project is first built, and then installed.
+ If you don't want this behavior, set this config value to ensure
+ that the build target is not added as a dependency to the install
+ target.
+ \row
+ \li no_default_install
+ \li A project has a top-level project target where, when you do a
+ \c{make install}, everything is installed. But, if you have an
+ install target with this config value set, it's not installed by
+ default. You then have to explicitly say \c{make install_<file>}.
+ \endtable
+
For more information, see \l{Installing Files}.
This variable is also used to specify which additional files will be
@@ -1580,6 +1615,14 @@
The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf}
and rarely needs to be modified.
+ \target QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
+ \section1 QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
+
+ Specifies the C compiler flags for release builds where
+ \c{force_debug_info} is set in \c{CONFIG}.
+ The value of this variable is typically handled by
+ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
+
\target QMAKE_CFLAGS_SHLIB
\section1 QMAKE_CFLAGS_SHLIB
@@ -1648,6 +1691,14 @@
The value of this variable is typically handled by
qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
+ \target QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO
+ \section1 QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO
+
+ Specifies the C++ compiler flags for release builds where
+ \c{force_debug_info} is set in \c{CONFIG}.
+ The value of this variable is typically handled by
+ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
+
\target QMAKE_CXXFLAGS_SHLIB
\section1 QMAKE_CXXFLAGS_SHLIB
@@ -2028,6 +2079,12 @@
The value of this variable is typically handled by
qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
+ \section1 QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO
+
+ Specifies the linker flags for release builds where \c{force_debug_info} is
+ set in \c{CONFIG}. The value of this variable is typically handled by
+ qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
+
\section1 QMAKE_LFLAGS_APP
Specifies the linker flags for building applications.
@@ -4813,6 +4870,7 @@
\li Unix
\list
\li GCC 3.4 and above
+ \li clang
\endlist
\endlist
diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp
index 89428bd454..3116238aa0 100644
--- a/qmake/generators/win32/msbuild_objectmodel.cpp
+++ b/qmake/generators/win32/msbuild_objectmodel.cpp
@@ -143,6 +143,7 @@ const char _InterfaceIdentifierFileName[] = "InterfaceIdentifierFileName";
const char _IntermediateDirectory[] = "IntermediateDirectory";
const char _KeyContainer[] = "KeyContainer";
const char _KeyFile[] = "KeyFile";
+const char _LanguageStandard[] = "LanguageStandard";
const char _LargeAddressAware[] = "LargeAddressAware";
const char _LinkDLL[] = "LinkDLL";
const char _LinkErrorReporting[] = "LinkErrorReporting";
@@ -1478,6 +1479,7 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool)
<< attrTagT(_IntrinsicFunctions, tool.EnableIntrinsicFunctions)
<< attrTagT(_MinimalRebuild, tool.MinimalRebuild)
<< attrTagT(_MultiProcessorCompilation, tool.MultiProcessorCompilation)
+ << attrTagS(_LanguageStandard, tool.LanguageStandard)
<< attrTagS(_ObjectFileName, tool.ObjectFile)
<< attrTagT(_OmitDefaultLibName, tool.OmitDefaultLibName)
<< attrTagT(_OmitFramePointers, tool.OmitFramePointers)
diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp
index eb46e0cf69..45f23e52bd 100644
--- a/qmake/generators/win32/msvc_objectmodel.cpp
+++ b/qmake/generators/win32/msvc_objectmodel.cpp
@@ -1147,6 +1147,14 @@ bool VCCLCompilerTool::parseOption(const char* option)
ShowIncludes = _True;
break;
}
+ if (strlen(option) > 8 && second == 't' && third == 'd') {
+ const QString version = option + 8;
+ static const QStringList knownVersions = { "14", "17", "latest" };
+ if (knownVersions.contains(version)) {
+ LanguageStandard = "stdcpp" + version;
+ break;
+ }
+ }
found = false; break;
case 'u':
if (!second)
diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h
index 33a96bf85e..b356f1bb73 100644
--- a/qmake/generators/win32/msvc_objectmodel.h
+++ b/qmake/generators/win32/msvc_objectmodel.h
@@ -526,6 +526,7 @@ public:
triState ImproveFloatingPointConsistency;
inlineExpansionOption InlineFunctionExpansion;
triState KeepComments;
+ QString LanguageStandard;
triState MinimalRebuild;
QString ObjectFile;
triState OmitDefaultLibName;
diff --git a/src/3rdparty/angle/src/libANGLE/Display.cpp b/src/3rdparty/angle/src/libANGLE/Display.cpp
index 735b472787..0bb0bb05b1 100644
--- a/src/3rdparty/angle/src/libANGLE/Display.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Display.cpp
@@ -364,6 +364,23 @@ Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attri
return display;
}
+//static
+void Display::CleanupDisplays()
+{
+ // ~Display takes care of removing the entry from the according map
+ {
+ ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
+ while (!displays->empty())
+ delete displays->begin()->second;
+ }
+
+ {
+ DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap();
+ while (!displays->empty())
+ delete displays->begin()->second;
+ }
+}
+
Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
: mImplementation(nullptr),
mDisplayId(displayId),
diff --git a/src/3rdparty/angle/src/libANGLE/Display.h b/src/3rdparty/angle/src/libANGLE/Display.h
index aa1d1c3b37..2a1c386d75 100644
--- a/src/3rdparty/angle/src/libANGLE/Display.h
+++ b/src/3rdparty/angle/src/libANGLE/Display.h
@@ -65,6 +65,7 @@ class Display final : angle::NonCopyable
static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap);
static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
const AttributeMap &attribMap);
+ static void CleanupDisplays();
static const ClientExtensions &GetClientExtensions();
static const std::string &GetClientExtensionString();
diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.cpp b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
index c5f3dfe4e1..26045bf5b2 100644
--- a/src/3rdparty/angle/src/libGLESv2/global_state.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
@@ -13,6 +13,7 @@
#include "common/tls.h"
#include "libANGLE/Thread.h"
+#include "libANGLE/Display.h"
namespace gl
{
@@ -140,6 +141,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
return static_cast<BOOL>(egl::DeallocateCurrentThread());
case DLL_PROCESS_DETACH:
+ egl::Display::CleanupDisplays();
return static_cast<BOOL>(egl::TerminateProcess());
}
diff --git a/src/angle/patches/0013-ANGLE-clean-up-displays-on-dll-unload.patch b/src/angle/patches/0013-ANGLE-clean-up-displays-on-dll-unload.patch
new file mode 100644
index 0000000000..fce3fd76b2
--- /dev/null
+++ b/src/angle/patches/0013-ANGLE-clean-up-displays-on-dll-unload.patch
@@ -0,0 +1,78 @@
+From d8ca4f6d0d8fffd8319f340685e03751049678ae Mon Sep 17 00:00:00 2001
+From: Oliver Wolff <oliver.wolff@qt.io>
+Date: Tue, 16 Apr 2019 10:19:27 +0200
+Subject: [PATCH] ANGLE: clean up displays on dll unload
+
+If the displays are not cleaned up on dll unloading, profilers might
+report memory leaks.
+
+Change-Id: I04cbc3c2448bfb450f7d840e216827f86856e963
+---
+ src/3rdparty/angle/src/libANGLE/Display.cpp | 17 +++++++++++++++++
+ src/3rdparty/angle/src/libANGLE/Display.h | 1 +
+ .../angle/src/libGLESv2/global_state.cpp | 2 ++
+ 3 files changed, 20 insertions(+)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/Display.cpp b/src/3rdparty/angle/src/libANGLE/Display.cpp
+index 735b472787..0bb0bb05b1 100644
+--- a/src/3rdparty/angle/src/libANGLE/Display.cpp
++++ b/src/3rdparty/angle/src/libANGLE/Display.cpp
+@@ -364,6 +364,23 @@ Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attri
+ return display;
+ }
+
++//static
++void Display::CleanupDisplays()
++{
++ // ~Display takes care of removing the entry from the according map
++ {
++ ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
++ while (!displays->empty())
++ delete displays->begin()->second;
++ }
++
++ {
++ DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap();
++ while (!displays->empty())
++ delete displays->begin()->second;
++ }
++}
++
+ Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
+ : mImplementation(nullptr),
+ mDisplayId(displayId),
+diff --git a/src/3rdparty/angle/src/libANGLE/Display.h b/src/3rdparty/angle/src/libANGLE/Display.h
+index aa1d1c3b37..2a1c386d75 100644
+--- a/src/3rdparty/angle/src/libANGLE/Display.h
++++ b/src/3rdparty/angle/src/libANGLE/Display.h
+@@ -65,6 +65,7 @@ class Display final : angle::NonCopyable
+ static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap);
+ static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
+ const AttributeMap &attribMap);
++ static void CleanupDisplays();
+
+ static const ClientExtensions &GetClientExtensions();
+ static const std::string &GetClientExtensionString();
+diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.cpp b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
+index c5f3dfe4e1..26045bf5b2 100644
+--- a/src/3rdparty/angle/src/libGLESv2/global_state.cpp
++++ b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
+@@ -13,6 +13,7 @@
+ #include "common/tls.h"
+
+ #include "libANGLE/Thread.h"
++#include "libANGLE/Display.h"
+
+ namespace gl
+ {
+@@ -140,6 +141,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
+ return static_cast<BOOL>(egl::DeallocateCurrentThread());
+
+ case DLL_PROCESS_DETACH:
++ egl::Display::CleanupDisplays();
+ return static_cast<BOOL>(egl::TerminateProcess());
+ }
+
+--
+2.20.1.windows.1
+
diff --git a/src/corelib/global/qglobal_p.h b/src/corelib/global/qglobal_p.h
index d52f6268e4..58bc8b7bf3 100644
--- a/src/corelib/global/qglobal_p.h
+++ b/src/corelib/global/qglobal_p.h
@@ -61,6 +61,9 @@
#endif
#if defined(__cplusplus)
+#ifdef Q_CC_MINGW
+# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
+#endif
#include <time.h>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 2020e34f93..279918b812 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -310,9 +310,18 @@ static QString readSymLink(const QFileSystemEntry &link)
const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset];
result = QString::fromWCharArray(PathBuffer, length);
}
- // cut-off "//?/" and "/??/"
- if (result.size() > 4 && result.at(0) == QLatin1Char('\\') && result.at(2) == QLatin1Char('?') && result.at(3) == QLatin1Char('\\'))
+ // cut-off "\\?\" and "\??\"
+ if (result.size() > 4
+ && result.at(0) == QLatin1Char('\\')
+ && result.at(2) == QLatin1Char('?')
+ && result.at(3) == QLatin1Char('\\')) {
result = result.mid(4);
+ // cut off UNC in addition when the link points at a UNC share
+ // in which case we need to prepend another backslash to get \\server\share
+ if (result.leftRef(3) == QLatin1String("UNC")) {
+ result.replace(0, 3, QLatin1Char('\\'));
+ }
+ }
}
free(rdb);
CloseHandle(handle);
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index 664e16540b..d171b313e6 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -3619,7 +3619,7 @@ QModelIndex QAbstractTableModel::sibling(int row, int column, const QModelIndex
bool QAbstractTableModel::hasChildren(const QModelIndex &parent) const
{
- if (parent.model() == this || !parent.isValid())
+ if (!parent.isValid())
return rowCount(parent) > 0 && columnCount(parent) > 0;
return false;
}
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 418b8cf1d2..0bceab6fb4 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -515,7 +515,7 @@ struct Q_CORE_EXPORT QMetaObject
Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr)
{
return invokeMethodImpl(context,
- new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(function),
+ new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
type,
ret);
}
@@ -527,7 +527,7 @@ struct Q_CORE_EXPORT QMetaObject
invokeMethod(QObject *context, Func function, typename std::result_of<Func()>::type *ret)
{
return invokeMethodImpl(context,
- new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(function),
+ new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
Qt::AutoConnection,
ret);
}
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 969065ffee..6fa735dab7 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -58,6 +58,9 @@
#endif
#include <cmath>
+#ifdef Q_CC_MINGW
+# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
+#endif
#include <time.h>
#ifdef Q_OS_WIN
# include <qt_windows.h>
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
index fc901234ec..51d5dd9759 100644
--- a/src/corelib/tools/qdatetime.h
+++ b/src/corelib/tools/qdatetime.h
@@ -335,7 +335,7 @@ public:
inline bool operator>(const QDateTime &other) const { return other < *this; }
inline bool operator>=(const QDateTime &other) const { return !(*this < other); }
-#if QT_DEPRECATED_SINCE(5, 2)
+#if QT_DEPRECATED_SINCE(5, 2) // ### Qt 6: remove
QT_DEPRECATED void setUtcOffset(int seconds);
QT_DEPRECATED int utcOffset() const;
#endif // QT_DEPRECATED_SINCE
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 9f414b1b72..8e47d350d1 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -2482,6 +2482,17 @@ QString QLocale::toString(double i, char f, int prec) const
Returns a QLocale object initialized to the "C" locale.
+ This locale is based on en_US but with various quirks of its own, such as
+ simplified number formatting and its own date formatting. It implements the
+ POSIX standards that describe the behavior of standard library functions of
+ the "C" programming language.
+
+ Among other things, this means its collation order is based on the ASCII
+ values of letters, so that (for case-sensitive sorting) all upper-case
+ letters sort before any lower-case one (rather than each letter's upper- and
+ lower-case forms sorting adjacent to one another, before the next letter's
+ two forms).
+
\sa system()
*/
diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc
index 91b0ab6442..f36fd7d6fc 100644
--- a/src/corelib/tools/qlocale.qdoc
+++ b/src/corelib/tools/qlocale.qdoc
@@ -104,7 +104,7 @@
This enumerated type is used to specify a language.
\value AnyLanguage
- \value C The "C" locale is identical in behavior to English/UnitedStates.
+ \value C A simplified English locale; see QLocale::c()
\value Abkhazian
\value Afan Obsolete, please use Oromo
diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp
index ae027af627..0cc11ca3bb 100644
--- a/src/gui/kernel/qoffscreensurface.cpp
+++ b/src/gui/kernel/qoffscreensurface.cpp
@@ -46,6 +46,8 @@
#include "qwindow.h"
#include "qplatformwindow.h"
+#include <private/qwindow_p.h>
+
QT_BEGIN_NAMESPACE
/*!
@@ -199,12 +201,18 @@ void QOffscreenSurface::create()
if (QThread::currentThread() != qGuiApp->thread())
qWarning("Attempting to create QWindow-based QOffscreenSurface outside the gui thread. Expect failures.");
d->offscreenWindow = new QWindow(d->screen);
+ // Make the window frameless to prevent Windows from enlarging it, should it
+ // violate the minimum title bar width on the platform.
+ d->offscreenWindow->setFlags(d->offscreenWindow->flags()
+ | Qt::CustomizeWindowHint | Qt::FramelessWindowHint);
d->offscreenWindow->setObjectName(QLatin1String("QOffscreenSurface"));
// Remove this window from the global list since we do not want it to be destroyed when closing the app.
// The QOffscreenSurface has to be usable even after exiting the event loop.
QGuiApplicationPrivate::window_list.removeOne(d->offscreenWindow);
d->offscreenWindow->setSurfaceType(QWindow::OpenGLSurface);
d->offscreenWindow->setFormat(d->requestedFormat);
+ // Prevent QPlatformWindow::initialGeometry() and platforms from setting a default geometry.
+ qt_window_private(d->offscreenWindow)->setAutomaticPositionAndResizeEnabled(false);
d->offscreenWindow->setGeometry(0, 0, d->size.width(), d->size.height());
d->offscreenWindow->create();
}
diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm
index 53066687d3..e2497eaadb 100644
--- a/src/gui/painting/qcoregraphics.mm
+++ b/src/gui/painting/qcoregraphics.mm
@@ -366,40 +366,35 @@ void qt_mac_scale_region(QRegion *region, qreal scaleFactor)
// ---------------------- QMacCGContext ----------------------
-QMacCGContext::QMacCGContext(QPaintDevice *paintDevice) : context(0)
+QMacCGContext::QMacCGContext(QPaintDevice *paintDevice)
{
- // In Qt 5, QWidget and QPixmap (and QImage) paint devices are all QImages under the hood.
- QImage *image = 0;
- if (paintDevice->devType() == QInternal::Image) {
- image = static_cast<QImage *>(paintDevice);
- } else if (paintDevice->devType() == QInternal::Pixmap) {
-
- const QPixmap *pm = static_cast<const QPixmap*>(paintDevice);
- QPlatformPixmap *data = const_cast<QPixmap *>(pm)->data_ptr().data();
- if (data && data->classId() == QPlatformPixmap::RasterClass) {
- image = data->buffer();
- } else {
- qDebug("QMacCGContext: Unsupported pixmap class");
- }
- } else if (paintDevice->devType() == QInternal::Widget) {
- // TODO test: image = static_cast<QImage *>(static_cast<const QWidget *>(paintDevice)->backingStore()->paintDevice());
- qDebug("QMacCGContext: not implemented: Widget class");
- }
-
- if (!image)
- return; // Context type not supported.
-
- QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
- context = CGBitmapContextCreate(image->bits(), image->width(), image->height(), 8,
- image->bytesPerLine(), colorSpace, qt_mac_bitmapInfoForImage(*image));
+ initialize(paintDevice);
+}
- CGContextTranslateCTM(context, 0, image->height());
- const qreal devicePixelRatio = paintDevice->devicePixelRatioF();
- CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
- CGContextScaleCTM(context, 1, -1);
+void QMacCGContext::initialize(QPaintDevice *paintDevice)
+{
+ // Find the underlying QImage of the paint device
+ switch (int deviceType = paintDevice->devType()) {
+ case QInternal::Pixmap: {
+ auto *platformPixmap = static_cast<QPixmap*>(paintDevice)->handle();
+ if (platformPixmap && platformPixmap->classId() == QPlatformPixmap::RasterClass)
+ initialize(platformPixmap->buffer());
+ else
+ qWarning() << "QMacCGContext: Unsupported pixmap class" << platformPixmap->classId();
+ break;
+ }
+ case QInternal::Image:
+ initialize(static_cast<const QImage *>(paintDevice));
+ break;
+ case QInternal::Widget:
+ qWarning() << "QMacCGContext: not implemented: Widget class";
+ break;
+ default:
+ qWarning() << "QMacCGContext:: Unsupported paint device type" << deviceType;
+ }
}
-QMacCGContext::QMacCGContext(QPainter *painter) : context(0)
+QMacCGContext::QMacCGContext(QPainter *painter)
{
QPaintEngine *paintEngine = painter->paintEngine();
@@ -414,51 +409,68 @@ QMacCGContext::QMacCGContext(QPainter *painter) : context(0)
return;
}
- int devType = painter->device()->devType();
- if (paintEngine->type() == QPaintEngine::Raster
- && (devType == QInternal::Widget ||
- devType == QInternal::Pixmap ||
- devType == QInternal::Image)) {
-
- const QImage *image = static_cast<const QImage *>(paintEngine->paintDevice());
- QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
- context = CGBitmapContextCreate((void *)image->bits(), image->width(), image->height(), 8,
- image->bytesPerLine(), colorSpace, qt_mac_bitmapInfoForImage(*image));
-
- // Invert y axis
- CGContextTranslateCTM(context, 0, image->height());
- CGContextScaleCTM(context, 1, -1);
-
- const qreal devicePixelRatio = image->devicePixelRatio();
-
- if (devType == QInternal::Widget) {
- // Set the clip rect which is an intersection of the system clip
- // and the painter clip. To make matters more interesting these
- // are in device pixels and device-independent pixels, respectively.
- QRegion clip = painter->paintEngine()->systemClip(); // get system clip in device pixels
- QTransform native = painter->deviceTransform(); // get device transform. dx/dy is in device pixels
-
- if (painter->hasClipping()) {
- QRegion r = painter->clipRegion(); // get painter clip, which is in device-independent pixels
- qt_mac_scale_region(&r, devicePixelRatio); // scale painter clip to device pixels
- r.translate(native.dx(), native.dy());
- if (clip.isEmpty())
- clip = r;
- else
- clip &= r;
- }
- qt_mac_clip_cg(context, clip, 0); // clip in device pixels
-
- // Scale the context so that painting happens in device-independent pixels
- CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
- CGContextTranslateCTM(context, native.dx() / devicePixelRatio, native.dy() / devicePixelRatio);
- } else {
- // Scale to paint in device-independent pixels
- CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
+ if (paintEngine->type() != QPaintEngine::Raster) {
+ qWarning() << "QMacCGContext:: Unsupported paint engine type" << paintEngine->type();
+ return;
+ }
+
+ // The raster paint engine always operates on a QImage
+ Q_ASSERT(paintEngine->paintDevice()->devType() == QInternal::Image);
+
+ // On behalf of one of these supported painter devices
+ switch (int painterDeviceType = painter->device()->devType()) {
+ case QInternal::Pixmap:
+ case QInternal::Image:
+ case QInternal::Widget:
+ break;
+ default:
+ qWarning() << "QMacCGContext:: Unsupported paint device type" << painterDeviceType;
+ return;
+ }
+
+ // Applying the clip is so entangled with the rest of the context setup
+ // that for simplicity we just pass in the painter.
+ initialize(static_cast<const QImage *>(paintEngine->paintDevice()), painter);
+}
+
+void QMacCGContext::initialize(const QImage *image, QPainter *painter)
+{
+ QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
+ context = CGBitmapContextCreate((void *)image->bits(), image->width(), image->height(), 8,
+ image->bytesPerLine(), colorSpace, qt_mac_bitmapInfoForImage(*image));
+
+ // Invert y axis
+ CGContextTranslateCTM(context, 0, image->height());
+ CGContextScaleCTM(context, 1, -1);
+
+ const qreal devicePixelRatio = image->devicePixelRatio();
+
+ if (painter && painter->device()->devType() == QInternal::Widget) {
+ // Set the clip rect which is an intersection of the system clip and the painter clip
+ QRegion clip = painter->paintEngine()->systemClip();
+ QTransform deviceTransform = painter->deviceTransform();
+
+ if (painter->hasClipping()) {
+ // To make matters more interesting the painter clip is in device-independent pixels,
+ // so we need to scale it to match the device-pixels of the system clip.
+ QRegion painterClip = painter->clipRegion();
+ qt_mac_scale_region(&painterClip, devicePixelRatio);
+
+ painterClip.translate(deviceTransform.dx(), deviceTransform.dy());
+
+ if (clip.isEmpty())
+ clip = painterClip;
+ else
+ clip &= painterClip;
}
- } else {
- qDebug() << "QMacCGContext:: Unsupported painter devtype type" << devType;
+
+ qt_mac_clip_cg(context, clip, 0);
+
+ CGContextTranslateCTM(context, deviceTransform.dx(), deviceTransform.dy());
}
+
+ // Scale the context so that painting happens in device-independent pixels
+ CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qcoregraphics_p.h b/src/gui/painting/qcoregraphics_p.h
index 868c2b08b5..ba2cde8325 100644
--- a/src/gui/painting/qcoregraphics_p.h
+++ b/src/gui/painting/qcoregraphics_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
+#include <QtCore/private/qcore_mac_p.h>
+
#include <QtGui/private/qtguiglobal_p.h>
#include <QtGui/qregion.h>
#include <QtGui/qpalette.h>
@@ -89,38 +91,16 @@ Q_GUI_EXPORT QBrush qt_mac_toQBrush(CGColorRef color);
class Q_GUI_EXPORT QMacCGContext
{
public:
- inline QMacCGContext() { context = 0; }
+ QMacCGContext() = default;
QMacCGContext(QPaintDevice *pdev);
QMacCGContext(QPainter *p);
- inline QMacCGContext(CGContextRef cg, bool takeOwnership = false) {
- context = cg;
- if (!takeOwnership)
- CGContextRetain(context);
- }
- inline QMacCGContext(const QMacCGContext &copy) : context(0) { *this = copy; }
- inline ~QMacCGContext() {
- if (context)
- CGContextRelease(context);
- }
- inline bool isNull() const { return context; }
- inline operator CGContextRef() { return context; }
- inline QMacCGContext &operator=(const QMacCGContext &copy) {
- if (context)
- CGContextRelease(context);
- context = copy.context;
- CGContextRetain(context);
- return *this;
- }
- inline QMacCGContext &operator=(CGContextRef cg) {
- if (context)
- CGContextRelease(context);
- context = cg;
- CGContextRetain(context); //we do not take ownership
- return *this;
- }
+
+ operator CGContextRef() { return context; }
private:
- CGContextRef context;
+ void initialize(QPaintDevice *paintDevice);
+ void initialize(const QImage *, QPainter *painter = nullptr);
+ QCFType<CGContextRef> context;
};
QT_END_NAMESPACE
diff --git a/src/gui/util/qshaderformat.cpp b/src/gui/util/qshaderformat.cpp
index 324d84ffe1..ea86dd6ca5 100644
--- a/src/gui/util/qshaderformat.cpp
+++ b/src/gui/util/qshaderformat.cpp
@@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE
QShaderFormat::QShaderFormat() noexcept
: m_api(NoApi)
+ , m_shaderType(Fragment)
{
}
@@ -106,6 +107,9 @@ bool QShaderFormat::supports(const QShaderFormat &other) const noexcept
if (m_version < other.m_version)
return false;
+ if (m_shaderType != other.m_shaderType)
+ return false;
+
const auto containsAllExtensionsFromOther = std::includes(m_extensions.constBegin(),
m_extensions.constEnd(),
other.m_extensions.constBegin(),
@@ -119,12 +123,23 @@ bool QShaderFormat::supports(const QShaderFormat &other) const noexcept
return true;
}
+QShaderFormat::ShaderType QShaderFormat::shaderType() const Q_DECL_NOTHROW
+{
+ return m_shaderType;
+}
+
+void QShaderFormat::setShaderType(QShaderFormat::ShaderType shaderType) Q_DECL_NOTHROW
+{
+ m_shaderType = shaderType;
+}
+
bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept
{
return lhs.api() == rhs.api()
&& lhs.version() == rhs.version()
&& lhs.extensions() == rhs.extensions()
- && lhs.vendor() == rhs.vendor();
+ && lhs.vendor() == rhs.vendor()
+ && lhs.shaderType() == rhs.shaderType();
}
QT_END_NAMESPACE
diff --git a/src/gui/util/qshaderformat_p.h b/src/gui/util/qshaderformat_p.h
index 84bf71fdb6..c50d7d5729 100644
--- a/src/gui/util/qshaderformat_p.h
+++ b/src/gui/util/qshaderformat_p.h
@@ -69,6 +69,15 @@ public:
OpenGLES
};
+ enum ShaderType : int {
+ Vertex = 0,
+ TessellationControl,
+ TessellationEvaluation,
+ Geometry,
+ Fragment,
+ Compute
+ };
+
Q_GUI_EXPORT QShaderFormat() noexcept;
Q_GUI_EXPORT Api api() const noexcept;
@@ -86,11 +95,15 @@ public:
Q_GUI_EXPORT bool isValid() const noexcept;
Q_GUI_EXPORT bool supports(const QShaderFormat &other) const noexcept;
+ Q_GUI_EXPORT ShaderType shaderType() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setShaderType(ShaderType shaderType) Q_DECL_NOTHROW;
+
private:
Api m_api;
QVersionNumber m_version;
QStringList m_extensions;
QString m_vendor;
+ ShaderType m_shaderType;
};
Q_GUI_EXPORT bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept;
diff --git a/src/gui/util/qshadergenerator.cpp b/src/gui/util/qshadergenerator.cpp
index 60cf5a2fc5..205118f41c 100644
--- a/src/gui/util/qshadergenerator.cpp
+++ b/src/gui/util/qshadergenerator.cpp
@@ -40,6 +40,7 @@
#include "qshadergenerator_p.h"
#include "qshaderlanguage_p.h"
+#include <QRegularExpression>
QT_BEGIN_NAMESPACE
@@ -56,7 +57,10 @@ namespace
case QShaderLanguage::Const:
return "const";
case QShaderLanguage::Input:
- return "varying";
+ if (format.shaderType() == QShaderFormat::Vertex)
+ return "attribute";
+ else
+ return "varying";
case QShaderLanguage::Output:
return ""; // Although fragment shaders for <=2 only have fixed outputs
case QShaderLanguage::Uniform:
@@ -314,12 +318,22 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
[enabledLayers] (const QString &s) { return enabledLayers.contains(s); });
};
+ QVector<QString> globalInputVariables;
+ const QRegularExpression globalInputExtractRegExp(QStringLiteral("^.*\\s+(\\w+).*;$"));
+
const QVector<QShaderNode> nodes = graph.nodes();
for (const QShaderNode &node : nodes) {
if (intersectsEnabledLayers(node.layers())) {
const QByteArrayList headerSnippets = node.rule(format).headerSnippets;
for (const QByteArray &snippet : headerSnippets) {
code << replaceParameters(snippet, node, format);
+
+ // If node is an input, record the variable name into the globalInputVariables vector
+ if (node.type() == QShaderNode::Input) {
+ const QRegularExpressionMatch match = globalInputExtractRegExp.match(QString::fromUtf8(code.last()));
+ if (match.hasMatch())
+ globalInputVariables.push_back(match.captured(1));
+ }
}
}
}
@@ -328,6 +342,14 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
code << QByteArrayLiteral("void main()");
code << QByteArrayLiteral("{");
+ // Table to store temporary variables that should be replaced by global
+ // variables. This avoids having vec3 v56 = vertexPosition; when we could
+ // just use vertexPosition directly.
+ // The added benefit is when having arrays, we don't try to create
+ // mat4 v38 = skinningPalelette[100] which would be invalid
+ QHash<QString, QString> localReferencesToGlobalInputs;
+ const QRegularExpression localToGlobalRegExp(QStringLiteral("^.*\\s+(\\w+)\\s*=\\s*(\\w+).*;$"));
+
for (const QShaderGraph::Statement &statement : graph.createStatements(enabledLayers)) {
const QShaderNode node = statement.node;
QByteArray line = node.rule(format).substitution;
@@ -338,6 +360,9 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
const bool isInput = port.direction == QShaderNodePort::Input;
const int portIndex = statement.portIndex(portDirection, portName);
+
+ Q_ASSERT(portIndex >= 0);
+
const int variableIndex = isInput ? statement.inputs.at(portIndex)
: statement.outputs.at(portIndex);
if (variableIndex < 0)
@@ -345,15 +370,51 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
const auto placeholder = QByteArray(QByteArrayLiteral("$") + portName.toUtf8());
const auto variable = QByteArray(QByteArrayLiteral("v") + QByteArray::number(variableIndex));
+
line.replace(placeholder, variable);
}
- code << QByteArrayLiteral(" ") + replaceParameters(line, node, format);
+ const QByteArray substitutionedLine = replaceParameters(line, node, format);
+
+ // Record name of temporary variable that possibly references a global input
+ // We will replace the temporary variables by the matching global variables later
+ bool isAGlobalInputVariable = false;
+ if (node.type() == QShaderNode::Input) {
+ const QRegularExpressionMatch match = localToGlobalRegExp.match(QString::fromUtf8(substitutionedLine));
+ if (match.hasMatch()) {
+ const QString globalVariable = match.captured(2);
+ if (globalInputVariables.contains(globalVariable)) {
+ const QString localVariable = match.captured(1);
+ // TO DO: Clean globalVariable (remove brackets ...)
+ localReferencesToGlobalInputs.insert(localVariable, globalVariable);
+ isAGlobalInputVariable = true;
+ }
+ }
+ }
+
+ // Only insert content for lines aren't inputs or have not matching
+ // globalVariables for now
+ if (!isAGlobalInputVariable)
+ code << QByteArrayLiteral(" ") + substitutionedLine;
}
code << QByteArrayLiteral("}");
code << QByteArray();
- return code.join('\n');
+
+ // Replace occurrences of local variables which reference a global variable
+ // by the global variables directly
+ auto it = localReferencesToGlobalInputs.cbegin();
+ const auto end = localReferencesToGlobalInputs.cend();
+ QString codeString = QString::fromUtf8(code.join('\n'));
+
+ while (it != end) {
+ const QRegularExpression r(QStringLiteral("\\b(%1)([\\b|\\.|;|\\)|\\[|\\s|\\*|\\+|\\/|\\-|,])").arg(it.key()),
+ QRegularExpression::MultilineOption);
+ codeString.replace(r, QStringLiteral("%1\\2").arg(it.value()));
+ ++it;
+ }
+
+ return codeString.toUtf8();
}
QT_END_NAMESPACE
diff --git a/src/gui/util/qshadernodesloader.cpp b/src/gui/util/qshadernodesloader.cpp
index af565c906d..922479332c 100644
--- a/src/gui/util/qshadernodesloader.cpp
+++ b/src/gui/util/qshadernodesloader.cpp
@@ -251,6 +251,17 @@ void QShaderNodesLoader::load(const QJsonObject &prototypesObject)
break;
}
+ // We default out to a Fragment ShaderType if nothing is specified
+ // as that was the initial behavior we introduced
+ const QString shaderType = formatObject.value(QStringLiteral("shaderType")).toString();
+ format.setShaderType(shaderType == QStringLiteral("Fragment") ? QShaderFormat::Fragment
+ : shaderType == QStringLiteral("Vertex") ? QShaderFormat::Vertex
+ : shaderType == QStringLiteral("TessellationControl") ? QShaderFormat::TessellationControl
+ : shaderType == QStringLiteral("TessellationEvaluation") ? QShaderFormat::TessellationEvaluation
+ : shaderType == QStringLiteral("Geometry") ? QShaderFormat::Geometry
+ : shaderType == QStringLiteral("Compute") ? QShaderFormat::Compute
+ : QShaderFormat::Fragment);
+
const QByteArray substitution = substitutionValue.toString().toUtf8();
const QJsonValue snippetsValue = ruleObject.value(QStringLiteral("headerSnippets"));
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index 644f4336ca..b54fb349fb 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -385,8 +385,8 @@ QHostAddress QNetmask::address(QAbstractSocket::NetworkLayerProtocol protocol) c
\value LocalHost The IPv4 localhost address. Equivalent to QHostAddress("127.0.0.1").
\value LocalHostIPv6 The IPv6 localhost address. Equivalent to QHostAddress("::1").
\value Broadcast The IPv4 broadcast address. Equivalent to QHostAddress("255.255.255.255").
- \value AnyIPv4 The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). A socket bound with this address will listen only on IPv4 interaces.
- \value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::"). A socket bound with this address will listen only on IPv6 interaces.
+ \value AnyIPv4 The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). A socket bound with this address will listen only on IPv4 interfaces.
+ \value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::"). A socket bound with this address will listen only on IPv6 interfaces.
\value Any The dual stack any-address. A socket bound with this address will listen on both IPv4 and IPv6 interfaces.
*/
diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp
index 020d035bf7..5ee4773b70 100644
--- a/src/platformsupport/eglconvenience/qeglconvenience.cpp
+++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp
@@ -268,7 +268,7 @@ EGLConfig QEglConfigChooser::chooseConfig()
configureAttributes.append(EGL_OPENGL_ES_BIT);
break;
}
- // fall through
+ Q_FALLTHROUGH();
default:
needsES2Plus = true;
break;
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
index c0e528f922..94def16748 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
@@ -134,7 +134,7 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform
void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
{
- m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig);
+ m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig, format);
// m_format now has the renderableType() resolved (it cannot be Default anymore)
// but does not yet contain version, profile, options.
m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0;
@@ -248,6 +248,12 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon
value = 0;
eglQueryContext(m_eglDisplay, context, EGL_CONTEXT_CLIENT_TYPE, &value);
if (value == EGL_OPENGL_API || value == EGL_OPENGL_ES_API) {
+ // if EGL config supports both OpenGL and OpenGL ES render type,
+ // q_glFormatFromConfig() with the default "referenceFormat" parameter
+ // will always figure it out as OpenGL render type.
+ // We can override it to match user's real render type.
+ if (value == EGL_OPENGL_ES_API)
+ m_format.setRenderableType(QSurfaceFormat::OpenGLES);
m_api = value;
eglBindAPI(m_api);
} else {
diff --git a/src/platformsupport/glxconvenience/glxconvenience.pro b/src/platformsupport/glxconvenience/glxconvenience.pro
index 8367dc5e31..1b9cf79080 100644
--- a/src/platformsupport/glxconvenience/glxconvenience.pro
+++ b/src/platformsupport/glxconvenience/glxconvenience.pro
@@ -6,7 +6,7 @@ CONFIG += static internal_module
DEFINES += QT_NO_CAST_FROM_ASCII
-QMAKE_USE_PRIVATE += xlib
+QMAKE_USE += xlib
HEADERS += qglxconvenience_p.h
SOURCES += qglxconvenience.cpp
diff --git a/src/platformsupport/input/tslib/qtslib.cpp b/src/platformsupport/input/tslib/qtslib.cpp
index c4caea5c80..df57147af6 100644
--- a/src/platformsupport/input/tslib/qtslib.cpp
+++ b/src/platformsupport/input/tslib/qtslib.cpp
@@ -96,8 +96,8 @@ void QTsLibMouseHandler::readMouseData()
int x = sample.x;
int y = sample.y;
- // work around missing coordinates on mouse release
- if (sample.pressure == 0 && sample.x == 0 && sample.y == 0) {
+ // coordinates on release events can contain arbitrary values, just ignore them
+ if (sample.pressure == 0) {
x = m_x;
y = m_y;
}
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
index 4b27522976..5838c43eca 100644
--- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp
+++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
@@ -59,6 +59,7 @@ enum OutputConfiguration {
OutputConfigOff,
OutputConfigPreferred,
OutputConfigCurrent,
+ OutputConfigSkip,
OutputConfigMode,
OutputConfigModeline
};
@@ -191,6 +192,8 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
configuration = OutputConfigPreferred;
} else if (mode == "current") {
configuration = OutputConfigCurrent;
+ } else if (mode == "skip") {
+ configuration = OutputConfigSkip;
} else if (sscanf(mode.constData(), "%dx%d@%d", &configurationSize.rwidth(), &configurationSize.rheight(),
&configurationRefresh) == 3)
{
@@ -229,6 +232,11 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
return nullptr;
}
+ if (configuration == OutputConfigSkip) {
+ qCDebug(qLcKmsDebug) << "Skipping output" << connectorName;
+ return nullptr;
+ }
+
// Get the current mode on the current crtc
drmModeModeInfo crtc_mode;
memset(&crtc_mode, 0, sizeof crtc_mode);
diff --git a/src/platformsupport/platformcompositor/qopenglcompositor.cpp b/src/platformsupport/platformcompositor/qopenglcompositor.cpp
index 0f4946f81a..635bf0107f 100644
--- a/src/platformsupport/platformcompositor/qopenglcompositor.cpp
+++ b/src/platformsupport/platformcompositor/qopenglcompositor.cpp
@@ -188,14 +188,15 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
topLeftRect.width(), topLeftRect.height());
}
-static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &targetWindowRect,
+static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &sourceWindowRect,
+ const QRect &targetWindowRect,
QOpenGLTextureBlitter *blitter, QMatrix4x4 *rotationMatrix)
{
const QRect clipRect = textures->clipRect(idx);
if (clipRect.isEmpty())
return;
- const QRect rectInWindow = textures->geometry(idx);
+ const QRect rectInWindow = textures->geometry(idx).translated(sourceWindowRect.topLeft());
const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft());
const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height());
@@ -218,7 +219,7 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
const QRect targetWindowRect(QPoint(0, 0), m_targetWindow->geometry().size());
float currentOpacity = 1.0f;
BlendStateBinder blend;
-
+ const QRect sourceWindowRect = window->sourceWindow()->geometry();
for (int i = 0; i < textures->count(); ++i) {
uint textureId = textures->textureId(i);
const float opacity = window->sourceWindow()->opacity();
@@ -243,16 +244,16 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
target = m_rotationMatrix * target;
m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
} else if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
- // Texture from an FBO belonging to a QOpenGLWidget
+ // Texture from an FBO belonging to a QOpenGLWidget or QQuickWidget
blend.set(false);
- clippedBlit(textures, i, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr);
+ clippedBlit(textures, i, sourceWindowRect, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr);
}
}
for (int i = 0; i < textures->count(); ++i) {
if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
blend.set(true);
- clippedBlit(textures, i, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr);
+ clippedBlit(textures, i, sourceWindowRect, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr);
}
}
diff --git a/src/plugins/bearer/generic/qgenericengine.cpp b/src/plugins/bearer/generic/qgenericengine.cpp
index 7472758418..b1f28849a7 100644
--- a/src/plugins/bearer/generic/qgenericengine.cpp
+++ b/src/plugins/bearer/generic/qgenericengine.cpp
@@ -300,7 +300,7 @@ void QGenericEngine::doRequestUpdate()
if (interface.flags() & QNetworkInterface::IsLoopBack)
continue;
-#ifndef Q_OS_WINRT
+#ifndef Q_OS_WIN
// ignore WLAN interface handled in separate engine
if (qGetInterfaceType(interface.name()) == QNetworkConfiguration::BearerWLAN)
continue;
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index 508f24d578..6f24598250 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -93,6 +93,7 @@ private:
QRegion dirtyRegion; // In unscaled coordinates
QImage *asImage();
+ qreal devicePixelRatio() const { return m_devicePixelRatio; }
private:
qreal m_devicePixelRatio;
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 8e4e928bc5..d42a723b47 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -460,12 +460,29 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region,
NSView *backingStoreView = static_cast<QCocoaWindow *>(window()->handle())->view();
NSView *flushedView = static_cast<QCocoaWindow *>(flushedWindow->handle())->view();
+ // If the backingstore is just flushed, without being painted to first, then we may
+ // end in a situation where the backingstore is flushed to a layer with a different
+ // scale factor than the one it was created for in beginPaint. This is the client's
+ // fault in not picking up the change in scale factor of the window and re-painting
+ // the backingstore accordingly. To smoothing things out, we warn about this situation,
+ // and change the layer's contentsScale to match the scale of the back buffer, so that
+ // we at least cover the whole layer. This is necessary since we set the view's
+ // contents placement policy to NSViewLayerContentsPlacementTopLeft, which means
+ // AppKit will not do any scaling on our behalf.
+ if (m_buffers.back()->devicePixelRatio() != flushedView.layer.contentsScale) {
+ qCWarning(lcQpaBackingStore) << "Back buffer dpr of" << m_buffers.back()->devicePixelRatio()
+ << "doesn't match" << flushedView.layer << "contents scale of" << flushedView.layer.contentsScale
+ << "- updating layer to match.";
+ flushedView.layer.contentsScale = m_buffers.back()->devicePixelRatio();
+ }
+
id backBufferSurface = (__bridge id)m_buffers.back()->surface();
if (flushedView.layer.contents == backBufferSurface) {
// We've managed to paint to the back buffer again before Core Animation had time
- // to flush the transaction and persist the layer changes to the window server.
- // The layer already knows about the back buffer, and we don't need to re-apply
- // it to pick up the surface changes, so bail out early.
+ // to flush the transaction and persist the layer changes to the window server, or
+ // we've been asked to flush without painting anything. The layer already knows about
+ // the back buffer, and we don't need to re-apply it to pick up any possible surface
+ // changes, so bail out early.
qCInfo(lcQpaBackingStore).nospace() << "Skipping flush of " << flushedView
<< ", layer already reflects back buffer";
return;
diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm
index cb1799b039..69d36ef61e 100644
--- a/src/plugins/platforms/cocoa/qnsview_drawing.mm
+++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm
@@ -154,6 +154,7 @@
<< "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested"
: [self shouldUseMetalLayer] ? "needed by surface type" : "enabled by macOS");
[super setLayer:layer];
+ layer.delegate = self;
}
- (NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy
diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
index 48469b0f8c..c8a1ddf9b9 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
@@ -199,6 +199,10 @@ QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const
QEglFSWindow *w = qt_egl_device_integration()->createWindow(window);
w->create();
+ const auto showWithoutActivating = window->property("_q_showWithoutActivating");
+ if (showWithoutActivating.isValid() && showWithoutActivating.toBool())
+ return w;
+
// Activate only the window for the primary screen to make input work
if (window->type() != Qt::ToolTip && window->screen() == QGuiApplication::primaryScreen())
w->requestActivateWindow();
diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp
index 98e9ee4728..c1d5af47aa 100644
--- a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp
@@ -167,6 +167,9 @@ void QEglFSWindow::create()
void QEglFSWindow::destroy()
{
+ if (!m_flags.testFlag(Created))
+ return; // already destroyed
+
#ifndef QT_NO_OPENGL
QOpenGLCompositor::instance()->removeWindow(this);
#endif
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h
index a19cf7e8bc..ee4b7978f1 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h
@@ -55,6 +55,9 @@ public:
: QEglFSWindow(w),
m_integration(integration)
{ }
+
+ ~QEglFSKmsGbmWindow() { destroy(); }
+
void resetSurface() override;
void invalidateSurface() override;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
index ef732f9832..2c6b4245b7 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
@@ -117,6 +117,8 @@ public:
, m_framePending(false)
{ }
+ ~QEglFSKmsEglDeviceWindow() { destroy(); }
+
void invalidateSurface() override;
void resetSurface() override;
void flip();
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp
index 0d9b6b6290..d1250ec9bf 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp
@@ -205,6 +205,9 @@ public:
: QEglFSWindow(w)
, m_integration(integration)
{}
+
+ ~QEglFSKmsVsp2Window() { destroy(); }
+
void resetSurface() override;
void invalidateSurface() override;
const QEglFSKmsVsp2Integration *m_integration;
diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp
index 229ff92894..e1a41c0ede 100644
--- a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp
+++ b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp
@@ -41,6 +41,7 @@
#include <QtCore/qurl.h>
#include <QtCore/qmimedata.h>
+#include "qwindowsmime.h"
QT_BEGIN_NAMESPACE
@@ -48,8 +49,9 @@ QT_BEGIN_NAMESPACE
\class QWindowsDropDataObject
\brief QWindowsOleDataObject subclass specialized for handling Drag&Drop.
- Only allows "text/uri-list" data to be exported as CF_HDROP, to allow dropped
- files to be attached to Office applications (instead of adding an URL link).
+ Prevents "text/uri-list" data for local files from being exported as text
+ or URLs, to allow dropped files to be attached to Office applications
+ (instead of creating local hyperlinks).
\internal
\ingroup qt-lighthouse-win
@@ -80,14 +82,22 @@ QWindowsDropDataObject::QueryGetData(LPFORMATETC pformatetc)
return QWindowsOleDataObject::QueryGetData(pformatetc);
}
-// If the data is text/uri-list for local files, tell we can only export it as CF_HDROP.
+// If the data is "text/uri-list" only, and all URIs are for local files,
+// we prevent it from being exported as text or URLs, to make target applications
+// like MS Office attach or open the files instead of creating local hyperlinks.
bool QWindowsDropDataObject::shouldIgnore(LPFORMATETC pformatetc) const
{
QMimeData *dropData = mimeData();
- if (dropData && dropData->hasFormat(QStringLiteral("text/uri-list")) && (pformatetc->cfFormat != CF_HDROP)) {
- QList<QUrl> urls = dropData->urls();
- return std::any_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); });
+ if (dropData && dropData->formats().size() == 1 && dropData->hasUrls()) {
+ QString formatName = QWindowsMimeConverter::clipboardFormatName(pformatetc->cfFormat);
+ if (pformatetc->cfFormat == CF_UNICODETEXT
+ || pformatetc->cfFormat == CF_TEXT
+ || formatName == QStringLiteral("UniformResourceLocator")
+ || formatName == QStringLiteral("UniformResourceLocatorW")) {
+ QList<QUrl> urls = dropData->urls();
+ return std::all_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); });
+ }
}
return false;
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index c050369801..c5af4d8042 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -879,21 +879,16 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con
#if defined(WM_APPCOMMAND)
const int cmd = GET_APPCOMMAND_LPARAM(msg.lParam);
// QTBUG-57198, do not send mouse-synthesized commands as key events in addition
+ bool skipPressRelease = false;
switch (GET_DEVICE_LPARAM(msg.lParam)) {
case FAPPCOMMAND_MOUSE:
return false;
case FAPPCOMMAND_KEY:
- // QTBUG-62838, swallow WM_KEYDOWN, WM_KEYUP for commands that are
- // reflected in VK(s) like VK_MEDIA_NEXT_TRACK. Don't do that for
- // APPCOMMAND_BROWSER_HOME as that one does not trigger two events
- if (cmd != APPCOMMAND_BROWSER_HOME) {
- MSG peekedMsg;
- if (PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_NOREMOVE)
- && peekedMsg.message == WM_KEYDOWN) {
- PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_REMOVE);
- PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_REMOVE);
- }
- }
+ // QTBUG-62838, use WM_KEYDOWN/WM_KEYUP for commands that are reflected
+ // in VK(s) like VK_MEDIA_NEXT_TRACK, to get correct codes and autorepeat.
+ // Don't do that for APPCOMMAND_BROWSER_HOME as that one does not trigger two events.
+ if (cmd != APPCOMMAND_BROWSER_HOME)
+ skipPressRelease = true;
break;
}
@@ -908,7 +903,8 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con
return false;
const int qtKey = int(CmdTbl[cmd]);
- sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
+ if (!skipPressRelease)
+ sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
// QTBUG-43343: Make sure to return false if Qt does not handle the key, otherwise,
// the keys are not passed to the active media player.
# if QT_CONFIG(shortcut)
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 96e34fb44c..030d8d1e0f 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -1087,7 +1087,10 @@ bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMi
const QImage image = qvariant_cast<QImage>(mimeData->imageData());
if (image.isNull())
return false;
- return cf == CF_DIBV5 || (cf == CF_DIB) || cf == int(CF_PNG);
+ // QTBUG-64322: Use PNG only for transparent images as otherwise MS PowerPoint
+ // cannot handle it.
+ return cf == CF_DIBV5 || cf == CF_DIB
+ || (cf == int(CF_PNG) && image.hasAlphaChannel());
}
bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index f1960f1585..9a8b5d5121 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -250,6 +250,23 @@ static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState)
return result;
}
+static Qt::MouseButtons queryMouseButtons()
+{
+ Qt::MouseButtons result = Qt::NoButton;
+ const bool mouseSwapped = GetSystemMetrics(SM_SWAPBUTTON);
+ if (GetAsyncKeyState(VK_LBUTTON) < 0)
+ result |= mouseSwapped ? Qt::RightButton: Qt::LeftButton;
+ if (GetAsyncKeyState(VK_RBUTTON) < 0)
+ result |= mouseSwapped ? Qt::LeftButton : Qt::RightButton;
+ if (GetAsyncKeyState(VK_MBUTTON) < 0)
+ result |= Qt::MidButton;
+ if (GetAsyncKeyState(VK_XBUTTON1) < 0)
+ result |= Qt::XButton1;
+ if (GetAsyncKeyState(VK_XBUTTON2) < 0)
+ result |= Qt::XButton2;
+ return result;
+}
+
static QWindow *getWindowUnderPointer(QWindow *window, QPoint globalPos)
{
QWindow *currentWindowUnderPointer = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
@@ -531,7 +548,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
return false;
- const quint32 pointerId = penInfo->pointerInfo.pointerId;
+ const qint64 sourceDevice = (qint64)penInfo->pointerInfo.sourceDevice;
const QPoint globalPos = QPoint(penInfo->pointerInfo.ptPixelLocation.x, penInfo->pointerInfo.ptPixelLocation.y);
const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
const QPointF hiResGlobalPos = QPointF(dRect.left + qreal(penInfo->pointerInfo.ptHimetricLocation.x - pRect.left)
@@ -547,7 +564,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaEvents).noquote().nospace() << showbase
- << __FUNCTION__ << " pointerId=" << pointerId
+ << __FUNCTION__ << " sourceDevice=" << sourceDevice
<< " globalPos=" << globalPos << " localPos=" << localPos << " hiResGlobalPos=" << hiResGlobalPos
<< " message=" << hex << msg.message
<< " flags=" << hex << penInfo->pointerInfo.pointerFlags;
@@ -570,7 +587,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
switch (msg.message) {
case WM_POINTERENTER: {
- QWindowSystemInterface::handleTabletEnterProximityEvent(device, type, pointerId);
+ QWindowSystemInterface::handleTabletEnterProximityEvent(device, type, sourceDevice);
m_windowUnderPointer = window;
// The local coordinates may fall outside the window.
// Wait until the next update to send the enter event.
@@ -583,12 +600,12 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
m_windowUnderPointer = nullptr;
m_currentWindow = nullptr;
}
- QWindowSystemInterface::handleTabletLeaveProximityEvent(device, type, pointerId);
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(device, type, sourceDevice);
break;
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE: {
- QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(pointerId).target; // Pass to window that grabbed it.
+ QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(sourceDevice).target; // Pass to window that grabbed it.
if (!target && m_windowUnderPointer)
target = m_windowUnderPointer;
if (!target)
@@ -607,7 +624,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons,
pressure, xTilt, yTilt, tangentialPressure, rotation, z,
- pointerId, keyModifiers);
+ sourceDevice, keyModifiers);
return false; // Allow mouse messages to be generated.
}
}
@@ -681,7 +698,6 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
}
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
- const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
if (et == QtWindows::MouseWheelEvent)
@@ -709,7 +725,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
const MouseEvent mouseEvent = eventFromMsg(msg);
if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) {
- QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons,
+ const Qt::MouseButtons nonclientButtons = queryMouseButtons();
+ QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, nonclientButtons,
mouseEvent.button, mouseEvent.type, keyModifiers, source);
return false; // Allow further event processing
}
@@ -725,6 +742,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
return true;
}
+ const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
+
handleCaptureRelease(window, currentWindowUnderPointer, hwnd, mouseEvent.type, mouseButtons);
handleEnterLeave(window, currentWindowUnderPointer, globalPos);
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
index 85a931e015..c7c0deab3f 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
@@ -113,6 +113,9 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
case QAccessible::ValueChanged:
QWindowsUiaMainProvider::notifyValueChange(static_cast<QAccessibleValueChangeEvent *>(event));
break;
+ case QAccessible::SelectionAdd:
+ QWindowsUiaMainProvider::notifySelectionChange(event);
+ break;
case QAccessible::TextAttributeChanged:
case QAccessible::TextColumnChanged:
case QAccessible::TextInserted:
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index fad83fb165..44328492a6 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -146,9 +146,33 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *event)
{
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
- if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
- // Notifies changes in values of controls supporting the value interface.
+ if (accessible->role() == QAccessible::ComboBox && accessible->childCount() > 0) {
+ QAccessibleInterface *listacc = accessible->child(0);
+ if (listacc && listacc->role() == QAccessible::List) {
+ int count = listacc->childCount();
+ for (int i = 0; i < count; ++i) {
+ QAccessibleInterface *item = listacc->child(i);
+ if (item && item->text(QAccessible::Name) == event->value()) {
+ if (!item->state().selected) {
+ if (QAccessibleActionInterface *actionInterface = item->actionInterface())
+ actionInterface->doAction(QAccessibleActionInterface::toggleAction());
+ }
+ break;
+ }
+ }
+ }
+ }
+ if (event->value().type() == QVariant::String) {
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ // Notifies changes in string values.
+ VARIANT oldVal, newVal;
+ clearVariant(&oldVal);
+ setVariantString(event->value().toString(), &newVal);
+ QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
+ }
+ } else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ // Notifies changes in values of controls supporting the value interface.
VARIANT oldVal, newVal;
clearVariant(&oldVal);
setVariantDouble(valueInterface->currentValue().toDouble(), &newVal);
@@ -158,6 +182,15 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
}
}
+void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_SelectionItem_ElementSelectedEventId);
+ }
+ }
+}
+
// Notifies changes in text content and selection state of text controls.
void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
{
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
index 325d5b3de4..df0d60f9c9 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
@@ -68,6 +68,7 @@ public:
static void notifyFocusChange(QAccessibleEvent *event);
static void notifyStateChange(QAccessibleStateChangeEvent *event);
static void notifyValueChange(QAccessibleValueChangeEvent *event);
+ static void notifySelectionChange(QAccessibleEvent *event);
static void notifyTextChange(QAccessibleEvent *event);
// IUnknown
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
index 476de6d1e5..4adf662152 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -270,7 +270,9 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
// ES does not support any format option
m_format.setOptions(QSurfaceFormat::FormatOptions());
}
-
+ // Robustness must match that of the shared context.
+ if (share && share->format().testOption(QSurfaceFormat::ResetNotification))
+ m_format.setOption(QSurfaceFormat::ResetNotification);
Q_ASSERT(glVersions.count() > 0);
for (int i = 0; !m_context && i < glVersions.count(); i++) {
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index d0e05c1e20..6d6648c1fa 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -1156,66 +1156,6 @@ static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QS
}
#endif
-static NSColor *qt_convertColorForContext(CGContextRef context, NSColor *color)
-{
- Q_ASSERT(color);
- Q_ASSERT(context);
-
- CGColorSpaceRef targetCGColorSpace = CGBitmapContextGetColorSpace(context);
- NSColorSpace *targetNSColorSpace = [[NSColorSpace alloc] initWithCGColorSpace:targetCGColorSpace];
- NSColor *adjusted = [color colorUsingColorSpace:targetNSColorSpace];
- [targetNSColorSpace release];
-
- return adjusted;
-}
-
-static NSColor *qt_colorForContext(CGContextRef context, const CGFloat (&rgba)[4])
-{
- Q_ASSERT(context);
-
- auto colorSpace = CGBitmapContextGetColorSpace(context);
- if (!colorSpace)
- return nil;
-
- return qt_convertColorForContext(context, [NSColor colorWithSRGBRed:rgba[0] green:rgba[1] blue:rgba[2] alpha:rgba[3]]);
-}
-
-static void qt_drawDisclosureButton(CGContextRef context, NSInteger state, bool selected, CGRect rect)
-{
- Q_ASSERT(context);
-
- static const CGFloat gray[] = {0.55, 0.55, 0.55, 0.97};
- static const CGFloat white[] = {1.0, 1.0, 1.0, 0.9};
-
- NSColor *fillColor = qt_colorForContext(context, selected ? white : gray);
- [fillColor setFill];
-
- if (state == NSOffState) {
- static NSBezierPath *triangle = [[NSBezierPath alloc] init];
- [triangle removeAllPoints];
- // In off state, a disclosure button is an equilateral triangle
- // ('pointing' to the right) with a bound rect that can be described
- // as NSMakeRect(0, 0, 8, 9). Inside the 'rect' it's translated by
- // (2, 4).
- [triangle moveToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4)];
- [triangle lineToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4 + 9)];
- [triangle lineToPoint:NSMakePoint(rect.origin.x + 2 + 8, rect.origin.y + 4 + 4.5)];
- [triangle closePath];
- [triangle fill];
- } else {
- static NSBezierPath *openTriangle = [[NSBezierPath alloc] init];
- [openTriangle removeAllPoints];
- // In 'on' state, the button is an equilateral triangle (looking down)
- // with the bounding rect NSMakeRect(0, 0, 9, 8). Inside the 'rect'
- // it's translated by (1, 4).
- [openTriangle moveToPoint:NSMakePoint(rect.origin.x + 1, rect.origin.y + 4 + 8)];
- [openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 9, rect.origin.y + 4 + 8)];
- [openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 4.5, rect.origin.y + 4)];
- [openTriangle closePath];
- [openTriangle fill];
- }
-}
-
void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const
{
QPainterPath focusRingPath;
@@ -3301,15 +3241,8 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
CGContextScaleCTM(cg, 1, -1);
CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y);
- if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave && !qt_mac_applicationIsInDarkMode()) {
- // When the real system theme is one of the 'Dark' themes, and an application forces the 'Aqua' theme,
- // under some conditions (see QTBUG-74515 for more details) NSButtonCell seems to select the 'Dark'
- // code path and is becoming transparent, thus 'invisible' on the white background. To workaround this,
- // we draw the disclose triangle manually:
- qt_drawDisclosureButton(cg, triangleCell.state, (opt->state & State_Selected) && viewHasFocus, rect);
- } else {
- [triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
- }
+ [triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
+
d->restoreNSGraphicsContext(cg);
break; }
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index 6e53ea94f3..713f022bdd 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -11343,7 +11343,7 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter)
}
// sourceRect must be in the given coordinate system
-QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
+QRectF QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
{
QRectF effectRectF;
@@ -11371,7 +11371,7 @@ QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem sy
*unpadded = true;
}
- return effectRectF.toAlignedRect();
+ return effectRectF;
}
QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
@@ -11389,7 +11389,8 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
bool unpadded;
const QRectF sourceRect = boundingRect(system);
- QRect effectRect = paddedEffectRect(system, mode, sourceRect, &unpadded);
+ QRectF effectRectF = paddedEffectRect(system, mode, sourceRect, &unpadded);
+ QRect effectRect = effectRectF.toAlignedRect();
if (offset)
*offset = effectRect.topLeft();
@@ -11405,7 +11406,9 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
if (effectRect.isEmpty())
return QPixmap();
- QPixmap pixmap(effectRect.size());
+ const auto dpr = info ? info->painter->device()->devicePixelRatioF() : 1.0;
+ QPixmap pixmap(QRectF(effectRectF.topLeft(), effectRectF.size() * dpr).toAlignedRect().size());
+ pixmap.setDevicePixelRatio(dpr);
pixmap.fill(Qt::transparent);
QPainter pixmapPainter(&pixmap);
pixmapPainter.setRenderHints(info ? info->painter->renderHints() : QPainter::TextAntialiasing);
diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h
index a2c3774f65..92d85f7125 100644
--- a/src/widgets/graphicsview/qgraphicsitem_p.h
+++ b/src/widgets/graphicsview/qgraphicsitem_p.h
@@ -644,7 +644,7 @@ public:
QPixmap pixmap(Qt::CoordinateSystem system,
QPoint *offset,
QGraphicsEffect::PixmapPadMode mode) const override;
- QRect paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = nullptr) const;
+ QRectF paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = nullptr) const;
QGraphicsItem *item;
QGraphicsItemPaintInfo *info;
diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp
index 19d9f25307..3897823e98 100644
--- a/src/widgets/graphicsview/qgraphicsscene.cpp
+++ b/src/widgets/graphicsview/qgraphicsscene.cpp
@@ -4852,7 +4852,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
&& painter->worldTransform().type() <= QTransform::TxTranslate)
{
QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates);
- QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect);
+ QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect).toAlignedRect();
sourced->setCachedOffset(effectRect.topLeft());
} else {
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index 62abf56751..99309633a7 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -2283,13 +2283,15 @@ void QHeaderViewPrivate::_q_sectionsChanged(const QList<QPersistentModelIndex> &
: index.row());
// the new visualIndices are already adjusted / reset by initializeSections()
const int newVisualIndex = visualIndex(newLogicalIndex);
- auto &newSection = sectionItems[newVisualIndex];
- newSection = item.section;
-
- if (newSection.isHidden) {
- // otherwise setSectionHidden will return without doing anything
- newSection.isHidden = false;
- q->setSectionHidden(newLogicalIndex, true);
+ if (newVisualIndex < sectionItems.count()) {
+ auto &newSection = sectionItems[newVisualIndex];
+ newSection = item.section;
+
+ if (newSection.isHidden) {
+ // otherwise setSectionHidden will return without doing anything
+ newSection.isHidden = false;
+ q->setSectionHidden(newLogicalIndex, true);
+ }
}
}
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index a9899983c2..e46d25bef1 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -650,11 +650,13 @@ QListWidgetItem::QListWidgetItem(const QString &text, QListWidget *listview, int
|Qt::ItemIsEnabled
|Qt::ItemIsDragEnabled)
{
+ QListModel *model = listModel();
{
QSignalBlocker b(view);
+ QSignalBlocker bm(model);
setData(Qt::DisplayRole, text);
}
- if (QListModel *model = listModel())
+ if (model)
model->insert(model->rowCount(), this);
}
@@ -683,12 +685,14 @@ QListWidgetItem::QListWidgetItem(const QIcon &icon,const QString &text,
|Qt::ItemIsEnabled
|Qt::ItemIsDragEnabled)
{
+ QListModel *model = listModel();
{
QSignalBlocker b(view);
+ QSignalBlocker bm(model);
setData(Qt::DisplayRole, text);
setData(Qt::DecorationRole, icon);
}
- if (QListModel *model = listModel())
+ if (model)
model->insert(model->rowCount(), this);
}
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index cf15614680..374ea53726 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -1448,7 +1448,8 @@ bool QOpenGLWidget::event(QEvent *e)
{
// Special case: did grabFramebuffer() for a hidden widget that then became visible.
// Recreate all resources since the context now needs to share with the TLW's.
- d->reset();
+ if (!qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts))
+ d->reset();
}
if (!d->initialized && !size().isEmpty() && window()->windowHandle()) {
d->initialize();
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 956c2be3a9..9c744000bd 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -2908,7 +2908,10 @@ void QStyleSheetStyle::polish(QPalette &pal)
void QStyleSheetStyle::repolish(QWidget *w)
{
- QList<const QObject *> children = w->findChildren<const QObject *>(QString());
+ QList<const QObject *> children;
+ children.reserve(w->children().size() + 1);
+ for (auto child: qAsConst(w->children()))
+ children.append(child);
children.append(w);
styleSheetCaches->styleSheetCache.remove(w);
updateObjects(children);
diff --git a/src/widgets/util/qsystemtrayicon_p.h b/src/widgets/util/qsystemtrayicon_p.h
index 5bdf020a47..e31532ea19 100644
--- a/src/widgets/util/qsystemtrayicon_p.h
+++ b/src/widgets/util/qsystemtrayicon_p.h
@@ -69,6 +69,7 @@
QT_BEGIN_NAMESPACE
class QSystemTrayIconSys;
+class QSystemTrayWatcher;
class QPlatformSystemTrayIcon;
class QToolButton;
class QLabel;
@@ -90,6 +91,8 @@ public:
void showMessage_sys(const QString &title, const QString &msg, const QIcon &icon,
QSystemTrayIcon::MessageIcon msgIcon, int msecs);
+ void destroyIcon();
+
static bool isSystemTrayAvailable_sys();
static bool supportsMessages_sys();
@@ -101,6 +104,7 @@ public:
QSystemTrayIconSys *sys;
QPlatformSystemTrayIcon *qpa_sys;
bool visible;
+ QSystemTrayWatcher *trayWatcher;
private:
void install_sys_qpa();
diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp
index 86532456c7..70e5f3678e 100644
--- a/src/widgets/util/qsystemtrayicon_x11.cpp
+++ b/src/widgets/util/qsystemtrayicon_x11.cpp
@@ -92,9 +92,6 @@ protected:
virtual void resizeEvent(QResizeEvent *) override;
virtual void moveEvent(QMoveEvent *) override;
-private slots:
- void systemTrayWindowChanged(QScreen *screen);
-
private:
QSystemTrayIcon *q;
};
@@ -116,15 +113,6 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn)
setMouseTracking(true);
}
-void QSystemTrayIconSys::systemTrayWindowChanged(QScreen *)
-{
- if (!locateSystemTray()) {
- QBalloonTip::hideBalloon();
- hide(); // still no luck
- destroy();
- }
-}
-
QRect QSystemTrayIconSys::globalGeometry() const
{
return QRect(mapToGlobal(QPoint(0, 0)), size());
@@ -199,10 +187,41 @@ void QSystemTrayIconSys::resizeEvent(QResizeEvent *event)
}
////////////////////////////////////////////////////////////////////////////
+class QSystemTrayWatcher: public QObject
+{
+ Q_OBJECT
+public:
+ QSystemTrayWatcher(QSystemTrayIcon *trayIcon)
+ : QObject(trayIcon)
+ , mTrayIcon(trayIcon)
+ {
+ // This code uses string-based syntax because we want to connect to a signal
+ // which is defined in XCB plugin - QXcbNativeInterface::systemTrayWindowChanged().
+ connect(qGuiApp->platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)),
+ this, SLOT(systemTrayWindowChanged(QScreen*)));
+ }
+
+private slots:
+ void systemTrayWindowChanged(QScreen *)
+ {
+ auto icon = static_cast<QSystemTrayIconPrivate *>(QObjectPrivate::get(mTrayIcon));
+ icon->destroyIcon();
+ if (icon->visible && locateSystemTray()) {
+ icon->sys = new QSystemTrayIconSys(mTrayIcon);
+ icon->sys->show();
+ }
+ }
+
+private:
+ QSystemTrayIcon *mTrayIcon = nullptr;
+};
+////////////////////////////////////////////////////////////////////////////
+
QSystemTrayIconPrivate::QSystemTrayIconPrivate()
: sys(0),
qpa_sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon()),
- visible(false)
+ visible(false),
+ trayWatcher(nullptr)
{
}
@@ -213,16 +232,21 @@ QSystemTrayIconPrivate::~QSystemTrayIconPrivate()
void QSystemTrayIconPrivate::install_sys()
{
+ Q_Q(QSystemTrayIcon);
+
if (qpa_sys) {
install_sys_qpa();
return;
}
- Q_Q(QSystemTrayIcon);
- if (!sys && locateSystemTray()) {
- sys = new QSystemTrayIconSys(q);
- QObject::connect(QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)),
- sys, SLOT(systemTrayWindowChanged(QScreen*)));
- sys->show();
+
+ if (!sys) {
+ if (!trayWatcher)
+ trayWatcher = new QSystemTrayWatcher(q);
+
+ if (locateSystemTray()) {
+ sys = new QSystemTrayIconSys(q);
+ sys->show();
+ }
}
}
@@ -241,14 +265,21 @@ void QSystemTrayIconPrivate::remove_sys()
remove_sys_qpa();
return;
}
+
+ destroyIcon();
+}
+
+void QSystemTrayIconPrivate::destroyIcon()
+{
if (!sys)
return;
QBalloonTip::hideBalloon();
- sys->hide(); // this should do the trick, but...
- delete sys; // wm may resize system tray only for DestroyEvents
- sys = 0;
+ sys->hide();
+ delete sys;
+ sys = nullptr;
}
+
void QSystemTrayIconPrivate::updateIcon_sys()
{
if (qpa_sys) {
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index dc8765ad88..bc1ff78de0 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -1239,6 +1239,8 @@ void QPlainTextEditPrivate::ensureViewportLayouted()
This property gets and sets the plain text editor's contents. The previous
contents are removed and undo/redo history is reset when this property is set.
+ currentCharFormat() is also reset, unless textCursor() is already at the
+ beginning of the document.
By default, for an editor with no contents, this property contains an empty string.
*/
@@ -1518,7 +1520,12 @@ void QPlainTextEdit::paste()
/*!
Deletes all the text in the text edit.
- Note that the undo/redo history is cleared by this function.
+ Notes:
+ \list
+ \li The undo/redo history is also cleared.
+ \li currentCharFormat() is reset, unless textCursor()
+ is already at the beginning of the document.
+ \endlist
\sa cut(), setPlainText()
*/
@@ -1651,7 +1658,12 @@ void QPlainTextEdit::timerEvent(QTimerEvent *e)
\a text is interpreted as plain text.
- Note that the undo/redo history is cleared by this function.
+ Notes:
+ \list
+ \li The undo/redo history is also cleared.
+ \li currentCharFormat() is reset, unless textCursor()
+ is already at the beginning of the document.
+ \endlist
\sa toPlainText()
*/
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index 4a06f58b4a..9e134493b5 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -556,7 +556,8 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
This property gets and sets the text editor's contents as plain
text. Previous contents are removed and undo/redo history is reset
- when the property is set.
+ when the property is set. currentCharFormat() is also reset, unless
+ textCursor() is already at the beginning of the document.
If the text edit has another content type, it will not be replaced
by plain text if you call toPlainText(). The only exception to this
@@ -1034,7 +1035,12 @@ void QTextEdit::paste()
/*!
Deletes all the text in the text edit.
- Note that the undo/redo history is cleared by this function.
+ Notes:
+ \list
+ \li The undo/redo history is also cleared.
+ \li currentCharFormat() is reset, unless textCursor()
+ is already at the beginning of the document.
+ \endlist
\sa cut(), setPlainText(), setHtml()
*/
@@ -1139,9 +1145,13 @@ void QTextEdit::timerEvent(QTimerEvent *e)
Changes the text of the text edit to the string \a text.
Any previous text is removed.
- \a text is interpreted as plain text.
-
- Note that the undo/redo history is cleared by this function.
+ Notes:
+ \list
+ \li \a text is interpreted as plain text.
+ \li The undo/redo history is also cleared.
+ \li currentCharFormat() is reset, unless textCursor()
+ is already at the beginning of the document.
+ \endlist
\sa toPlainText()
*/
@@ -1175,7 +1185,8 @@ QString QTextEdit::toPlainText() const
setHtml() changes the text of the text edit. Any previous text is
removed and the undo/redo history is cleared. The input text is
- interpreted as rich text in html format.
+ interpreted as rich text in html format. currentCharFormat() is also
+ reset, unless textCursor() is already at the beginning of the document.
\note It is the responsibility of the caller to make sure that the
text is correctly decoded when a QString containing HTML is created
diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
index 714c96b5e5..a92b4bd1cb 100644
--- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
@@ -1559,6 +1559,16 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
<< NtfsTestResource(NtfsTestResource::SymLink, relToRelSymlink, relToRelTarget)
<< relToRelSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
}
+ {
+ // Symlink to UNC share
+ pwd.mkdir("unc");
+ QString errorMessage;
+ QString uncTarget = QStringLiteral("//") + QtNetworkSettings::winServerName() + "/testshare";
+ QString uncSymlink = QDir::toNativeSeparators(pwd.absolutePath().append("\\unc\\link_to_unc"));
+ QTest::newRow("UNC symlink")
+ << NtfsTestResource(NtfsTestResource::SymLink, uncSymlink, uncTarget)
+ << QDir::fromNativeSeparators(uncSymlink) << true << QDir::fromNativeSeparators(uncTarget) << uncTarget;
+ }
//Junctions
QString target = "target";
@@ -1630,7 +1640,7 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks()
// Ensure that junctions, mountpoints are removed. If this fails, do not remove
// temporary directory to prevent it from trashing the system.
if (fi.isDir()) {
- if (!QDir().rmdir(fi.fileName())) {
+ if (!QDir().rmdir(fi.filePath())) {
qWarning("Unable to remove NTFS junction '%s'', keeping '%s'.",
qPrintable(fi.fileName()), qPrintable(QDir::toNativeSeparators(m_dir.path())));
m_dir.setAutoRemove(false);
diff --git a/tests/auto/corelib/kernel/qmetaobject/qmetaobject.pro b/tests/auto/corelib/kernel/qmetaobject/qmetaobject.pro
index e7e5a03a86..980c247ab5 100644
--- a/tests/auto/corelib/kernel/qmetaobject/qmetaobject.pro
+++ b/tests/auto/corelib/kernel/qmetaobject/qmetaobject.pro
@@ -1,4 +1,5 @@
CONFIG += testcase
+qtConfig(c++14): CONFIG += c++14
TARGET = tst_qmetaobject
QT = core-private testlib
SOURCES = tst_qmetaobject.cpp
diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
index 350ed24c28..89a06b358e 100644
--- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
+++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
@@ -816,6 +816,15 @@ void tst_QMetaObject::invokePointer()
QCOMPARE(obj.slotResult, QString("sl1:bubu"));
}
QCOMPARE(countedStructObjectsCount, 0);
+#ifdef __cpp_init_captures
+ {
+ CountedStruct str;
+ std::unique_ptr<int> ptr( new int );
+ QVERIFY(QMetaObject::invokeMethod(&obj, [str, &t1, &obj, p = std::move(ptr)]() { obj.sl1(t1); }));
+ QCOMPARE(obj.slotResult, QString("sl1:1"));
+ }
+ QCOMPARE(countedStructObjectsCount, 0);
+#endif
}
void tst_QMetaObject::invokeQueuedMetaMember()
@@ -1121,6 +1130,15 @@ void tst_QMetaObject::invokeBlockingQueuedPointer()
QCOMPARE(exp, QString("yessir"));
QCOMPARE(obj.slotResult, QString("sl1:bubu"));
}
+#ifdef __cpp_init_captures
+ {
+ std::unique_ptr<int> ptr(new int);
+ QVERIFY(QMetaObject::invokeMethod(&obj,
+ [&obj, p = std::move(ptr)]() { return obj.sl1("hehe"); },
+ Qt::BlockingQueuedConnection));
+ QCOMPARE(obj.slotResult, QString("sl1:hehe"));
+ }
+#endif
QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.moveToThread(QThread::currentThread());}, Qt::BlockingQueuedConnection));
t.quit();
QVERIFY(t.wait());
diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
index 6ad3357f40..38b72ab91f 100644
--- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
+++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
@@ -78,9 +78,11 @@ private slots:
void toString_isoDate_data();
void toString_isoDate();
void toString_isoDate_extra();
+#if QT_CONFIG(datestring)
void toString_textDate_data();
void toString_textDate();
void toString_textDate_extra();
+#endif
void toString_rfcDate_data();
void toString_rfcDate();
void toString_enumformat();
@@ -800,11 +802,11 @@ void tst_QDateTime::toString_isoDate_data()
QTest::newRow("positive OffsetFromUTC")
<< dt << Qt::ISODate
<< QString("1978-11-09T13:28:34+05:30");
- dt.setUtcOffset(-7200);
+ dt.setOffsetFromUtc(-7200);
QTest::newRow("negative OffsetFromUTC")
<< dt << Qt::ISODate
<< QString("1978-11-09T13:28:34-02:00");
- dt.setUtcOffset(-900);
+ dt.setOffsetFromUtc(-900);
QTest::newRow("negative non-integral OffsetFromUTC")
<< dt << Qt::ISODate
<< QString("1978-11-09T13:28:34-00:15");
@@ -840,7 +842,7 @@ void tst_QDateTime::toString_isoDate()
QCOMPARE(resultDatetime.date(), datetime.date());
QCOMPARE(resultDatetime.time(), datetime.time());
QCOMPARE(resultDatetime.timeSpec(), datetime.timeSpec());
- QCOMPARE(resultDatetime.utcOffset(), datetime.utcOffset());
+ QCOMPARE(resultDatetime.offsetFromUtc(), datetime.offsetFromUtc());
} else {
QCOMPARE(resultDatetime, QDateTime());
}
@@ -870,12 +872,14 @@ void tst_QDateTime::toString_isoDate_extra()
#endif // timezone
}
+#if QT_CONFIG(datestring)
void tst_QDateTime::toString_textDate_data()
{
QTest::addColumn<QDateTime>("datetime");
QTest::addColumn<QString>("expected");
- QString wednesdayJanuary = QDate::shortDayName(3) + ' ' + QDate::shortMonthName(1);
+ QString wednesdayJanuary = QLocale::system().dayName(3, QLocale::ShortFormat)
+ + ' ' + QLocale::system().monthName(1, QLocale::ShortFormat);
QTest::newRow("localtime") << QDateTime(QDate(2013, 1, 2), QTime(1, 2, 3), Qt::LocalTime)
<< wednesdayJanuary + QString(" 2 01:02:03 2013");
@@ -904,7 +908,7 @@ void tst_QDateTime::toString_textDate()
QCOMPARE(resultDatetime.date(), datetime.date());
QCOMPARE(resultDatetime.time(), datetime.time());
QCOMPARE(resultDatetime.timeSpec(), datetime.timeSpec());
- QCOMPARE(resultDatetime.utcOffset(), datetime.utcOffset());
+ QCOMPARE(resultDatetime.offsetFromUtc(), datetime.offsetFromUtc());
}
void tst_QDateTime::toString_textDate_extra()
@@ -953,6 +957,7 @@ void tst_QDateTime::toString_textDate_extra()
dt = QDateTime::fromMSecsSinceEpoch(0, Qt::UTC);
QVERIFY(dt.toString().endsWith(GMT));
}
+#endif // datestring
void tst_QDateTime::toString_rfcDate_data()
{
@@ -968,11 +973,11 @@ void tst_QDateTime::toString_rfcDate_data()
<< QDateTime(QDate(1978, 11, 9), QTime(13, 28, 34), Qt::UTC)
<< QString("09 Nov 1978 13:28:34 +0000");
QDateTime dt(QDate(1978, 11, 9), QTime(13, 28, 34));
- dt.setUtcOffset(19800);
+ dt.setOffsetFromUtc(19800);
QTest::newRow("positive OffsetFromUTC")
<< dt
<< QString("09 Nov 1978 13:28:34 +0530");
- dt.setUtcOffset(-7200);
+ dt.setOffsetFromUtc(-7200);
QTest::newRow("negative OffsetFromUTC")
<< dt
<< QString("09 Nov 1978 13:28:34 -0200");
diff --git a/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp b/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp
index 82197f815e..f8bb0c3851 100644
--- a/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp
+++ b/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp
@@ -35,11 +35,13 @@
namespace
{
- QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion)
+ QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion,
+ QShaderFormat::ShaderType shaderType= QShaderFormat::Fragment)
{
auto format = QShaderFormat();
format.setApi(api);
format.setVersion(QVersionNumber(majorVersion, minorVersion));
+ format.setShaderType(shaderType);
return format;
}
@@ -74,7 +76,7 @@ namespace
return edge;
}
- QShaderGraph createGraph()
+ QShaderGraph createFragmentShaderGraph()
{
const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
@@ -194,6 +196,7 @@ private slots:
void shouldProcessLanguageQualifierAndTypeEnums_data();
void shouldProcessLanguageQualifierAndTypeEnums();
void shouldGenerateDifferentCodeDependingOnActiveLayers();
+ void shouldUseGlobalVariableRatherThanTemporaries();
};
void tst_QShaderGenerator::shouldHaveDefaultState()
@@ -213,7 +216,7 @@ void tst_QShaderGenerator::shouldGenerateShaderCode_data()
QTest::addColumn<QShaderFormat>("format");
QTest::addColumn<QByteArray>("expectedCode");
- const auto graph = createGraph();
+ const auto graph = createFragmentShaderGraph();
const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
@@ -234,14 +237,9 @@ void tst_QShaderGenerator::shouldGenerateShaderCode_data()
<< ""
<< "void main()"
<< "{"
- << " highp vec2 v2 = texCoord;"
- << " sampler2D v1 = texture;"
- << " highp float v3 = lightIntensity;"
- << " highp vec4 v5 = texture2D(v1, v2);"
- << " highp vec3 v0 = worldPosition;"
- << " highp float v4 = exposure;"
- << " highp vec4 v6 = lightModel(v5, v0, v3);"
- << " highp vec4 v7 = v6 * pow(2.0, v4);"
+ << " highp vec4 v5 = texture2D(texture, texCoord);"
+ << " highp vec4 v6 = lightModel(v5, worldPosition, lightIntensity);"
+ << " highp vec4 v7 = v6 * pow(2.0, exposure);"
<< " gl_fragColor = v7;"
<< "}"
<< "";
@@ -256,14 +254,9 @@ void tst_QShaderGenerator::shouldGenerateShaderCode_data()
<< ""
<< "void main()"
<< "{"
- << " vec2 v2 = texCoord;"
- << " sampler2D v1 = texture;"
- << " float v3 = lightIntensity;"
- << " vec4 v5 = texture2D(v1, v2);"
- << " vec3 v0 = worldPosition;"
- << " float v4 = exposure;"
- << " vec4 v6 = lightModel(v5, v0, v3);"
- << " vec4 v7 = v6 * pow(2.0, v4);"
+ << " vec4 v5 = texture2D(texture, texCoord);"
+ << " vec4 v6 = lightModel(v5, worldPosition, lightIntensity);"
+ << " vec4 v7 = v6 * pow(2.0, exposure);"
<< " fragColor = v7;"
<< "}"
<< "";
@@ -580,120 +573,190 @@ void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums_data()
QTest::addColumn<QShaderFormat>("format");
QTest::addColumn<QByteArray>("expectedCode");
- const auto es2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
- const auto es3 = createFormat(QShaderFormat::OpenGLES, 3, 0);
- const auto gl2 = createFormat(QShaderFormat::OpenGLNoProfile, 2, 0);
- const auto gl3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
- const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
-
- const auto qualifierEnum = QMetaEnum::fromType<QShaderLanguage::StorageQualifier>();
- const auto typeEnum = QMetaEnum::fromType<QShaderLanguage::VariableType>();
-
- for (int qualifierIndex = 0; qualifierIndex < qualifierEnum.keyCount(); qualifierIndex++) {
- const auto qualifierName = qualifierEnum.key(qualifierIndex);
- const auto qualifierValue = static_cast<QShaderLanguage::StorageQualifier>(qualifierEnum.value(qualifierIndex));
+ {
+ const auto es2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
+ const auto es3 = createFormat(QShaderFormat::OpenGLES, 3, 0);
+ const auto gl2 = createFormat(QShaderFormat::OpenGLNoProfile, 2, 0);
+ const auto gl3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
+ const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
+
+ const auto qualifierEnum = QMetaEnum::fromType<QShaderLanguage::StorageQualifier>();
+ const auto typeEnum = QMetaEnum::fromType<QShaderLanguage::VariableType>();
+
+ for (int qualifierIndex = 0; qualifierIndex < qualifierEnum.keyCount(); qualifierIndex++) {
+ const auto qualifierName = qualifierEnum.key(qualifierIndex);
+ const auto qualifierValue = static_cast<QShaderLanguage::StorageQualifier>(qualifierEnum.value(qualifierIndex));
+
+ for (int typeIndex = 0; typeIndex < typeEnum.keyCount(); typeIndex++) {
+ const auto typeName = typeEnum.key(typeIndex);
+ const auto typeValue = static_cast<QShaderLanguage::VariableType>(typeEnum.value(typeIndex));
+
+ auto graph = QShaderGraph();
+
+ auto worldPosition = createNode({
+ createPort(QShaderNodePort::Output, "value")
+ });
+ worldPosition.setParameter("name", "worldPosition");
+ worldPosition.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(qualifierValue));
+ worldPosition.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(typeValue));
+ worldPosition.addRule(es2, QShaderNode::Rule("highp $type $value = $name;",
+ QByteArrayList() << "$qualifier highp $type $name;"));
+ worldPosition.addRule(gl2, QShaderNode::Rule("$type $value = $name;",
+ QByteArrayList() << "$qualifier $type $name;"));
+ worldPosition.addRule(gl3, QShaderNode::Rule("$type $value = $name;",
+ QByteArrayList() << "$qualifier $type $name;"));
+
+ auto fragColor = createNode({
+ createPort(QShaderNodePort::Input, "fragColor")
+ });
+ fragColor.addRule(es2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
+ fragColor.addRule(gl2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
+ fragColor.addRule(gl3, QShaderNode::Rule("fragColor = $fragColor;",
+ QByteArrayList() << "out vec4 fragColor;"));
+
+ graph.addNode(worldPosition);
+ graph.addNode(fragColor);
+
+ graph.addEdge(createEdge(worldPosition.uuid(), "value", fragColor.uuid(), "fragColor"));
+
+ const auto gl2Code = (QByteArrayList() << "#version 110"
+ << ""
+ << QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl2))
+ .arg(toGlsl(typeValue))
+ .toUtf8()
+ << ""
+ << "void main()"
+ << "{"
+ << " gl_fragColor = worldPosition;"
+ << "}"
+ << "").join("\n");
+ const auto gl3Code = (QByteArrayList() << "#version 130"
+ << ""
+ << QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl3))
+ .arg(toGlsl(typeValue))
+ .toUtf8()
+ << "out vec4 fragColor;"
+ << ""
+ << "void main()"
+ << "{"
+ << " fragColor = worldPosition;"
+ << "}"
+ << "").join("\n");
+ const auto gl4Code = (QByteArrayList() << "#version 400 core"
+ << ""
+ << QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl4))
+ .arg(toGlsl(typeValue))
+ .toUtf8()
+ << "out vec4 fragColor;"
+ << ""
+ << "void main()"
+ << "{"
+ << " fragColor = worldPosition;"
+ << "}"
+ << "").join("\n");
+ const auto es2Code = (QByteArrayList() << "#version 100"
+ << ""
+ << QStringLiteral("%1 highp %2 worldPosition;").arg(toGlsl(qualifierValue, es2))
+ .arg(toGlsl(typeValue))
+ .toUtf8()
+ << ""
+ << "void main()"
+ << "{"
+ << " gl_fragColor = worldPosition;"
+ << "}"
+ << "").join("\n");
+ const auto es3Code = (QByteArrayList() << "#version 300 es"
+ << ""
+ << QStringLiteral("%1 highp %2 worldPosition;").arg(toGlsl(qualifierValue, es3))
+ .arg(toGlsl(typeValue))
+ .toUtf8()
+ << ""
+ << "void main()"
+ << "{"
+ << " gl_fragColor = worldPosition;"
+ << "}"
+ << "").join("\n");
+
+ QTest::addRow("%s %s ES2", qualifierName, typeName) << graph << es2 << es2Code;
+ QTest::addRow("%s %s ES3", qualifierName, typeName) << graph << es3 << es3Code;
+ QTest::addRow("%s %s GL2", qualifierName, typeName) << graph << gl2 << gl2Code;
+ QTest::addRow("%s %s GL3", qualifierName, typeName) << graph << gl3 << gl3Code;
+ QTest::addRow("%s %s GL4", qualifierName, typeName) << graph << gl4 << gl4Code;
+ }
+ }
+ }
- for (int typeIndex = 0; typeIndex < typeEnum.keyCount(); typeIndex++) {
- const auto typeName = typeEnum.key(typeIndex);
- const auto typeValue = static_cast<QShaderLanguage::VariableType>(typeEnum.value(typeIndex));
+ {
+ const auto es2 = createFormat(QShaderFormat::OpenGLES, 2, 0, QShaderFormat::Vertex);
+ const auto es3 = createFormat(QShaderFormat::OpenGLES, 3, 0, QShaderFormat::Vertex);
+ const auto gl2 = createFormat(QShaderFormat::OpenGLNoProfile, 2, 0, QShaderFormat::Vertex);
+ const auto gl3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, QShaderFormat::Vertex);
+ const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0, QShaderFormat::Vertex);
auto graph = QShaderGraph();
- auto worldPosition = createNode({
+ auto vertexPosition = createNode({
createPort(QShaderNodePort::Output, "value")
});
- worldPosition.setParameter("name", "worldPosition");
- worldPosition.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(qualifierValue));
- worldPosition.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(typeValue));
- worldPosition.addRule(es2, QShaderNode::Rule("highp $type $value = $name;",
+ vertexPosition.setParameter("name", "vertexPosition");
+ vertexPosition.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(QShaderLanguage::Input));
+ vertexPosition.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(QShaderLanguage::Vec4));
+
+ vertexPosition.addRule(es2, QShaderNode::Rule("",
QByteArrayList() << "$qualifier highp $type $name;"));
- worldPosition.addRule(gl2, QShaderNode::Rule("$type $value = $name;",
+ vertexPosition.addRule(gl2, QShaderNode::Rule("",
QByteArrayList() << "$qualifier $type $name;"));
- worldPosition.addRule(gl3, QShaderNode::Rule("$type $value = $name;",
+ vertexPosition.addRule(gl3, QShaderNode::Rule("",
QByteArrayList() << "$qualifier $type $name;"));
- auto fragColor = createNode({
- createPort(QShaderNodePort::Input, "fragColor")
- });
- fragColor.addRule(es2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
- fragColor.addRule(gl2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
- fragColor.addRule(gl3, QShaderNode::Rule("fragColor = $fragColor;",
- QByteArrayList() << "out vec4 fragColor;"));
-
- graph.addNode(worldPosition);
- graph.addNode(fragColor);
-
- graph.addEdge(createEdge(worldPosition.uuid(), "value", fragColor.uuid(), "fragColor"));
+ graph.addNode(vertexPosition);
const auto gl2Code = (QByteArrayList() << "#version 110"
<< ""
- << QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl2))
- .arg(toGlsl(typeValue))
- .toUtf8()
+ << "attribute vec4 vertexPosition;"
<< ""
<< "void main()"
<< "{"
- << QStringLiteral(" %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
- << " gl_fragColor = v0;"
<< "}"
<< "").join("\n");
const auto gl3Code = (QByteArrayList() << "#version 130"
<< ""
- << QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl3))
- .arg(toGlsl(typeValue))
- .toUtf8()
- << "out vec4 fragColor;"
+ << "in vec4 vertexPosition;"
<< ""
<< "void main()"
<< "{"
- << QStringLiteral(" %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
- << " fragColor = v0;"
<< "}"
<< "").join("\n");
const auto gl4Code = (QByteArrayList() << "#version 400 core"
<< ""
- << QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl4))
- .arg(toGlsl(typeValue))
- .toUtf8()
- << "out vec4 fragColor;"
+ << "in vec4 vertexPosition;"
<< ""
<< "void main()"
<< "{"
- << QStringLiteral(" %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
- << " fragColor = v0;"
<< "}"
<< "").join("\n");
const auto es2Code = (QByteArrayList() << "#version 100"
<< ""
- << QStringLiteral("%1 highp %2 worldPosition;").arg(toGlsl(qualifierValue, es2))
- .arg(toGlsl(typeValue))
- .toUtf8()
+ << "attribute highp vec4 vertexPosition;"
<< ""
<< "void main()"
<< "{"
- << QStringLiteral(" highp %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
- << " gl_fragColor = v0;"
<< "}"
<< "").join("\n");
const auto es3Code = (QByteArrayList() << "#version 300 es"
<< ""
- << QStringLiteral("%1 highp %2 worldPosition;").arg(toGlsl(qualifierValue, es3))
- .arg(toGlsl(typeValue))
- .toUtf8()
+ << "in highp vec4 vertexPosition;"
<< ""
<< "void main()"
<< "{"
- << QStringLiteral(" highp %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
- << " gl_fragColor = v0;"
<< "}"
<< "").join("\n");
- QTest::addRow("%s %s ES2", qualifierName, typeName) << graph << es2 << es2Code;
- QTest::addRow("%s %s ES3", qualifierName, typeName) << graph << es3 << es3Code;
- QTest::addRow("%s %s GL2", qualifierName, typeName) << graph << gl2 << gl2Code;
- QTest::addRow("%s %s GL3", qualifierName, typeName) << graph << gl3 << gl3Code;
- QTest::addRow("%s %s GL4", qualifierName, typeName) << graph << gl4 << gl4Code;
- }
+ QTest::addRow("Attribute header substitution ES2") << graph << es2 << es2Code;
+ QTest::addRow("Attribute header substitution ES3") << graph << es3 << es3Code;
+ QTest::addRow("Attribute header substitution GL2") << graph << gl2 << gl2Code;
+ QTest::addRow("Attribute header substitution GL3") << graph << gl3 << gl3Code;
+ QTest::addRow("Attribute header substitution GL4") << graph << gl4 << gl4Code;
}
}
@@ -806,9 +869,7 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
<< ""
<< "void main()"
<< "{"
- << " vec3 v1 = normalUniform;"
- << " vec4 v0 = diffuseUniform;"
- << " vec4 v2 = lightModel(v0, v1);"
+ << " vec4 v2 = lightModel(diffuseUniform, normalUniform);"
<< " fragColor = v2;"
<< "}"
<< "";
@@ -831,10 +892,8 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
<< ""
<< "void main()"
<< "{"
- << " vec2 v0 = texCoord;"
- << " vec3 v2 = texture2D(normalTexture, v0).rgb;"
- << " vec4 v1 = diffuseUniform;"
- << " vec4 v3 = lightModel(v1, v2);"
+ << " vec3 v2 = texture2D(normalTexture, texCoord).rgb;"
+ << " vec4 v3 = lightModel(diffuseUniform, v2);"
<< " fragColor = v3;"
<< "}"
<< "";
@@ -857,10 +916,8 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
<< ""
<< "void main()"
<< "{"
- << " vec2 v0 = texCoord;"
- << " vec3 v2 = normalUniform;"
- << " vec4 v1 = texture2D(diffuseTexture, v0);"
- << " vec4 v3 = lightModel(v1, v2);"
+ << " vec4 v1 = texture2D(diffuseTexture, texCoord);"
+ << " vec4 v3 = lightModel(v1, normalUniform);"
<< " fragColor = v3;"
<< "}"
<< "";
@@ -883,9 +940,8 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
<< ""
<< "void main()"
<< "{"
- << " vec2 v0 = texCoord;"
- << " vec3 v2 = texture2D(normalTexture, v0).rgb;"
- << " vec4 v1 = texture2D(diffuseTexture, v0);"
+ << " vec3 v2 = texture2D(normalTexture, texCoord).rgb;"
+ << " vec4 v1 = texture2D(diffuseTexture, texCoord);"
<< " vec4 v3 = lightModel(v1, v2);"
<< " fragColor = v3;"
<< "}"
@@ -894,6 +950,133 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
}
}
+void tst_QShaderGenerator::shouldUseGlobalVariableRatherThanTemporaries()
+{
+ // GIVEN
+ const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
+
+ {
+ // WHEN
+ auto vertexPosition = createNode({
+ createPort(QShaderNodePort::Output, "vertexPosition")
+ });
+ vertexPosition.addRule(gl4, QShaderNode::Rule("vec4 $vertexPosition = vertexPosition;",
+ QByteArrayList() << "in vec4 vertexPosition;"));
+
+ auto fakeMultiPlyNoSpace = createNode({
+ createPort(QShaderNodePort::Input, "varName"),
+ createPort(QShaderNodePort::Output, "out")
+ });
+ fakeMultiPlyNoSpace.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName*v11;"));
+
+ auto fakeMultiPlySpace = createNode({
+ createPort(QShaderNodePort::Input, "varName"),
+ createPort(QShaderNodePort::Output, "out")
+ });
+ fakeMultiPlySpace.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName * v11;"));
+
+ auto fakeJoinNoSpace = createNode({
+ createPort(QShaderNodePort::Input, "varName"),
+ createPort(QShaderNodePort::Output, "out")
+ });
+ fakeJoinNoSpace.addRule(gl4, QShaderNode::Rule("vec4 $out = vec4($varName.xyz,$varName.w);"));
+
+ auto fakeJoinSpace = createNode({
+ createPort(QShaderNodePort::Input, "varName"),
+ createPort(QShaderNodePort::Output, "out")
+ });
+ fakeJoinSpace.addRule(gl4, QShaderNode::Rule("vec4 $out = vec4($varName.xyz, $varName.w);"));
+
+ auto fakeAdd = createNode({
+ createPort(QShaderNodePort::Input, "varName"),
+ createPort(QShaderNodePort::Output, "out")
+ });
+ fakeAdd.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName.xyzw + $varName;"));
+
+ auto fakeSub = createNode({
+ createPort(QShaderNodePort::Input, "varName"),
+ createPort(QShaderNodePort::Output, "out")
+ });
+ fakeSub.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName.xyzw - $varName;"));
+
+ auto fakeDiv = createNode({
+ createPort(QShaderNodePort::Input, "varName"),
+ createPort(QShaderNodePort::Output, "out")
+ });
+ fakeDiv.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName / v0;"));
+
+ auto fragColor = createNode({
+ createPort(QShaderNodePort::Input, "input1"),
+ createPort(QShaderNodePort::Input, "input2"),
+ createPort(QShaderNodePort::Input, "input3"),
+ createPort(QShaderNodePort::Input, "input4"),
+ createPort(QShaderNodePort::Input, "input5"),
+ createPort(QShaderNodePort::Input, "input6"),
+ createPort(QShaderNodePort::Input, "input7")
+ });
+ fragColor.addRule(gl4, QShaderNode::Rule("fragColor = $input1 + $input2 + $input3 + $input4 + $input5 + $input6 + $input7;",
+ QByteArrayList() << "out vec4 fragColor;"));
+
+ const auto graph = [=] {
+ auto res = QShaderGraph();
+
+ res.addNode(vertexPosition);
+ res.addNode(fakeMultiPlyNoSpace);
+ res.addNode(fakeMultiPlySpace);
+ res.addNode(fakeJoinNoSpace);
+ res.addNode(fakeJoinSpace);
+ res.addNode(fakeAdd);
+ res.addNode(fakeSub);
+ res.addNode(fakeDiv);
+ res.addNode(fragColor);
+
+ res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeMultiPlyNoSpace.uuid(), "varName"));
+ res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeMultiPlySpace.uuid(), "varName"));
+ res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeJoinNoSpace.uuid(), "varName"));
+ res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeJoinSpace.uuid(), "varName"));
+ res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeAdd.uuid(), "varName"));
+ res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeSub.uuid(), "varName"));
+ res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeDiv.uuid(), "varName"));
+ res.addEdge(createEdge(fakeMultiPlyNoSpace.uuid(), "out", fragColor.uuid(), "input1"));
+ res.addEdge(createEdge(fakeMultiPlySpace.uuid(), "out", fragColor.uuid(), "input2"));
+ res.addEdge(createEdge(fakeJoinNoSpace.uuid(), "out", fragColor.uuid(), "input3"));
+ res.addEdge(createEdge(fakeJoinSpace.uuid(), "out", fragColor.uuid(), "input4"));
+ res.addEdge(createEdge(fakeAdd.uuid(), "out", fragColor.uuid(), "input5"));
+ res.addEdge(createEdge(fakeSub.uuid(), "out", fragColor.uuid(), "input6"));
+ res.addEdge(createEdge(fakeDiv.uuid(), "out", fragColor.uuid(), "input7"));
+
+ return res;
+ }();
+
+ auto generator = QShaderGenerator();
+ generator.graph = graph;
+ generator.format = gl4;
+
+ const auto code = generator.createShaderCode({"diffuseUniform", "normalUniform"});
+
+ // THEN
+ const auto expected = QByteArrayList()
+ << "#version 400 core"
+ << ""
+ << "in vec4 vertexPosition;"
+ << "out vec4 fragColor;"
+ << ""
+ << "void main()"
+ << "{"
+ << " vec4 v7 = vertexPosition / vertexPosition;"
+ << " vec4 v6 = vertexPosition.xyzw - vertexPosition;"
+ << " vec4 v5 = vertexPosition.xyzw + vertexPosition;"
+ << " vec4 v4 = vec4(vertexPosition.xyz, vertexPosition.w);"
+ << " vec4 v3 = vec4(vertexPosition.xyz,vertexPosition.w);"
+ << " vec4 v2 = vertexPosition * v11;"
+ << " vec4 v1 = vertexPosition*v11;"
+ << " fragColor = v1 + v2 + v3 + v4 + v5 + v6 + v7;"
+ << "}"
+ << "";
+ QCOMPARE(code, expected.join("\n"));
+ }
+}
+
QTEST_MAIN(tst_QShaderGenerator)
#include "tst_qshadergenerator.moc"
diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
index 42258c85b9..f247889d55 100644
--- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
+++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
@@ -248,6 +248,7 @@ private slots:
void sizeHintCrash();
void testResetCachedSizeHint();
void statusTips();
+ void testRemovingColumnsViaLayoutChanged();
protected:
void setupTestData(bool use_reset_model = false);
@@ -353,6 +354,7 @@ public:
void cleanup()
{
+ emit layoutAboutToBeChanged();
cols = 3;
rows = 3;
emit layoutChanged();
@@ -3489,5 +3491,20 @@ void tst_QHeaderView::statusTips()
QCOMPARE(headerView.statusTipText, QLatin1String("[0,1,0] -- Header"));
}
+void tst_QHeaderView::testRemovingColumnsViaLayoutChanged()
+{
+ const int persistentSectionSize = 101;
+
+ QtTestModel model;
+ model.rows = model.cols = 5;
+ view->setModel(&model);
+ for (int i = 0; i < model.cols; ++i)
+ view->resizeSection(i, persistentSectionSize + i);
+ model.cleanup(); // down to 3 via layoutChanged (not columnsRemoved)
+ for (int j = 0; j < model.cols; ++j)
+ QCOMPARE(view->sectionSize(j), persistentSectionSize + j);
+ // The main point of this test is that the section-size restoring code didn't go out of bounds.
+}
+
QTEST_MAIN(tst_QHeaderView)
#include "tst_qheaderview.moc"
diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
index 30afa69c31..91088aeeca 100644
--- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
+++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
@@ -267,6 +267,7 @@ tst_QListWidget::tst_QListWidget(): testWidget(0), rcParent(8), rcFirst(8,0), rc
void tst_QListWidget::initTestCase()
{
+ qRegisterMetaType<QListWidgetItem*>("QListWidgetItem*");
testWidget = new QListWidget();
testWidget->show();
@@ -663,6 +664,9 @@ void tst_QListWidget::insertItems()
QFETCH(int, rowCount);
QFETCH(int, insertType);
+ QSignalSpy itemChangedSpy(testWidget, &QListWidget::itemChanged);
+ QSignalSpy dataChangedSpy(testWidget->model(), &QAbstractItemModel::dataChanged);
+
if (insertType == 3) {
QStringList strings;
for (int i=0; i<rowCount; ++i)
@@ -700,6 +704,9 @@ void tst_QListWidget::insertItems()
// make sure all items have view set correctly
for (int i=0; i<testWidget->count(); ++i)
QCOMPARE(testWidget->item(i)->listWidget(), testWidget);
+
+ QCOMPARE(itemChangedSpy.count(), 0);
+ QCOMPARE(dataChangedSpy.count(), 0);
}
void tst_QListWidget::itemAssignment()
@@ -1257,7 +1264,6 @@ void tst_QListWidget::setData()
QFETCH(IntList, roles);
QFETCH(QVariantList, values);
QFETCH(int, expectedSignalCount);
- qRegisterMetaType<QListWidgetItem *>("QListWidgetItem*");
QCOMPARE(roles.count(), values.count());
@@ -1715,7 +1721,6 @@ void tst_QListWidget::task258949_keypressHangup()
void tst_QListWidget::QTBUG8086_currentItemChangedOnClick()
{
- qRegisterMetaType<QListWidgetItem*>("QListWidgetItem*");
QWidget win;
QHBoxLayout layout(&win);
QListWidget list;
@@ -1837,7 +1842,6 @@ void tst_QListWidget::mimeData()
void tst_QListWidget::QTBUG50891_ensureSelectionModelSignalConnectionsAreSet()
{
- qRegisterMetaType<QListWidgetItem*>("QListWidgetItem*");
QListWidget list;
for (int i = 0 ; i < 4; ++i)
new QListWidgetItem(QString::number(i), &list);
diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST
index 3287d67875..03bec4286b 100644
--- a/tests/auto/widgets/kernel/qwidget/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST
@@ -46,3 +46,6 @@ osx
osx-10.12 ci
[multipleToplevelFocusCheck]
linux
+[windowState]
+# QTBUG-75270
+winrt
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
index 61b1fed1f8..a671a6c4d8 100644
--- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
+++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
@@ -48,6 +48,7 @@ public:
private slots:
void init();
void repolish();
+ void repolish_without_crashing();
void numinstances();
void widgetsBeforeAppStyleSheet();
void widgetsAfterAppStyleSheet();
@@ -367,6 +368,26 @@ void tst_QStyleSheetStyle::repolish()
QCOMPARE(BACKGROUND(p1), APPBACKGROUND(p1));
}
+void tst_QStyleSheetStyle::repolish_without_crashing()
+{
+ // This used to crash, QTBUG-69204
+ QMainWindow w;
+ QScopedPointer<QSplitter> splitter1(new QSplitter(w.centralWidget()));
+ QScopedPointer<QSplitter> splitter2(new QSplitter);
+ QScopedPointer<QSplitter> splitter3(new QSplitter);
+ splitter2->addWidget(splitter3.data());
+
+ splitter2->setStyleSheet("color: red");
+ QScopedPointer<QLabel> label(new QLabel);
+ label->setTextFormat(Qt::RichText);
+ splitter3->addWidget(label.data());
+ label->setText("hey");
+
+ splitter1->addWidget(splitter2.data());
+ w.show();
+ QCOMPARE(COLOR(*label), QColor(Qt::red));
+}
+
void tst_QStyleSheetStyle::widgetStyle()
{
qApp->setStyleSheet(QString());
diff --git a/util/corelib/qurl-generateTLDs/main.cpp b/util/corelib/qurl-generateTLDs/main.cpp
index 6fde287049..1baae92521 100644
--- a/util/corelib/qurl-generateTLDs/main.cpp
+++ b/util/corelib/qurl-generateTLDs/main.cpp
@@ -90,15 +90,15 @@ int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
if (argc < 3) {
- printf("\nusage: %s inputFile outputFile\n\n", argv[0]);
+ printf("\nUsage: ./%s inputFile outputFile\n\n", argv[0]);
printf("'inputFile' should be a list of effective TLDs, one per line,\n");
- printf("as obtained from http://publicsuffix.org . To create indices and data file\n");
+ printf("as obtained from http://publicsuffix.org/. To create indices and data\n");
printf("file, do the following:\n\n");
- printf(" wget https://publicsuffix.org/list/effective_tld_names.dat -O effective_tld_names.dat\n");
- printf(" grep '^[^\\/\\/]' effective_tld_names.dat > effective_tld_names.dat.trimmed\n");
- printf(" %s effective_tld_names.dat.trimmed effective_tld_names.dat.qt\n\n", argv[0]);
- printf("Now copy the data from effective_tld_names.dat.qt to the file src/corelib/io/qurltlds_p.h in your Qt repo\n\n");
- exit(1);
+ printf(" wget https://publicsuffix.org/list/public_suffix_list.dat -O public_suffix_list.dat\n");
+ printf(" grep -v '^//' public_suffix_list.dat | grep . > public_suffix_list.dat.trimmed\n");
+ printf(" ./%s public_suffix_list.dat.trimmed public_suffix_list.cpp\n\n", argv[0]);
+ printf("Now replace the code in qtbase/src/corelib/io/qurltlds_p.h with public_suffix_list.cpp's contents\n\n");
+ return 1;
}
QFile file(argv[1]);
if (!file.open(QIODevice::ReadOnly)) {