summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.cmake.conf2
-rw-r--r--.qmake.conf2
-rw-r--r--cmake/QtAndroidHelpers.cmake32
-rw-r--r--coin/module_config.yaml1
-rw-r--r--configure.cmake4
-rw-r--r--doc/global/qt-cpp-defines.qdocconf1
-rw-r--r--examples/corelib/CMakeLists.txt4
-rw-r--r--examples/widgets/animation/easing/animation.h4
-rw-r--r--examples/widgets/animation/easing/window.cpp2
-rw-r--r--mkspecs/common/macx.conf2
-rw-r--r--qmake/generators/unix/unixmake2.cpp10
-rw-r--r--src/3rdparty/forkfd/forkfd_c11.h4
-rw-r--r--src/3rdparty/libpng/ANNOUNCE29
-rw-r--r--src/3rdparty/libpng/CHANGES10
-rw-r--r--src/3rdparty/libpng/CMakeLists.txt2
-rw-r--r--src/3rdparty/libpng/INSTALL75
-rw-r--r--src/3rdparty/libpng/LICENSE4
-rw-r--r--src/3rdparty/libpng/README8
-rw-r--r--src/3rdparty/libpng/libpng-manual.txt8
-rw-r--r--src/3rdparty/libpng/png.c14
-rw-r--r--src/3rdparty/libpng/png.h26
-rw-r--r--src/3rdparty/libpng/pngconf.h8
-rw-r--r--src/3rdparty/libpng/pngget.c14
-rw-r--r--src/3rdparty/libpng/pnglibconf.h4
-rw-r--r--src/3rdparty/libpng/pngpriv.h76
-rw-r--r--src/3rdparty/libpng/pngread.c3
-rw-r--r--src/3rdparty/libpng/pngrtran.c2
-rw-r--r--src/3rdparty/libpng/pngrutil.c30
-rw-r--r--src/3rdparty/libpng/pngset.c13
-rw-r--r--src/3rdparty/libpng/pngstruct.h12
-rw-r--r--src/3rdparty/libpng/pngwrite.c12
-rw-r--r--src/3rdparty/libpng/qt_attribution.json13
-rw-r--r--src/3rdparty/libpng/qtpatches.diff62
-rw-r--r--src/3rdparty/zlib/CVE-2022-37434.patch68
-rw-r--r--src/3rdparty/zlib/qt_attribution.json6
-rw-r--r--src/3rdparty/zlib/qtpatches.diff12
-rw-r--r--src/3rdparty/zlib/src/ChangeLog26
-rw-r--r--src/3rdparty/zlib/src/README4
-rw-r--r--src/3rdparty/zlib/src/compress.c6
-rw-r--r--src/3rdparty/zlib/src/crc32.c33
-rw-r--r--src/3rdparty/zlib/src/deflate.c218
-rw-r--r--src/3rdparty/zlib/src/deflate.h4
-rw-r--r--src/3rdparty/zlib/src/gzlib.c2
-rw-r--r--src/3rdparty/zlib/src/gzread.c8
-rw-r--r--src/3rdparty/zlib/src/gzwrite.c2
-rw-r--r--src/3rdparty/zlib/src/infback.c17
-rw-r--r--src/3rdparty/zlib/src/inflate.c2
-rw-r--r--src/3rdparty/zlib/src/inftrees.c4
-rw-r--r--src/3rdparty/zlib/src/inftrees.h2
-rw-r--r--src/3rdparty/zlib/src/trees.c123
-rw-r--r--src/3rdparty/zlib/src/uncompr.c4
-rw-r--r--src/3rdparty/zlib/src/zconf.h16
-rw-r--r--src/3rdparty/zlib/src/zlib.h20
-rw-r--r--src/3rdparty/zlib/src/zutil.c16
-rw-r--r--src/3rdparty/zlib/src/zutil.h1
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/CursorHandle.java3
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/ExtractStyle.java37
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java16
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java16
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtLayout.java142
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java3
-rw-r--r--src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java10
-rw-r--r--src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java2
-rw-r--r--src/corelib/animation/qpropertyanimation.cpp4
-rw-r--r--src/corelib/doc/snippets/code/doc_src_containers.cpp59
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp94
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qstring.cpp3
-rw-r--r--src/corelib/doc/snippets/qstringlist/main.cpp18
-rw-r--r--src/corelib/doc/src/animation.qdoc338
-rw-r--r--src/corelib/doc/src/containers.qdoc31
-rw-r--r--src/corelib/global/qcompilerdetection.h25
-rw-r--r--src/corelib/global/qflags.h5
-rw-r--r--src/corelib/global/qlogging.cpp16
-rw-r--r--src/corelib/global/qnumeric.cpp31
-rw-r--r--src/corelib/global/qnumeric_p.h35
-rw-r--r--src/corelib/io/qdir.cpp3
-rw-r--r--src/corelib/io/qfilesystemwatcher_win_p.h5
-rw-r--r--src/corelib/io/qlockfile.h6
-rw-r--r--src/corelib/kernel/qcore_mac_p.h12
-rw-r--r--src/corelib/kernel/qdeadlinetimer.h8
-rw-r--r--src/corelib/kernel/qmetatype.cpp9
-rw-r--r--src/corelib/kernel/qmetatype.h5
-rw-r--r--src/corelib/kernel/qobject.h6
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp6
-rw-r--r--src/corelib/kernel/qtimer.h8
-rw-r--r--src/corelib/kernel/qvariant.cpp21
-rw-r--r--src/corelib/platform/android/qandroidextras.cpp6
-rw-r--r--src/corelib/text/qbytearray.cpp337
-rw-r--r--src/corelib/text/qlocale_win.cpp10
-rw-r--r--src/corelib/text/qstring.cpp19
-rw-r--r--src/corelib/text/qstringconverter.cpp2
-rw-r--r--src/corelib/text/qstringlist.cpp20
-rw-r--r--src/corelib/thread/qatomic.cpp82
-rw-r--r--src/corelib/thread/qatomic.h5
-rw-r--r--src/corelib/thread/qfutureinterface.cpp47
-rw-r--r--src/corelib/thread/qfutureinterface_p.h5
-rw-r--r--src/corelib/thread/qmutex.h8
-rw-r--r--src/corelib/thread/qpromise.h1
-rw-r--r--src/corelib/time/qdatetime.h17
-rw-r--r--src/corelib/tools/qlist.qdoc16
-rw-r--r--src/corelib/tools/qmap.h26
-rw-r--r--src/corelib/tools/qmap.qdoc9
-rw-r--r--src/corelib/tools/qtaggedpointer.h23
-rw-r--r--src/gui/configure.cmake2
-rw-r--r--src/gui/doc/src/external-resources.qdoc2
-rw-r--r--src/gui/image/qimage.cpp6
-rw-r--r--src/gui/itemmodels/qfilesystemmodel_p.h5
-rw-r--r--src/gui/kernel/qguiapplication.cpp5
-rw-r--r--src/gui/kernel/qpalette.cpp21
-rw-r--r--src/gui/kernel/qpointingdevice.cpp42
-rw-r--r--src/gui/kernel/qtestsupport_gui.cpp24
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp9
-rw-r--r--src/gui/painting/qpdf.cpp13
-rw-r--r--src/gui/rhi/qrhigles2.cpp4
-rw-r--r--src/gui/text/coretext/qcoretextfontdatabase.mm144
-rw-r--r--src/gui/text/coretext/qcoretextfontdatabase_p.h2
-rw-r--r--src/gui/text/coretext/qfontengine_coretext.mm3
-rw-r--r--src/gui/text/qtextlayout.cpp20
-rw-r--r--src/gui/text/windows/qwindowsfontdatabasebase.cpp22
-rw-r--r--src/gui/text/windows/qwindowsfontdatabasebase_p.h2
-rw-r--r--src/gui/text/windows/qwindowsfontenginedirectwrite.cpp94
-rw-r--r--src/gui/text/windows/qwindowsfontenginedirectwrite_p.h3
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp117
-rw-r--r--src/network/access/qnetworkreply.cpp4
-rw-r--r--src/network/access/qnetworkreplyfileimpl.cpp3
-rw-r--r--src/network/kernel/qhostaddress.cpp2
-rw-r--r--src/network/socket/qabstractsocketengine_p.h2
-rw-r--r--src/network/socket/qhttpsocketengine.cpp2
-rw-r--r--src/network/socket/qhttpsocketengine_p.h2
-rw-r--r--src/network/socket/qnativesocketengine.cpp6
-rw-r--r--src/network/socket/qnativesocketengine_p.h4
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp4
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp12
-rw-r--r--src/network/socket/qsctpserver.cpp2
-rw-r--r--src/network/socket/qsctpsocket.cpp2
-rw-r--r--src/network/socket/qsocks5socketengine.cpp2
-rw-r--r--src/network/socket/qsocks5socketengine_p.h2
-rw-r--r--src/network/socket/qtcpserver.cpp2
-rw-r--r--src/opengl/qopengltextureglyphcache.cpp5
-rw-r--r--src/plugins/platforms/android/androidjniclipboard.cpp22
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp21
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp5
-rw-r--r--src/plugins/platforms/android/qandroidplatformservices.cpp11
-rw-r--r--src/plugins/platforms/android/qandroidplatformtheme.cpp81
-rw-r--r--src/plugins/platforms/android/qandroidplatformtheme.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm6
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm15
-rw-r--r--src/plugins/platforms/cocoa/qnsview_keys.mm9
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.mm9
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp17
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp163
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h7
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h6
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm4
-rw-r--r--src/plugins/platforms/ios/qiosmessagedialog.mm20
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm2
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm8
-rw-r--r--src/plugins/platforms/ios/quiview.mm53
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp80
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp1
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp12
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp5
-rw-r--r--src/plugins/platforms/xcb/CMakeLists.txt2
-rw-r--r--src/plugins/platforms/xcb/qt_xlib_wrapper.c44
-rw-r--r--src/plugins/platforms/xcb/qt_xlib_wrapper.h54
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp8
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3theme.cpp16
-rw-r--r--src/plugins/sqldrivers/.cmake.conf2
-rw-r--r--src/plugins/sqldrivers/oci/qsql_oci_p.h2
-rw-r--r--src/plugins/sqldrivers/odbc/qsql_odbc.cpp29
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm29
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p_p.h3
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle.cpp9
-rw-r--r--src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp16
-rw-r--r--src/testlib/doc/src/qttest-best-practices.qdoc3
-rw-r--r--src/tools/androiddeployqt/main.cpp95
-rw-r--r--src/tools/moc/moc.cpp6
-rw-r--r--src/widgets/accessible/complexwidgets.cpp10
-rw-r--r--src/widgets/accessible/complexwidgets_p.h1
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp2
-rw-r--r--src/widgets/itemviews/qheaderview.cpp41
-rw-r--r--src/widgets/itemviews/qtreeview.cpp20
-rw-r--r--src/widgets/kernel/qtestsupport_widgets.cpp29
-rw-r--r--src/widgets/kernel/qwidget.cpp31
-rw-r--r--src/widgets/styles/qcommonstyle.cpp2
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp22
-rw-r--r--src/widgets/util/qsystemtrayicon.cpp4
-rw-r--r--src/widgets/widgets/qdockwidget.cpp8
-rw-r--r--src/widgets/widgets/qmainwindowlayout.cpp15
-rw-r--r--tests/auto/cmake/mockplugins/.cmake.conf2
-rw-r--r--tests/auto/cmake/test_static_resources/.cmake.conf2
-rw-r--r--tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp8
-rw-r--r--tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp10
-rw-r--r--tests/auto/corelib/platform/android/CMakeLists.txt4
-rw-r--r--tests/auto/corelib/platform/android/tst_android.cpp102
-rw-r--r--tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp75
-rw-r--r--tests/auto/corelib/text/qstring/tst_qstring.cpp37
-rw-r--r--tests/auto/corelib/thread/CMakeLists.txt2
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp71
-rw-r--r--tests/auto/corelib/thread/qmutex/tst_qmutex.cpp29
-rw-r--r--tests/auto/corelib/tools/collections/tst_collections.cpp68
-rw-r--r--tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp1
-rw-r--r--tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp2
-rw-r--r--tests/auto/corelib/tools/qmap/tst_qmap.cpp6
-rw-r--r--tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp42
-rw-r--r--tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp2
-rw-r--r--tests/auto/gui/kernel/qpalette/tst_qpalette.cpp57
-rw-r--r--tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp5
-rw-r--r--tests/auto/gui/kernel/qwindow/tst_qwindow.cpp17
-rw-r--r--tests/auto/gui/qopengl/tst_qopengl.cpp2
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp13
-rw-r--r--tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp6
-rw-r--r--tests/auto/network/socket/qsocks5socketengine/BLACKLIST3
-rw-r--r--tests/auto/network/socket/qtcpserver/BLACKLIST1
-rw-r--r--tests/auto/network/socket/qtcpserver/crashingServer/main.cpp23
-rw-r--r--tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp23
-rw-r--r--tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp2
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp2
-rw-r--r--tests/auto/other/android/CMakeLists.txt21
-rw-r--r--tests/auto/other/android/testdata/assets/test.txt1
-rw-r--r--tests/auto/other/android/tst_android.cpp82
-rw-r--r--tests/auto/other/gestures/BLACKLIST30
-rw-r--r--tests/auto/other/gestures/tst_gestures.cpp14
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp41
-rw-r--r--tests/auto/sql/kernel/qsqldatabase/tst_databases.h10
-rw-r--r--tests/auto/testlib/selftests/catch_p_p.h28
-rw-r--r--tests/auto/testlib/selftests/qt_attribution.json2
-rw-r--r--tests/auto/testlib/selftests/tst_selftests.cpp5
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp9
-rw-r--r--tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp5
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp45
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp4
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp12
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp3
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp34
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp6
-rw-r--r--tests/auto/widgets/kernel/qaction/tst_qaction.cpp3
-rw-r--r--tests/auto/widgets/kernel/qapplication/BLACKLIST1
-rw-r--r--tests/auto/widgets/kernel/qapplication/CMakeLists.txt5
-rw-r--r--tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp3
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp3
-rw-r--r--tests/auto/widgets/kernel/qwidget/BLACKLIST5
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp154
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp6
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp14
-rw-r--r--tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp18
-rw-r--r--tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp6
-rw-r--r--tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp49
-rw-r--r--tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss10
-rw-r--r--tests/benchmarks/CMakeLists.txt4
-rw-r--r--tests/benchmarks/corelib/text/qlocale/main.cpp271
-rw-r--r--tests/benchmarks/corelib/text/qstring/main.cpp158
-rw-r--r--tests/benchmarks/corelib/tools/qhash/main.h6
-rw-r--r--tests/benchmarks/corelib/tools/qhash/outofline.cpp14
-rwxr-xr-xutil/cmake/pro2cmake.py2
263 files changed, 4223 insertions, 1886 deletions
diff --git a/.cmake.conf b/.cmake.conf
index 8d892e3b2e..ee5191b2a8 100644
--- a/.cmake.conf
+++ b/.cmake.conf
@@ -1,4 +1,4 @@
-set(QT_REPO_MODULE_VERSION "6.2.6")
+set(QT_REPO_MODULE_VERSION "6.2.7")
set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "")
# Minimum requirement for building Qt
diff --git a/.qmake.conf b/.qmake.conf
index 18c5f98f9a..fd2bfa6c11 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -6,4 +6,4 @@ DEFINES += QT_NO_JAVA_STYLE_ITERATORS
QT_SOURCE_TREE = $$PWD
QT_BUILD_TREE = $$shadowed($$PWD)
-MODULE_VERSION = 6.2.6
+MODULE_VERSION = 6.2.7
diff --git a/cmake/QtAndroidHelpers.cmake b/cmake/QtAndroidHelpers.cmake
index 24233ac622..9cdd3fa2aa 100644
--- a/cmake/QtAndroidHelpers.cmake
+++ b/cmake/QtAndroidHelpers.cmake
@@ -118,8 +118,9 @@ function(qt_internal_android_dependencies_content target file_content_out)
if (init_class)
set(init_class "initClass=\"${init_class}\"")
endif()
- file(TO_NATIVE_PATH ${jar_file} jar_file_native)
- string(APPEND file_contents "<jar file=\"${jar_file_native}\" ${init_class} />\n")
+ # Use unix path to allow using files on any host platform.
+ file(TO_CMAKE_PATH ${jar_file} jar_file_unix_path)
+ string(APPEND file_contents "<jar file=\"${jar_file_unix_path}\" ${init_class} />\n")
endforeach()
endif()
@@ -130,8 +131,10 @@ function(qt_internal_android_dependencies_content target file_content_out)
if (init_class)
set(init_class "initClass=\"${init_class}\"")
endif()
- file(TO_NATIVE_PATH ${bundle_file} jar_bundle_native)
- string(APPEND file_contents "<jar bundling=\"1\" file=\"${jar_bundle_native}\" ${init_class} />\n")
+ # Use unix path to allow using files on any host platform.
+ file(TO_CMAKE_PATH ${bundle_file} jar_bundle_unix_path)
+ string(APPEND file_contents
+ "<jar bundling=\"1\" file=\"${jar_bundle_unix_path}\" ${init_class} />\n")
endforeach()
endif()
@@ -143,8 +146,9 @@ function(qt_internal_android_dependencies_content target file_content_out)
if (lib_extends)
set(lib_extends "extends=\"${lib_extends}\"")
endif()
- file(TO_NATIVE_PATH ${lib_file} lib_file_native)
- string(APPEND file_contents "<lib file=\"${lib_file_native}\" ${lib_extends} />\n")
+ # Use unix path to allow using files on any host platform.
+ file(TO_CMAKE_PATH ${lib_file} lib_file_unix_path)
+ string(APPEND file_contents "<lib file=\"${lib_file_unix_path}\" ${lib_extends} />\n")
endforeach()
endif()
@@ -154,19 +158,23 @@ function(qt_internal_android_dependencies_content target file_content_out)
string(REPLACE ".so" "_${CMAKE_ANDROID_ARCH_ABI}.so" lib ${lib})
section(${lib} ":" lib_file lib_replacement)
if (lib_replacement)
- file(TO_NATIVE_PATH ${lib_replacement} lib_replacement_native)
- set(lib_replacement "replaces=\"${lib_replacement_native}\"")
+ # Use unix path to allow using files on any host platform.
+ file(TO_CMAKE_PATH ${lib_replacement} lib_replacement_unix_path)
+ set(lib_replacement "replaces=\"${lib_replacement_unix_path}\"")
endif()
- file(TO_NATIVE_PATH ${lib_file} lib_file_native)
- string(APPEND file_contents "<lib file=\"${lib_file_native}\" ${lib_replacement} />\n")
+ # Use unix path to allow using files on any host platform.
+ file(TO_CMAKE_PATH ${lib_file} lib_file_unix_path)
+ string(APPEND file_contents
+ "<lib file=\"${lib_file_unix_path}\" ${lib_replacement} />\n")
endforeach()
endif()
# Bundled files
if(arg_BUNDLED_FILES)
foreach(bundled_file IN LISTS arg_BUNDLED_FILES)
- file(TO_NATIVE_PATH ${bundled_file} file_native)
- string(APPEND file_contents "<bundled file=\"${file_native}\" />\n")
+ # Use unix path to allow using files on any host platform.
+ file(TO_CMAKE_PATH ${bundled_file} file_unix_path)
+ string(APPEND file_contents "<bundled file=\"${file_unix_path}\" />\n")
endforeach()
endif()
diff --git a/coin/module_config.yaml b/coin/module_config.yaml
index 10df2694d9..1924174bb8 100644
--- a/coin/module_config.yaml
+++ b/coin/module_config.yaml
@@ -1,4 +1,5 @@
version: 2
+alias: qtbase
accept_configuration:
condition: property
property: features
diff --git a/configure.cmake b/configure.cmake
index 57e46a9d16..c18d035b3f 100644
--- a/configure.cmake
+++ b/configure.cmake
@@ -55,7 +55,7 @@ qt_feature("use_bfd_linker"
PRIVATE
LABEL "bfd"
AUTODETECT false
- CONDITION NOT WIN32 AND NOT INTEGRITY AND NOT WASM AND TEST_use_bfd_linker
+ CONDITION NOT MSVC AND NOT INTEGRITY AND NOT WASM AND TEST_use_bfd_linker
ENABLE INPUT_linker STREQUAL 'bfd'
DISABLE INPUT_linker STREQUAL 'gold' OR INPUT_linker STREQUAL 'lld'
OR INPUT_linker STREQUAL 'mold'
@@ -81,7 +81,7 @@ qt_feature("use_lld_linker"
PRIVATE
LABEL "lld"
AUTODETECT false
- CONDITION NOT WIN32 AND NOT INTEGRITY AND NOT WASM AND TEST_use_lld_linker
+ CONDITION NOT MSVC AND NOT INTEGRITY AND NOT WASM AND TEST_use_lld_linker
ENABLE INPUT_linker STREQUAL 'lld'
DISABLE INPUT_linker STREQUAL 'bfd' OR INPUT_linker STREQUAL 'gold'
OR INPUT_linker STREQUAL 'mold'
diff --git a/doc/global/qt-cpp-defines.qdocconf b/doc/global/qt-cpp-defines.qdocconf
index e8664ac615..4d63c7fe06 100644
--- a/doc/global/qt-cpp-defines.qdocconf
+++ b/doc/global/qt-cpp-defines.qdocconf
@@ -166,6 +166,7 @@ Cpp.ignoretokens += \
QT_FASTCALL \
QT_MUTEX_LOCK_NOEXCEPT \
QT_POPCOUNT_CONSTEXPR \
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS \
QT_SIZEPOLICY_CONSTEXPR \
QT_WARNING_DISABLE_DEPRECATED \
QT_WARNING_PUSH \
diff --git a/examples/corelib/CMakeLists.txt b/examples/corelib/CMakeLists.txt
index 30e2c8cd1f..0a155606e5 100644
--- a/examples/corelib/CMakeLists.txt
+++ b/examples/corelib/CMakeLists.txt
@@ -1,6 +1,5 @@
# Generated from corelib.pro.
-add_subdirectory(bindableproperties)
add_subdirectory(ipc)
add_subdirectory(mimetypes)
add_subdirectory(serialization)
@@ -9,3 +8,6 @@ add_subdirectory(platform)
if(QT_FEATURE_thread)
add_subdirectory(threads)
endif()
+if(QT_FEATURE_widgets)
+ add_subdirectory(bindableproperties)
+endif()
diff --git a/examples/widgets/animation/easing/animation.h b/examples/widgets/animation/easing/animation.h
index 696257bb4a..d78997d5ff 100644
--- a/examples/widgets/animation/easing/animation.h
+++ b/examples/widgets/animation/easing/animation.h
@@ -62,8 +62,8 @@ public:
CirclePath,
NPathTypes
};
- Animation(QObject *target, const QByteArray &prop)
- : QPropertyAnimation(target, prop)
+ Animation(QObject *target, const QByteArray &prop, QObject *parent = nullptr)
+ : QPropertyAnimation(target, prop, parent)
{
setPathType(LinearPath);
}
diff --git a/examples/widgets/animation/easing/window.cpp b/examples/widgets/animation/easing/window.cpp
index 7b4fe1d912..d0deb843e4 100644
--- a/examples/widgets/animation/easing/window.cpp
+++ b/examples/widgets/animation/easing/window.cpp
@@ -82,7 +82,7 @@ Window::Window(QWidget *parent)
m_scene.addItem(m_item);
m_ui.graphicsView->setScene(&m_scene);
- m_anim = new Animation(m_item, "pos");
+ m_anim = new Animation(m_item, "pos", this);
m_anim->setEasingCurve(QEasingCurve::OutBounce);
m_ui.easingCurvePicker->setCurrentRow(int(QEasingCurve::OutBounce));
diff --git a/mkspecs/common/macx.conf b/mkspecs/common/macx.conf
index 2c1c90fd2b..561dcbb37b 100644
--- a/mkspecs/common/macx.conf
+++ b/mkspecs/common/macx.conf
@@ -9,7 +9,7 @@ QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.14
QT_MAC_SDK_VERSION_MIN = 11
-QT_MAC_SDK_VERSION_MAX = 12
+QT_MAC_SDK_VERSION_MAX = 13
device.sdk = macosx
device.target = device
diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp
index 632d955a93..31933bae63 100644
--- a/qmake/generators/unix/unixmake2.cpp
+++ b/qmake/generators/unix/unixmake2.cpp
@@ -825,7 +825,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
QString icon = fileFixify(var("ICON"));
t << "@$(DEL_FILE) " << info_plist_out << "\n\t"
- << "@sed ";
+ << "@plutil -convert xml1 -o - " << info_plist << " | "
+ << "sed ";
for (const ProString &arg : qAsConst(commonSedArgs))
t << arg;
const QString iconName = icon.section(Option::dir_sep, -1);
@@ -836,7 +837,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
<< "-e \"s,\\$${EXECUTABLE_NAME}," << (app_bundle_name.isEmpty() ? app_bundle_name : plugin_bundle_name) << ",g\" "
<< "-e \"s,@TYPEINFO@,"<< typeInfo << ",g\" "
<< "-e \"s,\\$${QMAKE_PKGINFO_TYPEINFO},"<< typeInfo << ",g\" "
- << "" << info_plist << " >" << info_plist_out << Qt::endl;
+ << ">" << info_plist_out << Qt::endl;
//copy the icon
if (!project->isEmpty("ICON")) {
QString dir = bundle_dir + "Contents/Resources/";
@@ -857,14 +858,15 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
if (!isShallowBundle)
symlinks[bundle_dir + "Resources"] = "Versions/Current/Resources";
t << "@$(DEL_FILE) " << info_plist_out << "\n\t"
- << "@sed ";
+ << "@plutil -convert xml1 -o - " << info_plist << " | "
+ << "sed ";
for (const ProString &arg : qAsConst(commonSedArgs))
t << arg;
t << "-e \"s,@LIBRARY@," << lib_bundle_name << ",g\" "
<< "-e \"s,\\$${EXECUTABLE_NAME}," << lib_bundle_name << ",g\" "
<< "-e \"s,@TYPEINFO@," << typeInfo << ",g\" "
<< "-e \"s,\\$${QMAKE_PKGINFO_TYPEINFO}," << typeInfo << ",g\" "
- << "" << info_plist << " >" << info_plist_out << Qt::endl;
+ << ">" << info_plist_out << Qt::endl;
}
break;
} // project->isActiveConfig("no_plist")
diff --git a/src/3rdparty/forkfd/forkfd_c11.h b/src/3rdparty/forkfd/forkfd_c11.h
index 2b1d3f181e..934ce55a11 100644
--- a/src/3rdparty/forkfd/forkfd_c11.h
+++ b/src/3rdparty/forkfd/forkfd_c11.h
@@ -48,7 +48,11 @@ typedef std::atomic<int> ffd_atomic_int;
typedef atomic_int ffd_atomic_int;
#endif
+#ifdef __cpp_lib_atomic_value_initialization
+#define FFD_ATOMIC_INIT(val) { val }
+#else
#define FFD_ATOMIC_INIT(val) ATOMIC_VAR_INIT(val)
+#endif
#define ffd_atomic_load(ptr, order) \
atomic_load_explicit(ptr, order)
diff --git a/src/3rdparty/libpng/ANNOUNCE b/src/3rdparty/libpng/ANNOUNCE
index ecf9c7043b..9c9bb18918 100644
--- a/src/3rdparty/libpng/ANNOUNCE
+++ b/src/3rdparty/libpng/ANNOUNCE
@@ -1,5 +1,5 @@
-libpng 1.6.37 - April 14, 2019
-==============================
+libpng 1.6.38 - September 14, 2022
+==================================
This is a public release of libpng, intended for use in production code.
@@ -9,13 +9,13 @@ Files available for download
Source files with LF line endings (for Unix/Linux):
- * libpng-1.6.37.tar.xz (LZMA-compressed, recommended)
- * libpng-1.6.37.tar.gz
+ * libpng-1.6.38.tar.xz (LZMA-compressed, recommended)
+ * libpng-1.6.38.tar.gz
Source files with CRLF line endings (for Windows):
- * lp1637.7z (LZMA-compressed, recommended)
- * lp1637.zip
+ * lp1638.7z (LZMA-compressed, recommended)
+ * lp1638.zip
Other information:
@@ -25,20 +25,13 @@ Other information:
* TRADEMARK.md
-Changes since the previous public release (version 1.6.36)
+Changes since the previous public release (version 1.6.37)
----------------------------------------------------------
- * Fixed a use-after-free vulnerability (CVE-2019-7317) in png_image_free.
- * Fixed a memory leak in the ARM NEON implementation of png_do_expand_palette.
- * Fixed a memory leak in pngtest.c.
- * Fixed two vulnerabilities (CVE-2018-14048, CVE-2018-14550) in
- contrib/pngminus; refactor.
- * Changed the license of contrib/pngminus to MIT; refresh makefile and docs.
- (Contributed by Willem van Schaik)
- * Fixed a typo in the libpng license v2.
- (Contributed by Miguel Ojeda)
- * Added makefiles for AddressSanitizer-enabled builds.
- * Cleaned up various makefiles.
+ * Added configurations and scripts for continuous integration.
+ * Fixed various errors in the handling of tRNS, hIST and eXIf.
+ * Implemented many stability improvements across all platforms.
+ * Updated the internal documentation.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
diff --git a/src/3rdparty/libpng/CHANGES b/src/3rdparty/libpng/CHANGES
index f0b0a9342c..9a86869681 100644
--- a/src/3rdparty/libpng/CHANGES
+++ b/src/3rdparty/libpng/CHANGES
@@ -2295,7 +2295,7 @@ Version 1.4.0beta58 [May 14, 2009]
Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri)
Version 1.4.0beta59 [May 15, 2009]
- Reformated sources in libpng style (3-space intentation, comment format)
+ Reformated sources in libpng style (3-space indentation, comment format)
Fixed typo in libpng docs (PNG_FILTER_AVE should be PNG_FILTER_AVG)
Added sections about the git repository and our coding style to the
documentation
@@ -3886,7 +3886,7 @@ Version 1.6.0beta06 [January 24, 2012]
Version 1.6.0beta07 [January 28, 2012]
Eliminated Intel icc/icl compiler warnings. The Intel (GCC derived)
compiler issues slightly different warnings from those issued by the
- current vesions of GCC. This eliminates those warnings by
+ current versions of GCC. This eliminates those warnings by
adding/removing casts and small code rewrites.
Updated configure.ac from autoupdate: added --enable-werror option.
Also some layout regularization and removal of introduced tab characters
@@ -6103,6 +6103,12 @@ Version 1.6.37 [April 14, 2019]
Added makefiles for AddressSanitizer-enabled builds.
Cleaned up various makefiles.
+Version 1.6.38 [September 14, 2022]
+ Added configurations and scripts for continuous integration.
+ Fixed various errors in the handling of tRNS, hIST and eXIf.
+ Implemented many stability improvements across all platforms.
+ Updated the internal documentation.
+
Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
Subscription is required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
diff --git a/src/3rdparty/libpng/CMakeLists.txt b/src/3rdparty/libpng/CMakeLists.txt
index 637ebcf548..1714bf9987 100644
--- a/src/3rdparty/libpng/CMakeLists.txt
+++ b/src/3rdparty/libpng/CMakeLists.txt
@@ -27,6 +27,8 @@ qt_internal_add_3rdparty_library(BundledLibpng
DEFINES
PNG_ARM_NEON_OPT=0
PNG_POWERPC_VSX_OPT=0
+ PNG_IMPEXP=
+ _CRT_SECURE_NO_DEPRECATE
PUBLIC_INCLUDE_DIRECTORIES
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
)
diff --git a/src/3rdparty/libpng/INSTALL b/src/3rdparty/libpng/INSTALL
index 4c17022515..d3aaa28842 100644
--- a/src/3rdparty/libpng/INSTALL
+++ b/src/3rdparty/libpng/INSTALL
@@ -128,16 +128,18 @@ Your directory structure should look like this:
README
*.h, *.c => libpng source files
CMakeLists.txt => "cmake" script
+ ci
+ ci_*.sh
configuration files:
configure.ac, configure, Makefile.am, Makefile.in,
autogen.sh, config.guess, ltmain.sh, missing, libpng.pc.in,
libpng-config.in, aclocal.m4, config.h.in, config.sub,
- depcomp, install-sh, mkinstalldirs, test-pngtest.sh
+ depcomp, install-sh, mkinstalldirs, test-pngtest.sh, etc.
contrib
arm-neon, conftest, examples, gregbook, libtests, pngminim,
pngminus, pngsuite, tools, visupng
projects
- cbuilder5, owatcom, visualc71, vstudio, xcode
+ owatcom, visualc71, vstudio
scripts
makefile.*
*.def (module definition files)
@@ -145,7 +147,7 @@ Your directory structure should look like this:
pngtest.png
etc.
zlib
- README, *.h, *.c contrib, etc.
+ README, *.h, *.c, contrib, etc.
If the line endings in the files look funny, you may wish to get the other
distribution of libpng. It is available in both tar.gz (UNIX style line
@@ -153,28 +155,27 @@ endings) and zip (DOS style line endings) formats.
VI. Building with project files
-If you are building libpng with MSVC, you can enter the
-libpng projects\visualc71 or vstudio directory and follow the instructions
-in README.txt.
+If you are building libpng with Microsoft Visual Studio, you can enter
+the directory projects\visualc71 or projects\vstudio and follow the
+instructions in README.txt.
-Otherwise enter the zlib directory and follow the instructions in zlib/README,
-then come back here and run "configure" or choose the appropriate
-makefile.sys in the scripts directory.
+Otherwise, enter the zlib directory and follow the instructions in
+zlib/README, then come back here and run "configure" or choose the
+appropriate makefile in the scripts directory.
VII. Building with makefiles
Copy the file (or files) that you need from the
scripts directory into this directory, for example
-MSDOS example:
+UNIX example:
- copy scripts\makefile.msc makefile
- copy scripts\pnglibconf.h.prebuilt pnglibconf.h
+ cp scripts/makefile.std Makefile
+ make
-UNIX example:
+Windows example:
- cp scripts/makefile.std makefile
- cp scripts/pnglibconf.h.prebuilt pnglibconf.h
+ nmake -f scripts\makefile.vcwin32
Read the makefile to see if you need to change any source or
target directories to match your preferences.
@@ -197,30 +198,27 @@ do that, run "make install" in the zlib directory first if necessary).
Some also allow you to run "make test-installed" after you have
run "make install".
-VIII. Configuring libpng for 16-bit platforms
-
-You will want to look into zconf.h to tell zlib (and thus libpng) that
-it cannot allocate more than 64K at a time. Even if you can, the memory
-won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K.
+VIII. Configuring for DOS and other 16-bit platforms
-IX. Configuring for DOS
+Officially, the support for 16-bit platforms has been removed.
For DOS users who only have access to the lower 640K, you will
have to limit zlib's memory usage via a png_set_compression_mem_level()
call. See zlib.h or zconf.h in the zlib library for more information.
-X. Configuring for Medium Model
+You may be or may not be in luck if you target the "large" memory model,
+but all the smaller models ("small", "compact" and "medium") are known
+to be unworkable. For DOS users who have access beyond the lower 640K,
+a "flat" 32-bit DOS model (such as DJGPP) is strongly recommended.
-Libpng's support for medium model has been tested on most of the popular
-compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets
-defined, and FAR gets defined to far in pngconf.h, and you should be
-all set. Everything in the library (except for zlib's structure) is
-expecting far data. You must use the typedefs with the p or pp on
-the end for pointers (or at least look at them and be careful). Make
-note that the rows of data are defined as png_bytepp, which is
-an "unsigned char far * far *".
+For DOS users who only have access to the lower 640K, you will have to
+limit zlib's memory usage via a png_set_compression_mem_level() call.
+You will also have to look into zconf.h to tell zlib (and thus libpng)
+that it cannot allocate more than 64K at a time. Even if you can, the
+memory won't be accessible. Therefore, you should limit zlib and libpng
+to 64K by defining MAXSEG_64K.
-XI. Prepending a prefix to exported symbols
+IX. Prepending a prefix to exported symbols
Starting with libpng-1.6.0, you can configure libpng (when using the
"configure" script) to prefix all exported symbols by means of the
@@ -231,7 +229,7 @@ identifier). This creates a set of macros in pnglibconf.h, so this is
transparent to applications; their function calls get transformed by
the macros to use the modified names.
-XII. Configuring for compiler xxx:
+X. Configuring for compiler xxx:
All includes for libpng are in pngconf.h. If you need to add, change
or delete an include, this is the place to do it.
@@ -243,7 +241,7 @@ As of libpng-1.5.0, pngpriv.h also includes three other private header
files, pngstruct.h, pnginfo.h, and pngdebug.h, which contain material
that previously appeared in the public headers.
-XIII. Removing unwanted object code
+XI. Removing unwanted object code
There are a bunch of #define's in pngconf.h that control what parts of
libpng are compiled. All the defines end in _SUPPORTED. If you are
@@ -282,7 +280,7 @@ library to fail if they call functions not available in your library.
The size of the library itself should not be an issue, because only
those sections that are actually used will be loaded into memory.
-XIV. Enabling or disabling hardware optimizations
+XII. Enabling or disabling hardware optimizations
Certain hardware capabilities, such as the Intel SSE instructions,
are normally detected at run time. Enable them with configure options
@@ -332,7 +330,7 @@ or disable them all at once with
cmake . -DPNG_HARDWARE_OPTIMIZATIONS=no
-XV. Changes to the build and configuration of libpng in libpng-1.5.x
+XIII. Changes to the build and configuration of libpng in libpng-1.5.x
Details of internal changes to the library code can be found in the CHANGES
file and in the GIT repository logs. These will be of no concern to the vast
@@ -423,7 +421,7 @@ $PREFIX/include directory). Do not edit pnglibconf.h after you have built
libpng, because than the settings would not accurately reflect the settings
that were used to build libpng.
-XVI. Setjmp/longjmp issues
+XIV. Setjmp/longjmp issues
Libpng uses setjmp()/longjmp() for error handling. Unfortunately setjmp()
is known to be not thread-safe on some platforms and we don't know of
@@ -441,7 +439,7 @@ This requires setjmp/longjmp, so you must either build the library
with PNG_SETJMP_SUPPORTED defined, or with PNG_SIMPLIFIED_READ_SUPPORTED
and PNG_SIMPLIFIED_WRITE_SUPPORTED undefined.
-XVII. Common linking failures
+XV. Common linking failures
If your application fails to find libpng or zlib entries while linking:
@@ -453,12 +451,13 @@ If your application fails to find libpng or zlib entries while linking:
If you are using the vstudio project, observe the WARNING in
project/vstudio/README.txt.
-XVIII. Other sources of information about libpng:
+XVI. Other sources of information about libpng:
Further information can be found in the README and libpng-manual.txt
files, in the individual makefiles, in png.h, and the manual pages
libpng.3 and png.5.
+Copyright (c) 2022 Cosmin Truta
Copyright (c) 1998-2002,2006-2016 Glenn Randers-Pehrson
This document is released under the libpng license.
For conditions of distribution and use, see the disclaimer
diff --git a/src/3rdparty/libpng/LICENSE b/src/3rdparty/libpng/LICENSE
index e0c5b531cf..c8ad24eecf 100644
--- a/src/3rdparty/libpng/LICENSE
+++ b/src/3rdparty/libpng/LICENSE
@@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
PNG Reference Library License version 2
---------------------------------------
- * Copyright (c) 1995-2019 The PNG Reference Library Authors.
- * Copyright (c) 2018-2019 Cosmin Truta.
+ * Copyright (c) 1995-2022 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2022 Cosmin Truta.
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
* Copyright (c) 1996-1997 Andreas Dilger.
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
diff --git a/src/3rdparty/libpng/README b/src/3rdparty/libpng/README
index cfc1f0e3dc..e6e72aa547 100644
--- a/src/3rdparty/libpng/README
+++ b/src/3rdparty/libpng/README
@@ -1,12 +1,12 @@
-README for libpng version 1.6.37 - April 14, 2019
-=================================================
+README for libpng version 1.6.38
+================================
See the note about version numbers near the top of png.h.
See INSTALL for instructions on how to install libpng.
Libpng comes in several distribution formats. Get libpng-*.tar.gz or
-libpng-*.tar.xz or if you want UNIX-style line endings in the text
-files, or lpng*.7z or lpng*.zip if you want DOS-style line endings.
+libpng-*.tar.xz if you want UNIX-style line endings in the text files,
+or lpng*.7z or lpng*.zip if you want DOS-style line endings.
Version 0.89 was the first official release of libpng. Don't let the
fact that it's the first release fool you. The libpng library has been
diff --git a/src/3rdparty/libpng/libpng-manual.txt b/src/3rdparty/libpng/libpng-manual.txt
index 5dad92fbf7..19b1e0c356 100644
--- a/src/3rdparty/libpng/libpng-manual.txt
+++ b/src/3rdparty/libpng/libpng-manual.txt
@@ -1,6 +1,6 @@
libpng-manual.txt - A description on how to use and modify libpng
- Copyright (c) 2018-2019 Cosmin Truta
+ Copyright (c) 2018-2022 Cosmin Truta
Copyright (c) 1998-2018 Glenn Randers-Pehrson
This document is released under the libpng license.
@@ -9,9 +9,9 @@ libpng-manual.txt - A description on how to use and modify libpng
Based on:
- libpng version 1.6.36, December 2018, through 1.6.37 - April 2019
+ libpng version 1.6.36, December 2018, through 1.6.38 - September 2022
Updated and distributed by Cosmin Truta
- Copyright (c) 2018-2019 Cosmin Truta
+ Copyright (c) 2018-2022 Cosmin Truta
libpng versions 0.97, January 1998, through 1.6.35 - July 2018
Updated and distributed by Glenn Randers-Pehrson
@@ -1792,7 +1792,7 @@ the information. If, instead, you want to convert the image to an opaque
version with no alpha channel use png_set_background; see below.
As of libpng version 1.5.2, almost all useful expansions are supported, the
-major ommissions are conversion of grayscale to indexed images (which can be
+major omissions are conversion of grayscale to indexed images (which can be
done trivially in the application) and conversion of indexed to grayscale (which
can be done by a trivial manipulation of the palette.)
diff --git a/src/3rdparty/libpng/png.c b/src/3rdparty/libpng/png.c
index 757c755f97..fc09564262 100644
--- a/src/3rdparty/libpng/png.c
+++ b/src/3rdparty/libpng/png.c
@@ -1,7 +1,7 @@
/* png.c - location for general purpose libpng functions
*
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -14,7 +14,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_37 Your_png_h_is_not_version_1_6_37;
+typedef png_libpng_version_1_6_38 Your_png_h_is_not_version_1_6_38;
#ifdef __GNUC__
/* The version tests may need to be added to, but the problem warning has
@@ -720,7 +720,7 @@ png_init_io(png_structrp png_ptr, png_FILE_p fp)
*
* Where UNSIGNED_MAX is the appropriate maximum unsigned value, so when the
* negative integral value is added the result will be an unsigned value
- * correspnding to the 2's complement representation.
+ * corresponding to the 2's complement representation.
*/
void PNGAPI
png_save_int_32(png_bytep buf, png_int_32 i)
@@ -815,8 +815,8 @@ png_get_copyright(png_const_structrp png_ptr)
return PNG_STRING_COPYRIGHT
#else
return PNG_STRING_NEWLINE \
- "libpng version 1.6.37" PNG_STRING_NEWLINE \
- "Copyright (c) 2018-2019 Cosmin Truta" PNG_STRING_NEWLINE \
+ "libpng version 1.6.38" PNG_STRING_NEWLINE \
+ "Copyright (c) 2018-2022 Cosmin Truta" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
@@ -1843,12 +1843,12 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
# ifdef PNG_WARNINGS_SUPPORTED
else
{
- char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/
+ char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114 */
pos = png_safecat(message, (sizeof message), pos,
png_format_number(number, number+(sizeof number),
PNG_NUMBER_FORMAT_x, value));
- pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/
+ pos = png_safecat(message, (sizeof message), pos, "h: "); /* +2 = 116 */
}
# endif
/* The 'reason' is an arbitrary message, allow +79 maximum 195 */
diff --git a/src/3rdparty/libpng/png.h b/src/3rdparty/libpng/png.h
index 139eb0dc0f..5fb494fb1a 100644
--- a/src/3rdparty/libpng/png.h
+++ b/src/3rdparty/libpng/png.h
@@ -1,9 +1,9 @@
/* png.h - header file for PNG reference library
*
- * libpng version 1.6.37 - April 14, 2019
+ * libpng version 1.6.38 - September 14, 2022
*
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -15,7 +15,7 @@
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
* libpng versions 0.97, January 1998, through 1.6.35, July 2018:
* Glenn Randers-Pehrson
- * libpng versions 1.6.36, December 2018, through 1.6.37, April 2019:
+ * libpng versions 1.6.36, December 2018, through 1.6.38, September 2022:
* Cosmin Truta
* See also "Contributing Authors", below.
*/
@@ -27,8 +27,8 @@
* PNG Reference Library License version 2
* ---------------------------------------
*
- * * Copyright (c) 1995-2019 The PNG Reference Library Authors.
- * * Copyright (c) 2018-2019 Cosmin Truta.
+ * * Copyright (c) 1995-2022 The PNG Reference Library Authors.
+ * * Copyright (c) 2018-2022 Cosmin Truta.
* * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
* * Copyright (c) 1996-1997 Andreas Dilger.
* * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -239,7 +239,7 @@
* ...
* 1.5.30 15 10530 15.so.15.30[.0]
* ...
- * 1.6.37 16 10637 16.so.16.37[.0]
+ * 1.6.38 16 10638 16.so.16.38[.0]
*
* Henceforth the source version will match the shared-library major and
* minor numbers; the shared-library major version number will be used for
@@ -278,8 +278,8 @@
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.37"
-#define PNG_HEADER_VERSION_STRING " libpng version 1.6.37 - April 14, 2019\n"
+#define PNG_LIBPNG_VER_STRING "1.6.38"
+#define PNG_HEADER_VERSION_STRING " libpng version 1.6.38 - September 14, 2022\n"
#define PNG_LIBPNG_VER_SONUM 16
#define PNG_LIBPNG_VER_DLLNUM 16
@@ -287,7 +287,7 @@
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6
-#define PNG_LIBPNG_VER_RELEASE 37
+#define PNG_LIBPNG_VER_RELEASE 38
/* This should be zero for a public release, or non-zero for a
* development version. [Deprecated]
@@ -318,7 +318,7 @@
* From version 1.0.1 it is:
* XXYYZZ, where XX=major, YY=minor, ZZ=release
*/
-#define PNG_LIBPNG_VER 10637 /* 1.6.37 */
+#define PNG_LIBPNG_VER 10638 /* 1.6.38 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -428,7 +428,7 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_6_37;
+typedef char* png_libpng_version_1_6_38;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
@@ -1446,7 +1446,7 @@ PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action,
* mainly useful for testing, as the defaults should work with most users.
* Those users who are tight on memory or want faster performance at the
* expense of compression can modify them. See the compression library
- * header file (zlib.h) for an explination of the compression functions.
+ * header file (zlib.h) for an explanation of the compression functions.
*/
/* Set the filtering method(s) used by libpng. Currently, the only valid
@@ -1501,7 +1501,7 @@ PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
* 0 - 9, corresponding directly to the zlib compression levels 0 - 9
* (0 - no compression, 9 - "maximal" compression). Note that tests have
* shown that zlib compression levels 3-6 usually perform as well as level 9
- * for PNG images, and do considerably fewer caclulations. In the future,
+ * for PNG images, and do considerably fewer calculations. In the future,
* these values may not correspond directly to the zlib compression levels.
*/
#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
diff --git a/src/3rdparty/libpng/pngconf.h b/src/3rdparty/libpng/pngconf.h
index 927a769dbe..89d28f83a0 100644
--- a/src/3rdparty/libpng/pngconf.h
+++ b/src/3rdparty/libpng/pngconf.h
@@ -1,9 +1,9 @@
/* pngconf.h - machine-configurable file for libpng
*
- * libpng version 1.6.37
+ * libpng version 1.6.38
*
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -180,8 +180,8 @@
* compiler-specific macros to the values required to change the calling
* conventions of the various functions.
*/
-#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
- defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \
+ defined(__CYGWIN__)
/* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or
* MinGW on any architecture currently supported by Windows. Also includes
* Watcom builds but these need special treatment because they are not
diff --git a/src/3rdparty/libpng/pngget.c b/src/3rdparty/libpng/pngget.c
index 5abf1efd9f..e44933c0d2 100644
--- a/src/3rdparty/libpng/pngget.c
+++ b/src/3rdparty/libpng/pngget.c
@@ -1151,7 +1151,7 @@ png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr,
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
png_byte PNGAPI
-png_get_rgb_to_gray_status (png_const_structrp png_ptr)
+png_get_rgb_to_gray_status(png_const_structrp png_ptr)
{
return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0);
}
@@ -1192,27 +1192,27 @@ png_get_compression_buffer_size(png_const_structrp png_ptr)
/* These functions were added to libpng 1.2.6 and were enabled
* by default in libpng-1.4.0 */
png_uint_32 PNGAPI
-png_get_user_width_max (png_const_structrp png_ptr)
+png_get_user_width_max(png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_width_max : 0);
}
png_uint_32 PNGAPI
-png_get_user_height_max (png_const_structrp png_ptr)
+png_get_user_height_max(png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_height_max : 0);
}
/* This function was added to libpng 1.4.0 */
png_uint_32 PNGAPI
-png_get_chunk_cache_max (png_const_structrp png_ptr)
+png_get_chunk_cache_max(png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_chunk_cache_max : 0);
}
/* This function was added to libpng 1.4.1 */
png_alloc_size_t PNGAPI
-png_get_chunk_malloc_max (png_const_structrp png_ptr)
+png_get_chunk_malloc_max(png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_chunk_malloc_max : 0);
}
@@ -1221,13 +1221,13 @@ png_get_chunk_malloc_max (png_const_structrp png_ptr)
/* These functions were added to libpng 1.4.0 */
#ifdef PNG_IO_STATE_SUPPORTED
png_uint_32 PNGAPI
-png_get_io_state (png_const_structrp png_ptr)
+png_get_io_state(png_const_structrp png_ptr)
{
return png_ptr->io_state;
}
png_uint_32 PNGAPI
-png_get_io_chunk_type (png_const_structrp png_ptr)
+png_get_io_chunk_type(png_const_structrp png_ptr)
{
return png_ptr->chunk_name;
}
diff --git a/src/3rdparty/libpng/pnglibconf.h b/src/3rdparty/libpng/pnglibconf.h
index e1e27e957e..89d5b4c8ad 100644
--- a/src/3rdparty/libpng/pnglibconf.h
+++ b/src/3rdparty/libpng/pnglibconf.h
@@ -1,8 +1,8 @@
/* pnglibconf.h - library build configuration */
-/* libpng version 1.6.37 */
+/* libpng version 1.6.38 */
-/* Copyright (c) 2018-2019 Cosmin Truta */
+/* Copyright (c) 2018-2022 Cosmin Truta */
/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */
diff --git a/src/3rdparty/libpng/pngpriv.h b/src/3rdparty/libpng/pngpriv.h
index acfc9cf280..2e426cf47d 100644
--- a/src/3rdparty/libpng/pngpriv.h
+++ b/src/3rdparty/libpng/pngpriv.h
@@ -1,7 +1,7 @@
/* pngpriv.h - private declarations for use inside libpng
*
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -23,12 +23,6 @@
#ifndef PNGPRIV_H
#define PNGPRIV_H
-#ifdef _MSC_VER
-# ifndef _CRT_SECURE_NO_DEPRECATE
-# define _CRT_SECURE_NO_DEPRECATE
-# endif
-#endif
-
/* Feature Test Macros. The following are defined here to ensure that correctly
* implemented libraries reveal the APIs libpng needs to build and hide those
* that are not needed and potentially damaging to the compilation.
@@ -180,7 +174,7 @@
# else /* !defined __ARM_NEON__ */
/* The 'intrinsics' code simply won't compile without this -mfpu=neon:
*/
-# if !defined(__aarch64__)
+# if !defined(__aarch64__) && !defined(_M_ARM64)
/* The assembler code currently does not work on ARM64 */
# define PNG_ARM_NEON_IMPLEMENTATION 2
# endif /* __aarch64__ */
@@ -191,6 +185,8 @@
/* Use the intrinsics code by default. */
# define PNG_ARM_NEON_IMPLEMENTATION 1
# endif
+#else /* PNG_ARM_NEON_OPT == 0 */
+# define PNG_ARM_NEON_IMPLEMENTATION 0
#endif /* PNG_ARM_NEON_OPT > 0 */
#ifndef PNG_MIPS_MSA_OPT
@@ -269,11 +265,15 @@
# ifndef PNG_MIPS_MSA_IMPLEMENTATION
# define PNG_MIPS_MSA_IMPLEMENTATION 1
# endif
+#else
+# define PNG_MIPS_MSA_IMPLEMENTATION 0
#endif /* PNG_MIPS_MSA_OPT > 0 */
#if PNG_POWERPC_VSX_OPT > 0
# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx
# define PNG_POWERPC_VSX_IMPLEMENTATION 1
+#else
+# define PNG_POWERPC_VSX_IMPLEMENTATION 0
#endif
@@ -314,11 +314,6 @@
# endif
#endif /* Setting PNG_BUILD_DLL if required */
-/* Modfied for usage in Qt: Do not export the libpng APIs */
-#ifdef PNG_BUILD_DLL
-#undef PNG_BUILD_DLL
-#endif
-
/* See pngconf.h for more details: the builder of the library may set this on
* the command line to the right thing for the specific compilation system or it
* may be automagically set above (at present we know of no system where it does
@@ -503,16 +498,7 @@
static_cast<type>(static_cast<const void*>(value))
#else
# define png_voidcast(type, value) (value)
-# ifdef _WIN64
-# ifdef __GNUC__
- typedef unsigned long long png_ptruint;
-# else
- typedef unsigned __int64 png_ptruint;
-# endif
-# else
- typedef unsigned long png_ptruint;
-# endif
-# define png_constcast(type, value) ((type)(png_ptruint)(const void*)(value))
+# define png_constcast(type, value) ((type)(void*)(const void*)(value))
# define png_aligncast(type, value) ((void*)(value))
# define png_aligncastconst(type, value) ((const void*)(value))
#endif /* __cplusplus */
@@ -554,9 +540,8 @@
# include <alloc.h>
#endif
-#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \
- defined(_WIN32) || defined(__WIN32__)
-# include <windows.h> /* defines _WINDOWS_ macro */
+#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
+# include <windows.h>
#endif
#endif /* PNG_VERSION_INFO_ONLY */
@@ -565,24 +550,20 @@
* functions that are passed far data must be model-independent.
*/
-/* Memory model/platform independent fns */
+/* Platform-independent functions */
#ifndef PNG_ABORT
-# if (defined(_WINDOWS_) || defined(_WIN32_WCE))
-# define PNG_ABORT() ExitProcess(0)
-# else
-# define PNG_ABORT() abort()
-# endif
+# define PNG_ABORT() abort()
#endif
/* These macros may need to be architecture dependent. */
-#define PNG_ALIGN_NONE 0 /* do not use data alignment */
-#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */
+#define PNG_ALIGN_NONE 0 /* do not use data alignment */
+#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */
#ifdef offsetof
-# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */
+# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */
#else
# define PNG_ALIGN_OFFSET -1 /* prevent the use of this */
#endif
-#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */
+#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */
#ifndef PNG_ALIGN_TYPE
/* Default to using aligned access optimizations and requiring alignment to a
@@ -596,26 +577,25 @@
/* This is used because in some compiler implementations non-aligned
* structure members are supported, so the offsetof approach below fails.
* Set PNG_ALIGN_SIZE=0 for compiler combinations where unaligned access
- * is good for performance. Do not do this unless you have tested the result
- * and understand it.
+ * is good for performance. Do not do this unless you have tested the
+ * result and understand it.
*/
-# define png_alignof(type) (sizeof (type))
+# define png_alignof(type) (sizeof(type))
#else
# if PNG_ALIGN_TYPE == PNG_ALIGN_OFFSET
-# define png_alignof(type) offsetof(struct{char c; type t;}, t)
+# define png_alignof(type) offsetof(struct{char c; type t;}, t)
# else
-# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS
-# define png_alignof(type) (1)
-# endif
- /* Else leave png_alignof undefined to prevent use thereof */
+# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS
+# define png_alignof(type) 1
+# endif
+ /* Else leave png_alignof undefined to prevent use thereof */
# endif
#endif
-/* This implicitly assumes alignment is always to a power of 2. */
+/* This implicitly assumes alignment is always a multiple of 2. */
#ifdef png_alignof
-# define png_isaligned(ptr, type)\
- (((type)((const char*)ptr-(const char*)0) & \
- (type)(png_alignof(type)-1)) == 0)
+# define png_isaligned(ptr, type) \
+ (((type)(size_t)((const void*)(ptr)) & (type)(png_alignof(type)-1)) == 0)
#else
# define png_isaligned(ptr, type) 0
#endif
diff --git a/src/3rdparty/libpng/pngread.c b/src/3rdparty/libpng/pngread.c
index 8fa7d9f162..5ab9224038 100644
--- a/src/3rdparty/libpng/pngread.c
+++ b/src/3rdparty/libpng/pngread.c
@@ -3452,7 +3452,6 @@ png_image_read_background(png_voidp argument)
for (pass = 0; pass < passes; ++pass)
{
- png_bytep row = png_voidcast(png_bytep, display->first_row);
unsigned int startx, stepx, stepy;
png_uint_32 y;
@@ -3557,8 +3556,6 @@ png_image_read_background(png_voidp argument)
inrow += 2; /* gray and alpha channel */
}
-
- row += display->row_bytes;
}
}
}
diff --git a/src/3rdparty/libpng/pngrtran.c b/src/3rdparty/libpng/pngrtran.c
index 9a8fad9f4a..238f5afe7e 100644
--- a/src/3rdparty/libpng/pngrtran.c
+++ b/src/3rdparty/libpng/pngrtran.c
@@ -21,7 +21,7 @@
#ifdef PNG_ARM_NEON_IMPLEMENTATION
# if PNG_ARM_NEON_IMPLEMENTATION == 1
# define PNG_ARM_NEON_INTRINSICS_AVAILABLE
-# if defined(_MSC_VER) && defined(_M_ARM64)
+# if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64)
# include <arm64_neon.h>
# else
# include <arm_neon.h>
diff --git a/src/3rdparty/libpng/pngrutil.c b/src/3rdparty/libpng/pngrutil.c
index 4db3de990b..ca060dd15f 100644
--- a/src/3rdparty/libpng/pngrutil.c
+++ b/src/3rdparty/libpng/pngrutil.c
@@ -1,7 +1,7 @@
/* pngrutil.c - utilities to read a PNG file
*
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -302,7 +302,6 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
if (buffer != NULL && new_size > png_ptr->read_buffer_size)
{
png_ptr->read_buffer = NULL;
- png_ptr->read_buffer = NULL;
png_ptr->read_buffer_size = 0;
png_free(png_ptr, buffer);
buffer = NULL;
@@ -2076,14 +2075,17 @@ png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
png_byte buf[1];
png_crc_read(png_ptr, buf, 1);
info_ptr->eXIf_buf[i] = buf[0];
- if (i == 1 && buf[0] != 'M' && buf[0] != 'I'
- && info_ptr->eXIf_buf[0] != buf[0])
+ if (i == 1)
{
- png_crc_finish(png_ptr, length);
- png_chunk_benign_error(png_ptr, "incorrect byte-order specifier");
- png_free(png_ptr, info_ptr->eXIf_buf);
- info_ptr->eXIf_buf = NULL;
- return;
+ if ((buf[0] != 'M' && buf[0] != 'I') ||
+ (info_ptr->eXIf_buf[0] != buf[0]))
+ {
+ png_crc_finish(png_ptr, length - 2);
+ png_chunk_benign_error(png_ptr, "incorrect byte-order specifier");
+ png_free(png_ptr, info_ptr->eXIf_buf);
+ info_ptr->eXIf_buf = NULL;
+ return;
+ }
}
}
@@ -2124,8 +2126,9 @@ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
num = length / 2 ;
- if (num != (unsigned int) png_ptr->num_palette ||
- num > (unsigned int) PNG_MAX_PALETTE_LENGTH)
+ if (length != num * 2 ||
+ num != (unsigned int)png_ptr->num_palette ||
+ num > (unsigned int)PNG_MAX_PALETTE_LENGTH)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "invalid");
@@ -4619,14 +4622,13 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
*/
{
png_bytep temp = png_ptr->big_row_buf + 32;
- int extra = (int)((temp - (png_bytep)0) & 0x0f);
+ size_t extra = (size_t)temp & 0x0f;
png_ptr->row_buf = temp - extra - 1/*filter byte*/;
temp = png_ptr->big_prev_row + 32;
- extra = (int)((temp - (png_bytep)0) & 0x0f);
+ extra = (size_t)temp & 0x0f;
png_ptr->prev_row = temp - extra - 1/*filter byte*/;
}
-
#else
/* Use 31 bytes of padding before and 17 bytes after row_buf. */
png_ptr->row_buf = png_ptr->big_row_buf + 31;
diff --git a/src/3rdparty/libpng/pngset.c b/src/3rdparty/libpng/pngset.c
index ec75dbe369..8c372cf415 100644
--- a/src/3rdparty/libpng/pngset.c
+++ b/src/3rdparty/libpng/pngset.c
@@ -1,7 +1,7 @@
/* pngset.c - storage of image information into info struct
*
- * Copyright (c) 2018 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -1019,6 +1019,9 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
info_ptr->trans_alpha = png_voidcast(png_bytep,
png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans);
+
+ info_ptr->valid |= PNG_INFO_tRNS;
+ info_ptr->free_me |= PNG_FREE_TRNS;
}
png_ptr->trans_alpha = info_ptr->trans_alpha;
}
@@ -1326,7 +1329,7 @@ png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
#ifdef PNG_MNG_FEATURES_SUPPORTED
png_uint_32 PNGAPI
-png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
+png_permit_mng_features(png_structrp png_ptr, png_uint_32 mng_features)
{
png_debug(1, "in png_permit_mng_features");
@@ -1633,7 +1636,7 @@ png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* This function was added to libpng 1.2.6 */
void PNGAPI
-png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
+png_set_user_limits(png_structrp png_ptr, png_uint_32 user_width_max,
png_uint_32 user_height_max)
{
/* Images with dimensions larger than these limits will be
@@ -1649,7 +1652,7 @@ png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
/* This function was added to libpng 1.4.0 */
void PNGAPI
-png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
+png_set_chunk_cache_max(png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
{
if (png_ptr != NULL)
png_ptr->user_chunk_cache_max = user_chunk_cache_max;
@@ -1657,7 +1660,7 @@ png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
/* This function was added to libpng 1.4.1 */
void PNGAPI
-png_set_chunk_malloc_max (png_structrp png_ptr,
+png_set_chunk_malloc_max(png_structrp png_ptr,
png_alloc_size_t user_chunk_malloc_max)
{
if (png_ptr != NULL)
diff --git a/src/3rdparty/libpng/pngstruct.h b/src/3rdparty/libpng/pngstruct.h
index 8bdc7ce46d..e591d94d58 100644
--- a/src/3rdparty/libpng/pngstruct.h
+++ b/src/3rdparty/libpng/pngstruct.h
@@ -1,7 +1,7 @@
/* pngstruct.h - header file for PNG reference library
*
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -334,18 +334,8 @@ struct png_struct_def
size_t current_buffer_size; /* amount of data now in current_buffer */
int process_mode; /* what push library is currently doing */
int cur_palette; /* current push library palette index */
-
#endif /* PROGRESSIVE_READ */
-#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
-/* For the Borland special 64K segment handler */
- png_bytepp offset_table_ptr;
- png_bytep offset_table;
- png_uint_16 offset_table_number;
- png_uint_16 offset_table_count;
- png_uint_16 offset_table_count_free;
-#endif
-
#ifdef PNG_READ_QUANTIZE_SUPPORTED
png_bytep palette_lookup; /* lookup table for quantizing */
png_bytep quantize_index; /* index translation for palette files */
diff --git a/src/3rdparty/libpng/pngwrite.c b/src/3rdparty/libpng/pngwrite.c
index 59377a4dde..06c45d16ab 100644
--- a/src/3rdparty/libpng/pngwrite.c
+++ b/src/3rdparty/libpng/pngwrite.c
@@ -1,7 +1,7 @@
/* pngwrite.c - general routines to write a PNG file
*
- * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -489,6 +489,16 @@ png_convert_from_time_t(png_timep ptime, time_t ttime)
png_debug(1, "in png_convert_from_time_t");
tbuf = gmtime(&ttime);
+ if (tbuf == NULL)
+ {
+ /* TODO: add a safe function which takes a png_ptr argument and raises
+ * a png_error if the ttime argument is invalid and the call to gmtime
+ * fails as a consequence.
+ */
+ memset(ptime, 0, sizeof(*ptime));
+ return;
+ }
+
png_convert_from_struct_tm(ptime, tbuf);
}
#endif
diff --git a/src/3rdparty/libpng/qt_attribution.json b/src/3rdparty/libpng/qt_attribution.json
index 612aa67791..4867220ca3 100644
--- a/src/3rdparty/libpng/qt_attribution.json
+++ b/src/3rdparty/libpng/qt_attribution.json
@@ -6,21 +6,23 @@
"Description": "libpng is the official PNG reference library.",
"Homepage": "http://www.libpng.org/pub/png/libpng.html",
- "Version": "1.6.37",
+ "Version": "1.6.38",
"License": "libpng License and PNG Reference Library version 2",
"LicenseId": "Libpng AND libpng-2.0",
"LicenseFile": "LICENSE",
- "Copyright": "Copyright (c) 1998-2018 Glenn Randers-Pehrson
+ "Copyright": "Copyright (c) 1995-2022 The PNG Reference Library Authors
+Copyright (c) 2000-2022 Cosmin Truta
+Copyright (c) 1998-2018 Glenn Randers-Pehrson
+Copyright (c) 1996-1997 Andreas Dilger
+Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
Copyright (c) 2000-2017 Simon-Pierre Cadieux
Copyright (c) 2000-2017 Eric S. Raymond
Copyright (c) 2000-2017 Mans Rullgard
-Copyright (c) 2000-2019 Cosmin Truta
Copyright (c) 2000-2017 Gilles Vollant
Copyright (c) 2000-2017 James Yu
Copyright (c) 2000-2017 Mandar Sahastrabuddhe
Copyright (c) 1998-2000 Tom Lane
Copyright (c) 1998-2000 Willem van Schaik
-Copyright (c) 1996-1997 Andreas Dilger
Copyright (c) 1996-1997 John Bowler
Copyright (c) 1996-1997 Kevin Bracey
Copyright (c) 1996-1997 Sam Bushell
@@ -29,6 +31,5 @@ Copyright (c) 1996-1997 Greg Roelofs
Copyright (c) 1996-1997 Tom Tanner
Copyright (c) 1995-1996 Dave Martindale
Copyright (c) 1995-1996 Paul Schmidt
-Copyright (c) 1995-1996 Tim Wegner
-Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."
+Copyright (c) 1995-1996 Tim Wegner"
}
diff --git a/src/3rdparty/libpng/qtpatches.diff b/src/3rdparty/libpng/qtpatches.diff
deleted file mode 100644
index b2bdb1475d..0000000000
--- a/src/3rdparty/libpng/qtpatches.diff
+++ /dev/null
@@ -1,62 +0,0 @@
-diff --git a/src/3rdparty/libpng/pngpriv.h b/src/3rdparty/libpng/pngpriv.h
-index 583c26f9bd..2ab9b70d73 100644
---- a/src/3rdparty/libpng/pngpriv.h
-+++ b/src/3rdparty/libpng/pngpriv.h
-@@ -23,6 +23,12 @@
- #ifndef PNGPRIV_H
- #define PNGPRIV_H
-
-+#ifdef _MSC_VER
-+# ifndef _CRT_SECURE_NO_DEPRECATE
-+# define _CRT_SECURE_NO_DEPRECATE
-+# endif
-+#endif
-+
- /* Feature Test Macros. The following are defined here to ensure that correctly
- * implemented libraries reveal the APIs libpng needs to build and hide those
- * that are not needed and potentially damaging to the compilation.
-@@ -308,6 +314,11 @@
- # endif
- #endif /* Setting PNG_BUILD_DLL if required */
-
-+/* Modfied for usage in Qt: Do not export the libpng APIs */
-+#ifdef PNG_BUILD_DLL
-+#undef PNG_BUILD_DLL
-+#endif
-+
- /* See pngconf.h for more details: the builder of the library may set this on
- * the command line to the right thing for the specific compilation system or it
- * may be automagically set above (at present we know of no system where it does
-@@ -546,6 +557,9 @@
- #if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \
- defined(_WIN32) || defined(__WIN32__)
- # include <windows.h> /* defines _WINDOWS_ macro */
- #endif
- #endif /* PNG_VERSION_INFO_ONLY */
-
-@@ -556,7 +570,7 @@
-
- /* Memory model/platform independent fns */
- #ifndef PNG_ABORT
--# ifdef _WINDOWS_
-+# if (defined(_WINDOWS_) || defined(_WIN32_WCE))
- # define PNG_ABORT() ExitProcess(0)
- # else
- # define PNG_ABORT() abort()
-diff --git a/src/3rdparty/libpng/pngrutil.c b/src/3rdparty/libpng/pngrutil.c
-index d5fa08c397..4db3de990b 100644
---- a/src/3rdparty/libpng/pngrutil.c
-+++ b/src/3rdparty/libpng/pngrutil.c
-@@ -2087,10 +2087,8 @@ png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
- }
- }
-
-- if (png_crc_finish(png_ptr, 0) != 0)
-- return;
--
-- png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf);
-+ if (png_crc_finish(png_ptr, 0) == 0)
-+ png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf);
-
- png_free(png_ptr, info_ptr->eXIf_buf);
- info_ptr->eXIf_buf = NULL;
diff --git a/src/3rdparty/zlib/CVE-2022-37434.patch b/src/3rdparty/zlib/CVE-2022-37434.patch
deleted file mode 100644
index db2c3ded14..0000000000
--- a/src/3rdparty/zlib/CVE-2022-37434.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From eff308af425b67093bab25f80f1ae950166bece1 Mon Sep 17 00:00:00 2001
-From: Mark Adler <fork@madler.net>
-Date: Sat, 30 Jul 2022 15:51:11 -0700
-Subject: [PATCH] Fix a bug when getting a gzip header extra field with
- inflate().
-
-If the extra field was larger than the space the user provided with
-inflateGetHeader(), and if multiple calls of inflate() delivered
-the extra header data, then there could be a buffer overflow of the
-provided space. This commit assures that provided space is not
-exceeded.
----
- inflate.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/inflate.c b/inflate.c
-index 7be8c63..7a72897 100644
---- a/inflate.c
-+++ b/inflate.c
-@@ -763,9 +763,10 @@ int flush;
- copy = state->length;
- if (copy > have) copy = have;
- if (copy) {
-+ len = state->head->extra_len - state->length;
- if (state->head != Z_NULL &&
-- state->head->extra != Z_NULL) {
-- len = state->head->extra_len - state->length;
-+ state->head->extra != Z_NULL &&
-+ len < state->head->extra_max) {
- zmemcpy(state->head->extra + len, next,
- len + copy > state->head->extra_max ?
- state->head->extra_max - len : copy);
---
-2.37.1
-
-
-From 1eb7682f845ac9e9bf9ae35bbfb3bad5dacbd91d Mon Sep 17 00:00:00 2001
-From: Mark Adler <fork@madler.net>
-Date: Mon, 8 Aug 2022 10:50:09 -0700
-Subject: [PATCH] Fix extra field processing bug that dereferences NULL
- state->head.
-
-The recent commit to fix a gzip header extra field processing bug
-introduced the new bug fixed here.
----
- inflate.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/inflate.c b/inflate.c
-index 7a72897..2a3c4fe 100644
---- a/inflate.c
-+++ b/inflate.c
-@@ -763,10 +763,10 @@ int flush;
- copy = state->length;
- if (copy > have) copy = have;
- if (copy) {
-- len = state->head->extra_len - state->length;
- if (state->head != Z_NULL &&
- state->head->extra != Z_NULL &&
-- len < state->head->extra_max) {
-+ (len = state->head->extra_len - state->length) <
-+ state->head->extra_max) {
- zmemcpy(state->head->extra + len, next,
- len + copy > state->head->extra_max ?
- state->head->extra_max - len : copy);
---
-2.37.1
-
diff --git a/src/3rdparty/zlib/qt_attribution.json b/src/3rdparty/zlib/qt_attribution.json
index 07bea6ba86..db176cbe6a 100644
--- a/src/3rdparty/zlib/qt_attribution.json
+++ b/src/3rdparty/zlib/qt_attribution.json
@@ -2,11 +2,11 @@
"Id": "zlib",
"Name": "Data Compression Library (zlib)",
"QDocModule": "qtcore",
- "QtUsage": "Optionally used in Qt Core and and development tools. Configure with -system-zlib to avoid.",
+ "QtUsage": "Optionally used in Qt Core and development tools. Configure with -system-zlib to avoid.",
"Description": "zlib is a general purpose data compression library.",
- "Homepage": "http://zlib.net/",
- "Version": "1.2.12",
+ "Homepage": "https://zlib.net/",
+ "Version": "1.2.13",
"License": "zlib License",
"LicenseId": "Zlib",
diff --git a/src/3rdparty/zlib/qtpatches.diff b/src/3rdparty/zlib/qtpatches.diff
index b7d150b8fd..ae316294dc 100644
--- a/src/3rdparty/zlib/qtpatches.diff
+++ b/src/3rdparty/zlib/qtpatches.diff
@@ -5,13 +5,13 @@ diff -ruN orig/ChangeLog src/ChangeLog
ChangeLog file for zlib
-+Changes in 1.2.12 (Qt) (28 Mar 2022)
++Changes in 1.2.13 (Qt) (14 Nov 2022)
+- This is a stripped down copy of zlib that contains patches to
+ make it compile as part of Qt. See also "qtpatches.diff".
+
- Changes in 1.2.12 (27 Mar 2022)
- - Cygwin does not have _wopen(), so do not create gzopen_w() there
- - Permit a deflateParams() parameter change as soon as possible
+ Changes in 1.2.13 (13 Oct 2022)
+ - Fix configure issue that discarded provided CC definition
+ - Correct incorrect inputs provided to the CRC functions
diff -ruN orig/gzguts.h src/gzguts.h
--- orig/gzguts.h
+++ src/gzguts.h
@@ -109,8 +109,8 @@ diff -ruN orig/zlib.h src/zlib.h
extern "C" {
#endif
--#define ZLIB_VERSION "1.2.12"
-+#define ZLIB_VERSION "1.2.12 (Qt)"
+-#define ZLIB_VERSION "1.2.13"
++#define ZLIB_VERSION "1.2.13 (Qt)"
#define ZLIB_VERNUM 0x12c0
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 2
diff --git a/src/3rdparty/zlib/src/ChangeLog b/src/3rdparty/zlib/src/ChangeLog
index 14939b2025..900c2393a1 100644
--- a/src/3rdparty/zlib/src/ChangeLog
+++ b/src/3rdparty/zlib/src/ChangeLog
@@ -1,10 +1,22 @@
ChangeLog file for zlib
-Changes in 1.2.12 (Qt) (28 Mar 2022)
+Changes in 1.2.13 (Qt) (14 Nov 2022)
- This is a stripped down copy of zlib that contains patches to
make it compile as part of Qt. See also "qtpatches.diff".
+Changes in 1.2.13 (13 Oct 2022)
+- Fix configure issue that discarded provided CC definition
+- Correct incorrect inputs provided to the CRC functions
+- Repair prototypes and exporting of new CRC functions
+- Fix inflateBack to detect invalid input with distances too far
+- Have infback() deliver all of the available output up to any error
+- Fix a bug when getting a gzip header extra field with inflate()
+- Fix bug in block type selection when Z_FIXED used
+- Tighten deflateBound bounds
+- Remove deleted assembler code references
+- Various portability and appearance improvements
+
Changes in 1.2.12 (27 Mar 2022)
- Cygwin does not have _wopen(), so do not create gzopen_w() there
- Permit a deflateParams() parameter change as soon as possible
@@ -163,7 +175,7 @@ Changes in 1.2.7.1 (24 Mar 2013)
- Fix types in contrib/minizip to match result of get_crc_table()
- Simplify contrib/vstudio/vc10 with 'd' suffix
- Add TOP support to win32/Makefile.msc
-- Suport i686 and amd64 assembler builds in CMakeLists.txt
+- Support i686 and amd64 assembler builds in CMakeLists.txt
- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h
- Add vc11 and vc12 build files to contrib/vstudio
- Add gzvprintf() as an undocumented function in zlib
@@ -363,14 +375,14 @@ Changes in 1.2.5.1 (10 Sep 2011)
- Use u4 type for crc_table to avoid conversion warnings
- Apply casts in zlib.h to avoid conversion warnings
- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller]
-- Improve inflateSync() documentation to note indeterminancy
+- Improve inflateSync() documentation to note indeterminacy
- Add deflatePending() function to return the amount of pending output
- Correct the spelling of "specification" in FAQ [Randers-Pehrson]
- Add a check in configure for stdarg.h, use for gzprintf()
- Check that pointers fit in ints when gzprint() compiled old style
- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler]
- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt]
-- Add debug records in assmebler code [Londer]
+- Add debug records in assembler code [Londer]
- Update RFC references to use http://tools.ietf.org/html/... [Li]
- Add --archs option, use of libtool to configure for Mac OS X [Borstel]
@@ -1037,7 +1049,7 @@ Changes in 1.2.0.1 (17 March 2003)
- Include additional header file on VMS for off_t typedef
- Try to use _vsnprintf where it supplants vsprintf [Vollant]
- Add some casts in inffast.c
-- Enchance comments in zlib.h on what happens if gzprintf() tries to
+- Enhance comments in zlib.h on what happens if gzprintf() tries to
write more than 4095 bytes before compression
- Remove unused state from inflateBackEnd()
- Remove exit(0) from minigzip.c, example.c
@@ -1215,7 +1227,7 @@ Changes in 1.0.9 (17 Feb 1998)
- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
- the declaration of FAR (Gilles VOllant)
+ the declaration of FAR (Gilles Vollant)
- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
- read_buf buf parameter of type Bytef* instead of charf*
- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
@@ -1571,7 +1583,7 @@ Changes in 0.4:
- renamed deflateOptions as deflateInit2, call one or the other but not both
- added the method parameter for deflateInit2
- added inflateInit2
-- simplied considerably deflateInit and inflateInit by not supporting
+- simplified considerably deflateInit and inflateInit by not supporting
user-provided history buffer. This is supported only in deflateInit2
and inflateInit2
diff --git a/src/3rdparty/zlib/src/README b/src/3rdparty/zlib/src/README
index 1e4f39181d..10c63e17bc 100644
--- a/src/3rdparty/zlib/src/README
+++ b/src/3rdparty/zlib/src/README
@@ -1,6 +1,6 @@
ZLIB DATA COMPRESSION LIBRARY
-zlib 1.2.12 is a general purpose data compression library. All the code is
+zlib 1.2.13 is a general purpose data compression library. All the code is
thread safe. The data format used by the zlib library is described by RFCs
(Request for Comments) 1950 to 1952 in the files
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
@@ -34,7 +34,7 @@ Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
issue of Dr. Dobb's Journal; a copy of the article is available at
http://marknelson.us/1997/01/01/zlib-engine/ .
-The changes made in version 1.2.12 are documented in the file ChangeLog.
+The changes made in version 1.2.13 are documented in the file ChangeLog.
Unsupported third party contributions are provided in directory contrib/ .
diff --git a/src/3rdparty/zlib/src/compress.c b/src/3rdparty/zlib/src/compress.c
index e2db404abf..2ad5326c14 100644
--- a/src/3rdparty/zlib/src/compress.c
+++ b/src/3rdparty/zlib/src/compress.c
@@ -19,7 +19,7 @@
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
Z_STREAM_ERROR if the level parameter is invalid.
*/
-int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
+int ZEXPORT compress2(dest, destLen, source, sourceLen, level)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
@@ -65,7 +65,7 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
/* ===========================================================================
*/
-int ZEXPORT compress (dest, destLen, source, sourceLen)
+int ZEXPORT compress(dest, destLen, source, sourceLen)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
@@ -78,7 +78,7 @@ int ZEXPORT compress (dest, destLen, source, sourceLen)
If the default memLevel or windowBits for deflateInit() is changed, then
this function needs to be updated.
*/
-uLong ZEXPORT compressBound (sourceLen)
+uLong ZEXPORT compressBound(sourceLen)
uLong sourceLen;
{
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
diff --git a/src/3rdparty/zlib/src/crc32.c b/src/3rdparty/zlib/src/crc32.c
index a1bdce5c23..f8357b083f 100644
--- a/src/3rdparty/zlib/src/crc32.c
+++ b/src/3rdparty/zlib/src/crc32.c
@@ -98,13 +98,22 @@
# endif
#endif
+/* If available, use the ARM processor CRC32 instruction. */
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8
+# define ARMCRC32
+#endif
+
/* Local functions. */
local z_crc_t multmodp OF((z_crc_t a, z_crc_t b));
local z_crc_t x2nmodp OF((z_off64_t n, unsigned k));
-/* If available, use the ARM processor CRC32 instruction. */
-#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8
-# define ARMCRC32
+#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
+ local z_word_t byte_swap OF((z_word_t word));
+#endif
+
+#if defined(W) && !defined(ARMCRC32)
+ local z_crc_t crc_word OF((z_word_t data));
+ local z_word_t crc_word_big OF((z_word_t data));
#endif
#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
@@ -630,7 +639,7 @@ unsigned long ZEXPORT crc32_z(crc, buf, len)
#endif /* DYNAMIC_CRC_TABLE */
/* Pre-condition the CRC */
- crc ^= 0xffffffff;
+ crc = (~crc) & 0xffffffff;
/* Compute the CRC up to a word boundary. */
while (len && ((z_size_t)buf & 7) != 0) {
@@ -645,8 +654,8 @@ unsigned long ZEXPORT crc32_z(crc, buf, len)
len &= 7;
/* Do three interleaved CRCs to realize the throughput of one crc32x
- instruction per cycle. Each CRC is calcuated on Z_BATCH words. The three
- CRCs are combined into a single CRC after each set of batches. */
+ instruction per cycle. Each CRC is calculated on Z_BATCH words. The
+ three CRCs are combined into a single CRC after each set of batches. */
while (num >= 3 * Z_BATCH) {
crc1 = 0;
crc2 = 0;
@@ -749,7 +758,7 @@ unsigned long ZEXPORT crc32_z(crc, buf, len)
#endif /* DYNAMIC_CRC_TABLE */
/* Pre-condition the CRC */
- crc ^= 0xffffffff;
+ crc = (~crc) & 0xffffffff;
#ifdef W
@@ -1077,7 +1086,7 @@ uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
#ifdef DYNAMIC_CRC_TABLE
once(&made, make_crc_table);
#endif /* DYNAMIC_CRC_TABLE */
- return multmodp(x2nmodp(len2, 3), crc1) ^ crc2;
+ return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff);
}
/* ========================================================================= */
@@ -1086,7 +1095,7 @@ uLong ZEXPORT crc32_combine(crc1, crc2, len2)
uLong crc2;
z_off_t len2;
{
- return crc32_combine64(crc1, crc2, len2);
+ return crc32_combine64(crc1, crc2, (z_off64_t)len2);
}
/* ========================================================================= */
@@ -1103,14 +1112,14 @@ uLong ZEXPORT crc32_combine_gen64(len2)
uLong ZEXPORT crc32_combine_gen(len2)
z_off_t len2;
{
- return crc32_combine_gen64(len2);
+ return crc32_combine_gen64((z_off64_t)len2);
}
/* ========================================================================= */
-uLong crc32_combine_op(crc1, crc2, op)
+uLong ZEXPORT crc32_combine_op(crc1, crc2, op)
uLong crc1;
uLong crc2;
uLong op;
{
- return multmodp(op, crc1) ^ crc2;
+ return multmodp(op, crc1) ^ (crc2 & 0xffffffff);
}
diff --git a/src/3rdparty/zlib/src/deflate.c b/src/3rdparty/zlib/src/deflate.c
index 799fb93cc0..4a689db359 100644
--- a/src/3rdparty/zlib/src/deflate.c
+++ b/src/3rdparty/zlib/src/deflate.c
@@ -52,7 +52,7 @@
#include "deflate.h"
const char deflate_copyright[] =
- " deflate 1.2.12 Copyright 1995-2022 Jean-loup Gailly and Mark Adler ";
+ " deflate 1.2.13 Copyright 1995-2022 Jean-loup Gailly and Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -87,13 +87,7 @@ local void lm_init OF((deflate_state *s));
local void putShortMSB OF((deflate_state *s, uInt b));
local void flush_pending OF((z_streamp strm));
local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
-#ifdef ASMV
-# pragma message("Assembler code may have bugs -- use at your own risk")
- void match_init OF((void)); /* asm code initialization */
- uInt longest_match OF((deflate_state *s, IPos cur_match));
-#else
local uInt longest_match OF((deflate_state *s, IPos cur_match));
-#endif
#ifdef ZLIB_DEBUG
local void check_match OF((deflate_state *s, IPos start, IPos match,
@@ -160,7 +154,7 @@ local const config configuration_table[10] = {
* characters, so that a running hash key can be computed from the previous
* key instead of complete recalculation each time.
*/
-#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+#define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask)
/* ===========================================================================
@@ -191,9 +185,9 @@ local const config configuration_table[10] = {
*/
#define CLEAR_HASH(s) \
do { \
- s->head[s->hash_size-1] = NIL; \
+ s->head[s->hash_size - 1] = NIL; \
zmemzero((Bytef *)s->head, \
- (unsigned)(s->hash_size-1)*sizeof(*s->head)); \
+ (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \
} while (0)
/* ===========================================================================
@@ -285,6 +279,8 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
if (windowBits < 0) { /* suppress zlib wrapper */
wrap = 0;
+ if (windowBits < -15)
+ return Z_STREAM_ERROR;
windowBits = -windowBits;
}
#ifdef GZIP
@@ -314,7 +310,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
s->hash_bits = (uInt)memLevel + 7;
s->hash_size = 1 << s->hash_bits;
s->hash_mask = s->hash_size - 1;
- s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+ s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH);
s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
@@ -340,11 +336,11 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
* sym_buf value to read moves forward three bytes. From that symbol, up to
* 31 bits are written to pending_buf. The closest the written pending_buf
* bits gets to the next sym_buf symbol to read is just before the last
- * code is written. At that time, 31*(n-2) bits have been written, just
- * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at
- * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1
+ * code is written. At that time, 31*(n - 2) bits have been written, just
+ * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at
+ * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1
* symbols are written.) The closest the writing gets to what is unread is
- * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and
+ * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and
* can range from 128 to 32768.
*
* Therefore, at a minimum, there are 142 bits of space between what is
@@ -390,7 +386,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
/* =========================================================================
* Check for a valid deflate stream state. Return 0 if ok, 1 if not.
*/
-local int deflateStateCheck (strm)
+local int deflateStateCheck(strm)
z_streamp strm;
{
deflate_state *s;
@@ -413,7 +409,7 @@ local int deflateStateCheck (strm)
}
/* ========================================================================= */
-int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+int ZEXPORT deflateSetDictionary(strm, dictionary, dictLength)
z_streamp strm;
const Bytef *dictionary;
uInt dictLength;
@@ -482,7 +478,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
}
/* ========================================================================= */
-int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength)
+int ZEXPORT deflateGetDictionary(strm, dictionary, dictLength)
z_streamp strm;
Bytef *dictionary;
uInt *dictLength;
@@ -504,7 +500,7 @@ int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength)
}
/* ========================================================================= */
-int ZEXPORT deflateResetKeep (strm)
+int ZEXPORT deflateResetKeep(strm)
z_streamp strm;
{
deflate_state *s;
@@ -542,7 +538,7 @@ int ZEXPORT deflateResetKeep (strm)
}
/* ========================================================================= */
-int ZEXPORT deflateReset (strm)
+int ZEXPORT deflateReset(strm)
z_streamp strm;
{
int ret;
@@ -554,7 +550,7 @@ int ZEXPORT deflateReset (strm)
}
/* ========================================================================= */
-int ZEXPORT deflateSetHeader (strm, head)
+int ZEXPORT deflateSetHeader(strm, head)
z_streamp strm;
gz_headerp head;
{
@@ -565,7 +561,7 @@ int ZEXPORT deflateSetHeader (strm, head)
}
/* ========================================================================= */
-int ZEXPORT deflatePending (strm, pending, bits)
+int ZEXPORT deflatePending(strm, pending, bits)
unsigned *pending;
int *bits;
z_streamp strm;
@@ -579,7 +575,7 @@ int ZEXPORT deflatePending (strm, pending, bits)
}
/* ========================================================================= */
-int ZEXPORT deflatePrime (strm, bits, value)
+int ZEXPORT deflatePrime(strm, bits, value)
z_streamp strm;
int bits;
int value;
@@ -674,36 +670,50 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
}
/* =========================================================================
- * For the default windowBits of 15 and memLevel of 8, this function returns
- * a close to exact, as well as small, upper bound on the compressed size.
- * They are coded as constants here for a reason--if the #define's are
- * changed, then this function needs to be changed as well. The return
- * value for 15 and 8 only works for those exact settings.
+ * For the default windowBits of 15 and memLevel of 8, this function returns a
+ * close to exact, as well as small, upper bound on the compressed size. This
+ * is an expansion of ~0.03%, plus a small constant.
+ *
+ * For any setting other than those defaults for windowBits and memLevel, one
+ * of two worst case bounds is returned. This is at most an expansion of ~4% or
+ * ~13%, plus a small constant.
*
- * For any setting other than those defaults for windowBits and memLevel,
- * the value returned is a conservative worst case for the maximum expansion
- * resulting from using fixed blocks instead of stored blocks, which deflate
- * can emit on compressed data for some combinations of the parameters.
+ * Both the 0.03% and 4% derive from the overhead of stored blocks. The first
+ * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second
+ * is for stored blocks of 127 bytes (the worst case memLevel == 1). The
+ * expansion results from five bytes of header for each stored block.
*
- * This function could be more sophisticated to provide closer upper bounds for
- * every combination of windowBits and memLevel. But even the conservative
- * upper bound of about 14% expansion does not seem onerous for output buffer
- * allocation.
+ * The larger expansion of 13% results from a window size less than or equal to
+ * the symbols buffer size (windowBits <= memLevel + 7). In that case some of
+ * the data being compressed may have slid out of the sliding window, impeding
+ * a stored block from being emitted. Then the only choice is a fixed or
+ * dynamic block, where a fixed block limits the maximum expansion to 9 bits
+ * per 8-bit byte, plus 10 bits for every block. The smallest block size for
+ * which this can occur is 255 (memLevel == 2).
+ *
+ * Shifts are used to approximate divisions, for speed.
*/
uLong ZEXPORT deflateBound(strm, sourceLen)
z_streamp strm;
uLong sourceLen;
{
deflate_state *s;
- uLong complen, wraplen;
+ uLong fixedlen, storelen, wraplen;
+
+ /* upper bound for fixed blocks with 9-bit literals and length 255
+ (memLevel == 2, which is the lowest that may not use stored blocks) --
+ ~13% overhead plus a small constant */
+ fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) +
+ (sourceLen >> 9) + 4;
- /* conservative upper bound for compressed data */
- complen = sourceLen +
- ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
+ /* upper bound for stored blocks with length 127 (memLevel == 1) --
+ ~4% overhead plus a small constant */
+ storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) +
+ (sourceLen >> 11) + 7;
- /* if can't get parameters, return conservative bound plus zlib wrapper */
+ /* if can't get parameters, return larger bound plus a zlib wrapper */
if (deflateStateCheck(strm))
- return complen + 6;
+ return (fixedlen > storelen ? fixedlen : storelen) + 6;
/* compute wrapper length */
s = strm->state;
@@ -740,11 +750,12 @@ uLong ZEXPORT deflateBound(strm, sourceLen)
wraplen = 6;
}
- /* if not default parameters, return conservative bound */
+ /* if not default parameters, return one of the conservative bounds */
if (s->w_bits != 15 || s->hash_bits != 8 + 7)
- return complen + wraplen;
+ return (s->w_bits <= s->hash_bits ? fixedlen : storelen) + wraplen;
- /* default settings: return tight bound for that case */
+ /* default settings: return tight bound for that case -- ~0.03% overhead
+ plus a small constant */
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
(sourceLen >> 25) + 13 - 6 + wraplen;
}
@@ -754,7 +765,7 @@ uLong ZEXPORT deflateBound(strm, sourceLen)
* IN assertion: the stream state is correct and there is enough room in
* pending_buf.
*/
-local void putShortMSB (s, b)
+local void putShortMSB(s, b)
deflate_state *s;
uInt b;
{
@@ -801,7 +812,7 @@ local void flush_pending(strm)
} while (0)
/* ========================================================================= */
-int ZEXPORT deflate (strm, flush)
+int ZEXPORT deflate(strm, flush)
z_streamp strm;
int flush;
{
@@ -856,7 +867,7 @@ int ZEXPORT deflate (strm, flush)
s->status = BUSY_STATE;
if (s->status == INIT_STATE) {
/* zlib header */
- uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+ uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8;
uInt level_flags;
if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
@@ -1116,7 +1127,7 @@ int ZEXPORT deflate (strm, flush)
}
/* ========================================================================= */
-int ZEXPORT deflateEnd (strm)
+int ZEXPORT deflateEnd(strm)
z_streamp strm;
{
int status;
@@ -1142,7 +1153,7 @@ int ZEXPORT deflateEnd (strm)
* To simplify the source, this is not supported for 16-bit MSDOS (which
* doesn't have enough memory anyway to duplicate compression states).
*/
-int ZEXPORT deflateCopy (dest, source)
+int ZEXPORT deflateCopy(dest, source)
z_streamp dest;
z_streamp source;
{
@@ -1231,7 +1242,7 @@ local unsigned read_buf(strm, buf, size)
/* ===========================================================================
* Initialize the "longest match" routines for a new zlib stream
*/
-local void lm_init (s)
+local void lm_init(s)
deflate_state *s;
{
s->window_size = (ulg)2L*s->w_size;
@@ -1252,11 +1263,6 @@ local void lm_init (s)
s->match_length = s->prev_length = MIN_MATCH-1;
s->match_available = 0;
s->ins_h = 0;
-#ifndef FASTEST
-#ifdef ASMV
- match_init(); /* initialize the asm code */
-#endif
-#endif
}
#ifndef FASTEST
@@ -1269,10 +1275,6 @@ local void lm_init (s)
* string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
* OUT assertion: the match length is not greater than s->lookahead.
*/
-#ifndef ASMV
-/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
- * match.S. The code will be functionally equivalent.
- */
local uInt longest_match(s, cur_match)
deflate_state *s;
IPos cur_match; /* current match */
@@ -1297,10 +1299,10 @@ local uInt longest_match(s, cur_match)
*/
register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
register ush scan_start = *(ushf*)scan;
- register ush scan_end = *(ushf*)(scan+best_len-1);
+ register ush scan_end = *(ushf*)(scan + best_len - 1);
#else
register Bytef *strend = s->window + s->strstart + MAX_MATCH;
- register Byte scan_end1 = scan[best_len-1];
+ register Byte scan_end1 = scan[best_len - 1];
register Byte scan_end = scan[best_len];
#endif
@@ -1318,7 +1320,8 @@ local uInt longest_match(s, cur_match)
*/
if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead;
- Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+ "need lookahead");
do {
Assert(cur_match < s->strstart, "no future");
@@ -1336,43 +1339,44 @@ local uInt longest_match(s, cur_match)
/* This code assumes sizeof(unsigned short) == 2. Do not use
* UNALIGNED_OK if your compiler uses a different size.
*/
- if (*(ushf*)(match+best_len-1) != scan_end ||
+ if (*(ushf*)(match + best_len - 1) != scan_end ||
*(ushf*)match != scan_start) continue;
/* It is not necessary to compare scan[2] and match[2] since they are
* always equal when the other bytes match, given that the hash keys
* are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
- * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * strstart + 3, + 5, up to strstart + 257. We check for insufficient
* lookahead only every 4th comparison; the 128th check will be made
- * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is
* necessary to put more guard bytes at the end of the window, or
* to check more often for insufficient lookahead.
*/
Assert(scan[2] == match[2], "scan[2]?");
scan++, match++;
do {
- } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
- *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
- *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
- *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
scan < strend);
/* The funny "do {}" generates better code on most compilers */
- /* Here, scan <= window+strstart+257 */
- Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ /* Here, scan <= window + strstart + 257 */
+ Assert(scan <= s->window + (unsigned)(s->window_size - 1),
+ "wild scan");
if (*scan == *match) scan++;
- len = (MAX_MATCH - 1) - (int)(strend-scan);
+ len = (MAX_MATCH - 1) - (int)(strend - scan);
scan = strend - (MAX_MATCH-1);
#else /* UNALIGNED_OK */
- if (match[best_len] != scan_end ||
- match[best_len-1] != scan_end1 ||
- *match != *scan ||
- *++match != scan[1]) continue;
+ if (match[best_len] != scan_end ||
+ match[best_len - 1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
- /* The check at best_len-1 can be removed because it will be made
+ /* The check at best_len - 1 can be removed because it will be made
* again later. (This heuristic is not always a win.)
* It is not necessary to compare scan[2] and match[2] since they
* are always equal when the other bytes match, given that
@@ -1382,7 +1386,7 @@ local uInt longest_match(s, cur_match)
Assert(*scan == *match, "match[2]?");
/* We check for insufficient lookahead only every 8th comparison;
- * the 256th check will be made at strstart+258.
+ * the 256th check will be made at strstart + 258.
*/
do {
} while (*++scan == *++match && *++scan == *++match &&
@@ -1391,7 +1395,8 @@ local uInt longest_match(s, cur_match)
*++scan == *++match && *++scan == *++match &&
scan < strend);
- Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ Assert(scan <= s->window + (unsigned)(s->window_size - 1),
+ "wild scan");
len = MAX_MATCH - (int)(strend - scan);
scan = strend - MAX_MATCH;
@@ -1403,9 +1408,9 @@ local uInt longest_match(s, cur_match)
best_len = len;
if (len >= nice_match) break;
#ifdef UNALIGNED_OK
- scan_end = *(ushf*)(scan+best_len-1);
+ scan_end = *(ushf*)(scan + best_len - 1);
#else
- scan_end1 = scan[best_len-1];
+ scan_end1 = scan[best_len - 1];
scan_end = scan[best_len];
#endif
}
@@ -1415,7 +1420,6 @@ local uInt longest_match(s, cur_match)
if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
return s->lookahead;
}
-#endif /* ASMV */
#else /* FASTEST */
@@ -1436,7 +1440,8 @@ local uInt longest_match(s, cur_match)
*/
Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
- Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+ "need lookahead");
Assert(cur_match < s->strstart, "no future");
@@ -1446,7 +1451,7 @@ local uInt longest_match(s, cur_match)
*/
if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
- /* The check at best_len-1 can be removed because it will be made
+ /* The check at best_len - 1 can be removed because it will be made
* again later. (This heuristic is not always a win.)
* It is not necessary to compare scan[2] and match[2] since they
* are always equal when the other bytes match, given that
@@ -1456,7 +1461,7 @@ local uInt longest_match(s, cur_match)
Assert(*scan == *match, "match[2]?");
/* We check for insufficient lookahead only every 8th comparison;
- * the 256th check will be made at strstart+258.
+ * the 256th check will be made at strstart + 258.
*/
do {
} while (*++scan == *++match && *++scan == *++match &&
@@ -1465,7 +1470,7 @@ local uInt longest_match(s, cur_match)
*++scan == *++match && *++scan == *++match &&
scan < strend);
- Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan");
len = MAX_MATCH - (int)(strend - scan);
@@ -1501,7 +1506,7 @@ local void check_match(s, start, match, length)
z_error("invalid match");
}
if (z_verbose > 1) {
- fprintf(stderr,"\\[%d,%d]", start-match, length);
+ fprintf(stderr,"\\[%d,%d]", start - match, length);
do { putc(s->window[start++], stderr); } while (--length != 0);
}
}
@@ -1547,9 +1552,9 @@ local void fill_window(s)
/* If the window is almost full and there is insufficient lookahead,
* move the upper half to the lower one to make room in the upper half.
*/
- if (s->strstart >= wsize+MAX_DIST(s)) {
+ if (s->strstart >= wsize + MAX_DIST(s)) {
- zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more);
+ zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more);
s->match_start -= wsize;
s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
s->block_start -= (long) wsize;
@@ -1680,7 +1685,7 @@ local void fill_window(s)
*
* deflate_stored() is written to minimize the number of times an input byte is
* copied. It is most efficient with large input and output buffers, which
- * maximizes the opportunites to have a single copy from next_in to next_out.
+ * maximizes the opportunities to have a single copy from next_in to next_out.
*/
local block_state deflate_stored(s, flush)
deflate_state *s;
@@ -1890,7 +1895,7 @@ local block_state deflate_fast(s, flush)
if (s->lookahead == 0) break; /* flush the current block */
}
- /* Insert the string window[strstart .. strstart+2] in the
+ /* Insert the string window[strstart .. strstart + 2] in the
* dictionary, and set hash_head to the head of the hash chain:
*/
hash_head = NIL;
@@ -1938,7 +1943,7 @@ local block_state deflate_fast(s, flush)
s->strstart += s->match_length;
s->match_length = 0;
s->ins_h = s->window[s->strstart];
- UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]);
#if MIN_MATCH != 3
Call UPDATE_HASH() MIN_MATCH-3 more times
#endif
@@ -1949,7 +1954,7 @@ local block_state deflate_fast(s, flush)
} else {
/* No match, output a literal byte */
Tracevv((stderr,"%c", s->window[s->strstart]));
- _tr_tally_lit (s, s->window[s->strstart], bflush);
+ _tr_tally_lit(s, s->window[s->strstart], bflush);
s->lookahead--;
s->strstart++;
}
@@ -1993,7 +1998,7 @@ local block_state deflate_slow(s, flush)
if (s->lookahead == 0) break; /* flush the current block */
}
- /* Insert the string window[strstart .. strstart+2] in the
+ /* Insert the string window[strstart .. strstart + 2] in the
* dictionary, and set hash_head to the head of the hash chain:
*/
hash_head = NIL;
@@ -2035,17 +2040,17 @@ local block_state deflate_slow(s, flush)
uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
/* Do not insert strings in hash table beyond this. */
- check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+ check_match(s, s->strstart - 1, s->prev_match, s->prev_length);
- _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+ _tr_tally_dist(s, s->strstart - 1 - s->prev_match,
s->prev_length - MIN_MATCH, bflush);
/* Insert in hash table all strings up to the end of the match.
- * strstart-1 and strstart are already inserted. If there is not
+ * strstart - 1 and strstart are already inserted. If there is not
* enough lookahead, the last two strings are not inserted in
* the hash table.
*/
- s->lookahead -= s->prev_length-1;
+ s->lookahead -= s->prev_length - 1;
s->prev_length -= 2;
do {
if (++s->strstart <= max_insert) {
@@ -2063,8 +2068,8 @@ local block_state deflate_slow(s, flush)
* single literal. If there was a match but the current match
* is longer, truncate the previous match to a single literal.
*/
- Tracevv((stderr,"%c", s->window[s->strstart-1]));
- _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ Tracevv((stderr,"%c", s->window[s->strstart - 1]));
+ _tr_tally_lit(s, s->window[s->strstart - 1], bflush);
if (bflush) {
FLUSH_BLOCK_ONLY(s, 0);
}
@@ -2082,8 +2087,8 @@ local block_state deflate_slow(s, flush)
}
Assert (flush != Z_NO_FLUSH, "no flush?");
if (s->match_available) {
- Tracevv((stderr,"%c", s->window[s->strstart-1]));
- _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ Tracevv((stderr,"%c", s->window[s->strstart - 1]));
+ _tr_tally_lit(s, s->window[s->strstart - 1], bflush);
s->match_available = 0;
}
s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
@@ -2140,7 +2145,8 @@ local block_state deflate_rle(s, flush)
if (s->match_length > s->lookahead)
s->match_length = s->lookahead;
}
- Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
+ Assert(scan <= s->window + (uInt)(s->window_size - 1),
+ "wild scan");
}
/* Emit match if have run of MIN_MATCH or longer, else emit literal */
@@ -2155,7 +2161,7 @@ local block_state deflate_rle(s, flush)
} else {
/* No match, output a literal byte */
Tracevv((stderr,"%c", s->window[s->strstart]));
- _tr_tally_lit (s, s->window[s->strstart], bflush);
+ _tr_tally_lit(s, s->window[s->strstart], bflush);
s->lookahead--;
s->strstart++;
}
@@ -2195,7 +2201,7 @@ local block_state deflate_huff(s, flush)
/* Output a literal byte */
s->match_length = 0;
Tracevv((stderr,"%c", s->window[s->strstart]));
- _tr_tally_lit (s, s->window[s->strstart], bflush);
+ _tr_tally_lit(s, s->window[s->strstart], bflush);
s->lookahead--;
s->strstart++;
if (bflush) FLUSH_BLOCK(s, 0);
diff --git a/src/3rdparty/zlib/src/deflate.h b/src/3rdparty/zlib/src/deflate.h
index 17c226113b..1a06cd5f25 100644
--- a/src/3rdparty/zlib/src/deflate.h
+++ b/src/3rdparty/zlib/src/deflate.h
@@ -329,8 +329,8 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
# define _tr_tally_dist(s, distance, length, flush) \
{ uch len = (uch)(length); \
ush dist = (ush)(distance); \
- s->sym_buf[s->sym_next++] = dist; \
- s->sym_buf[s->sym_next++] = dist >> 8; \
+ s->sym_buf[s->sym_next++] = (uch)dist; \
+ s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \
s->sym_buf[s->sym_next++] = len; \
dist--; \
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
diff --git a/src/3rdparty/zlib/src/gzlib.c b/src/3rdparty/zlib/src/gzlib.c
index dddaf26873..55da46a453 100644
--- a/src/3rdparty/zlib/src/gzlib.c
+++ b/src/3rdparty/zlib/src/gzlib.c
@@ -30,7 +30,7 @@ local gzFile gz_open OF((const void *, int, const char *));
The gz_strwinerror function does not change the current setting of
GetLastError. */
-char ZLIB_INTERNAL *gz_strwinerror (error)
+char ZLIB_INTERNAL *gz_strwinerror(error)
DWORD error;
{
static char buf[1024];
diff --git a/src/3rdparty/zlib/src/gzread.c b/src/3rdparty/zlib/src/gzread.c
index 884c9bfe4c..dd77381596 100644
--- a/src/3rdparty/zlib/src/gzread.c
+++ b/src/3rdparty/zlib/src/gzread.c
@@ -157,11 +157,9 @@ local int gz_look(state)
the output buffer is larger than the input buffer, which also assures
space for gzungetc() */
state->x.next = state->out;
- if (strm->avail_in) {
- memcpy(state->x.next, strm->next_in, strm->avail_in);
- state->x.have = strm->avail_in;
- strm->avail_in = 0;
- }
+ memcpy(state->x.next, strm->next_in, strm->avail_in);
+ state->x.have = strm->avail_in;
+ strm->avail_in = 0;
state->how = COPY;
state->direct = 1;
return 0;
diff --git a/src/3rdparty/zlib/src/gzwrite.c b/src/3rdparty/zlib/src/gzwrite.c
index a8ffc8f53d..eb8a0e5893 100644
--- a/src/3rdparty/zlib/src/gzwrite.c
+++ b/src/3rdparty/zlib/src/gzwrite.c
@@ -474,7 +474,7 @@ int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
#else /* !STDC && !Z_HAVE_STDARG_H */
/* -- see zlib.h -- */
-int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+int ZEXPORTVA gzprintf(file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
gzFile file;
const char *format;
diff --git a/src/3rdparty/zlib/src/infback.c b/src/3rdparty/zlib/src/infback.c
index a390c58e81..babeaf1806 100644
--- a/src/3rdparty/zlib/src/infback.c
+++ b/src/3rdparty/zlib/src/infback.c
@@ -66,6 +66,7 @@ int stream_size;
state->window = window;
state->wnext = 0;
state->whave = 0;
+ state->sane = 1;
return Z_OK;
}
@@ -605,25 +606,27 @@ void FAR *out_desc;
break;
case DONE:
- /* inflate stream terminated properly -- write leftover output */
+ /* inflate stream terminated properly */
ret = Z_STREAM_END;
- if (left < state->wsize) {
- if (out(out_desc, state->window, state->wsize - left))
- ret = Z_BUF_ERROR;
- }
goto inf_leave;
case BAD:
ret = Z_DATA_ERROR;
goto inf_leave;
- default: /* can't happen, but makes compilers happy */
+ default:
+ /* can't happen, but makes compilers happy */
ret = Z_STREAM_ERROR;
goto inf_leave;
}
- /* Return unused input */
+ /* Write leftover output and return unused input */
inf_leave:
+ if (left < state->wsize) {
+ if (out(out_desc, state->window, state->wsize - left) &&
+ ret == Z_STREAM_END)
+ ret = Z_BUF_ERROR;
+ }
strm->next_in = next;
strm->avail_in = have;
return ret;
diff --git a/src/3rdparty/zlib/src/inflate.c b/src/3rdparty/zlib/src/inflate.c
index 2a3c4fe984..8acbef44e9 100644
--- a/src/3rdparty/zlib/src/inflate.c
+++ b/src/3rdparty/zlib/src/inflate.c
@@ -168,6 +168,8 @@ int windowBits;
/* extract wrap request from windowBits parameter */
if (windowBits < 0) {
+ if (windowBits < -15)
+ return Z_STREAM_ERROR;
wrap = 0;
windowBits = -windowBits;
}
diff --git a/src/3rdparty/zlib/src/inftrees.c b/src/3rdparty/zlib/src/inftrees.c
index 09462a740b..57d2793bec 100644
--- a/src/3rdparty/zlib/src/inftrees.c
+++ b/src/3rdparty/zlib/src/inftrees.c
@@ -9,7 +9,7 @@
#define MAXBITS 15
const char inflate_copyright[] =
- " inflate 1.2.12 Copyright 1995-2022 Mark Adler ";
+ " inflate 1.2.13 Copyright 1995-2022 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -62,7 +62,7 @@ unsigned short FAR *work;
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
- 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 202};
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 194, 65};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
diff --git a/src/3rdparty/zlib/src/inftrees.h b/src/3rdparty/zlib/src/inftrees.h
index baa53a0b1a..f53665311c 100644
--- a/src/3rdparty/zlib/src/inftrees.h
+++ b/src/3rdparty/zlib/src/inftrees.h
@@ -38,7 +38,7 @@ typedef struct {
/* Maximum size of the dynamic table. The maximum number of code structures is
1444, which is the sum of 852 for literal/length codes and 592 for distance
codes. These values were found by exhaustive searches using the program
- examples/enough.c found in the zlib distribtution. The arguments to that
+ examples/enough.c found in the zlib distribution. The arguments to that
program are the number of symbols, the initial root table size, and the
maximum bit length of a code. "enough 286 9 15" for literal/length codes
returns returns 852, and "enough 30 6 15" for distance codes returns 592.
diff --git a/src/3rdparty/zlib/src/trees.c b/src/3rdparty/zlib/src/trees.c
index f73fd99c37..5f305c4722 100644
--- a/src/3rdparty/zlib/src/trees.c
+++ b/src/3rdparty/zlib/src/trees.c
@@ -193,7 +193,7 @@ local void send_bits(s, value, length)
s->bits_sent += (ulg)length;
/* If not enough room in bi_buf, use (valid) bits from bi_buf and
- * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid))
* unused bits in value.
*/
if (s->bi_valid > (int)Buf_size - length) {
@@ -256,7 +256,7 @@ local void tr_static_init()
length = 0;
for (code = 0; code < LENGTH_CODES-1; code++) {
base_length[code] = length;
- for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ for (n = 0; n < (1 << extra_lbits[code]); n++) {
_length_code[length++] = (uch)code;
}
}
@@ -265,13 +265,13 @@ local void tr_static_init()
* in two different ways: code 284 + 5 bits or code 285, so we
* overwrite length_code[255] to use the best encoding:
*/
- _length_code[length-1] = (uch)code;
+ _length_code[length - 1] = (uch)code;
/* Initialize the mapping dist (0..32K) -> dist code (0..29) */
dist = 0;
for (code = 0 ; code < 16; code++) {
base_dist[code] = dist;
- for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ for (n = 0; n < (1 << extra_dbits[code]); n++) {
_dist_code[dist++] = (uch)code;
}
}
@@ -279,11 +279,11 @@ local void tr_static_init()
dist >>= 7; /* from now on, all distances are divided by 128 */
for ( ; code < D_CODES; code++) {
base_dist[code] = dist << 7;
- for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
_dist_code[256 + dist++] = (uch)code;
}
}
- Assert (dist == 256, "tr_static_init: 256+dist != 512");
+ Assert (dist == 256, "tr_static_init: 256 + dist != 512");
/* Construct the codes of the static literal tree */
for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
@@ -312,7 +312,7 @@ local void tr_static_init()
}
/* ===========================================================================
- * Genererate the file trees.h describing the static trees.
+ * Generate the file trees.h describing the static trees.
*/
#ifdef GEN_TREES_H
# ifndef ZLIB_DEBUG
@@ -321,7 +321,7 @@ local void tr_static_init()
# define SEPARATOR(i, last, width) \
((i) == (last)? "\n};\n\n" : \
- ((i) % (width) == (width)-1 ? ",\n" : ", "))
+ ((i) % (width) == (width) - 1 ? ",\n" : ", "))
void gen_trees_header()
{
@@ -458,7 +458,7 @@ local void pqdownheap(s, tree, k)
while (j <= s->heap_len) {
/* Set j to the smallest of the two sons: */
if (j < s->heap_len &&
- smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+ smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) {
j++;
}
/* Exit if v is smaller than both sons */
@@ -507,7 +507,7 @@ local void gen_bitlen(s, desc)
*/
tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
- for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+ for (h = s->heap_max + 1; h < HEAP_SIZE; h++) {
n = s->heap[h];
bits = tree[tree[n].Dad].Len + 1;
if (bits > max_length) bits = max_length, overflow++;
@@ -518,7 +518,7 @@ local void gen_bitlen(s, desc)
s->bl_count[bits]++;
xbits = 0;
- if (n >= base) xbits = extra[n-base];
+ if (n >= base) xbits = extra[n - base];
f = tree[n].Freq;
s->opt_len += (ulg)f * (unsigned)(bits + xbits);
if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits);
@@ -530,10 +530,10 @@ local void gen_bitlen(s, desc)
/* Find the first bit length which could increase: */
do {
- bits = max_length-1;
+ bits = max_length - 1;
while (s->bl_count[bits] == 0) bits--;
- s->bl_count[bits]--; /* move one leaf down the tree */
- s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */
s->bl_count[max_length]--;
/* The brother of the overflow item also moves one step up,
* but this does not affect bl_count[max_length]
@@ -569,7 +569,7 @@ local void gen_bitlen(s, desc)
* OUT assertion: the field code is set for all tree elements of non
* zero code length.
*/
-local void gen_codes (tree, max_code, bl_count)
+local void gen_codes(tree, max_code, bl_count)
ct_data *tree; /* the tree to decorate */
int max_code; /* largest code with non zero frequency */
ushf *bl_count; /* number of codes at each bit length */
@@ -583,13 +583,13 @@ local void gen_codes (tree, max_code, bl_count)
* without bit reversal.
*/
for (bits = 1; bits <= MAX_BITS; bits++) {
- code = (code + bl_count[bits-1]) << 1;
+ code = (code + bl_count[bits - 1]) << 1;
next_code[bits] = (ush)code;
}
/* Check that the bit counts in bl_count are consistent. The last code
* must be all ones.
*/
- Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
"inconsistent bit counts");
Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
@@ -600,7 +600,7 @@ local void gen_codes (tree, max_code, bl_count)
tree[n].Code = (ush)bi_reverse(next_code[len]++, len);
Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
- n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1));
}
}
@@ -624,7 +624,7 @@ local void build_tree(s, desc)
int node; /* new node being created */
/* Construct the initial heap, with least frequent element in
- * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n + 1].
* heap[0] is not used.
*/
s->heap_len = 0, s->heap_max = HEAP_SIZE;
@@ -652,7 +652,7 @@ local void build_tree(s, desc)
}
desc->max_code = max_code;
- /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree,
* establish sub-heaps of increasing lengths:
*/
for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
@@ -700,7 +700,7 @@ local void build_tree(s, desc)
* Scan a literal or distance tree to determine the frequencies of the codes
* in the bit length tree.
*/
-local void scan_tree (s, tree, max_code)
+local void scan_tree(s, tree, max_code)
deflate_state *s;
ct_data *tree; /* the tree to be scanned */
int max_code; /* and its largest code of non zero frequency */
@@ -714,10 +714,10 @@ local void scan_tree (s, tree, max_code)
int min_count = 4; /* min repeat count */
if (nextlen == 0) max_count = 138, min_count = 3;
- tree[max_code+1].Len = (ush)0xffff; /* guard */
+ tree[max_code + 1].Len = (ush)0xffff; /* guard */
for (n = 0; n <= max_code; n++) {
- curlen = nextlen; nextlen = tree[n+1].Len;
+ curlen = nextlen; nextlen = tree[n + 1].Len;
if (++count < max_count && curlen == nextlen) {
continue;
} else if (count < min_count) {
@@ -745,7 +745,7 @@ local void scan_tree (s, tree, max_code)
* Send a literal or distance tree in compressed form, using the codes in
* bl_tree.
*/
-local void send_tree (s, tree, max_code)
+local void send_tree(s, tree, max_code)
deflate_state *s;
ct_data *tree; /* the tree to be scanned */
int max_code; /* and its largest code of non zero frequency */
@@ -758,11 +758,11 @@ local void send_tree (s, tree, max_code)
int max_count = 7; /* max repeat count */
int min_count = 4; /* min repeat count */
- /* tree[max_code+1].Len = -1; */ /* guard already set */
+ /* tree[max_code + 1].Len = -1; */ /* guard already set */
if (nextlen == 0) max_count = 138, min_count = 3;
for (n = 0; n <= max_code; n++) {
- curlen = nextlen; nextlen = tree[n+1].Len;
+ curlen = nextlen; nextlen = tree[n + 1].Len;
if (++count < max_count && curlen == nextlen) {
continue;
} else if (count < min_count) {
@@ -773,13 +773,13 @@ local void send_tree (s, tree, max_code)
send_code(s, curlen, s->bl_tree); count--;
}
Assert(count >= 3 && count <= 6, " 3_6?");
- send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2);
} else if (count <= 10) {
- send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3);
} else {
- send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7);
}
count = 0; prevlen = curlen;
if (nextlen == 0) {
@@ -807,8 +807,8 @@ local int build_bl_tree(s)
/* Build the bit length tree: */
build_tree(s, (tree_desc *)(&(s->bl_desc)));
- /* opt_len now includes the length of the tree representations, except
- * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ /* opt_len now includes the length of the tree representations, except the
+ * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts.
*/
/* Determine the number of bit length codes to send. The pkzip format
@@ -819,7 +819,7 @@ local int build_bl_tree(s)
if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
}
/* Update opt_len to include the bit length tree and counts */
- s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4;
+ s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4;
Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
s->opt_len, s->static_len));
@@ -841,19 +841,19 @@ local void send_all_trees(s, lcodes, dcodes, blcodes)
Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
"too many codes");
Tracev((stderr, "\nbl counts: "));
- send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
- send_bits(s, dcodes-1, 5);
- send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes - 1, 5);
+ send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */
for (rank = 0; rank < blcodes; rank++) {
Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
}
Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
- send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */
Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
- send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */
Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
}
@@ -866,7 +866,7 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
ulg stored_len; /* length of input block */
int last; /* one if this is the last block for a file */
{
- send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */
+ send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */
bi_windup(s); /* align on byte boundary */
put_short(s, (ush)stored_len);
put_short(s, (ush)~stored_len);
@@ -877,7 +877,7 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
s->compressed_len += (stored_len + 4) << 3;
s->bits_sent += 2*16;
- s->bits_sent += stored_len<<3;
+ s->bits_sent += stored_len << 3;
#endif
}
@@ -943,14 +943,17 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
max_blindex = build_bl_tree(s);
/* Determine the best encoding. Compute the block lengths in bytes. */
- opt_lenb = (s->opt_len+3+7)>>3;
- static_lenb = (s->static_len+3+7)>>3;
+ opt_lenb = (s->opt_len + 3 + 7) >> 3;
+ static_lenb = (s->static_len + 3 + 7) >> 3;
Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
s->sym_next / 3));
- if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+#ifndef FORCE_STATIC
+ if (static_lenb <= opt_lenb || s->strategy == Z_FIXED)
+#endif
+ opt_lenb = static_lenb;
} else {
Assert(buf != (char*)0, "lost buf");
@@ -960,7 +963,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
#ifdef FORCE_STORED
if (buf != (char*)0) { /* force stored block */
#else
- if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ if (stored_len + 4 <= opt_lenb && buf != (char*)0) {
/* 4: two words for the lengths */
#endif
/* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
@@ -971,21 +974,17 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
*/
_tr_stored_block(s, buf, stored_len, last);
-#ifdef FORCE_STATIC
- } else if (static_lenb >= 0) { /* force static trees */
-#else
- } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
-#endif
- send_bits(s, (STATIC_TREES<<1)+last, 3);
+ } else if (static_lenb == opt_lenb) {
+ send_bits(s, (STATIC_TREES<<1) + last, 3);
compress_block(s, (const ct_data *)static_ltree,
(const ct_data *)static_dtree);
#ifdef ZLIB_DEBUG
s->compressed_len += 3 + s->static_len;
#endif
} else {
- send_bits(s, (DYN_TREES<<1)+last, 3);
- send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
- max_blindex+1);
+ send_bits(s, (DYN_TREES<<1) + last, 3);
+ send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1,
+ max_blindex + 1);
compress_block(s, (const ct_data *)s->dyn_ltree,
(const ct_data *)s->dyn_dtree);
#ifdef ZLIB_DEBUG
@@ -1004,22 +1003,22 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
s->compressed_len += 7; /* align on byte boundary */
#endif
}
- Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
- s->compressed_len-7*last));
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3,
+ s->compressed_len - 7*last));
}
/* ===========================================================================
* Save the match info and tally the frequency counts. Return true if
* the current block must be flushed.
*/
-int ZLIB_INTERNAL _tr_tally (s, dist, lc)
+int ZLIB_INTERNAL _tr_tally(s, dist, lc)
deflate_state *s;
unsigned dist; /* distance of matched string */
- unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
+ unsigned lc; /* match length - MIN_MATCH or unmatched char (dist==0) */
{
- s->sym_buf[s->sym_next++] = dist;
- s->sym_buf[s->sym_next++] = dist >> 8;
- s->sym_buf[s->sym_next++] = lc;
+ s->sym_buf[s->sym_next++] = (uch)dist;
+ s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
+ s->sym_buf[s->sym_next++] = (uch)lc;
if (dist == 0) {
/* lc is the unmatched char */
s->dyn_ltree[lc].Freq++;
@@ -1031,7 +1030,7 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
(ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
(ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
- s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+ s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++;
s->dyn_dtree[d_code(dist)].Freq++;
}
return (s->sym_next == s->sym_end);
@@ -1061,7 +1060,7 @@ local void compress_block(s, ltree, dtree)
} else {
/* Here, lc is the match length - MIN_MATCH */
code = _length_code[lc];
- send_code(s, code+LITERALS+1, ltree); /* send the length code */
+ send_code(s, code + LITERALS + 1, ltree); /* send length code */
extra = extra_lbits[code];
if (extra != 0) {
lc -= base_length[code];
@@ -1177,6 +1176,6 @@ local void bi_windup(s)
s->bi_buf = 0;
s->bi_valid = 0;
#ifdef ZLIB_DEBUG
- s->bits_sent = (s->bits_sent+7) & ~7;
+ s->bits_sent = (s->bits_sent + 7) & ~7;
#endif
}
diff --git a/src/3rdparty/zlib/src/uncompr.c b/src/3rdparty/zlib/src/uncompr.c
index f03a1a865e..f9532f46c1 100644
--- a/src/3rdparty/zlib/src/uncompr.c
+++ b/src/3rdparty/zlib/src/uncompr.c
@@ -24,7 +24,7 @@
Z_DATA_ERROR if the input data was corrupted, including if the input data is
an incomplete zlib stream.
*/
-int ZEXPORT uncompress2 (dest, destLen, source, sourceLen)
+int ZEXPORT uncompress2(dest, destLen, source, sourceLen)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
@@ -83,7 +83,7 @@ int ZEXPORT uncompress2 (dest, destLen, source, sourceLen)
err;
}
-int ZEXPORT uncompress (dest, destLen, source, sourceLen)
+int ZEXPORT uncompress(dest, destLen, source, sourceLen)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
diff --git a/src/3rdparty/zlib/src/zconf.h b/src/3rdparty/zlib/src/zconf.h
index 837f7bcc57..a0997ab0e9 100644
--- a/src/3rdparty/zlib/src/zconf.h
+++ b/src/3rdparty/zlib/src/zconf.h
@@ -356,6 +356,9 @@
# ifdef FAR
# undef FAR
# endif
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
# include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
@@ -474,11 +477,18 @@ typedef uLong FAR uLongf;
# undef _LARGEFILE64_SOURCE
#endif
-#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
-# define Z_HAVE_UNISTD_H
+#ifndef Z_HAVE_UNISTD_H
+# ifdef __WATCOMC__
+# define Z_HAVE_UNISTD_H
+# endif
+#endif
+#ifndef Z_HAVE_UNISTD_H
+# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
+# define Z_HAVE_UNISTD_H
+# endif
#endif
#ifndef Z_SOLO
-# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
+# if defined(Z_HAVE_UNISTD_H)
# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
# ifdef VMS
# include <unixio.h> /* for off_t */
diff --git a/src/3rdparty/zlib/src/zlib.h b/src/3rdparty/zlib/src/zlib.h
index 84087ef332..b06a50c5ca 100644
--- a/src/3rdparty/zlib/src/zlib.h
+++ b/src/3rdparty/zlib/src/zlib.h
@@ -1,5 +1,5 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
- version 1.2.12, March 11th, 2022
+ version 1.2.13, October 13th, 2022
Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
@@ -41,11 +41,11 @@
extern "C" {
#endif
-#define ZLIB_VERSION "1.2.12 (Qt)"
-#define ZLIB_VERNUM 0x12c0
+#define ZLIB_VERSION "1.2.13 (Qt)"
+#define ZLIB_VERNUM 0x12d0
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 2
-#define ZLIB_VER_REVISION 12
+#define ZLIB_VER_REVISION 13
#define ZLIB_VER_SUBREVISION 0
/*
@@ -280,7 +280,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
== 0), or after each call of deflate(). If deflate returns Z_OK and with
zero avail_out, it must be called again after making room in the output
buffer because there might be more output pending. See deflatePending(),
- which can be used if desired to determine whether or not there is more ouput
+ which can be used if desired to determine whether or not there is more output
in that case.
Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
@@ -664,7 +664,7 @@ ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,
to dictionary. dictionary must have enough space, where 32768 bytes is
always enough. If deflateGetDictionary() is called with dictionary equal to
Z_NULL, then only the dictionary length is returned, and nothing is copied.
- Similary, if dictLength is Z_NULL, then it is not set.
+ Similarly, if dictLength is Z_NULL, then it is not set.
deflateGetDictionary() may return a length less than the window size, even
when more than the window size in input has been provided. It may return up
@@ -919,7 +919,7 @@ ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
to dictionary. dictionary must have enough space, where 32768 bytes is
always enough. If inflateGetDictionary() is called with dictionary equal to
Z_NULL, then only the dictionary length is returned, and nothing is copied.
- Similary, if dictLength is Z_NULL, then it is not set.
+ Similarly, if dictLength is Z_NULL, then it is not set.
inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
stream state is inconsistent.
@@ -1441,12 +1441,12 @@ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
In the event that the end of file is reached and only a partial item is
available at the end, i.e. the remaining uncompressed data length is not a
- multiple of size, then the final partial item is nevetheless read into buf
+ multiple of size, then the final partial item is nevertheless read into buf
and the end-of-file flag is set. The length of the partial item read is not
provided, but could be inferred from the result of gztell(). This behavior
is the same as the behavior of fread() implementations in common libraries,
but it prevents the direct use of gzfread() to read a concurrently written
- file, reseting and retrying on end-of-file, when size is not 1.
+ file, resetting and retrying on end-of-file, when size is not 1.
*/
ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));
@@ -1917,7 +1917,7 @@ ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp));
ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void));
ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int));
ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int));
-ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp));
+ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF((z_streamp));
ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
#if defined(_WIN32) && !defined(Z_SOLO)
diff --git a/src/3rdparty/zlib/src/zutil.c b/src/3rdparty/zlib/src/zutil.c
index dcab28a0d5..9543ae825e 100644
--- a/src/3rdparty/zlib/src/zutil.c
+++ b/src/3rdparty/zlib/src/zutil.c
@@ -61,9 +61,11 @@ uLong ZEXPORT zlibCompileFlags()
#ifdef ZLIB_DEBUG
flags += 1 << 8;
#endif
+ /*
#if defined(ASMV) || defined(ASMINF)
flags += 1 << 9;
#endif
+ */
#ifdef ZLIB_WINAPI
flags += 1 << 10;
#endif
@@ -119,7 +121,7 @@ uLong ZEXPORT zlibCompileFlags()
# endif
int ZLIB_INTERNAL z_verbose = verbose;
-void ZLIB_INTERNAL z_error (m)
+void ZLIB_INTERNAL z_error(m)
char *m;
{
fprintf(stderr, "%s\n", m);
@@ -214,7 +216,7 @@ local ptr_table table[MAX_PTR];
* a protected system like OS/2. Use Microsoft C instead.
*/
-voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size)
{
voidpf buf;
ulg bsize = (ulg)items*size;
@@ -240,7 +242,7 @@ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
return buf;
}
-void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr)
{
int n;
@@ -277,13 +279,13 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
# define _hfree hfree
#endif
-voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size)
{
(void)opaque;
return _halloc((long)items, size);
}
-void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr)
{
(void)opaque;
_hfree(ptr);
@@ -302,7 +304,7 @@ extern voidp calloc OF((uInt items, uInt size));
extern void free OF((voidpf ptr));
#endif
-voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
+voidpf ZLIB_INTERNAL zcalloc(opaque, items, size)
voidpf opaque;
unsigned items;
unsigned size;
@@ -312,7 +314,7 @@ voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
(voidpf)calloc(items, size);
}
-void ZLIB_INTERNAL zcfree (opaque, ptr)
+void ZLIB_INTERNAL zcfree(opaque, ptr)
voidpf opaque;
voidpf ptr;
{
diff --git a/src/3rdparty/zlib/src/zutil.h b/src/3rdparty/zlib/src/zutil.h
index 0d78483358..14aba921b0 100644
--- a/src/3rdparty/zlib/src/zutil.h
+++ b/src/3rdparty/zlib/src/zutil.h
@@ -206,6 +206,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
(!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));
#endif
/* common defaults */
diff --git a/src/android/jar/src/org/qtproject/qt/android/CursorHandle.java b/src/android/jar/src/org/qtproject/qt/android/CursorHandle.java
index d754b3b620..c15a654b79 100644
--- a/src/android/jar/src/org/qtproject/qt/android/CursorHandle.java
+++ b/src/android/jar/src/org/qtproject/qt/android/CursorHandle.java
@@ -124,8 +124,7 @@ public class CursorHandle implements ViewTreeObserver.OnPreDrawListener
m_id = id;
m_attr = attr;
m_layout = layout;
- DisplayMetrics metrics = new DisplayMetrics();
- activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ DisplayMetrics metrics = activity.getResources().getDisplayMetrics();
m_yShift = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1f, metrics);
tolerance = Math.min(1, (int)(m_yShift / 2f));
m_lastX = m_lastY = -1 - tolerance;
diff --git a/src/android/jar/src/org/qtproject/qt/android/ExtractStyle.java b/src/android/jar/src/org/qtproject/qt/android/ExtractStyle.java
index 8c391a7e7b..109a0e5d93 100644
--- a/src/android/jar/src/org/qtproject/qt/android/ExtractStyle.java
+++ b/src/android/jar/src/org/qtproject/qt/android/ExtractStyle.java
@@ -70,6 +70,7 @@ import android.graphics.drawable.ScaleDrawable;
import android.graphics.drawable.StateListDrawable;
import android.graphics.drawable.VectorDrawable;
import android.os.Build;
+import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
@@ -171,6 +172,42 @@ public class ExtractStyle {
Context m_context;
private final HashMap<String, DrawableCache> m_drawableCache = new HashMap<>();
+ private static final String EXTRACT_STYLE_KEY = "extract.android.style";
+ private static final String EXTRACT_STYLE_MINIMAL_KEY = "extract.android.style.option";
+
+ private static boolean m_missingNormalStyle = false;
+ private static boolean m_missingDarkStyle = false;
+ private static String m_stylePath = null;
+ private static boolean m_extractMinimal = false;
+
+ public static void setup(Bundle loaderParams) {
+ if (loaderParams.containsKey(EXTRACT_STYLE_KEY)) {
+ m_stylePath = loaderParams.getString(EXTRACT_STYLE_KEY);
+
+ boolean darkModeFileMissing = !(new File(m_stylePath + "darkUiMode/style.json").exists());
+ m_missingDarkStyle = Build.VERSION.SDK_INT > 28 && darkModeFileMissing;
+
+ m_missingNormalStyle = !(new File(m_stylePath + "style.json").exists());
+
+ m_extractMinimal = loaderParams.containsKey(EXTRACT_STYLE_MINIMAL_KEY) &&
+ loaderParams.getBoolean(EXTRACT_STYLE_MINIMAL_KEY);
+ }
+ }
+
+ public static void runIfNeeded(Context context, boolean extractDarkMode) {
+ if (m_stylePath == null)
+ return;
+ if (extractDarkMode) {
+ if (m_missingDarkStyle) {
+ new ExtractStyle(context, m_stylePath + "darkUiMode/", m_extractMinimal);
+ m_missingDarkStyle = false;
+ }
+ } else if (m_missingNormalStyle) {
+ new ExtractStyle(context, m_stylePath, m_extractMinimal);
+ m_missingNormalStyle = false;
+ }
+ }
+
public ExtractStyle(Context context, String extractPath, boolean minimal) {
m_minimal = minimal;
m_extractPath = extractPath + "/";
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
index 7d49fb71b1..1c6c0dad2d 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
@@ -120,8 +120,6 @@ public class QtActivityDelegate
private static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables";
private static final String APPLICATION_PARAMETERS_KEY = "application.parameters";
private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
- private static final String EXTRACT_STYLE_KEY = "extract.android.style";
- private static final String EXTRACT_STYLE_MINIMAL_KEY = "extract.android.style.option";
public static final int SYSTEM_UI_VISIBILITY_NORMAL = 0;
public static final int SYSTEM_UI_VISIBILITY_FULLSCREEN = 1;
@@ -743,11 +741,8 @@ public class QtActivityDelegate
libraries.remove(libraries.size() - 1);
}
- if (loaderParams.containsKey(EXTRACT_STYLE_KEY)) {
- String path = loaderParams.getString(EXTRACT_STYLE_KEY);
- new ExtractStyle(m_activity, path, loaderParams.containsKey(EXTRACT_STYLE_MINIMAL_KEY) &&
- loaderParams.getBoolean(EXTRACT_STYLE_MINIMAL_KEY));
- }
+ ExtractStyle.setup(loaderParams);
+ ExtractStyle.runIfNeeded(m_activity, isUiModeDark(m_activity.getResources().getConfiguration()));
try {
m_super_dispatchKeyEvent = m_activity.getClass().getMethod("super_dispatchKeyEvent", KeyEvent.class);
@@ -1025,13 +1020,20 @@ public class QtActivityDelegate
updateFullScreen();
}
+ boolean isUiModeDark(Configuration config)
+ {
+ return (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
+ }
+
private void handleUiModeChange(int uiMode)
{
switch (uiMode) {
case Configuration.UI_MODE_NIGHT_NO:
+ ExtractStyle.runIfNeeded(m_activity, false);
QtNative.handleUiDarkModeChanged(0);
break;
case Configuration.UI_MODE_NIGHT_YES:
+ ExtractStyle.runIfNeeded(m_activity, true);
QtNative.handleUiDarkModeChanged(1);
break;
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java
index 6cf1aca5bf..a6930e4d97 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java
@@ -41,6 +41,8 @@
package org.qtproject.qt.android;
import android.content.Context;
+import android.os.Build;
+import android.view.WindowMetrics;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.ExtractedText;
@@ -94,9 +96,17 @@ class HideKeyboardRunnable implements Runnable {
Activity activity = QtNative.activity();
Rect r = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
- DisplayMetrics metrics = new DisplayMetrics();
- activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
- final int kbHeight = metrics.heightPixels - r.bottom;
+
+ int screenHeight = 0;
+ if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ screenHeight = metrics.heightPixels;
+ } else {
+ final WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics();
+ screenHeight = maximumWindowMetrics.getBounds().height();
+ }
+ final int kbHeight = screenHeight - r.bottom;
if (kbHeight < 100)
QtNative.activityDelegate().setKeyboardVisibility(false, m_hideTimeStamp);
}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtLayout.java b/src/android/jar/src/org/qtproject/qt/android/QtLayout.java
index 6c52a00422..5ff46fc96b 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtLayout.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtLayout.java
@@ -42,7 +42,9 @@ package org.qtproject.qt.android;
import android.app.Activity;
import android.content.Context;
+import android.graphics.Rect;
import android.os.Build;
+import android.util.Log;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Display;
@@ -50,6 +52,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.WindowManager;
+import android.graphics.Insets;
+import android.view.WindowMetrics;
+import android.content.res.Configuration;
+import android.content.res.Resources;
public class QtLayout extends ViewGroup
{
@@ -93,15 +99,95 @@ public class QtLayout extends ViewGroup
@Override
protected void onSizeChanged (int w, int h, int oldw, int oldh)
{
- WindowInsets insets = getRootWindowInsets();
+ Activity activity = (Activity)getContext();
+ if (activity == null)
+ return;
+
+ final WindowManager windowManager = activity.getWindowManager();
+ Display display;
+
+ int appWidth = 0;
+ int appHeight = 0;
+
+ int insetLeft = 0;
+ int insetTop = 0;
+
+ int maxWidth = 0;
+ int maxHeight = 0;
+
+ double xdpi = 0;
+ double ydpi = 0;
+ double scaledDensity = 0;
+ double density = 0;
+
+ if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+ display = windowManager.getDefaultDisplay();
+
+ final DisplayMetrics appMetrics = new DisplayMetrics();
+ display.getMetrics(appMetrics);
+
+ final WindowInsets rootInsets = getRootWindowInsets();
+
+ insetLeft = rootInsets.getStableInsetLeft();
+ insetTop = rootInsets.getStableInsetTop();
- DisplayMetrics realMetrics = new DisplayMetrics();
- Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
- ? ((Activity)getContext()).getWindowManager().getDefaultDisplay()
- : ((Activity)getContext()).getDisplay();
- display.getRealMetrics(realMetrics);
+ appWidth = appMetrics.widthPixels - rootInsets.getStableInsetRight() + rootInsets.getStableInsetLeft();
- if ((realMetrics.widthPixels > realMetrics.heightPixels) != (w > h)) {
+ if (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
+ appHeight = appMetrics.heightPixels - rootInsets.getStableInsetTop();
+ } else {
+ appHeight = appMetrics.heightPixels - rootInsets.getStableInsetTop() + rootInsets.getStableInsetBottom();
+ }
+
+ final DisplayMetrics maxMetrics = new DisplayMetrics();
+ display.getRealMetrics(maxMetrics);
+
+ maxWidth = maxMetrics.widthPixels;
+ maxHeight = maxMetrics.heightPixels;
+
+ density = appMetrics.density;
+ xdpi = appMetrics.xdpi;
+ ydpi = appMetrics.ydpi;
+ scaledDensity = appMetrics.scaledDensity;
+
+ } else {
+ // after API 30 use getCurrentWindowMetrics for application metrics
+ // getMaximumWindowMetrics for the screen metrics
+ // resource configuration for density as best practice
+ // and the resource display metrics for the rest
+ display = activity.getDisplay();
+
+ final WindowMetrics appMetrics = windowManager.getCurrentWindowMetrics();
+ final WindowMetrics maxMetrics = windowManager.getMaximumWindowMetrics();
+
+ final WindowInsets windowInsets = appMetrics.getWindowInsets();
+ Insets statusBarInsets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.statusBars());
+ Insets cutoutInsets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.displayCutout());
+ Insets imeInsets = windowInsets.getInsets(WindowInsets.Type.ime());
+
+ insetLeft = cutoutInsets.left;
+ insetTop = statusBarInsets.top;
+
+ appWidth = w;
+ appHeight = h - imeInsets.bottom;
+
+ maxWidth = maxMetrics.getBounds().width();
+ maxHeight = maxMetrics.getBounds().height();
+
+ final Resources resources = activity.getResources();
+ final Configuration configuration = resources.getConfiguration();
+ density = configuration.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
+
+ final DisplayMetrics displayMetrics = resources.getDisplayMetrics();
+ xdpi = displayMetrics.xdpi;
+ ydpi = displayMetrics.ydpi;
+ density = displayMetrics.density;
+ scaledDensity = displayMetrics.scaledDensity;
+ }
+
+ float refreshRate = display.getRefreshRate();
+
+ if ((appWidth > appHeight) != (w > h)) {
// This is an intermediate state during display rotation.
// The new size is still reported for old orientation, while
// realMetrics contain sizes for new orientation. Setting
@@ -112,34 +198,20 @@ public class QtLayout extends ViewGroup
return;
}
- boolean isFullScreenView = h == realMetrics.heightPixels;
- // The code uses insets for fullscreen mode only. However in practice
- // the insets can be reported incorrectly. Both on Android 6 and Android 11
- // a non-zero bottom inset is reported even when the
- // WindowManager.LayoutParams.FLAG_FULLSCREEN flag is set.
- // To avoid that, add an extra check for the fullscreen mode.
- // The insets-related logic is not removed for the case when
- // isFullScreenView == true, but hasFlagFullscreen == false, although
- // I can't get such case in my tests.
- final int windowFlags = ((Activity)getContext()).getWindow().getAttributes().flags;
- final boolean hasFlagFullscreen =
- (windowFlags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
- int insetLeft =
- (isFullScreenView && !hasFlagFullscreen) ? insets.getSystemWindowInsetLeft() : 0;
- int insetTop =
- (isFullScreenView && !hasFlagFullscreen) ? insets.getSystemWindowInsetTop() : 0;
- int insetRight =
- (isFullScreenView && !hasFlagFullscreen) ? insets.getSystemWindowInsetRight() : 0;
- int insetBottom =
- (isFullScreenView && !hasFlagFullscreen) ? insets.getSystemWindowInsetBottom() : 0;
-
- int usableAreaWidth = w - insetLeft - insetRight;
- int usableAreaHeight = h - insetTop - insetBottom;
-
- QtNative.setApplicationDisplayMetrics(
- realMetrics.widthPixels, realMetrics.heightPixels, insetLeft, insetTop,
- usableAreaWidth, usableAreaHeight, realMetrics.xdpi, realMetrics.ydpi,
- realMetrics.scaledDensity, realMetrics.density, display.getRefreshRate());
+ final int flag =
+ activity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN;
+
+ if (flag == WindowManager.LayoutParams.FLAG_FULLSCREEN || h == maxHeight) {
+ // immersive mode uses the whole screen
+ appWidth = maxWidth;
+ appHeight = maxHeight;
+ insetLeft = insetTop = 0;
+ }
+
+ QtNative.setApplicationDisplayMetrics(maxWidth, maxHeight, insetLeft,
+ insetTop, appWidth, appHeight,
+ xdpi,ydpi,scaledDensity, density,
+ refreshRate);
int newRotation = display.getRotation();
if (m_ownDisplayRotation != m_activityDisplayRotation
diff --git a/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java
index 4ed6d66b42..88312cbdbd 100644
--- a/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java
@@ -57,6 +57,7 @@ import android.view.MotionEvent;
import android.view.View.OnHoverListener;
import android.content.Context;
+import android.system.Os;
import java.util.LinkedList;
import java.util.List;
@@ -124,6 +125,8 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
@Override
public void onAccessibilityStateChanged(boolean enabled)
{
+ if (Os.getenv("QT_ANDROID_DISABLE_ACCESSIBILITY") != null)
+ return;
if (enabled) {
try {
View view = m_view;
diff --git a/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java
index 47b500fbf3..8edade7c7d 100644
--- a/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java
+++ b/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java
@@ -97,8 +97,14 @@ public class QtActivity extends Activity
public QtActivity()
{
m_loader = new QtActivityLoader(this);
- QT_ANDROID_THEMES = new String[] {"Theme_Holo_Light"};
- QT_ANDROID_DEFAULT_THEME = "Theme_Holo_Light";
+
+ if (Build.VERSION.SDK_INT < 29) {
+ QT_ANDROID_THEMES = new String[] {"Theme_Holo_Light"};
+ QT_ANDROID_DEFAULT_THEME = "Theme_Holo_Light";
+ } else {
+ QT_ANDROID_THEMES = new String[] {"Theme_DeviceDefault_DayNight"};
+ QT_ANDROID_DEFAULT_THEME = "Theme_DeviceDefault_DayNight";
+ }
}
diff --git a/src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java b/src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java
index d2e94ffa92..0012af5951 100644
--- a/src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java
+++ b/src/android/java/src/org/qtproject/qt/android/bindings/QtLoader.java
@@ -361,7 +361,7 @@ public abstract class QtLoader {
}
}
- if (!(new File(stylePath)).exists() && !extractOption.equals("none")) {
+ if (!extractOption.equals("none")) {
loaderParams.putString(EXTRACT_STYLE_KEY, stylePath);
loaderParams.putBoolean(EXTRACT_STYLE_MINIMAL_KEY, extractOption.equals("minimal"));
}
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp
index fe7ab0c070..94bf442a74 100644
--- a/src/corelib/animation/qpropertyanimation.cpp
+++ b/src/corelib/animation/qpropertyanimation.cpp
@@ -58,6 +58,10 @@
\snippet code/src_corelib_animation_qpropertyanimation.cpp 0
+ \note You can also control an animation's lifespan by choosing a
+ \l{QAbstractAnimation::DeletionPolicy}{delete policy} while starting the
+ animation.
+
The property name and the QObject instance of which property
should be animated are passed to the constructor. You can then
specify the start and end value of the property. The procedure is
diff --git a/src/corelib/doc/snippets/code/doc_src_containers.cpp b/src/corelib/doc/snippets/code/doc_src_containers.cpp
index a191c9af5c..15380da378 100644
--- a/src/corelib/doc/snippets/code/doc_src_containers.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_containers.cpp
@@ -63,10 +63,30 @@ private:
};
//! [0]
+//! [range_for]
+QList<QString> list = {"A", "B", "C", "D"};
+for (const auto &item : list) {
+ ...
+}
+//! [range_for]
+
+//! [range_for_as_const]
+QList<QString> list = {"A", "B", "C", "D"};
+for (const auto &item : std::as_const(list)) {
+ ...
+}
+//! [range_for_as_const]
+
+//! [index]
+QList<QString> list = {"A", "B", "C", "D"};
+for (qsizetype i = 0; i < list.size(); ++i) {
+ const auto &item = list.at(i);
+ ...
+}
+//! [index]
//! [1]
-QList<QString> list;
-list << "A" << "B" << "C" << "D";
+QList<QString> list = {"A", "B", "C", "D"};
QListIterator<QString> i(list);
while (i.hasNext())
@@ -118,11 +138,12 @@ while (i.hasNext())
//! [7]
-QMap<QString, QString> map;
-map.insert("Paris", "France");
-map.insert("Guatemala City", "Guatemala");
-map.insert("Mexico City", "Mexico");
-map.insert("Moscow", "Russia");
+QMap<QString, QString> map = {
+ {"Paris", "France"},
+ {"Guatemala City", "Guatemala"},
+ {"Mexico City", "Mexico"},
+ {"Moscow", "Russia"}
+};
...
QMutableMapIterator<QString, QString> i(map);
@@ -153,28 +174,23 @@ while (i.findNext(widget))
//! [10]
-QList<QString> list;
-list << "A" << "B" << "C" << "D";
+QList<QString> list = {"A", "B", "C", "D"};
-QList<QString>::iterator i;
-for (i = list.begin(); i != list.end(); ++i)
+for (auto i = list.begin(), end = list.end(); i != end; ++i)
*i = (*i).toLower();
//! [10]
//! [11]
-QList<QString> list;
-list << "A" << "B" << "C" << "D";
+QList<QString> list = {"A", "B", "C", "D"};
-QList<QString>::reverse_iterator i;
-for (i = list.rbegin(); i != list.rend(); ++i)
+for (auto i = list.rbegin(), rend = list.rend(); i != rend; ++i)
*i = i->toLower();
//! [11]
//! [12]
-QList<QString>::const_iterator i;
-for (i = list.constBegin(); i != list.constEnd(); ++i)
+for (auto i = list.cbegin(), end = list.cend(); i != end; ++i)
qDebug() << *i;
//! [12]
@@ -182,8 +198,7 @@ for (i = list.constBegin(); i != list.constEnd(); ++i)
//! [13]
QMap<int, int> map;
...
-QMap<int, int>::const_iterator i;
-for (i = map.constBegin(); i != map.constEnd(); ++i)
+for (auto i = map.cbegin(), end = map.cend(); i != end; ++i)
qDebug() << i.key() << ':' << i.value();
//! [13]
@@ -191,13 +206,11 @@ for (i = map.constBegin(); i != map.constEnd(); ++i)
//! [14]
// RIGHT
const QList<int> sizes = splitter->sizes();
-QList<int>::const_iterator i;
-for (i = sizes.begin(); i != sizes.end(); ++i)
+for (auto i = sizes.begin(), end = sizes.end(); i != end; ++i)
...
// WRONG
-QList<int>::const_iterator i;
-for (i = splitter->sizes().begin();
+for (auto i = splitter->sizes().begin();
i != splitter->sizes().end(); ++i)
...
//! [14]
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
index 7bd8121b90..e507c78a3d 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
@@ -50,10 +50,94 @@
//! [0]
- QPropertyAnimation *animation = new QPropertyAnimation(myWidget, "geometry");
- animation->setDuration(10000);
- animation->setStartValue(QRect(0, 0, 100, 30));
- animation->setEndValue(QRect(250, 250, 100, 30));
+#include <QApplication>
+#include <QPushButton>
+#include <QPropertyAnimation>
+//! [1]
+class MyButtonWidget : public QWidget
+{
+public:
+ MyButtonWidget(QWidget *parent = nullptr);
+};
- animation->start();
+MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
+{
+ QPushButton *button = new QPushButton(tr("Animated Button"), this);
+ QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
+ anim->setDuration(10000);
+ anim->setStartValue(QPoint(0, 0));
+ anim->setEndValue(QPoint(100, 250));
+ anim->start();
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ MyButtonWidget buttonAnimWidget;
+ buttonAnimWidget.resize(QSize(800, 600));
+ buttonAnimWidget.show();
+ return a.exec();
+}
+//! [1]
//! [0]
+
+
+//! [easing-curve]
+MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
+{
+ QPushButton *button = new QPushButton(tr("Animated Button"), this);
+ QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
+ anim->setDuration(10000);
+ anim->setStartValue(QPoint(0, 0));
+ anim->setEndValue(QPoint(100, 250));
+ anim->setEasingCurve(QEasingCurve::OutBounce);
+ anim->start();
+}
+//! [easing-curve]
+
+
+//! [animation-group1]
+MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
+{
+ QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
+ QPushButton *clyde = new QPushButton(tr("Clyde"), this);
+
+ QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
+ anim1->setDuration(3000);
+ anim1->setStartValue(QPoint(0, 0));
+ anim1->setEndValue(QPoint(100, 250));
+
+ QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
+ anim2->setDuration(3000);
+ anim2->setStartValue(QPoint(100, 250));
+ anim2->setEndValue(QPoint(500, 500));
+
+ QParallelAnimationGroup *parallelAnim = new QParallelAnimationGroup;
+ parallelAnim->addAnimation(anim1);
+ parallelAnim->addAnimation(anim2);
+ parallelAnim->start();
+}
+//! [animation-group1]
+
+//! [animation-group2]
+MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
+{
+ QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
+ QPushButton *clyde = new QPushButton(tr("Clyde"), this);
+
+ QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
+ anim1->setDuration(3000);
+ anim1->setStartValue(QPoint(0, 0));
+ anim1->setEndValue(QPoint(100, 250));
+
+ QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
+ anim2->setDuration(3000);
+ anim2->setStartValue(QPoint(0, 0));
+ anim2->setEndValue(QPoint(200, 250));
+
+ QSequentialAnimationGroup *sequenceAnim = new QSequentialAnimationGroup;
+ sequenceAnim->addAnimation(anim1);
+ sequenceAnim->addAnimation(anim2);
+ sequenceAnim->start();
+}
+//! [animation-group2]
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qstring.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qstring.cpp
index fe44bee4a8..4f7831d642 100644
--- a/src/corelib/doc/snippets/code/src_corelib_text_qstring.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qstring.cpp
@@ -75,6 +75,9 @@ if (str == QString("auto") || str == QString("extern")
}
//! [4]
+//! [4bis]
+str.append("Hello ").append("World");
+//! [4bis]
//! [5]
if (str == QLatin1String("auto")
diff --git a/src/corelib/doc/snippets/qstringlist/main.cpp b/src/corelib/doc/snippets/qstringlist/main.cpp
index fceadc4e99..5ee0624487 100644
--- a/src/corelib/doc/snippets/qstringlist/main.cpp
+++ b/src/corelib/doc/snippets/qstringlist/main.cpp
@@ -69,24 +69,6 @@ Widget::Widget(QWidget *parent)
fonts << "Courier" << "Verdana";
//! [0b]
-//! [1]
- for (int i = 0; i < fonts.size(); ++i)
- cout << fonts.at(i).toLocal8Bit().constData() << Qt::endl;
-//! [1]
-
-//! [2]
- QStringListIterator javaStyleIterator(fonts);
- while (javaStyleIterator.hasNext())
- cout << javaStyleIterator.next().toLocal8Bit().constData() << Qt::endl;
-//! [2]
-
-//! [3]
- QStringList::const_iterator constIterator;
- for (constIterator = fonts.constBegin(); constIterator != fonts.constEnd();
- ++constIterator)
- cout << (*constIterator).toLocal8Bit().constData() << Qt::endl;
-//! [3]
-
//! [4]
QString str = fonts.join(", ");
// str == "Arial, Helvetica, Times, Courier"
diff --git a/src/corelib/doc/src/animation.qdoc b/src/corelib/doc/src/animation.qdoc
index d67ac2e505..ceef6efc45 100644
--- a/src/corelib/doc/src/animation.qdoc
+++ b/src/corelib/doc/src/animation.qdoc
@@ -46,153 +46,134 @@
\keyword Animation
- The animation framework aims to provide an easy way for creating animated
- and smooth GUIs. By animating Qt properties, the framework provides great
- freedom for animating widgets and other \l{QObject}s. The framework can
- also be used with the Graphics View framework. Many of the concepts
- available in the animation framework are also available in \l{Qt Quick},
- where it offers a declarative way of defining animations. Much of the
- knowledge acquired about the animation framework can be applied to
- \l{Qt Quick}.
-
- In this overview, we explain the basics of its architecture. We
- also show examples of the most common techniques that the
- framework allows for animating \l{QObject}s and graphics items.
+ The animation framework provides an easy way to animate your GUI elements.
+ It enables you to animate a Qt property value of a widget or QObject.
+ Most of the features offered by the framework are also available in
+ \l{Qt Quick}, where it's possible to define animations in a declarative way.
+
+ This overview explains the framework's architecture, with examples that
+ demonstrate the common techniques used for animating QObject and
+ GUI elements.
\tableofcontents
- \section1 The Animation Architecture
+ \section1 The Animation architecture
- We will in this section take a high-level look at the animation
- framework's architecture and how it is used to animate Qt
- properties. The following diagram shows the most important classes
- in the animation framework.
+ The following diagram shows the most important classes provided by the
+ framework:
\image animations-architecture.png
- The animation framework foundation consists of the base class
- QAbstractAnimation, and its two subclasses QVariantAnimation and
- QAnimationGroup. QAbstractAnimation is the ancestor of all
- animations. It represents basic properties that are common for all
- animations in the framework; notably, the ability to start, stop,
- and pause an animation. It is also receives the time change
- notifications.
-
- The animation framework further provides the QPropertyAnimation
- class, which inherits QVariantAnimation and performs animation of
- a Qt property, which is part of Qt's \l{Meta-Object
- System}{meta-object system}. The class performs an interpolation
- over the property using an easing curve. So when you want to
- animate a value, you can declare it as a property and make your
- class a QObject. Note that this gives us great freedom in
- animating already existing widgets and other \l{QObject}s.
+ It includes the QAbstractAnimation class, which provides the
+ necessary foundation for animations. This class defines the
+ generic properties for all animations supported by the framework.
+ For example, the ability to start, stop, and pause an animation. The
+ class also receives the time change notifications.
+
+ The framework further provides the QVariantAnimation and
+ QAnimationGroup classes, which build on their base case, QAbstractAnimation.
+ Next in the hierarchy is QPropertyAnimation, which is derived from
+ QVariantAnmiation, and it lets you animate a Qt property of a widget or
+ QObject. The class performs interpolation on the property value using an
+ easing curve. With these in place, you just need a QObject class with a
+ Qt property value that you can animate.
+
+ \note It is required that the target object you are animating is a QObject
+ or its subclass. This is necessary as the animation framework depends on the
+ \l{Meta-Object System}{meta-object system} for all the information about the
+ object it is animating.
Complex animations can be constructed by building a tree structure
- of \l{QAbstractAnimation}s. The tree is built by using
- \l{QAnimationGroup}s, which function as containers for other
- animations. Note also that the groups are subclasses of
- QAbstractAnimation, so groups can themselves contain other groups.
+ of \l{QAbstractAnimation}s, where the tree is a QAnimationGroup that
+ contains other animations. These animation groups can also contain
+ subgroups representing different groups or animations, such as
+ QParallelAnimationGroup and QSequentialAnimationGroup.
- Behind the scenes, the animations are controlled by a global
- timer, which sends \l{QAbstractAnimation::updateCurrentTime()}{updates} to
- all animations that are playing.
+ Behind the scenes, all animations are controlled by a global
+ timer, which sends \l{QAbstractAnimation::updateCurrentTime()}{updates} about
+ all animations that are running.
- For detailed descriptions of the classes' function and roles in
- the framework, please look up their class descriptions.
+ For detailed information of these individual classes' and their roles in
+ the framework, refer to their documentation.
- \section1 Classes in the Animation Framework
+ \section1 Classes offered by the framework
- These classes provide a framework for creating both simple and complex
- animations.
+ These classes provide the necessary infrastructure to create both simple and
+ complex animations.
\annotatedlist animation
- \section1 Animating Qt Properties
+ \section1 Animating Qt properties
- As mentioned in the previous section, the QPropertyAnimation class can
- interpolate over Qt properties. It is often this class that should be used
- for animation of values; in fact, its superclass, QVariantAnimation, has an
- empty implementation of \l{QVariantAnimation::}{updateCurrentValue()}, and
- does not change any value unless we change it ourselves on the
+ As the QPropertyAnimation class can interpolate on Qt properties, it is
+ used often. In fact, its superclass---QVariantAnimation---provides an
+ abstract implementation of \l{QVariantAnimation::}{updateCurrentValue()},
+ which does not change any value unless you change it on the
\l{QVariantAnimation::valueChanged()}{valueChanged signal}.
- A major reason we chose to animate Qt properties is that it
- presents us with freedom to animate already existing classes in
- the Qt API. Notably, the QWidget class (which we can also embed in
- a QGraphicsView) has properties for its bounds, colors, etc.
- Let's look at a small example:
-
- \code
- QPushButton button("Animated Button");
- button.show();
+ The framework lets you animate the Qt properties of the existing
+ classes in Qt. For example, the QWidget class---can be embedded in
+ a QGraphicsView---has properties for its bounds, colors, and so on.
+ The following example demonstrates how you can animate a QPushButton
+ widget:
- QPropertyAnimation animation(&button, "geometry");
- animation.setDuration(10000);
- animation.setStartValue(QRect(0, 0, 100, 30));
- animation.setEndValue(QRect(250, 250, 100, 30));
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp 0
- animation.start();
- \endcode
+ The example animates the \c pos Qt property of a QPushButton, to move
+ it from the top--left corner of the screen to the end position (250, 250),
+ in 10 seconds (10000 milliseconds).
- This code will move \c button from the top left corner of the
- screen to the position (250, 250) in 10 seconds (10000 milliseconds).
-
- The example above will do a linear interpolation between the
- start and end value. It is also possible to set values
- situated between the start and end value. The interpolation
- will then go by these points.
+ It uses the linear interpolation method to control the speed of
+ animation between the start and end values. Try adding another value
+ in--between the start and end value to see how they are interpolated.
+ This time use the QPropertyAnimation::setKeyValueAt function to add
+ these values:
\code
- QPushButton button("Animated Button");
- button.show();
-
- QPropertyAnimation animation(&button, "geometry");
- animation.setDuration(10000);
-
- animation.setKeyValueAt(0, QRect(0, 0, 100, 30));
- animation.setKeyValueAt(0.8, QRect(250, 250, 100, 30));
- animation.setKeyValueAt(1, QRect(0, 0, 100, 30));
-
- animation.start();
+ ...
+ anim->setDuration(10000);
+ anim->setKeyValueAt(0, QPoint(0, 0));
+ anim->setKeyValueAt(0.8, QPoint(250, 250));
+ anim->setKeyValueAt(1, QPoint(0, 0));
+ ...
\endcode
- In this example, the animation will take the button to (250, 250)
- in 8 seconds, and then move it back to its original position in
- the remaining 2 seconds. The movement will be linearly
- interpolated between these points.
+ In this example, the animation moves the button to
+ (250, 250) in 8 seconds, and moves it back to its original position in
+ the remaining 2 seconds. The button's movement is linear-interpolated
+ between these points.
+
+ You can also animate a QObject's value that is not declared as a Qt
+ property, if the value has a setter method. In such cases, derive
+ a new class from the class that contains the value, and add a Qt property
+ for that value with the setter.
- You also have the possibility to animate values of a QObject
- that is not declared as a Qt property. The only requirement is
- that this value has a setter. You can then subclass the class
- containing the value and declare a property that uses this setter.
- Note that each Qt property requires a getter, so you will need to
- provide a getter yourself if this is not defined.
+ \note Each Qt property requires a getter also, so you should provide a
+ getter if that is not defined.
\code
class MyGraphicsRectItem : public QObject, public QGraphicsRectItem
{
Q_OBJECT
- Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
+ Q_PROPERTY(QPointF pos READ pos WRITE setPos)
};
\endcode
- In the above code example, we subclass QGraphicsRectItem and
- define a geometry property. We can now animate the widgets
- geometry even if QGraphicsRectItem does not provide the geometry
- property.
+ In this example, the \c MyGraphicsRectItem derives from
+ QGraphicsRectItem and QObject, and defines the \c pos property. You can
+ animate the item's \c pos even if QGraphicsRectItem does not provide
+ the \c pos property.
- For a general introduction to the Qt property system, see its
- \l{Qt's Property System}{overview}.
+ For a general introduction to the Qt property system, refer to
+ \l{Qt's Property System}.
\section1 Animations and the Graphics View Framework
- When you want to animate \l{QGraphicsItem}s, you also use
- QPropertyAnimation. However, QGraphicsItem does not inherit QObject.
- A good solution is to subclass the graphics item you wish to animate.
- This class will then also inherit QObject.
- This way, QPropertyAnimation can be used for \l{QGraphicsItem}s.
- The example below shows how this is done. Another possibility is
- to inherit QGraphicsWidget, which already is a QObject.
+ QPropertyAnimation can also be used to animate a QGraphicsItem, which does
+ not inherit QObject. In such cases, you derive a class from the graphics
+ item that you want to animate. This derived class should also inherit form
+ QObject to enable using QPropertyAnimation on a QGraphicsItem. The
+ following example shows how this is done:
\code
class Pixmap : public QObject, public QGraphicsPixmapItem
@@ -200,121 +181,78 @@
Q_OBJECT
Q_PROPERTY(QPointF pos READ pos WRITE setPos)
...
+ }
\endcode
- As described in the previous section, we need to define
- properties that we wish to animate.
+ \note You can also derive from QGraphicsWidget, which already is a
+ QObject.
- Note that QObject must be the first class inherited as the
- meta-object system demands this.
+ As described in the previous section, you need to define
+ properties that you want to animate. The derived class must inherit
+ from QObject first as the meta-object system requires it.
- \section1 Easing Curves
+ \section1 Easing curves
- As mentioned, QPropertyAnimation performs an interpolation between
- the start and end property value. In addition to adding more key
- values to the animation, you can also use an easing curve. Easing
- curves describe a function that controls how the speed of the
- interpolation between 0 and 1 should be, and are useful if you
- want to control the speed of an animation without changing the
- path of the interpolation.
+ A QPropertyAnimation performs linear interpolation
+ between the start and end property values. In addition to adding more key
+ values to the animation, you can also choose an easing curve to control the
+ speed of interpolation between 0 and 1, without changing the
+ path.
- \code
- QPushButton button("Animated Button");
- button.show();
- QPropertyAnimation animation(&button, "geometry");
- animation.setDuration(3000);
- animation.setStartValue(QRect(0, 0, 100, 30));
- animation.setEndValue(QRect(250, 250, 100, 30));
-
- animation.setEasingCurve(QEasingCurve::OutBounce);
-
- animation.start();
- \endcode
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp easing-curve
- Here the animation will follow a curve that makes it bounce like a
- ball as if it was dropped from the start to the end position.
- QEasingCurve has a large collection of curves for you to choose
- from. These are defined by the QEasingCurve::Type enum. If you are
- in need of another curve, you can also implement one yourself, and
+ In this example, the animation follows a curve that makes the
+ \c button bounce like a ball. QEasingCurve offers a large collection of curves
+ to choose from the QEasingCurve::Type enum. If you want
+ to use another curve that is not available, implement one yourself and
register it with QEasingCurve.
- \omit Drop this for the first Lab release
- (Example of custom easing curve (without the actual impl of
- the function I expect)
- \endomit
+ \section1 Grouping animations
- \section1 Putting Animations Together
-
- An application will often contain more than one animation. For
- instance, you might want to move more than one graphics item
+ An application often contains more than one animation. For
+ example, it wants to move more than one graphics item
simultaneously or move them in sequence after each other.
- The subclasses of QAnimationGroup (QSequentialAnimationGroup and
- QParallelAnimationGroup) are containers for other animations so
+ The subclasses of QAnimationGroup---QSequentialAnimationGroup and
+ QParallelAnimationGroup---are containers for other animations so
that these animations can be animated either in sequence or
- parallel. The QAnimationGroup is an example of an animation that
- does not animate properties, but it gets notified of time changes
- periodically. This enables it to forward those time changes to its
- contained animations, and thereby controlling when its animations
- are played.
-
- Let's look at code examples that use both
- QSequentialAnimationGroup and QParallelAnimationGroup, starting
- off with the latter.
-
- \code
- QPushButton *bonnie = new QPushButton("Bonnie");
- bonnie->show();
+ parallel. The QAnimationGroup does not animate properties, but it
+ gets notified of time changes periodically. This enables it to
+ forward those time changes to the animation groups, which control when
+ their animations are played.
- QPushButton *clyde = new QPushButton("Clyde");
- clyde->show();
+ The two following examples demonstrate the use of both
+ QSequentialAnimationGroup and QParallelAnimationGroup:
- QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "geometry");
- // Set up anim1
-
- QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "geometry");
- // Set up anim2
-
- QParallelAnimationGroup *group = new QParallelAnimationGroup;
- group->addAnimation(anim1);
- group->addAnimation(anim2);
-
- group->start();
- \endcode
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp animation-group1
A parallel group plays more than one animation at the same time.
- Calling its \l{QAbstractAnimation::}{start()} function will start
- all animations it governs.
-
- \code
- QPushButton button("Animated Button");
- button.show();
+ Its \l{QAbstractAnimation::}{start()} function starts all
+ animations that are part of the group.
- QPropertyAnimation anim1(&button, "geometry");
- anim1.setDuration(3000);
- anim1.setStartValue(QRect(0, 0, 100, 30));
- anim1.setEndValue(QRect(500, 500, 100, 30));
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp animation-group2
- QPropertyAnimation anim2(&button, "geometry");
- anim2.setDuration(3000);
- anim2.setStartValue(QRect(500, 500, 100, 30));
- anim2.setEndValue(QRect(1000, 500, 100, 30));
+ As the name suggests, a QSequentialAnimationGroup plays
+ its animations in sequence. It starts the next animation in
+ the list after the previous finishes.
- QSequentialAnimationGroup group;
+ A group is an animation itself, so you can add
+ it to another group. This way, building an animation tree, which define
+ when the animations are played in relation to each other.
- group.addAnimation(&anim1);
- group.addAnimation(&anim2);
+ \section1 Object ownership
- group.start();
- \endcode
+ A QPropertyAnimation should always have a parent that controls
+ its lifespan. A typical application may include several animations that
+ are grouped, where the animation group takes ownership of those animations.
+ An independent QProperyAnimation must be explicitly assigned a parent to
+ control its lifespan. In the following example, you can see that an
+ independent QPropertyAnimation has the QApplication instance as its
+ parent:
- As you no doubt have guessed, QSequentialAnimationGroup plays
- its animations in sequence. It starts the next animation in
- the list after the previous is finished.
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp 0
- Since an animation group is an animation itself, you can add
- it to another group. This way, you can build a tree structure
- of animations which specifies when the animations are played
- in relation to each other.
+ \note You can also control the animation's lifespan by choosing a
+ \l{QAbstractAnimation::DeletionPolicy}{delete policy} while starting it.
*/
diff --git a/src/corelib/doc/src/containers.qdoc b/src/corelib/doc/src/containers.qdoc
index 1050223791..93ba5b456d 100644
--- a/src/corelib/doc/src/containers.qdoc
+++ b/src/corelib/doc/src/containers.qdoc
@@ -215,7 +215,30 @@
the C++ language doesn't specify any initialization; in those
cases, Qt's containers automatically initialize the value to 0.
- \section1 The Iterator Classes
+ \section1 Iterating over Containers
+
+ \section2 Range-based for
+
+ Range-based \c for should preferably be used for containers:
+
+ \snippet code/doc_src_containers.cpp range_for
+
+ Note that when using a Qt container in a non-const context,
+ \l{implicit sharing} may perform an undesired detach of the container.
+ To prevent this, use \c std::as_const():
+
+ \snippet code/doc_src_containers.cpp range_for_as_const
+
+ For associative containers, this will loop over the values.
+
+ \section2 Index-based
+
+ For sequential containers that store their items contiguously in memory
+ (for example, QList), index-based iteration can be used:
+
+ \snippet code/doc_src_containers.cpp index
+
+ \section2 The Iterator Classes
Iterators provide a uniform means to access items in a container.
Qt's container classes provide two types of iterators: STL-style
@@ -224,7 +247,7 @@
from \l{Implicit Sharing}{implicitly shared copies} due to a call
to a non-const member function.
- \section2 STL-Style Iterators
+ \section3 STL-Style Iterators
STL-style iterators have been available since the release of Qt
2.0. They are compatible with Qt's and STL's \l{generic
@@ -339,7 +362,7 @@
This problem doesn't occur with functions that return a const or
non-const reference to a container.
- \section3 Implicit sharing iterator problem
+ \section4 Implicit sharing iterator problem
\l{Implicit sharing} has another consequence on STL-style
iterators: you should avoid copying a container while
@@ -352,7 +375,7 @@
The above example only shows a problem with QList, but
the problem exists for all the implicitly shared Qt containers.
- \section2 Java-Style Iterators
+ \section3 Java-Style Iterators
\l{java-style-iterators}{Java-Style iterators} were introduced in Qt 4. Their API is modelled
on Java's iterator classes.
New code should should prefer \l{STL-Style Iterators}.
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 898abb12e8..5a19a20367 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -48,6 +48,7 @@
/*
The compiler, must be one of: (Q_CC_x)
+ COVERITY - Coverity cov-scan
SYM - Digital Mars C/C++ (used to be Symantec C++)
MSVC - Microsoft Visual C/C++, Intel C++ for Windows
BOR - Borland/Turbo C++
@@ -74,6 +75,10 @@
Should be sorted most to least authoritative.
*/
+#if defined(__COVERITY__)
+# define Q_CC_COVERITY
+#endif
+
/* Symantec C++ is now Digital Mars */
#if defined(__DMC__) || defined(__SC__)
# define Q_CC_SYM
@@ -1255,6 +1260,26 @@
#endif
/*
+ * If one wants to add functions that use post-C++17 APIs, one needs to:
+ *
+ * 1) make them fully inline; and
+ * 2) guard them using the necessary feature-testing macros.
+ *
+ * This decouples the C++ version used to build Qt with the one used by
+ * end-user applications; Qt and the application can either choose any C++
+ * version.
+ *
+ * A problem arises on MSVC for member functions of exported classes. Client
+ * code that tries to use such a function will see it as exported, and simply
+ * try to consume the function's *symbol*. However, if Qt has been built in
+ * C++17, it won't have such a symbol, and linking will fail.
+ *
+ * The workaround: declare such functions as function templates.
+ * (Obviously a function template does not need this marker.)
+*/
+#define QT_POST_CXX17_API_IN_EXPORTED_CLASS template <typename = void>
+
+/*
* Warning/diagnostic handling
*/
diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h
index c6cbaa1adb..afec512fd4 100644
--- a/src/corelib/global/qflags.h
+++ b/src/corelib/global/qflags.h
@@ -184,12 +184,16 @@ typedef QFlags<Enum> Flags;
#endif
#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
+[[maybe_unused]] \
constexpr inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) noexcept \
{ return QFlags<Flags::enum_type>(f1) | f2; } \
+[[maybe_unused]] \
constexpr inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
{ return f2 | f1; } \
+[[maybe_unused]] \
constexpr inline QFlags<Flags::enum_type> operator&(Flags::enum_type f1, Flags::enum_type f2) noexcept \
{ return QFlags<Flags::enum_type>(f1) & f2; } \
+[[maybe_unused]] \
constexpr inline QFlags<Flags::enum_type> operator&(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
{ return f2 & f1; } \
constexpr inline void operator+(Flags::enum_type f1, Flags::enum_type f2) noexcept = delete; \
@@ -210,6 +214,7 @@ constexpr inline void operator-(Flags::enum_type f1, int f2) noexcept = delete;
#if __cplusplus > 201702L // assume compilers don't warn if in C++17 mode
// in C++20 mode, provide user-defined operators to override the deprecated operations:
# define Q_DECLARE_MIXED_ENUM_OPERATOR(op, Ret, LHS, RHS) \
+ [[maybe_unused]] \
constexpr inline Ret operator op (LHS lhs, RHS rhs) noexcept \
{ return static_cast<Ret>(qToUnderlying(lhs) op qToUnderlying(rhs)); } \
/* end */
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 0d76bbec41..d5c448094f 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -902,7 +902,7 @@ Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
if (info.isEmpty())
return info;
- int pos;
+ qsizetype pos;
// Skip trailing [with XXX] for templates (gcc), but make
// sure to not affect Objective-C message names.
@@ -949,7 +949,7 @@ Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
info.truncate(++pos);
if (info.at(pos - 1) == ')') {
- if (info.indexOf(operator_call) == pos - (int)strlen(operator_call))
+ if (info.indexOf(operator_call) == pos - qsizetype(strlen(operator_call)))
break;
// this function returns a pointer to a function
@@ -972,19 +972,19 @@ Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
if (pos > -1) {
switch (info.at(pos)) {
case ')':
- if (info.indexOf(operator_call) == pos - (int)strlen(operator_call) + 1)
+ if (info.indexOf(operator_call) == pos - qsizetype(strlen(operator_call)) + 1)
pos -= 2;
break;
case '<':
- if (info.indexOf(operator_lessThan) == pos - (int)strlen(operator_lessThan) + 1)
+ if (info.indexOf(operator_lessThan) == pos - qsizetype(strlen(operator_lessThan)) + 1)
--pos;
break;
case '>':
- if (info.indexOf(operator_greaterThan) == pos - (int)strlen(operator_greaterThan) + 1)
+ if (info.indexOf(operator_greaterThan) == pos - qsizetype(strlen(operator_greaterThan)) + 1)
--pos;
break;
case '=': {
- int operatorLength = (int)strlen(operator_lessThanEqual);
+ auto operatorLength = qsizetype(strlen(operator_lessThanEqual));
if (info.indexOf(operator_lessThanEqual) == pos - operatorLength + 1)
pos -= 2;
else if (info.indexOf(operator_greaterThanEqual) == pos - operatorLength + 1)
@@ -1028,7 +1028,7 @@ Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
break;
// find the matching close
- int end = pos;
+ qsizetype end = pos;
templatecount = 1;
--pos;
while (pos && templatecount) {
@@ -1193,7 +1193,7 @@ void QMessagePattern::setPattern(const QString &pattern)
tokens[i] = qthreadptrTokenC;
else if (lexeme.startsWith(QLatin1String(timeTokenC))) {
tokens[i] = timeTokenC;
- int spaceIdx = lexeme.indexOf(QChar::fromLatin1(' '));
+ qsizetype spaceIdx = lexeme.indexOf(QChar::fromLatin1(' '));
if (spaceIdx > 0)
timeArgs.append(lexeme.mid(spaceIdx + 1, lexeme.length() - spaceIdx - 2));
else
diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp
index 63055a0b61..8d83ab5392 100644
--- a/src/corelib/global/qnumeric.cpp
+++ b/src/corelib/global/qnumeric.cpp
@@ -349,4 +349,35 @@ Q_CORE_EXPORT quint64 qFloatDistance(double a, double b)
This can be faster than calling the version with only variable arguments.
*/
+template <typename T> static constexpr T max = std::numeric_limits<T>::max();
+template <typename T> static constexpr T min = std::numeric_limits<T>::min();
+
+static_assert(qt_saturate<short>(max<unsigned>) == max<short>);
+static_assert(qt_saturate<int>(max<unsigned>) == max<int>);
+static_assert(qt_saturate<qint64>(max<unsigned>) == qint64(max<unsigned>));
+
+static_assert(qt_saturate<short>(max<int>) == max<short>);
+static_assert(qt_saturate<unsigned>(max<int>) == unsigned(max<int>));
+static_assert(qt_saturate<qint64>(max<int>) == qint64(max<int>));
+
+static_assert(qt_saturate<short>(max<qint64>) == max<short>);
+static_assert(qt_saturate<int>(max<qint64>) == max<int>);
+static_assert(qt_saturate<unsigned>(max<qint64>) == max<unsigned>);
+static_assert(qt_saturate<quint64>(max<qint64>) == quint64(max<qint64>));
+
+static_assert(qt_saturate<short>(max<quint64>) == max<short>);
+static_assert(qt_saturate<int>(max<quint64>) == max<int>);
+static_assert(qt_saturate<unsigned>(max<quint64>) == max<unsigned>);
+static_assert(qt_saturate<qint64>(max<quint64>) == max<qint64>);
+
+static_assert(qt_saturate<short>(min<int>) == min<short>);
+static_assert(qt_saturate<qint64>(min<int>) == qint64(min<int>));
+static_assert(qt_saturate<unsigned>(min<int>) == 0);
+static_assert(qt_saturate<quint64>(min<int>) == 0);
+
+static_assert(qt_saturate<short>(min<qint64>) == min<short>);
+static_assert(qt_saturate<int>(min<qint64>) == min<int>);
+static_assert(qt_saturate<unsigned>(min<qint64>) == 0);
+static_assert(qt_saturate<quint64>(min<qint64>) == 0);
+
QT_END_NAMESPACE
diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h
index 823a1812de..9957377667 100644
--- a/src/corelib/global/qnumeric_p.h
+++ b/src/corelib/global/qnumeric_p.h
@@ -267,6 +267,41 @@ template <auto V2, typename T> bool mul_overflow(T v1, T *r)
}
#endif // Q_CLANG_QDOC
+/*
+ Safely narrows \a x to \c{To}. Let \c L be
+ \c{std::numeric_limit<To>::min()} and \c H be \c{std::numeric_limit<To>::max()}.
+
+ If \a x is less than L, returns L. If \a x is greater than H,
+ returns H. Otherwise, returns \c{To(x)}.
+*/
+template <typename To, typename From>
+static constexpr auto qt_saturate(From x)
+{
+ static_assert(std::is_integral_v<To>);
+ static_assert(std::is_integral_v<From>);
+
+ [[maybe_unused]]
+ constexpr auto Lo = (std::numeric_limits<To>::min)();
+ constexpr auto Hi = (std::numeric_limits<To>::max)();
+
+ if constexpr (std::is_signed_v<From> == std::is_signed_v<To>) {
+ // same signedness, we can accept regular integer conversion rules
+ return x < Lo ? Lo :
+ x > Hi ? Hi :
+ /*else*/ To(x);
+ } else {
+ if constexpr (std::is_signed_v<From>) { // ie. !is_signed_v<To>
+ if (x < From{0})
+ return To{0};
+ }
+
+ // from here on, x >= 0
+ using FromU = std::make_unsigned_t<From>;
+ using ToU = std::make_unsigned_t<To>;
+ return FromU(x) > ToU(Hi) ? Hi : To(x); // assumes Hi >= 0
+ }
+}
+
QT_END_NAMESPACE
#endif // QNUMERIC_P_H
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index a038f125cb..01340828c2 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -1913,7 +1913,8 @@ bool QDir::isEmpty(Filters filters) const
Returns a list of the root directories on this system.
On Windows this returns a list of QFileInfo objects containing "C:/",
- "D:/", etc. On other operating systems, it returns a list containing
+ "D:/", etc. This does not return drives with ejectable media that are empty.
+ On other operating systems, it returns a list containing
just one root directory (i.e. "/").
\sa root(), rootPath()
diff --git a/src/corelib/io/qfilesystemwatcher_win_p.h b/src/corelib/io/qfilesystemwatcher_win_p.h
index 778ed8ce23..da6e73caf6 100644
--- a/src/corelib/io/qfilesystemwatcher_win_p.h
+++ b/src/corelib/io/qfilesystemwatcher_win_p.h
@@ -140,7 +140,10 @@ public:
Q_DECLARE_TYPEINFO(QFileSystemWatcherPathKey, Q_RELOCATABLE_TYPE);
-inline size_t qHash(const QFileSystemWatcherPathKey &key) { return qHash(key.toCaseFolded()); }
+inline size_t qHash(const QFileSystemWatcherPathKey &key, size_t seed = 0)
+{
+ return qHash(key.toCaseFolded(), seed);
+}
class QWindowsFileSystemWatcherEngineThread : public QThread
{
diff --git a/src/corelib/io/qlockfile.h b/src/corelib/io/qlockfile.h
index aa5ad5e772..ad58ba727d 100644
--- a/src/corelib/io/qlockfile.h
+++ b/src/corelib/io/qlockfile.h
@@ -43,9 +43,7 @@
#include <QtCore/qstring.h>
#include <QtCore/qscopedpointer.h>
-#if __has_include(<chrono>)
-# include <chrono>
-#endif
+#include <chrono>
QT_BEGIN_NAMESPACE
@@ -66,7 +64,6 @@ public:
void setStaleLockTime(int);
int staleLockTime() const;
-#if __has_include(<chrono>)
bool tryLock(std::chrono::milliseconds timeout) { return tryLock(int(timeout.count())); }
void setStaleLockTime(std::chrono::milliseconds value) { setStaleLockTime(int(value.count())); }
@@ -75,7 +72,6 @@ public:
{
return std::chrono::milliseconds(staleLockTime());
}
-#endif
bool isLocked() const;
bool getLockInfo(qint64 *pid, QString *hostname, QString *appname) const;
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index 7633b7420c..395b426cf4 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -310,8 +310,8 @@ public:
void swap(QAppleLogActivity &other)
{
- qSwap(activity, other.activity);
- qSwap(state, other.state);
+ activity.swap(other.activity);
+ std::swap(state, other.state);
}
private:
@@ -368,7 +368,7 @@ public:
void swap(QMacNotificationObserver &other) noexcept
{
- qSwap(observer, other.observer);
+ qt_ptr_swap(observer, other.observer);
}
void remove();
@@ -418,9 +418,9 @@ public:
void swap(QMacKeyValueObserver &other) noexcept
{
- qSwap(object, other.object);
- qSwap(keyPath, other.keyPath);
- qSwap(callback, other.callback);
+ qt_ptr_swap(object, other.object);
+ qt_ptr_swap(keyPath, other.keyPath);
+ callback.swap(other.callback);
}
private:
diff --git a/src/corelib/kernel/qdeadlinetimer.h b/src/corelib/kernel/qdeadlinetimer.h
index 0720a32b56..2437e9a4b2 100644
--- a/src/corelib/kernel/qdeadlinetimer.h
+++ b/src/corelib/kernel/qdeadlinetimer.h
@@ -52,9 +52,7 @@
#include <limits>
-#if __has_include(<chrono>)
-# include <chrono>
-#endif
+#include <chrono>
QT_BEGIN_NAMESPACE
@@ -120,7 +118,6 @@ public:
QDeadlineTimer &operator-=(qint64 msecs)
{ *this = *this + (-msecs); return *this; }
-#if __has_include(<chrono>) || defined(Q_CLANG_QDOC)
template <class Clock, class Duration>
QDeadlineTimer(std::chrono::time_point<Clock, Duration> deadline_,
Qt::TimerType type_ = Qt::CoarseTimer) : t2(0)
@@ -178,7 +175,6 @@ public:
template <class Rep, class Period>
friend QDeadlineTimer operator+=(QDeadlineTimer &dt, std::chrono::duration<Rep, Period> value)
{ return dt = dt + value; }
-#endif
private:
qint64 t1;
@@ -192,7 +188,7 @@ public:
QPair<qint64, unsigned> _q_data() const { return qMakePair(t1, t2); }
};
-#if __has_include(<chrono>) && (defined(Q_OS_DARWIN) || defined(Q_OS_LINUX) || (defined(Q_CC_MSVC) && Q_CC_MSVC >= 1900))
+#if defined(Q_OS_DARWIN) || defined(Q_OS_LINUX) || (defined(Q_CC_MSVC) && Q_CC_MSVC >= 1900)
// We know for these OS/compilers that the std::chrono::steady_clock uses the same
// reference time as QDeadlineTimer
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index eeccbd9093..26f3a0178d 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -43,6 +43,7 @@
#include "qmetatype.h"
#undef QT_QMETATYPE_BC_COMPAT
#include "qmetatype_p.h"
+#include "qobject.h"
#include "qobjectdefs.h"
#include "qdatetime.h"
#include "qbytearray.h"
@@ -393,6 +394,7 @@ const char *QtMetaTypePrivate::typedefNameForType(const QtPrivate::QMetaTypeInte
\value QStringList QStringList
\value QVariantMap QVariantMap
\value QVariantHash QVariantHash
+ \value QVariantPair QVariantPair
\value QIcon QIcon
\value QPen QPen
\value QLineF QLineF
@@ -3011,6 +3013,13 @@ static const QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
}
/*!
+ \fn QMetaType::QMetaType()
+ \since 6.0
+
+ Constructs a default, invalid, QMetaType object.
+*/
+
+/*!
\fn QMetaType::QMetaType(int typeId)
\since 5.0
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 2a341b870a..6584754be9 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -363,7 +363,7 @@ public:
QByteArrayList = 49, QObjectStar = 39, SChar = 40,
Void = 43,
Nullptr = 51,
- QVariantMap = 8, QVariantList = 9, QVariantHash = 28,
+ QVariantMap = 8, QVariantList = 9, QVariantHash = 28, QVariantPair = 58,
QCborSimpleType = 52, QCborValue = 53, QCborArray = 54, QCborMap = 55,
Char16 = 56, Char32 = 57,
@@ -1905,10 +1905,9 @@ public:
#if defined (Q_CC_CLANG)
if (name.find("anonymous ") != std::string_view::npos)
return normalizeType(begin, end);
-#else
+#endif
if (name.find("unnamed ") != std::string_view::npos)
return normalizeType(begin, end);
-#endif
while (begin < end) {
if (*begin == ' ') {
if (last == ',' || last == '>' || last == '<' || last == '*' || last == '&') {
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index 06778dcde4..c93ce8cf2e 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -56,9 +56,7 @@
#include <QtCore/qobject_impl.h>
#include <QtCore/qbindingstorage.h>
-#if __has_include(<chrono>)
-# include <chrono>
-#endif
+#include <chrono>
QT_BEGIN_NAMESPACE
@@ -150,13 +148,11 @@ public:
void moveToThread(QThread *thread);
int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer);
-#if __has_include(<chrono>)
Q_ALWAYS_INLINE
int startTimer(std::chrono::milliseconds time, Qt::TimerType timerType = Qt::CoarseTimer)
{
return startTimer(int(time.count()), timerType);
}
-#endif
void killTimer(int id);
template<typename T>
diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp
index 3dbbe75fc4..6dc73fa1cf 100644
--- a/src/corelib/kernel/qsharedmemory.cpp
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -178,6 +178,12 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
\endlist
+ Qt for iOS comes with support for POSIX shared memory out of the box.
+ With Qt for \macos an additional configure flag must be added when
+ building Qt to enable the feature. To enable the feature pass
+ \c {-feature-ipc_posix} Note that the pre-built Qt libraries for
+ \macos available through the Qt installer do not include this feature.
+
\endlist
Remember to lock the shared memory with lock() before reading from
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
index 2b262f6311..7e6404b2c5 100644
--- a/src/corelib/kernel/qtimer.h
+++ b/src/corelib/kernel/qtimer.h
@@ -47,9 +47,7 @@
#include <QtCore/qbasictimer.h> // conceptual inheritance
#include <QtCore/qobject.h>
-#if __has_include(<chrono>)
-# include <chrono>
-#endif
+#include <chrono>
QT_BEGIN_NAMESPACE
@@ -181,7 +179,6 @@ Q_SIGNALS:
void timeout(QPrivateSignal);
public:
-#if __has_include(<chrono>) || defined(Q_QDOC)
void setInterval(std::chrono::milliseconds value)
{
setInterval(int(value.count()));
@@ -211,7 +208,6 @@ public:
{
start(int(value.count()));
}
-#endif
protected:
void timerEvent(QTimerEvent *) override;
@@ -228,7 +224,6 @@ private:
static void singleShotImpl(int msec, Qt::TimerType timerType,
const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
-#if __has_include(<chrono>)
static Qt::TimerType defaultTypeFor(std::chrono::milliseconds interval)
{ return defaultTypeFor(int(interval.count())); }
@@ -238,7 +233,6 @@ private:
singleShotImpl(int(interval.count()),
timerType, receiver, slotObj);
}
-#endif
};
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 2844f09949..74d064af6e 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -1105,7 +1105,7 @@ void QVariant::clear()
/*!
\fn QVariant::Type QVariant::nameToType(const char *name)
- \deprecated [6.0] Use \c QMetaType.fromName(name).id() instead
+ \deprecated [6.0] Use \c QMetaType::fromName(name).id() instead
Converts the string representation of the storage type given in \a
name, to its enum representation.
@@ -1426,8 +1426,13 @@ QString QVariant::toString() const
}
/*!
- Returns the variant as a QMap<QString, QVariant> if the variant
- has type() \l QMetaType::QVariantMap; otherwise returns an empty map.
+ Returns the variant as a QVariantMap if the variant has type() \l
+ QMetaType::QVariantMap. If it doesn't, QVariant will attempt to
+ convert the type to a map and then return it. This will succeed for
+ any type that has registered a converter to QVariantMap or which was
+ declared as a associative container using
+ \l{Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE}. If none of those
+ conditions are true, this function will return an empty map.
\sa canConvert(), convert()
*/
@@ -1977,9 +1982,13 @@ qreal QVariant::toReal(bool *ok) const
}
/*!
- Returns the variant as a QVariantList if the variant has userType()
- \l QMetaType::QVariantList or \l QMetaType::QStringList; otherwise returns
- an empty list.
+ Returns the variant as a QVariantList if the variant has userType() \l
+ QMetaType::QVariantList. If it doesn't, QVariant will attempt to convert
+ the type to a list and then return it. This will succeed for any type that
+ has registered a converter to QVariantList or which was declared as a
+ sequential container using \l{Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE}. If
+ none of those conditions are true, this function will return an empty
+ list.
\sa canConvert(), convert()
*/
diff --git a/src/corelib/platform/android/qandroidextras.cpp b/src/corelib/platform/android/qandroidextras.cpp
index 9087a6a6ac..3a8a8e9343 100644
--- a/src/corelib/platform/android/qandroidextras.cpp
+++ b/src/corelib/platform/android/qandroidextras.cpp
@@ -153,6 +153,7 @@ QAndroidBinder QAndroidParcelPrivate::readBinder() const
/*!
\class QAndroidParcel
+ \inheaderfile QtCore/private/qandroidextras_p.h
\preliminary
\inmodule QtCore
\brief Wraps the most important methods of Android Parcel class.
@@ -269,6 +270,7 @@ QJniObject QAndroidParcel::handle() const
/*!
\class QAndroidBinder
+ \inheaderfile QtCore/private/qandroidextras_p.h
\preliminary
\inmodule QtCore
\brief Wraps the most important methods of Android Binder class.
@@ -406,6 +408,7 @@ QJniObject QAndroidBinder::handle() const
/*!
\class QAndroidServiceConnection
+ \inheaderfile QtCore/private/qandroidextras_p.h
\preliminary
\inmodule QtCore
\brief Wraps the most important methods of Android ServiceConnection class.
@@ -529,6 +532,7 @@ public:
/*!
\class QAndroidActivityResultReceiver
+ \inheaderfile QtCore/private/qandroidextras_p.h
\preliminary
\inmodule QtCore
\since 6.2
@@ -624,6 +628,7 @@ public:
/*!
\class QAndroidService
+ \inheaderfile QtCore/private/qandroidextras_p.h
\preliminary
\inmodule QtCore
\brief Wraps the most important methods of Android Service class.
@@ -693,6 +698,7 @@ QAndroidBinder* QAndroidService::onBind(const QAndroidIntent &/*intent*/)
/*!
\class QAndroidIntent
+ \inheaderfile QtCore/private/qandroidextras_p.h
\preliminary
\inmodule QtCore
\brief Wraps the most important methods of Android Intent class.
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index 825a431820..adf2a8de9a 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -41,6 +41,7 @@
#include "qbytearray.h"
#include "qbytearraymatcher.h"
+#include "qendian.h"
#include "private/qtools_p.h"
#include "qhashfunctions.h"
#include "qlist.h"
@@ -532,67 +533,212 @@ quint16 qChecksum(QByteArrayView data, Qt::ChecksumType standard)
The default value is -1, which specifies zlib's default
compression.
-//![compress-limit-note]
- \note The maximum size of data that this function can consume is limited by
- what the platform's \c{unsigned long} can represent (a Zlib limitation).
- That means that data > 4GiB can be compressed and decompressed on a 64-bit
- Unix system, but not on a 64-bit Windows system. Portable code should
- therefore avoid using qCompress()/qUncompress() to compress more than 4GiB
- of input.
-//![compress-limit-note]
-
\sa qUncompress(const QByteArray &data)
*/
-/*! \relates QByteArray
+/*!
+ \fn QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel)
+ \relates QByteArray
\overload
Compresses the first \a nbytes of \a data at compression level
\a compressionLevel and returns the compressed data in a new byte array.
-
- \include qbytearray.cpp compress-limit-note
*/
#ifndef QT_NO_COMPRESS
+using CompressSizeHint_t = quint32; // 32-bit BE, historically
+
+enum class ZLibOp : bool { Compression, Decompression };
+
+Q_DECL_COLD_FUNCTION
+static const char *zlibOpAsString(ZLibOp op)
+{
+ switch (op) {
+ case ZLibOp::Compression: return "qCompress";
+ case ZLibOp::Decompression: return "qUncompress";
+ }
+ Q_UNREACHABLE();
+ return nullptr;
+}
+
+Q_DECL_COLD_FUNCTION
+static QByteArray zlibError(ZLibOp op, const char *what)
+{
+ qWarning("%s: %s", zlibOpAsString(op), what);
+ return QByteArray();
+}
+
+Q_DECL_COLD_FUNCTION
+static QByteArray dataIsNull(ZLibOp op)
+{
+ return zlibError(op, "Data is null");
+}
+
+Q_DECL_COLD_FUNCTION
+static QByteArray lengthIsNegative(ZLibOp op)
+{
+ return zlibError(op, "Input length is negative");
+}
+
+Q_DECL_COLD_FUNCTION
+static QByteArray tooMuchData(ZLibOp op)
+{
+ return zlibError(op, "Not enough memory");
+}
+
+Q_DECL_COLD_FUNCTION
+static QByteArray invalidCompressedData()
+{
+ return zlibError(ZLibOp::Decompression, "Input data is corrupted");
+}
+
+Q_DECL_COLD_FUNCTION
+static QByteArray unexpectedZlibError(ZLibOp op, int err, const char *msg)
+{
+ qWarning("%s unexpected zlib error: %s (%d)",
+ zlibOpAsString(op),
+ msg ? msg : "",
+ err);
+ return QByteArray();
+}
+
+template <typename Init, typename ProcessChunk, typename Deinit>
+static QByteArray xxflate(ZLibOp op, QArrayDataPointer<char> out, QByteArrayView input,
+ Init init,
+ ProcessChunk processChunk,
+ Deinit deinit)
+{
+ if (out.data() == nullptr) // allocation failed
+ return tooMuchData(op);
+ qsizetype capacity = out.allocatedCapacity();
+
+ const auto initalSize = out.size;
+
+ z_stream zs = {};
+ zs.next_in = reinterpret_cast<uchar *>(const_cast<char *>(input.data())); // 1980s C API...
+ if (const int err = init(&zs); err != Z_OK)
+ return unexpectedZlibError(op, err, zs.msg);
+ const auto sg = qScopeGuard([&] { deinit(&zs); });
+
+ using ZlibChunkSize_t = decltype(zs.avail_in);
+ static_assert(!std::is_signed_v<ZlibChunkSize_t>);
+ static_assert(std::is_same_v<ZlibChunkSize_t, decltype(zs.avail_out)>);
+ constexpr auto MaxChunkSize = std::numeric_limits<ZlibChunkSize_t>::max();
+ [[maybe_unused]]
+ constexpr auto MaxStatisticsSize = std::numeric_limits<decltype(zs.total_out)>::max();
+
+ size_t inputLeft = size_t(input.size());
+
+ int res;
+ do {
+ Q_ASSERT(out.freeSpaceAtBegin() == 0); // ensure prepend optimization stays out of the way
+ Q_ASSERT(capacity == out.allocatedCapacity());
+
+ if (zs.avail_out == 0) {
+ Q_ASSERT(size_t(out.size) - initalSize > MaxStatisticsSize || // total_out overflow
+ size_t(out.size) - initalSize == zs.total_out);
+ Q_ASSERT(out.size <= capacity);
+
+ qsizetype avail_out = capacity - out.size;
+ if (avail_out == 0) {
+ out->reallocateAndGrow(QArrayData::GrowsAtEnd, 1); // grow to next natural capacity
+ if (out.data() == nullptr) // reallocation failed
+ return tooMuchData(op);
+ capacity = out.allocatedCapacity();
+ avail_out = capacity - out.size;
+ }
+ zs.next_out = reinterpret_cast<uchar *>(out.data()) + out.size;
+ zs.avail_out = size_t(avail_out) > size_t(MaxChunkSize) ? MaxChunkSize
+ : ZlibChunkSize_t(avail_out);
+ out.size += zs.avail_out;
+
+ Q_ASSERT(zs.avail_out > 0);
+ }
+
+ if (zs.avail_in == 0) {
+ // zs.next_in is kept up-to-date by processChunk(), so nothing to do
+ zs.avail_in = inputLeft > MaxChunkSize ? MaxChunkSize : ZlibChunkSize_t(inputLeft);
+ inputLeft -= zs.avail_in;
+ }
+
+ res = processChunk(&zs, inputLeft);
+ } while (res == Z_OK);
+
+ switch (res) {
+ case Z_STREAM_END:
+ out.size -= zs.avail_out;
+ Q_ASSERT(size_t(out.size) - initalSize > MaxStatisticsSize || // total_out overflow
+ size_t(out.size) - initalSize == zs.total_out);
+ Q_ASSERT(out.size <= out.allocatedCapacity());
+ out.data()[out.size] = '\0';
+ return QByteArray(std::move(out));
+
+ case Z_MEM_ERROR:
+ return tooMuchData(op);
+
+ case Z_BUF_ERROR:
+ Q_UNREACHABLE(); // cannot happen - we supply a buffer that can hold the result,
+ // or else error out early
+
+ case Z_DATA_ERROR: // can only happen on decompression
+ Q_ASSERT(op == ZLibOp::Decompression);
+ return invalidCompressedData();
+
+ default:
+ return unexpectedZlibError(op, res, zs.msg);
+ }
+}
+
QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel)
{
+ constexpr qsizetype HeaderSize = sizeof(CompressSizeHint_t);
if (nbytes == 0) {
- return QByteArray(4, '\0');
- }
- if (!data) {
- qWarning("qCompress: Data is null");
- return QByteArray();
+ return QByteArray(HeaderSize, '\0');
}
+ if (!data)
+ return dataIsNull(ZLibOp::Compression);
+
+ if (nbytes < 0)
+ return lengthIsNegative(ZLibOp::Compression);
+
if (compressionLevel < -1 || compressionLevel > 9)
compressionLevel = -1;
- ulong len = nbytes + nbytes / 100 + 13;
- QByteArray bazip;
- int res;
- do {
- bazip.resize(len + 4);
- res = ::compress2((uchar*)bazip.data()+4, &len, data, nbytes, compressionLevel);
-
- switch (res) {
- case Z_OK:
- bazip.resize(len + 4);
- bazip[0] = (nbytes & 0xff000000) >> 24;
- bazip[1] = (nbytes & 0x00ff0000) >> 16;
- bazip[2] = (nbytes & 0x0000ff00) >> 8;
- bazip[3] = (nbytes & 0x000000ff);
- break;
- case Z_MEM_ERROR:
- qWarning("qCompress: Z_MEM_ERROR: Not enough memory");
- bazip.resize(0);
- break;
- case Z_BUF_ERROR:
- len *= 2;
- break;
+ QArrayDataPointer out = [&] {
+ constexpr qsizetype SingleAllocLimit = 256 * 1024; // the maximum size for which we use
+ // zlib's compressBound() to guarantee
+ // the output buffer size is sufficient
+ // to hold result
+ qsizetype capacity = HeaderSize;
+ if (nbytes < SingleAllocLimit) {
+ // use maximum size
+ capacity += compressBound(uLong(nbytes)); // cannot overflow (both times)!
+ return QArrayDataPointer{QTypedArrayData<char>::allocate(capacity)};
}
- } while (res == Z_BUF_ERROR);
- return bazip;
+ // for larger buffers, assume it compresses optimally, and
+ // grow geometrically from there:
+ constexpr qsizetype MaxCompressionFactor = 1024; // max theoretical factor is 1032
+ // cf. http://www.zlib.org/zlib_tech.html,
+ // but use a nearby power-of-two (faster)
+ capacity += std::max(qsizetype(compressBound(uLong(SingleAllocLimit))),
+ nbytes / MaxCompressionFactor);
+ return QArrayDataPointer{QTypedArrayData<char>::allocate(capacity, QArrayData::Grow)};
+ }();
+
+ if (out.data() == nullptr) // allocation failed
+ return tooMuchData(ZLibOp::Compression);
+
+ qToBigEndian(qt_saturate<CompressSizeHint_t>(nbytes), out.data());
+ out.size = HeaderSize;
+
+ return xxflate(ZLibOp::Compression, std::move(out), {data, nbytes},
+ [=] (z_stream *zs) { return deflateInit(zs, compressionLevel); },
+ [] (z_stream *zs, size_t inputLeft) {
+ return deflate(zs, inputLeft ? Z_NO_FLUSH : Z_FINISH);
+ },
+ [] (z_stream *zs) { deflateEnd(zs); });
}
#endif
@@ -614,98 +760,63 @@ QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel)
data that was compressed using zlib, you first need to prepend a four
byte header to the byte array containing the data. The header must
contain the expected length (in bytes) of the uncompressed data,
- expressed as an unsigned, big-endian, 32-bit integer.
+ expressed as an unsigned, big-endian, 32-bit integer. This number is
+ just a hint for the initial size of the output buffer size,
+ though. If the indicated size is too small to hold the result, the
+ output buffer size will still be increased until either the output
+ fits or the system runs out of memory. So, despite the 32-bit
+ header, this function, on 64-bit platforms, can produce more than
+ 4GiB of output.
-//![uncompress-limit-note]
- \note The maximum size of data that this function can produce is limited by
- what the platform's \c{unsigned long} can represent (a Zlib limitation).
- That means that data > 4GiB can be compressed and decompressed on a 64-bit
- Unix system, but not on a 64-bit Windows system. Portable code should
- therefore avoid using qCompress()/qUncompress() to compress more than 4GiB
- of input.
-//![uncompress-limit-note]
+ \note In Qt versions prior to Qt 6.5, more than 2GiB of data
+ worked unreliably; in Qt versions prior to Qt 6.0, not at all.
\sa qCompress()
*/
#ifndef QT_NO_COMPRESS
-static QByteArray invalidCompressedData()
-{
- qWarning("qUncompress: Input data is corrupted");
- return QByteArray();
-}
-
/*! \relates QByteArray
\overload
Uncompresses the first \a nbytes of \a data and returns a new byte
array with the uncompressed data.
-
- \include qbytearray.cpp uncompress-limit-note
*/
QByteArray qUncompress(const uchar* data, qsizetype nbytes)
{
- if (!data) {
- qWarning("qUncompress: Data is null");
- return QByteArray();
- }
- if (nbytes <= 4) {
- if (nbytes < 4 || (data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0))
- qWarning("qUncompress: Input data is corrupted");
- return QByteArray();
- }
- size_t expectedSize = size_t((data[0] << 24) | (data[1] << 16) |
- (data[2] << 8) | (data[3] ));
- size_t len = qMax(expectedSize, 1ul);
- constexpr size_t maxPossibleSize = MaxAllocSize - sizeof(QByteArray::Data);
- if (Q_UNLIKELY(len >= maxPossibleSize)) {
- // QByteArray does not support that huge size anyway.
- return invalidCompressedData();
- }
+ if (!data)
+ return dataIsNull(ZLibOp::Decompression);
- QByteArray::DataPointer d(QByteArray::Data::allocate(len));
- if (Q_UNLIKELY(d.data() == nullptr))
- return invalidCompressedData();
+ if (nbytes < 0)
+ return lengthIsNegative(ZLibOp::Decompression);
- forever {
- const auto alloc = len;
- int res = ::uncompress((uchar*)d.data(), reinterpret_cast<uLongf*>(&len),
- data+4, nbytes-4);
-
- switch (res) {
- case Z_OK: {
- Q_ASSERT(len <= alloc);
- Q_UNUSED(alloc);
- d.data()[len] = '\0';
- d.size = len;
- return QByteArray(d);
- }
+ constexpr qsizetype HeaderSize = sizeof(CompressSizeHint_t);
+ if (nbytes < HeaderSize)
+ return invalidCompressedData();
- case Z_MEM_ERROR:
- qWarning("qUncompress: Z_MEM_ERROR: Not enough memory");
- return QByteArray();
-
- case Z_BUF_ERROR:
- static_assert(maxPossibleSize <= (std::numeric_limits<decltype(len)>::max)() / 2,
- "oops, next line may overflow");
- len *= 2;
- if (Q_UNLIKELY(len >= maxPossibleSize)) {
- // QByteArray does not support that huge size anyway.
- return invalidCompressedData();
- } else {
- // grow the block
- d->reallocate(d->allocatedCapacity()*2, QArrayData::Grow);
- if (Q_UNLIKELY(d.data() == nullptr))
- return invalidCompressedData();
- }
- continue;
+ const auto expectedSize = qFromBigEndian<CompressSizeHint_t>(data);
+ if (nbytes == HeaderSize) {
+ if (expectedSize != 0)
+ return invalidCompressedData();
+ return QByteArray();
+ }
- case Z_DATA_ERROR:
- qWarning("qUncompress: Z_DATA_ERROR: Input data is corrupted");
- return QByteArray();
- }
+ constexpr auto MaxDecompressedSize = size_t(MaxByteArraySize);
+ if constexpr (MaxDecompressedSize < std::numeric_limits<CompressSizeHint_t>::max()) {
+ if (expectedSize > MaxDecompressedSize)
+ return tooMuchData(ZLibOp::Decompression);
}
+
+ // expectedSize may be truncated, so always use at least nbytes
+ // (larger by at most 1%, according to zlib docs)
+ qsizetype capacity = std::max(qsizetype(expectedSize), // cannot overflow!
+ nbytes);
+
+ QArrayDataPointer d(QTypedArrayData<char>::allocate(capacity, QArrayData::KeepSize));
+ return xxflate(ZLibOp::Decompression, std::move(d), {data + HeaderSize, nbytes - HeaderSize},
+ [] (z_stream *zs) { return inflateInit(zs); },
+ [] (z_stream *zs, size_t) { return inflate(zs, Z_NO_FLUSH); },
+ [] (z_stream *zs) { inflateEnd(zs); });
}
#endif
diff --git a/src/corelib/text/qlocale_win.cpp b/src/corelib/text/qlocale_win.cpp
index 40d34ddfeb..5566d44449 100644
--- a/src/corelib/text/qlocale_win.cpp
+++ b/src/corelib/text/qlocale_win.cpp
@@ -634,9 +634,13 @@ QVariant QSystemLocalePrivate::uiLanguages()
#if QT_CONFIG(cpp_winrt) && !defined(Q_CC_CLANG)
using namespace winrt;
using namespace Windows::System::UserProfile;
- auto languages = GlobalizationPreferences::Languages();
- for (const auto &lang : languages)
- result << QString::fromStdString(winrt::to_string(lang));
+ QT_TRY {
+ auto languages = GlobalizationPreferences::Languages();
+ for (const auto &lang : languages)
+ result << QString::fromStdString(winrt::to_string(lang));
+ } QT_CATCH(...) {
+ // pass, just fall back to WIN32 API implementation
+ }
if (!result.isEmpty())
return result; // else just fall back to WIN32 API implementation
#endif // QT_CONFIG(cpp_winrt) && !defined(Q_CC_CLANG)
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 6ec93835b4..a8365e8aef 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -2890,6 +2890,14 @@ QString &QString::append(const QString &str)
}
/*!
+ \fn QString &QString::append(QStringView v)
+ \overload append()
+ \since 6.0
+
+ Appends the given string view \a v to this string and returns the result.
+*/
+
+/*!
\overload append()
\since 5.0
@@ -6763,6 +6771,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
int precision = -1; // -1 means unspecified
if (*c == '.') {
++c;
+ precision = 0;
if (qIsDigit(*c)) {
precision = parse_field_width(c);
} else if (*c == '*') { // can't parse this in another function, not portably, at least
@@ -8833,8 +8842,8 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
\c{const char *} instead of QString. This includes the copy
constructor, the assignment operator, the comparison operators,
and various other functions such as \l{QString::insert()}{insert()},
- \l{QString::replace()}{replace()}, and \l{QString::indexOf()}{indexOf()}.
- These functions are usually optimized to avoid constructing a
+ \l{QString::append()}{append()}, and \l{QString::prepend()}{prepend()}.
+ Some of these functions are optimized to avoid constructing a
QString object for the \c{const char *} data. For example,
assuming \c str is a QString,
@@ -8847,6 +8856,12 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
because it doesn't construct four temporary QString objects and
make a deep copy of the character data.
+ However, that is not true for all QString member functions that take
+ \c{const char *} and therefore applications should assume a temporary will
+ be created, such as in
+
+ \snippet code/src_corelib_text_qstring.cpp 4bis
+
Applications that define \l QT_NO_CAST_FROM_ASCII (as explained
in the QString documentation) don't have access to QString's
\c{const char *} API. To provide an efficient way of specifying
diff --git a/src/corelib/text/qstringconverter.cpp b/src/corelib/text/qstringconverter.cpp
index b72ac6f515..5045137fd5 100644
--- a/src/corelib/text/qstringconverter.cpp
+++ b/src/corelib/text/qstringconverter.cpp
@@ -218,7 +218,7 @@ static inline const uchar *simdFindNonAscii(const uchar *src, const uchar *end,
#ifdef __AVX2__
// do 32 characters at a time
// (this is similar to simdTestMask in qstring.cpp)
- const __m256i mask = _mm256_set1_epi8(0x80);
+ const __m256i mask = _mm256_set1_epi8(char(0x80));
for ( ; end - src >= 32; src += 32) {
__m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src));
if (_mm256_testz_si256(mask, data))
diff --git a/src/corelib/text/qstringlist.cpp b/src/corelib/text/qstringlist.cpp
index 07a419423a..f0d385184d 100644
--- a/src/corelib/text/qstringlist.cpp
+++ b/src/corelib/text/qstringlist.cpp
@@ -120,25 +120,7 @@ QT_BEGIN_NAMESPACE
\section1 Iterating Over the Strings
- To iterate over a list, you can either use index positions or
- QList's Java-style and STL-style iterator types:
-
- Indexing:
-
- \snippet qstringlist/main.cpp 1
-
- Java-style iterator:
-
- \snippet qstringlist/main.cpp 2
-
- STL-style iterator:
-
- \snippet qstringlist/main.cpp 3
-
- The QStringListIterator class is simply a type definition for
- QListIterator<QString>. QStringList also provide the
- QMutableStringListIterator class which is a type definition for
- QMutableListIterator<QString>.
+ See \l {Iterating over Containers}.
\section1 Manipulating the Strings
diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp
index 9956314322..986b12f797 100644
--- a/src/corelib/thread/qatomic.cpp
+++ b/src/corelib/thread/qatomic.cpp
@@ -433,14 +433,21 @@
Atomic test-and-set.
+ \note If you use this function in a loop, consider using the overload with the
+ additional \c{T &currentValue} argument instead, which avoids the extra load() on
+ failure.
+
If the current value of this QAtomicInteger is the \a expectedValue,
the test-and-set functions assign the \a newValue to this
QAtomicInteger and return true. If the values are \e not the same,
this function does nothing and returns \c false.
+//![memory-order-relaxed]
This function uses \e relaxed \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, leaving the compiler and
processor to freely reorder memory accesses.
+//![memory-order-relaxed]
+
*/
/*!
@@ -448,15 +455,21 @@
Atomic test-and-set.
+ \note If you use this function in a loop, consider using the overload with the
+ additional \c{T &currentValue} argument instead, which avoids the extra load() on
+ failure.
+
If the current value of this QAtomicInteger is the \a expectedValue,
the test-and-set functions assign the \a newValue to this
QAtomicInteger and return true. If the values are \e not the same,
this function does nothing and returns \c false.
+//![memory-order-acquire]
This function uses \e acquire \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access following the atomic operation (in program order) may not
be re-ordered before the atomic operation.
+//![memory-order-acquire]
*/
/*!
@@ -464,15 +477,21 @@
Atomic test-and-set.
+ \note If you use this function in a loop, consider using the overload with the
+ additional \c{T &currentValue} argument instead, which avoids the extra load() on
+ failure.
+
If the current value of this QAtomicInteger is the \a expectedValue,
the test-and-set functions assign the \a newValue to this
QAtomicInteger and return true. If the values are \e not the same,
this function does nothing and returns \c false.
+//![memory-order-release]
This function uses \e release \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access before the atomic operation (in program order) may not be
re-ordered after the atomic operation.
+//![memory-order-release]
*/
/*!
@@ -480,15 +499,78 @@
Atomic test-and-set.
+ \note If you use this function in a loop, consider using the overload with the
+ additional \c{T &currentValue} argument instead, which avoids the extra load() on
+ failure.
+
If the current value of this QAtomicInteger is the \a expectedValue,
the test-and-set functions assign the \a newValue to this
QAtomicInteger and return true. If the values are \e not the same,
this function does nothing and returns \c false.
+//![memory-order-ordered]
This function uses \e ordered \l {QAtomicInteger#Memory
ordering}{memory ordering} semantics, which ensures that memory
access before and after the atomic operation (in program order)
may not be re-ordered.
+//![memory-order-ordered]
+
+*/
+
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::testAndSetRelaxed(T expectedValue, T newValue, T &currentValue)
+ \since 5.3
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicInteger is the \a expectedValue, the
+ test-and-set functions assign the \a newValue to this QAtomicInteger and
+ return \c true. If the values are \e not the same, the functions load the
+ current value of this QAtomicInteger into \a currentValue and return \c false.
+
+ \include qatomic.cpp memory-order-relaxed
+*/
+
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::testAndSetAcquire(T expectedValue, T newValue, T &currentValue)
+ \since 5.3
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicInteger is the \a expectedValue, the
+ test-and-set functions assign the \a newValue to this QAtomicInteger and
+ return \c true. If the values are \e not the same, the functions load the
+ current value of this QAtomicInteger into \a currentValue and return \c false.
+
+ \include qatomic.cpp memory-order-acquire
+*/
+
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::testAndSetRelease(T expectedValue, T newValue, T &currentValue)
+ \since 5.3
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicInteger is the \a expectedValue, the
+ test-and-set functions assign the \a newValue to this QAtomicInteger and
+ return \c true. If the values are \e not the same, the functions loads the
+ current value of this QAtomicInteger into \a currentValue and return \c false.
+
+ \include qatomic.cpp memory-order-release
+*/
+
+/*!
+ \fn template <typename T> bool QAtomicInteger<T>::testAndSetOrdered(T expectedValue, T newValue, T &currentValue)
+ \since 5.3
+
+ Atomic test-and-set.
+
+ If the current value of this QAtomicInteger is the \a expectedValue, the
+ test-and-set functions assign the \a newValue to this QAtomicInteger and
+ return \c true. If the values are \e not the same, it loads the current
+ value of this QAtomicInteger into \a currentValue and return \c false.
+
+ \include qatomic.cpp memory-order-ordered
*/
/*!
diff --git a/src/corelib/thread/qatomic.h b/src/corelib/thread/qatomic.h
index 2080167d2c..d04f82cff2 100644
--- a/src/corelib/thread/qatomic.h
+++ b/src/corelib/thread/qatomic.h
@@ -106,6 +106,11 @@ public:
bool testAndSetRelease(T expectedValue, T newValue);
bool testAndSetOrdered(T expectedValue, T newValue);
+ bool testAndSetRelaxed(T expectedValue, T newValue, T &currentValue);
+ bool testAndSetAcquire(T expectedValue, T newValue, T &currentValue);
+ bool testAndSetRelease(T expectedValue, T newValue, T &currentValue);
+ bool testAndSetOrdered(T expectedValue, T newValue, T &currentValue);
+
static constexpr bool isFetchAndStoreNative();
static constexpr bool isFetchAndStoreWaitFree();
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp
index ae6c45d385..6b35ed1eb8 100644
--- a/src/corelib/thread/qfutureinterface.cpp
+++ b/src/corelib/thread/qfutureinterface.cpp
@@ -120,6 +120,14 @@ void QFutureInterfaceBase::cancel()
return;
switch_from_to(d->state, suspendingOrSuspended, Canceled);
+
+ // Cancel the continuations chain
+ QFutureInterfaceBasePrivate *next = d->continuationData;
+ while (next) {
+ next->continuationState = QFutureInterfaceBasePrivate::Canceled;
+ next = next->continuationData;
+ }
+
d->waitCondition.wakeAll();
d->pausedWaitCondition.wakeAll();
d->sendCallOut(QFutureCallOutEvent(QFutureCallOutEvent::Canceled));
@@ -769,16 +777,19 @@ void QFutureInterfaceBase::setContinuation(std::function<void(const QFutureInter
{
QMutexLocker lock(&d->continuationMutex);
- if (continuationFutureData)
- continuationFutureData->parentData = d;
-
// If the state is ready, run continuation immediately,
// otherwise save it for later.
if (isFinished()) {
lock.unlock();
func(*this);
- } else {
+ lock.relock();
+ }
+ // Unless the continuation has been cleaned earlier, we have to
+ // store the move-only continuation, to guarantee that the associated
+ // future's data stays alive.
+ if (d->continuationState != QFutureInterfaceBasePrivate::Cleaned) {
d->continuation = std::move(func);
+ d->continuationData = continuationFutureData;
}
}
@@ -792,34 +803,32 @@ void QFutureInterfaceBase::cleanContinuation()
// copies of this, so that the allocated memory can be freed.
QMutexLocker lock(&d->continuationMutex);
d->continuation = nullptr;
+ d->continuationState = QFutureInterfaceBasePrivate::Cleaned;
}
void QFutureInterfaceBase::runContinuation() const
{
QMutexLocker lock(&d->continuationMutex);
if (d->continuation) {
- auto fn = std::exchange(d->continuation, nullptr);
+ // Save the continuation in a local function, to avoid calling
+ // a null std::function below, in case cleanContinuation() is
+ // called from some other thread right after unlock() below.
+ auto fn = std::move(d->continuation);
lock.unlock();
fn(*this);
+
+ lock.relock();
+ // Unless the continuation has been cleaned earlier, we have to
+ // store the move-only continuation, to guarantee that the associated
+ // future's data stays alive.
+ if (d->continuationState != QFutureInterfaceBasePrivate::Cleaned)
+ d->continuation = std::move(fn);
}
}
bool QFutureInterfaceBase::isChainCanceled() const
{
- if (isCanceled())
- return true;
-
- auto parent = d->parentData;
- while (parent) {
- // If the future is in Canceled state because it had an exception, we want to
- // continue checking the chain of parents for cancellation, otherwise if the exception
- // is handeled inside the chain, it won't be interrupted even though cancellation has
- // been requested.
- if ((parent->state.loadRelaxed() & Canceled) && !parent->m_exceptionStore.hasException())
- return true;
- parent = parent->parentData;
- }
- return false;
+ return isCanceled() || d->continuationState == QFutureInterfaceBasePrivate::Canceled;
}
void QFutureInterfaceBase::setLaunchAsync(bool value)
diff --git a/src/corelib/thread/qfutureinterface_p.h b/src/corelib/thread/qfutureinterface_p.h
index 287972ba50..651aa853a5 100644
--- a/src/corelib/thread/qfutureinterface_p.h
+++ b/src/corelib/thread/qfutureinterface_p.h
@@ -175,7 +175,10 @@ public:
QThreadPool *m_pool = nullptr;
// Wrapper for continuation
std::function<void(const QFutureInterfaceBase &)> continuation;
- QFutureInterfaceBasePrivate *parentData = nullptr;
+ QFutureInterfaceBasePrivate *continuationData = nullptr;
+
+ enum ContinuationState : quint8 { Default, Canceled, Cleaned };
+ std::atomic<ContinuationState> continuationState { Default };
RefCount refCount = 1;
QAtomicInt state; // reads and writes can happen unprotected, both must be atomic
diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h
index 3e861ca0cb..beb68ccc02 100644
--- a/src/corelib/thread/qmutex.h
+++ b/src/corelib/thread/qmutex.h
@@ -44,10 +44,8 @@
#include <QtCore/qatomic.h>
#include <new>
-#if __has_include(<chrono>)
-# include <chrono>
-# include <limits>
-#endif
+#include <chrono>
+#include <limits>
class tst_QMutex;
@@ -66,7 +64,6 @@ class QMutex;
class QRecursiveMutex;
class QMutexPrivate;
-#if __has_include(<chrono>)
namespace QtPrivate
{
template<class Rep, class Period>
@@ -92,7 +89,6 @@ namespace QtPrivate
return ms < maxInt ? int(ms) : maxInt;
}
}
-#endif
class Q_CORE_EXPORT QBasicMutex
{
diff --git a/src/corelib/thread/qpromise.h b/src/corelib/thread/qpromise.h
index 3dcb13f99a..d55ea1a4cd 100644
--- a/src/corelib/thread/qpromise.h
+++ b/src/corelib/thread/qpromise.h
@@ -77,6 +77,7 @@ public:
d.cancel();
finish(); // required to finalize the state
}
+ d.cleanContinuation();
}
// Core QPromise APIs
diff --git a/src/corelib/time/qdatetime.h b/src/corelib/time/qdatetime.h
index d0d7e1c47f..722b66a9d2 100644
--- a/src/corelib/time/qdatetime.h
+++ b/src/corelib/time/qdatetime.h
@@ -229,18 +229,25 @@ class QDateTimePrivate;
class Q_CORE_EXPORT QDateTime
{
struct ShortData {
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- quintptr status : 8;
-#endif
#if QT_VERSION >= QT_VERSION_CHECK(7,0,0)
+# if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ qint64 status : 8;
+# endif
qint64 msecs : 56;
+
+# if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ qint64 status : 8;
+# endif
#else
+# if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ quintptr status : 8;
+# endif
// note: this is only 24 bits on 32-bit systems...
qintptr msecs : sizeof(void *) * 8 - 8;
-#endif
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+# if Q_BYTE_ORDER == Q_BIG_ENDIAN
quintptr status : 8;
+# endif
#endif
};
diff --git a/src/corelib/tools/qlist.qdoc b/src/corelib/tools/qlist.qdoc
index 4e92e2c047..e366a30324 100644
--- a/src/corelib/tools/qlist.qdoc
+++ b/src/corelib/tools/qlist.qdoc
@@ -153,21 +153,7 @@
support \c operator==(). These requirements are documented on a
per-function basis.
- Like the other container classes, QList provides \l{Java-style iterators}
- (QListIterator and QMutableListIterator) and \l{STL-style iterators}
- (QList::const_iterator and QList::iterator). In practice, iterators are
- handy when working with generic algorithms provided by \l{generic
- algorithms}{Qt} and the C++ standard library. \l{Java-style iterators} are
- provided for backwards compatibility, prefer \l{STL-style iterators} when
- writing C++ code.
-
- \note Iterators over a QList, and references to individual elements
- within one, cannot be relied on to remain valid when any non-const method
- of the QList is called. Accessing such an iterator or reference after
- the call to a non-const method leads to undefined behavior. When stability
- for iterator-like functionality is required, you should use indexes instead
- of iterators as they are not tied to QList's internal state and thus do
- not get invalidated.
+ For iterating over the items, see \l {Iterating over Containers}.
In addition to QList, Qt also provides QVarLengthArray, a very
low-level class with little functionality that is optimized for
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index 59070c947c..5daf24189b 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -359,6 +359,7 @@ public:
if (!d)
return T();
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
// TODO: improve. There is no need of copying all the
// elements (the one to be removed can be skipped).
detach();
@@ -400,6 +401,7 @@ public:
T &operator[](const Key &key)
{
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
detach();
auto i = d->m.find(key);
if (i == d->m.end())
@@ -669,6 +671,7 @@ public:
iterator find(const Key &key)
{
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
detach();
return iterator(d->m.find(key));
}
@@ -687,6 +690,7 @@ public:
iterator lowerBound(const Key &key)
{
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
detach();
return iterator(d->m.lower_bound(key));
}
@@ -700,6 +704,7 @@ public:
iterator upperBound(const Key &key)
{
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
detach();
return iterator(d->m.upper_bound(key));
}
@@ -713,6 +718,7 @@ public:
iterator insert(const Key &key, const T &value)
{
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
// TODO: improve. In case of assignment, why copying first?
detach();
return iterator(d->m.insert_or_assign(key, value).first);
@@ -722,6 +728,7 @@ public:
{
// TODO: improve. In case of assignment, why copying first?
typename Map::const_iterator dpos;
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key`/`value` alive across the detach
if (!d || d.isShared()) {
auto posDistance = d ? std::distance(d->m.cbegin(), pos.i) : 0;
detach();
@@ -789,6 +796,7 @@ public:
QPair<iterator, iterator> equal_range(const Key &akey)
{
+ const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
detach();
auto result = d->m.equal_range(akey);
return {iterator(result.first), iterator(result.second)};
@@ -986,15 +994,15 @@ public:
if (!d)
return 0;
- // TODO: improve. Copy over only the elements not to be removed.
- detach();
-
// key and value may belong to this map. As such, we need to copy
// them to ensure they stay valid throughout the iteration below
// (which may destroy them)
const Key keyCopy = key;
const T valueCopy = value;
+ // TODO: improve. Copy over only the elements not to be removed.
+ detach();
+
size_type result = 0;
const auto &keyCompare = d->m.key_comp();
@@ -1024,6 +1032,8 @@ public:
if (!d)
return T();
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
+
// TODO: improve. There is no need of copying all the
// elements (the one to be removed can be skipped).
detach();
@@ -1361,6 +1371,7 @@ public:
iterator find(const Key &key)
{
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
detach();
return iterator(d->m.find(key));
}
@@ -1379,6 +1390,8 @@ public:
iterator find(const Key &key, const T &value)
{
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
+
detach();
auto range = d->m.equal_range(key);
@@ -1411,6 +1424,7 @@ public:
iterator lowerBound(const Key &key)
{
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
detach();
return iterator(d->m.lower_bound(key));
}
@@ -1424,6 +1438,7 @@ public:
iterator upperBound(const Key &key)
{
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
detach();
return iterator(d->m.upper_bound(key));
}
@@ -1437,6 +1452,7 @@ public:
iterator insert(const Key &key, const T &value)
{
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
detach();
// note that std::multimap inserts at the end of an equal_range for a key,
// QMultiMap at the beginning.
@@ -1446,6 +1462,7 @@ public:
iterator insert(const_iterator pos, const Key &key, const T &value)
{
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
typename Map::const_iterator dpos;
if (!d || d.isShared()) {
auto posDistance = d ? std::distance(d->m.cbegin(), pos.i) : 0;
@@ -1484,6 +1501,8 @@ public:
iterator replace(const Key &key, const T &value)
{
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
+
// TODO: improve. No need of copying and then overwriting.
detach();
@@ -1503,6 +1522,7 @@ public:
QPair<iterator, iterator> equal_range(const Key &akey)
{
+ const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
detach();
auto result = d->m.equal_range(akey);
return {iterator(result.first), iterator(result.second)};
diff --git a/src/corelib/tools/qmap.qdoc b/src/corelib/tools/qmap.qdoc
index a14a3bdb09..f9eed72d67 100644
--- a/src/corelib/tools/qmap.qdoc
+++ b/src/corelib/tools/qmap.qdoc
@@ -238,6 +238,15 @@
Returns an STL map equivalent to this QMap.
*/
+/*! \fn template <class Key, class T> std::map<Key, T> QMap<Key, T>::toStdMap() &&
+
+ \overload
+ \since 6.0
+
+ \note Calling this function will leave this QMap in the partially-formed state, in which
+ the only valid operations are destruction or assignment of a new value.
+*/
+
/*! \fn template <class Key, class T> bool QMap<Key, T>::operator==(const QMap<Key, T> &lhs, const QMap<Key, T> &rhs)
Returns \c true if \a lhs is equal to \a rhs; otherwise returns
diff --git a/src/corelib/tools/qtaggedpointer.h b/src/corelib/tools/qtaggedpointer.h
index 68074cc43d..b60fc424f4 100644
--- a/src/corelib/tools/qtaggedpointer.h
+++ b/src/corelib/tools/qtaggedpointer.h
@@ -108,11 +108,30 @@ public:
return !isNull();
}
- QTaggedPointer &operator=(T *other) noexcept
+#ifdef Q_QDOC
+ QTaggedPointer &operator=(T *other) noexcept;
+#else
+ // Disables the usage of `ptr = {}`, which would go through this operator
+ // (rather than using the implicitly-generated assignment operator).
+ // The operators have different semantics: the ones here leave the tag intact,
+ // the implicitly-generated one overwrites it.
+ template <typename U,
+ std::enable_if_t<std::is_convertible_v<U *, T *>, bool> = false>
+ QTaggedPointer &operator=(U *other) noexcept
+ {
+ T *otherT = other;
+ d = reinterpret_cast<quintptr>(otherT) | (d & tagMask());
+ return *this;
+ }
+
+ template <typename U,
+ std::enable_if_t<std::is_null_pointer_v<U>, bool> = false>
+ QTaggedPointer &operator=(U) noexcept
{
- d = reinterpret_cast<quintptr>(other) | (d & tagMask());
+ d = reinterpret_cast<quintptr>(static_cast<T *>(nullptr)) | (d & tagMask());
return *this;
}
+#endif
static constexpr Tag maximumTag() noexcept
{
diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake
index cfb9f8412f..611928d13a 100644
--- a/src/gui/configure.cmake
+++ b/src/gui/configure.cmake
@@ -644,7 +644,7 @@ qt_feature("system-freetype" PRIVATE
qt_feature("fontconfig" PUBLIC PRIVATE
LABEL "Fontconfig"
AUTODETECT NOT APPLE
- CONDITION NOT WIN32 AND QT_FEATURE_system_freetype AND FONTCONFIG_FOUND
+ CONDITION NOT WIN32 AND QT_FEATURE_system_freetype AND Fontconfig_FOUND
)
qt_feature_definition("fontconfig" "QT_NO_FONTCONFIG" NEGATE VALUE "1")
qt_feature("gbm"
diff --git a/src/gui/doc/src/external-resources.qdoc b/src/gui/doc/src/external-resources.qdoc
index d58230ed2b..6d7e2f95c0 100644
--- a/src/gui/doc/src/external-resources.qdoc
+++ b/src/gui/doc/src/external-resources.qdoc
@@ -32,7 +32,7 @@
*/
/*!
- \externalpage http://www.linux-foundation.org/en/Accessibility/IAccessible2
+ \externalpage https://accessibility.linuxfoundation.org/a11yspecs/ia2/docs/html/index.html
\title IAccessible2 Specification
*/
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index c8ce42f4b9..662be6abc9 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -4661,6 +4661,8 @@ QImage QImage::smoothScaled(int w, int h) const
static QImage rotated90(const QImage &image)
{
QImage out(image.height(), image.width(), image.format());
+ if (out.isNull())
+ return out;
copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
@@ -4689,6 +4691,8 @@ static QImage rotated180(const QImage &image)
return image.mirrored(true, true);
QImage out(image.width(), image.height(), image.format());
+ if (out.isNull())
+ return out;
copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
@@ -4701,6 +4705,8 @@ static QImage rotated180(const QImage &image)
static QImage rotated270(const QImage &image)
{
QImage out(image.height(), image.width(), image.format());
+ if (out.isNull())
+ return out;
copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
diff --git a/src/gui/itemmodels/qfilesystemmodel_p.h b/src/gui/itemmodels/qfilesystemmodel_p.h
index fe27457b4e..35d1c85e0a 100644
--- a/src/gui/itemmodels/qfilesystemmodel_p.h
+++ b/src/gui/itemmodels/qfilesystemmodel_p.h
@@ -86,7 +86,10 @@ public:
Q_DECLARE_TYPEINFO(QFileSystemModelNodePathKey, Q_RELOCATABLE_TYPE);
-inline size_t qHash(const QFileSystemModelNodePathKey &key) { return qHash(key.toCaseFolded()); }
+inline size_t qHash(const QFileSystemModelNodePathKey &key, size_t seed = 0)
+{
+ return qHash(key.toCaseFolded(), seed);
+}
#else // Q_OS_WIN
typedef QString QFileSystemModelNodePathKey;
#endif
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index af903f92f1..55c3fab2c2 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -2650,8 +2650,9 @@ void QGuiApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::Cl
{
if (e->window.isNull())
return;
- if (e->window.data()->d_func()->blockedByModalWindow) {
- // a modal window is blocking this window, don't allow close events through
+ if (e->window.data()->d_func()->blockedByModalWindow && !e->window.data()->d_func()->inClose) {
+ // a modal window is blocking this window, don't allow close events through, unless they
+ // originate from a call to QWindow::close.
return;
}
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index f088a01c63..4ccadadee7 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -71,14 +71,25 @@ class QPalettePrivate
public:
class Data : public QSharedData {
public:
- Data() : ser_no(qt_palette_count++) { }
+ // Every instance of Data has to have a unique serial number, even
+ // if it gets created by copying another - we wouldn't create a copy
+ // in the first place if the serial number should be the same!
+ Data(const Data &other)
+ : QSharedData(other)
+ {
+ for (int grp = 0; grp < int(QPalette::NColorGroups); grp++) {
+ for (int role = 0; role < int(QPalette::NColorRoles); role++)
+ br[grp][role] = other.br[grp][role];
+ }
+ }
+ Data() = default;
QBrush br[QPalette::NColorGroups][QPalette::NColorRoles];
- const int ser_no;
+ const int ser_no = qt_palette_count++;
};
QPalettePrivate(const QExplicitlySharedDataPointer<Data> &data)
- : ref(1), detach_no(0), data(data)
+ : ref(1), data(data)
{ }
QPalettePrivate()
: QPalettePrivate(QExplicitlySharedDataPointer<Data>(new Data))
@@ -86,7 +97,8 @@ public:
QAtomicInt ref;
QPalette::ResolveMask resolveMask = {0};
- int detach_no;
+ static inline int qt_palette_private_count = 0;
+ const int detach_no = ++qt_palette_private_count;
QExplicitlySharedDataPointer<Data> data;
};
@@ -889,7 +901,6 @@ void QPalette::detach()
delete d;
d = x;
}
- ++d->detach_no;
}
/*!
diff --git a/src/gui/kernel/qpointingdevice.cpp b/src/gui/kernel/qpointingdevice.cpp
index d02f81a8af..4ca0351287 100644
--- a/src/gui/kernel/qpointingdevice.cpp
+++ b/src/gui/kernel/qpointingdevice.cpp
@@ -143,6 +143,48 @@ Q_LOGGING_CATEGORY(lcPointerGrab, "qt.pointer.grab");
Any of the above (used as a default filter value).
*/
+/*! \enum QPointingDevice::GrabTransition
+
+ This enum represents a transition of exclusive or passive grab
+ from one object (possibly \c nullptr) to another (possibly \c nullptr).
+ It is emitted as an argument of the QPointingDevice::grabChanged() signal.
+
+ Valid values are:
+
+ \value GrabExclusive
+ Emitted after QPointerEvent::setExclusiveGrabber().
+ \value UngrabExclusive
+ Emitted after QPointerEvent::setExclusiveGrabber() when the grabber is
+ set to \c nullptr, to notify that the grab has terminated normally.
+ \value CancelGrabExclusive
+ Emitted after QPointerEvent::setExclusiveGrabber() when the grabber is set
+ to a different object, to notify that the old grabber's grab is "stolen".
+ \value GrabPassive
+ Emitted after QPointerEvent::addPassiveGrabber().
+ \value UngrabPassive
+ Emitted when a passive grab is terminated normally,
+ for example after QPointerEvent::removePassiveGrabber().
+ \value CancelGrabPassive
+ Emitted when a passive grab is terminated abnormally (a gesture is canceled).
+ \value OverrideGrabPassive
+ This value is not currently used.
+*/
+
+/*! \fn void QPointingDevice::grabChanged(QObject *grabber, QPointingDevice::GrabTransition transition, const QPointerEvent *event, const QEventPoint &point) const
+
+ This signal is emitted when the \a grabber object gains or loses an
+ exclusive or passive grab of \a point during delivery of \a event.
+ The \a transition tells what happened, from the perspective of the
+ \c grabber object.
+
+ \note A grab transition from one object to another results in two signals,
+ to notify that one object has lost its grab, and to notify that there is
+ another grabber. In other cases, when transitioning to or from a non-grabbing
+ state, only one signal is emitted: the \a grabber argument is never \c nullptr.
+
+ \sa QPointerEvent::setExclusiveGrabber(), QPointerEvent::addPassiveGrabber(), QPointerEvent::removePassiveGrabber()
+*/
+
/*!
Creates a new invalid pointing device instance as a child of \a parent.
*/
diff --git a/src/gui/kernel/qtestsupport_gui.cpp b/src/gui/kernel/qtestsupport_gui.cpp
index ab48111fb5..19f4ea27df 100644
--- a/src/gui/kernel/qtestsupport_gui.cpp
+++ b/src/gui/kernel/qtestsupport_gui.cpp
@@ -53,9 +53,16 @@ QT_BEGIN_NAMESPACE
/*!
\since 5.0
- Waits for \a timeout milliseconds or until the \a window is active.
+ Returns \c true, if \a window is active within \a timeout milliseconds. Otherwise returns \c false.
- Returns \c true if \c window is active within \a timeout milliseconds, otherwise returns \c false.
+ The method is useful in tests that call QWindow::show() and rely on the window actually being
+ active (i.e. being visible and having focus) before proceeding.
+
+ \note The method will time out and return \c false if another window prevents \a window from
+ becoming active.
+
+ \note Since focus is an exclusive property, \a window may loose its focus to another window at
+ any time - even after the method has returned \c true.
\sa qWaitForWindowExposed(), QWindow::isActive()
*/
@@ -75,15 +82,14 @@ Q_GUI_EXPORT bool QTest::qWaitForWindowActive(QWindow *window, int timeout)
/*!
\since 5.0
- Waits for \a timeout milliseconds or until the \a window is exposed.
- Returns \c true if \c window is exposed within \a timeout milliseconds, otherwise returns \c false.
+ Returns \c true, if \a window is exposed within \a timeout milliseconds. Otherwise returns \c false.
- This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
- time after being asked to show itself on the screen.
+ The method is useful in tests that call QWindow::show() and rely on the window actually being
+ being visible before proceeding.
- Note that a window that is mapped to screen may still not be considered exposed if the window client
- area is completely covered by other windows, or if the window is otherwise not visible. This function
- will then time out when waiting for such a window.
+ \note A window mapped to screen may still not be considered exposed, if the window client area is
+ not visible, e.g. because it is completely covered by other windows.
+ In such cases, the method will time out and return \c false.
\sa qWaitForWindowActive(), QWindow::isExposed()
*/
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 7858a37d4f..be7f13f81e 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -313,15 +313,6 @@ QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() :
*/
/*!
- \typedef QSpan
- \relates QRasterPaintEngine
-
- A struct equivalent to QT_FT_Span, containing a position (x,
- y), the span's length in pixels and its color/coverage (a value
- ranging from 0 to 255).
-*/
-
-/*!
\since 4.5
Creates a raster based paint engine for operating on the given
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 2d25b5811e..fa03388cce 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -2312,16 +2312,15 @@ int QPdfEnginePrivate::writeCompressed(const char *src, int len)
{
#ifndef QT_NO_COMPRESS
if (do_compress) {
- uLongf destLen = len + len/100 + 13; // zlib requirement
- Bytef* dest = new Bytef[destLen];
- if (Z_OK == ::compress(dest, &destLen, (const Bytef*) src, (uLongf)len)) {
- stream->writeRawData((const char*)dest, destLen);
+ const QByteArray data = qCompress(reinterpret_cast<const uchar *>(src), len);
+ constexpr qsizetype HeaderSize = 4;
+ if (!data.isNull()) {
+ stream->writeRawData(data.data() + HeaderSize, data.size() - HeaderSize);
+ len = data.size() - HeaderSize;
} else {
qWarning("QPdfStream::writeCompressed: Error in compress()");
- destLen = 0;
+ len = 0;
}
- delete [] dest;
- len = destLen;
} else
#endif
{
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index 6bb7536748..f5d002dc3c 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -2902,8 +2902,10 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
f->glDepthMask(GL_TRUE);
f->glClearDepthf(cmd.args.clear.d);
}
- if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT)
+ if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT) {
+ f->glStencilMask(0xFF);
f->glClearStencil(GLint(cmd.args.clear.s));
+ }
f->glClear(cmd.args.clear.mask);
cbD->graphicsPassState.reset(); // altered depth/color write, invalidate in order to avoid confusing the state tracking
break;
diff --git a/src/gui/text/coretext/qcoretextfontdatabase.mm b/src/gui/text/coretext/qcoretextfontdatabase.mm
index bdf0e502f3..9c454fa8c3 100644
--- a/src/gui/text/coretext/qcoretextfontdatabase.mm
+++ b/src/gui/text/coretext/qcoretextfontdatabase.mm
@@ -114,6 +114,12 @@ QCoreTextFontDatabase::~QCoreTextFontDatabase()
qDeleteAll(m_themeFonts);
}
+CTFontDescriptorRef descriptorForFamily(const QString &familyName)
+{
+ return CTFontDescriptorCreateWithAttributes(CFDictionaryRef(@{
+ (id)kCTFontFamilyNameAttribute: familyName.toNSString()
+ }));
+}
void QCoreTextFontDatabase::populateFontDatabase()
{
qCDebug(lcQpaFonts) << "Populating font database...";
@@ -125,6 +131,110 @@ void QCoreTextFontDatabase::populateFontDatabase()
for (NSString *familyName in familyNames.as<const NSArray *>())
QPlatformFontDatabase::registerFontFamily(QString::fromNSString(familyName));
+ // Some fonts has special handling since macOS Catalina: It is available
+ // on the platform, so that it may be used by applications directly, but does not
+ // get enumerated. Since there are no alternatives, we hardcode it.
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSCatalina
+ && !qEnvironmentVariableIsSet("QT_NO_HARDCODED_FALLBACK_FONTS")) {
+ m_hardcodedFallbackFonts[QChar::Script_Adlam] = QStringLiteral("Noto Sans Adlam");
+ m_hardcodedFallbackFonts[QChar::Script_Ahom] = QStringLiteral("Noto Serif Ahom");
+ m_hardcodedFallbackFonts[QChar::Script_Avestan] = QStringLiteral("Noto Sans Avestan");
+ m_hardcodedFallbackFonts[QChar::Script_Balinese] = QStringLiteral("Noto Serif Balinese");
+ m_hardcodedFallbackFonts[QChar::Script_Bamum] = QStringLiteral("Noto Sans Bamum");
+ m_hardcodedFallbackFonts[QChar::Script_BassaVah] = QStringLiteral("Noto Sans Bassa Vah");
+ m_hardcodedFallbackFonts[QChar::Script_Batak] = QStringLiteral("Noto Sans Batak");
+ m_hardcodedFallbackFonts[QChar::Script_Bhaiksuki] = QStringLiteral("Noto Sans Bhaiksuki");
+ m_hardcodedFallbackFonts[QChar::Script_Brahmi] = QStringLiteral("Noto Sans Brahmi");
+ m_hardcodedFallbackFonts[QChar::Script_Buginese] = QStringLiteral("Noto Sans Buginese");
+ m_hardcodedFallbackFonts[QChar::Script_Buhid] = QStringLiteral("Noto Sans Buhid");
+ m_hardcodedFallbackFonts[QChar::Script_Carian] = QStringLiteral("Noto Sans Carian");
+ m_hardcodedFallbackFonts[QChar::Script_CaucasianAlbanian] = QStringLiteral("Noto Sans Caucasian Albanian");
+ m_hardcodedFallbackFonts[QChar::Script_Chakma] = QStringLiteral("Noto Sans Chakma");
+ m_hardcodedFallbackFonts[QChar::Script_Cham] = QStringLiteral("Noto Sans Cham");
+ m_hardcodedFallbackFonts[QChar::Script_Coptic] = QStringLiteral("Noto Sans Coptic");
+ m_hardcodedFallbackFonts[QChar::Script_Cuneiform] = QStringLiteral("Noto Sans Cuneiform");
+ m_hardcodedFallbackFonts[QChar::Script_Cypriot] = QStringLiteral("Noto Sans Cypriot");
+ m_hardcodedFallbackFonts[QChar::Script_Duployan] = QStringLiteral("Noto Sans Duployan");
+ m_hardcodedFallbackFonts[QChar::Script_EgyptianHieroglyphs] = QStringLiteral("Noto Sans Egyptian Hieroglyphs");
+ m_hardcodedFallbackFonts[QChar::Script_Elbasan] = QStringLiteral("Noto Sans Elbasan");
+ m_hardcodedFallbackFonts[QChar::Script_Glagolitic] = QStringLiteral("Noto Sans Glagolitic");
+ m_hardcodedFallbackFonts[QChar::Script_Gothic] = QStringLiteral("Noto Sans Gothic");
+ m_hardcodedFallbackFonts[QChar::Script_HanifiRohingya] = QStringLiteral("Noto Sans Hanifi Rohingya");
+ m_hardcodedFallbackFonts[QChar::Script_Hanunoo] = QStringLiteral("Noto Sans Hanunoo");
+ m_hardcodedFallbackFonts[QChar::Script_Hatran] = QStringLiteral("Noto Sans Hatran");
+ m_hardcodedFallbackFonts[QChar::Script_ImperialAramaic] = QStringLiteral("Noto Sans Imperial Aramaic");
+ m_hardcodedFallbackFonts[QChar::Script_InscriptionalPahlavi] = QStringLiteral("Noto Sans Inscriptional Pahlavi");
+ m_hardcodedFallbackFonts[QChar::Script_InscriptionalParthian] = QStringLiteral("Noto Sans Inscriptional Parthian");
+ m_hardcodedFallbackFonts[QChar::Script_Javanese] = QStringLiteral("Noto Sans Javanese");
+ m_hardcodedFallbackFonts[QChar::Script_Kaithi] = QStringLiteral("Noto Sans Kaithi");
+ m_hardcodedFallbackFonts[QChar::Script_KayahLi] = QStringLiteral("Noto Sans Kayah Li");
+ m_hardcodedFallbackFonts[QChar::Script_Kharoshthi] = QStringLiteral("Noto Sans Kharoshthi");
+ m_hardcodedFallbackFonts[QChar::Script_Khojki] = QStringLiteral("Noto Sans Khojki");
+ m_hardcodedFallbackFonts[QChar::Script_Khudawadi] = QStringLiteral("Noto Sans Khudawadi");
+ m_hardcodedFallbackFonts[QChar::Script_Lepcha] = QStringLiteral("Noto Sans Lepcha");
+ m_hardcodedFallbackFonts[QChar::Script_Limbu] = QStringLiteral("Noto Sans Limbu");
+ m_hardcodedFallbackFonts[QChar::Script_LinearA] = QStringLiteral("Noto Sans Linear A");
+ m_hardcodedFallbackFonts[QChar::Script_LinearB] = QStringLiteral("Noto Sans Linear B");
+ m_hardcodedFallbackFonts[QChar::Script_Lisu] = QStringLiteral("Noto Sans Lisu");
+ m_hardcodedFallbackFonts[QChar::Script_Lycian] = QStringLiteral("Noto Sans Lycian");
+ m_hardcodedFallbackFonts[QChar::Script_Lydian] = QStringLiteral("Noto Sans Lydian");
+ m_hardcodedFallbackFonts[QChar::Script_Mahajani] = QStringLiteral("Noto Sans Mahajani");
+ m_hardcodedFallbackFonts[QChar::Script_Mandaic] = QStringLiteral("Noto Sans Mandaic");
+ m_hardcodedFallbackFonts[QChar::Script_Manichaean] = QStringLiteral("Noto Sans Manichaean");
+ m_hardcodedFallbackFonts[QChar::Script_Marchen] = QStringLiteral("Noto Sans Marchen");
+ m_hardcodedFallbackFonts[QChar::Script_MendeKikakui] = QStringLiteral("Noto Sans Mende Kikakui");
+ m_hardcodedFallbackFonts[QChar::Script_MeroiticCursive] = QStringLiteral("Noto Sans Meroitic");
+ m_hardcodedFallbackFonts[QChar::Script_MeroiticHieroglyphs] = QStringLiteral("Noto Sans Meroitic");
+ m_hardcodedFallbackFonts[QChar::Script_Miao] = QStringLiteral("Noto Sans Miao");
+ m_hardcodedFallbackFonts[QChar::Script_Modi] = QStringLiteral("Noto Sans Modi");
+ m_hardcodedFallbackFonts[QChar::Script_Mongolian] = QStringLiteral("Noto Sans Mongolian");
+ m_hardcodedFallbackFonts[QChar::Script_Mro] = QStringLiteral("Noto Sans Mro");
+ m_hardcodedFallbackFonts[QChar::Script_MeeteiMayek] = QStringLiteral("Noto Sans Meetei Mayek");
+ m_hardcodedFallbackFonts[QChar::Script_Multani] = QStringLiteral("Noto Sans Multani");
+ m_hardcodedFallbackFonts[QChar::Script_Nabataean] = QStringLiteral("Noto Sans Nabataean");
+ m_hardcodedFallbackFonts[QChar::Script_Newa] = QStringLiteral("Noto Sans Newa");
+ m_hardcodedFallbackFonts[QChar::Script_NewTaiLue] = QStringLiteral("Noto Sans New Tai Lue");
+ m_hardcodedFallbackFonts[QChar::Script_Nko] = QStringLiteral("Noto Sans Nko");
+ m_hardcodedFallbackFonts[QChar::Script_OlChiki] = QStringLiteral("Noto Sans Ol Chiki");
+ m_hardcodedFallbackFonts[QChar::Script_OldHungarian] = QStringLiteral("Noto Sans Old Hungarian");
+ m_hardcodedFallbackFonts[QChar::Script_OldItalic] = QStringLiteral("Noto Sans Old Italic");
+ m_hardcodedFallbackFonts[QChar::Script_OldNorthArabian] = QStringLiteral("Noto Sans Old North Arabian");
+ m_hardcodedFallbackFonts[QChar::Script_OldPermic] = QStringLiteral("Noto Sans Old Permic");
+ m_hardcodedFallbackFonts[QChar::Script_OldPersian] = QStringLiteral("Noto Sans Old Persian");
+ m_hardcodedFallbackFonts[QChar::Script_OldSouthArabian] = QStringLiteral("Noto Sans Old South Arabian");
+ m_hardcodedFallbackFonts[QChar::Script_OldTurkic] = QStringLiteral("Noto Sans Old Turkic");
+ m_hardcodedFallbackFonts[QChar::Script_Osage] = QStringLiteral("Noto Sans Osage");
+ m_hardcodedFallbackFonts[QChar::Script_Osmanya] = QStringLiteral("Noto Sans Osmanya");
+ m_hardcodedFallbackFonts[QChar::Script_PahawhHmong] = QStringLiteral("Noto Sans Pahawh Hmong");
+ m_hardcodedFallbackFonts[QChar::Script_Palmyrene] = QStringLiteral("Noto Sans Palmyrene");
+ m_hardcodedFallbackFonts[QChar::Script_PauCinHau] = QStringLiteral("Noto Sans Pau Cin Hau");
+ m_hardcodedFallbackFonts[QChar::Script_PhagsPa] = QStringLiteral("Noto Sans PhagsPa");
+ m_hardcodedFallbackFonts[QChar::Script_Phoenician] = QStringLiteral("Noto Sans Phoenician");
+ m_hardcodedFallbackFonts[QChar::Script_PsalterPahlavi] = QStringLiteral("Noto Sans Psalter Pahlavi");
+ m_hardcodedFallbackFonts[QChar::Script_Rejang] = QStringLiteral("Noto Sans Rejang");
+ m_hardcodedFallbackFonts[QChar::Script_Samaritan] = QStringLiteral("Noto Sans Samaritan");
+ m_hardcodedFallbackFonts[QChar::Script_Saurashtra] = QStringLiteral("Noto Sans Saurashtra");
+ m_hardcodedFallbackFonts[QChar::Script_Sharada] = QStringLiteral("Noto Sans Sharada");
+ m_hardcodedFallbackFonts[QChar::Script_Siddham] = QStringLiteral("Noto Sans Siddham");
+ m_hardcodedFallbackFonts[QChar::Script_SoraSompeng] = QStringLiteral("Noto Sans Sora Sompeng");
+ m_hardcodedFallbackFonts[QChar::Script_Sundanese] = QStringLiteral("Noto Sans Sundanese");
+ m_hardcodedFallbackFonts[QChar::Script_SylotiNagri] = QStringLiteral("Noto Sans Syloti Nagri");
+ m_hardcodedFallbackFonts[QChar::Script_Tagalog] = QStringLiteral("Noto Sans Tagalog");
+ m_hardcodedFallbackFonts[QChar::Script_Tagbanwa] = QStringLiteral("Noto Sans Tagbanwa");
+ m_hardcodedFallbackFonts[QChar::Script_Takri] = QStringLiteral("Noto Sans Takri");
+ m_hardcodedFallbackFonts[QChar::Script_TaiLe] = QStringLiteral("Noto Sans Tai Le");
+ m_hardcodedFallbackFonts[QChar::Script_TaiTham] = QStringLiteral("Noto Sans Tai Tham");
+ m_hardcodedFallbackFonts[QChar::Script_TaiViet] = QStringLiteral("Noto Sans Tai Viet");
+ m_hardcodedFallbackFonts[QChar::Script_Thaana] = QStringLiteral("Noto Sans Thaana");
+ m_hardcodedFallbackFonts[QChar::Script_Tifinagh] = QStringLiteral("Noto Sans Tifinagh");
+ m_hardcodedFallbackFonts[QChar::Script_Tirhuta] = QStringLiteral("Noto Sans Tirhuta");
+ m_hardcodedFallbackFonts[QChar::Script_Ugaritic] = QStringLiteral("Noto Sans Ugaritic");
+ m_hardcodedFallbackFonts[QChar::Script_Vai] = QStringLiteral("Noto Sans Vai");
+ m_hardcodedFallbackFonts[QChar::Script_WarangCiti] = QStringLiteral("Noto Sans Warang Citi");
+ m_hardcodedFallbackFonts[QChar::Script_Wancho] = QStringLiteral("Noto Sans Wancho");
+ m_hardcodedFallbackFonts[QChar::Script_Yi] = QStringLiteral("Noto Sans Yi");
+ }
+
qCDebug(lcQpaFonts) << "Populating available families took" << elapsed.restart() << "ms";
populateThemeFonts();
@@ -198,13 +308,6 @@ bool QCoreTextFontDatabase::populateFamilyAliases(const QString &missingFamily)
#endif
}
-CTFontDescriptorRef descriptorForFamily(const QString &familyName)
-{
- return CTFontDescriptorCreateWithAttributes(CFDictionaryRef(@{
- (id)kCTFontFamilyNameAttribute: familyName.toNSString()
- }));
-}
-
CTFontDescriptorRef descriptorForFamily(const char *familyName)
{
return descriptorForFamily(QString::fromLatin1(familyName));
@@ -594,6 +697,31 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
// add Apple Symbols to cover those too.
if (!fallbackList.contains(QStringLiteral("Apple Symbols")))
fallbackList.append(QStringLiteral("Apple Symbols"));
+ // Some Noto* fonts are not automatically enumerated by system, despite being the main
+ // fonts for their writing system.
+ QString hardcodedFont = m_hardcodedFallbackFonts.value(script);
+ if (!hardcodedFont.isEmpty() && !fallbackList.contains(hardcodedFont)) {
+ if (!isFamilyPopulated(hardcodedFont)) {
+ if (!m_privateFamilies.contains(hardcodedFont)) {
+ QCFType<CTFontDescriptorRef> familyDescriptor = descriptorForFamily(hardcodedFont);
+ QCFType<CFArrayRef> matchingFonts = CTFontDescriptorCreateMatchingFontDescriptors(familyDescriptor, nullptr);
+ if (matchingFonts) {
+ const int numFonts = CFArrayGetCount(matchingFonts);
+ for (int i = 0; i < numFonts; ++i)
+ const_cast<QCoreTextFontDatabase *>(this)->populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)),
+ hardcodedFont);
+
+ fallbackList.append(hardcodedFont);
+ }
+
+ // Register as private family even if the font is not found, in order to avoid
+ // redoing the check later. In later calls, the font will then just be ignored.
+ m_privateFamilies.insert(hardcodedFont);
+ }
+ } else {
+ fallbackList.append(hardcodedFont);
+ }
+ }
#endif
extern QStringList qt_sort_families_by_writing_system(QChar::Script, const QStringList &);
@@ -644,7 +772,7 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData
bool QCoreTextFontDatabase::isPrivateFontFamily(const QString &family) const
{
- if (family.startsWith(QLatin1Char('.')) || family == QLatin1String("LastResort"))
+ if (family.startsWith(QLatin1Char('.')) || family == QLatin1String("LastResort") || m_privateFamilies.contains(family))
return true;
return QPlatformFontDatabase::isPrivateFontFamily(family);
diff --git a/src/gui/text/coretext/qcoretextfontdatabase_p.h b/src/gui/text/coretext/qcoretextfontdatabase_p.h
index c07ed57d31..91508afb22 100644
--- a/src/gui/text/coretext/qcoretextfontdatabase_p.h
+++ b/src/gui/text/coretext/qcoretextfontdatabase_p.h
@@ -93,6 +93,8 @@ private:
QHash<QPlatformTheme::Font, QFont *> m_themeFonts;
QHash<QString, QList<QCFType<CTFontDescriptorRef>>> m_systemFontDescriptors;
+ QHash<QChar::Script, QString> m_hardcodedFallbackFonts;
+ mutable QSet<QString> m_privateFamilies;
bool m_hasPopulatedAliases;
};
diff --git a/src/gui/text/coretext/qfontengine_coretext.mm b/src/gui/text/coretext/qfontengine_coretext.mm
index 57738ef9fc..e38af34d5b 100644
--- a/src/gui/text/coretext/qfontengine_coretext.mm
+++ b/src/gui/text/coretext/qfontengine_coretext.mm
@@ -422,7 +422,8 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt
CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight);
- CGAffineTransformConcat(cgMatrix, oldTextMatrix);
+ // FIXME: Should we include the old matrix here? If so we need to assign it.
+ Q_UNUSED(CGAffineTransformConcat(cgMatrix, oldTextMatrix));
if (synthesisFlags & QFontEngine::SynthesizedItalic)
cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index b263c9c00a..b8d21c9a8e 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1282,7 +1282,6 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
QFixed base = sl.base();
QFixed descent = sl.descent;
- QFixed cursorDescent = descent;
bool rightToLeft = d->isRightToLeft();
const int realCursorPosition = cursorPosition;
@@ -1311,15 +1310,16 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
si = &d->layoutData->items[itm];
}
}
- if (si->ascent >= 0)
- base = si->ascent;
- if (si->descent == 0)
- descent = si->descent;
- else if (si->descent > 0 && si->descent < descent)
- cursorDescent = si->descent;
+ // objects need some special treatment as they can have special alignment or be floating
+ if (si->analysis.flags != QScriptAnalysis::Object) {
+ if (si->ascent > 0)
+ base = si->ascent;
+ if (si->descent > 0)
+ descent = si->descent;
+ }
rightToLeft = si->analysis.bidiLevel % 2;
}
- qreal y = position.y() + (sl.y + sl.base() + sl.descent - base - descent).toReal();
+ qreal y = position.y() + (sl.y + sl.base() - base).toReal();
bool toggleAntialiasing = !(p->renderHints() & QPainter::Antialiasing)
&& (p->transform().type() > QTransform::TxTranslate);
if (toggleAntialiasing)
@@ -1330,7 +1330,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
const QTransform &deviceTransform = p->deviceTransform();
const qreal xScale = deviceTransform.m11();
if (deviceTransform.type() != QTransform::TxScale || std::trunc(xScale) == xScale) {
- p->fillRect(QRectF(x, y, qreal(width), (base + cursorDescent).toReal()), p->pen().brush());
+ p->fillRect(QRectF(x, y, qreal(width), (base + descent).toReal()), p->pen().brush());
} else {
// Ensure consistently rendered cursor width under fractional scaling
const QPen origPen = p->pen();
@@ -1338,7 +1338,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
pen.setCosmetic(true);
const qreal center = x + qreal(width) / 2;
p->setPen(pen);
- p->drawLine(QPointF(center, y), QPointF(center, y + (base + cursorDescent).toReal()));
+ p->drawLine(QPointF(center, y), QPointF(center, y + (base + descent).toReal()));
p->setPen(origPen);
}
p->setCompositionMode(origCompositionMode);
diff --git a/src/gui/text/windows/qwindowsfontdatabasebase.cpp b/src/gui/text/windows/qwindowsfontdatabasebase.cpp
index 47ef300cfa..0c190bc02e 100644
--- a/src/gui/text/windows/qwindowsfontdatabasebase.cpp
+++ b/src/gui/text/windows/qwindowsfontdatabasebase.cpp
@@ -604,16 +604,9 @@ void QWindowsFontDatabaseBase::createDirectWriteFactory(IDWriteFactory **factory
}
#endif // directwrite && direct2d
-static int s_defaultVerticalDPI = 96; // Native Pixels
-
int QWindowsFontDatabaseBase::defaultVerticalDPI()
{
- return s_defaultVerticalDPI;
-}
-
-void QWindowsFontDatabaseBase::setDefaultVerticalDPI(int d)
-{
- s_defaultVerticalDPI = d;
+ return 96;
}
LOGFONT QWindowsFontDatabaseBase::fontDefToLOGFONT(const QFontDef &request, const QString &faceName)
@@ -728,9 +721,9 @@ HFONT QWindowsFontDatabaseBase::systemFont()
QFont QWindowsFontDatabaseBase::systemDefaultFont()
{
// Qt 6: Obtain default GUI font (typically "Segoe UI, 9pt", see QTBUG-58610)
- NONCLIENTMETRICS ncm;
- ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
+ NONCLIENTMETRICS ncm = {};
+ ncm.cbSize = sizeof(ncm);
+ SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, defaultVerticalDPI());
const QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont);
qCDebug(lcQpaFonts) << __FUNCTION__ << systemFont;
return systemFont;
@@ -789,6 +782,13 @@ IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArra
}
#endif // directwrite && direct2d
+QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QFontDef &fontDef, void *handle)
+{
+ // This function was apparently not used before, and probably isn't now either,
+ // call the base implementation which just prints that it's not supported.
+ return QPlatformFontDatabase::fontEngine(fontDef, handle);
+}
+
QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
{
QFontEngine *fontEngine = nullptr;
diff --git a/src/gui/text/windows/qwindowsfontdatabasebase_p.h b/src/gui/text/windows/qwindowsfontdatabasebase_p.h
index 158991a796..b161721bb7 100644
--- a/src/gui/text/windows/qwindowsfontdatabasebase_p.h
+++ b/src/gui/text/windows/qwindowsfontdatabasebase_p.h
@@ -89,10 +89,10 @@ public:
QWindowsFontDatabaseBase();
~QWindowsFontDatabaseBase() override;
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override;
static int defaultVerticalDPI();
- static void setDefaultVerticalDPI(int d);
static QSharedPointer<QWindowsFontEngineData> data();
#if QT_CONFIG(directwrite)
diff --git a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
index 55aab15132..210036f080 100644
--- a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
@@ -101,7 +101,7 @@ namespace {
};
void GeometrySink::AddBeziers(const D2D1_BEZIER_SEGMENT *beziers,
- UINT bezierCount)
+ UINT bezierCount) noexcept
{
for (uint i=0; i<bezierCount; ++i) {
QPointF c1 = fromD2D1_POINT_2F(beziers[i].point1);
@@ -112,48 +112,48 @@ namespace {
}
}
- void GeometrySink::AddLines(const D2D1_POINT_2F *points, UINT pointsCount)
+ void GeometrySink::AddLines(const D2D1_POINT_2F *points, UINT pointsCount) noexcept
{
for (uint i=0; i<pointsCount; ++i)
m_path->lineTo(fromD2D1_POINT_2F(points[i]));
}
void GeometrySink::BeginFigure(D2D1_POINT_2F startPoint,
- D2D1_FIGURE_BEGIN /*figureBegin*/)
+ D2D1_FIGURE_BEGIN /*figureBegin*/) noexcept
{
m_startPoint = fromD2D1_POINT_2F(startPoint);
m_path->moveTo(m_startPoint);
}
- IFACEMETHODIMP GeometrySink::Close()
+ IFACEMETHODIMP GeometrySink::Close() noexcept
{
return E_NOTIMPL;
}
- void GeometrySink::EndFigure(D2D1_FIGURE_END figureEnd)
+ void GeometrySink::EndFigure(D2D1_FIGURE_END figureEnd) noexcept
{
if (figureEnd == D2D1_FIGURE_END_CLOSED)
m_path->closeSubpath();
}
- void GeometrySink::SetFillMode(D2D1_FILL_MODE fillMode)
+ void GeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) noexcept
{
m_path->setFillRule(fillMode == D2D1_FILL_MODE_ALTERNATE
? Qt::OddEvenFill
: Qt::WindingFill);
}
- void GeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT /*vertexFlags*/)
+ void GeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT /*vertexFlags*/) noexcept
{
/* Not implemented */
}
- IFACEMETHODIMP_(unsigned long) GeometrySink::AddRef()
+ IFACEMETHODIMP_(unsigned long) GeometrySink::AddRef() noexcept
{
return InterlockedIncrement(&m_refCount);
}
- IFACEMETHODIMP_(unsigned long) GeometrySink::Release()
+ IFACEMETHODIMP_(unsigned long) GeometrySink::Release() noexcept
{
unsigned long newCount = InterlockedDecrement(&m_refCount);
if (newCount == 0)
@@ -165,7 +165,7 @@ namespace {
return newCount;
}
- IFACEMETHODIMP GeometrySink::QueryInterface(IID const &riid, void **ppvObject)
+ IFACEMETHODIMP GeometrySink::QueryInterface(IID const &riid, void **ppvObject) noexcept
{
if (__uuidof(IDWriteGeometrySink) == riid) {
*ppvObject = this;
@@ -530,6 +530,53 @@ void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEn
}
}
+void QWindowsFontEngineDirectWrite::getUnscaledGlyph(glyph_t glyph,
+ QPainterPath *path,
+ glyph_metrics_t *metric)
+{
+ float advance = 0.0f;
+ UINT16 g = glyph;
+ DWRITE_GLYPH_OFFSET offset;
+ offset.advanceOffset = 0;
+ offset.ascenderOffset = 0;
+ GeometrySink geometrySink(path);
+ HRESULT hr = m_directWriteFontFace->GetGlyphRunOutline(m_unitsPerEm,
+ &g,
+ &advance,
+ &offset,
+ 1,
+ false,
+ false,
+ &geometrySink);
+ if (FAILED(hr)) {
+ qErrnoWarning("%s: GetGlyphRunOutline failed", __FUNCTION__);
+ return;
+ }
+
+ DWRITE_GLYPH_METRICS glyphMetrics;
+ hr = m_directWriteFontFace->GetDesignGlyphMetrics(&g, 1, &glyphMetrics);
+ if (FAILED(hr)) {
+ qErrnoWarning("%s: GetDesignGlyphMetrics failed", __FUNCTION__);
+ return;
+ }
+
+ QFixed advanceWidth = QFixed(int(glyphMetrics.advanceWidth));
+ QFixed leftSideBearing = QFixed(glyphMetrics.leftSideBearing);
+ QFixed rightSideBearing = QFixed(glyphMetrics.rightSideBearing);
+ QFixed advanceHeight = QFixed(int(glyphMetrics.advanceHeight));
+ QFixed verticalOriginY = QFixed(glyphMetrics.verticalOriginY);
+ QFixed topSideBearing = QFixed(glyphMetrics.topSideBearing);
+ QFixed bottomSideBearing = QFixed(glyphMetrics.bottomSideBearing);
+ QFixed width = advanceWidth - leftSideBearing - rightSideBearing;
+ QFixed height = advanceHeight - topSideBearing - bottomSideBearing;
+ *metric = glyph_metrics_t(leftSideBearing,
+ -verticalOriginY + topSideBearing,
+ width,
+ height,
+ advanceWidth,
+ 0);
+}
+
void QWindowsFontEngineDirectWrite::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
QPainterPath *path, QTextItem::RenderFlags flags)
{
@@ -651,6 +698,33 @@ bool QWindowsFontEngineDirectWrite::supportsHorizontalSubPixelPositions() const
return true;
}
+QFontEngine::Properties QWindowsFontEngineDirectWrite::properties() const
+{
+ IDWriteFontFace2 *directWriteFontFace2;
+ if (SUCCEEDED(m_directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace2),
+ reinterpret_cast<void **>(&directWriteFontFace2)))) {
+ DWRITE_FONT_METRICS1 metrics;
+ directWriteFontFace2->GetMetrics(&metrics);
+
+ Properties p = QFontEngine::properties();
+ p.emSquare = metrics.designUnitsPerEm;
+ p.boundingBox = QRectF(metrics.glyphBoxLeft,
+ -metrics.glyphBoxTop,
+ metrics.glyphBoxRight - metrics.glyphBoxLeft,
+ metrics.glyphBoxTop - metrics.glyphBoxBottom);
+ p.ascent = metrics.ascent;
+ p.descent = metrics.descent;
+ p.leading = metrics.lineGap;
+ p.capHeight = metrics.capHeight;
+ p.lineWidth = metrics.underlineThickness;
+
+ directWriteFontFace2->Release();
+ return p;
+ } else {
+ return QFontEngine::properties();
+ }
+}
+
QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
const QFixedPoint &subPixelPosition,
int margin,
diff --git a/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h b/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h
index 06eb5ae475..dd2b16048b 100644
--- a/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h
+++ b/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h
@@ -134,6 +134,9 @@ public:
void initializeHeightMetrics() const override;
+ Properties properties() const override;
+ void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) override;
+
private:
QImage imageForGlyph(glyph_t t,
const QFixedPoint &subPixelPosition,
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 58c377761f..6bf43c5300 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -66,6 +66,8 @@
#include "QtCore/qbuffer.h"
#include "QtCore/qlist.h"
#include "QtCore/qurl.h"
+#include "QtCore/qloggingcategory.h"
+
#include "QtNetwork/private/qauthenticator_p.h"
#include "QtNetwork/qsslconfiguration.h"
#include "QtNetwork/private/http2protocol_p.h"
@@ -83,9 +85,11 @@
#include <QtCore/private/qfactoryloader_p.h>
#if defined(Q_OS_MACOS)
+#include <QtCore/private/qcore_mac_p.h>
+
#include <CoreServices/CoreServices.h>
#include <SystemConfiguration/SystemConfiguration.h>
-#include <Security/SecKeychain.h>
+#include <Security/Security.h>
#endif
#ifdef Q_OS_WASM
#include "qnetworkreplywasmimpl_p.h"
@@ -101,6 +105,8 @@ QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QNetworkAccessFileBackendFactory, fileBackend)
+Q_LOGGING_CATEGORY(lcQnam, "qt.network.access.manager")
+
#ifdef QT_BUILD_INTERNAL
Q_GLOBAL_STATIC(QNetworkAccessDebugPipeBackendFactory, debugpipeBackend)
#endif
@@ -111,55 +117,72 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
#if defined(Q_OS_MACOS)
bool getProxyAuth(const QString& proxyHostname, const QString &scheme, QString& username, QString& password)
{
- OSStatus err;
- SecKeychainItemRef itemRef;
- bool retValue = false;
- SecProtocolType protocolType = kSecProtocolTypeAny;
- if (scheme.compare(QLatin1String("ftp"),Qt::CaseInsensitive)==0) {
- protocolType = kSecProtocolTypeFTPProxy;
- } else if (scheme.compare(QLatin1String("http"),Qt::CaseInsensitive)==0
- || scheme.compare(QLatin1String("preconnect-http"),Qt::CaseInsensitive)==0) {
- protocolType = kSecProtocolTypeHTTPProxy;
- } else if (scheme.compare(QLatin1String("https"),Qt::CaseInsensitive)==0
- || scheme.compare(QLatin1String("preconnect-https"),Qt::CaseInsensitive)==0) {
- protocolType = kSecProtocolTypeHTTPSProxy;
+ CFStringRef protocolType = nullptr;
+ if (scheme.compare(QStringLiteral("ftp"), Qt::CaseInsensitive) == 0) {
+ protocolType = kSecAttrProtocolFTPProxy;
+ } else if (scheme.compare(QStringLiteral("http"), Qt::CaseInsensitive) == 0
+ || scheme.compare(QStringLiteral("preconnect-http"), Qt::CaseInsensitive) == 0) {
+ protocolType = kSecAttrProtocolHTTPProxy;
+ } else if (scheme.compare(QStringLiteral("https"),Qt::CaseInsensitive)==0
+ || scheme.compare(QStringLiteral("preconnect-https"), Qt::CaseInsensitive) == 0) {
+ protocolType = kSecAttrProtocolHTTPSProxy;
+ } else {
+ qCWarning(lcQnam) << "Cannot query user name and password for a proxy, unnknown protocol:"
+ << scheme;
+ return false;
}
- QByteArray proxyHostnameUtf8(proxyHostname.toUtf8());
- err = SecKeychainFindInternetPassword(NULL,
- proxyHostnameUtf8.length(), proxyHostnameUtf8.constData(),
- 0,NULL,
- 0, NULL,
- 0, NULL,
- 0,
- protocolType,
- kSecAuthenticationTypeAny,
- 0, NULL,
- &itemRef);
- if (err == noErr) {
-
- SecKeychainAttribute attr;
- SecKeychainAttributeList attrList;
- UInt32 length;
- void *outData;
-
- attr.tag = kSecAccountItemAttr;
- attr.length = 0;
- attr.data = NULL;
-
- attrList.count = 1;
- attrList.attr = &attr;
-
- if (SecKeychainItemCopyContent(itemRef, NULL, &attrList, &length, &outData) == noErr) {
- username = QString::fromUtf8((const char*)attr.data, attr.length);
- password = QString::fromUtf8((const char*)outData, length);
- SecKeychainItemFreeContent(&attrList,outData);
- retValue = true;
- }
- CFRelease(itemRef);
+
+ QCFType<CFMutableDictionaryRef> query(CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0, nullptr, nullptr));
+ Q_ASSERT(query);
+
+ CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword);
+ CFDictionaryAddValue(query, kSecAttrProtocol, protocolType);
+
+ QCFType<CFStringRef> serverName; // Note the scope.
+ if (proxyHostname.size()) {
+ serverName = proxyHostname.toCFString();
+ CFDictionaryAddValue(query, kSecAttrServer, serverName);
}
- return retValue;
+
+ // This is to get the user name in the result:
+ CFDictionaryAddValue(query, kSecReturnAttributes, kCFBooleanTrue);
+ // This one to get the password:
+ CFDictionaryAddValue(query, kSecReturnData, kCFBooleanTrue);
+
+ // The default for kSecMatchLimit key is 1 (the first match only), which is fine,
+ // so don't set this value explicitly.
+
+ QCFType<CFTypeRef> replyData;
+ if (SecItemCopyMatching(query, &replyData) != errSecSuccess) {
+ qCWarning(lcQnam, "Failed to extract user name and password from the keychain.");
+ return false;
+ }
+
+ if (!replyData || CFDictionaryGetTypeID() != CFGetTypeID(replyData)) {
+ qCWarning(lcQnam, "Query returned data in unexpected format.");
+ return false;
+ }
+
+ CFDictionaryRef accountData = replyData.as<CFDictionaryRef>();
+ const void *value = CFDictionaryGetValue(accountData, kSecAttrAccount);
+ if (!value || CFGetTypeID(value) != CFStringGetTypeID()) {
+ qCWarning(lcQnam, "Cannot find user name or its format is unknown.");
+ return false;
+ }
+ username = QString::fromCFString(static_cast<CFStringRef>(value));
+
+ value = CFDictionaryGetValue(accountData, kSecValueData);
+ if (!value || CFGetTypeID(value) != CFDataGetTypeID()) {
+ qCWarning(lcQnam, "Cannot find password or its format is unknown.");
+ return false;
+ }
+ const CFDataRef passData = static_cast<const CFDataRef>(value);
+ password = QString::fromLocal8Bit(reinterpret_cast<const char *>(CFDataGetBytePtr(passData)),
+ qsizetype(CFDataGetLength(passData)));
+ return true;
}
-#endif
+#endif // Q_OS_MACOS
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index 80c0223e20..24fca0017a 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -76,7 +76,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
itself.
QNetworkReply is a sequential-access QIODevice, which means that
- once data is read from the object, it no longer kept by the
+ once data is read from the object, it is no longer kept by the
device. It is therefore the application's responsibility to keep
this data if it needs to. Whenever more data is received from the
network and processed, the readyRead() signal is emitted.
@@ -344,7 +344,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
processing. After this signal is emitted, there will be no more
updates to the reply's data or metadata.
- Unless close() or abort() have been called, the reply will be still be opened
+ Unless close() or abort() have been called, the reply will still be opened
for reading, so the data can be retrieved by calls to read() or
readAll(). In particular, if no calls to read() were made as a
result of readyRead(), a call to readAll() will retrieve the full
diff --git a/src/network/access/qnetworkreplyfileimpl.cpp b/src/network/access/qnetworkreplyfileimpl.cpp
index b6be93147a..6e69b4c4d3 100644
--- a/src/network/access/qnetworkreplyfileimpl.cpp
+++ b/src/network/access/qnetworkreplyfileimpl.cpp
@@ -89,9 +89,10 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, con
// we handle only local files
QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString());
setError(QNetworkReply::ProtocolInvalidOperationError, msg);
+ setFinished(true); // We're finished, will emit finished() after ctor is done.
QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolInvalidOperationError));
- fileOpenFinished(false);
+ QMetaObject::invokeMethod(this, [this](){ fileOpenFinished(false); }, Qt::QueuedConnection);
return;
}
#endif
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index fc1cb2e9ee..e800176cea 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -854,7 +854,7 @@ bool QHostAddress::isEqual(const QHostAddress &other, ConversionMode mode) const
return memcmp(&d->a6, &other.d->a6, sizeof(Q_IPV6ADDR)) == 0;
case QHostAddress::AnyIPProtocol:
return (mode & QHostAddress::ConvertUnspecifiedAddress)
- && (other.d->a6_64.c[0] == 0) && (other.d->a6_64.c[1] == 0);
+ && (d->a6_64.c[0] == 0) && (d->a6_64.c[1] == 0);
case QHostAddress::UnknownNetworkLayerProtocol:
return false;
}
diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h
index 3d9ce96cb3..bdfc37ac70 100644
--- a/src/network/socket/qabstractsocketengine_p.h
+++ b/src/network/socket/qabstractsocketengine_p.h
@@ -134,7 +134,7 @@ public:
virtual bool connectToHostByName(const QString &name, quint16 port) = 0;
virtual bool bind(const QHostAddress &address, quint16 port) = 0;
virtual bool listen() = 0;
- virtual int accept() = 0;
+ virtual qintptr accept() = 0;
virtual void close() = 0;
virtual qint64 bytesAvailable() const = 0;
diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp
index 6170f114f5..cea0b6f291 100644
--- a/src/network/socket/qhttpsocketengine.cpp
+++ b/src/network/socket/qhttpsocketengine.cpp
@@ -199,7 +199,7 @@ bool QHttpSocketEngine::listen()
return false;
}
-int QHttpSocketEngine::accept()
+qintptr QHttpSocketEngine::accept()
{
qWarning("Operation is not supported");
setError(QAbstractSocket::UnsupportedSocketOperationError,
diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h
index 0c2c450c81..203beb7339 100644
--- a/src/network/socket/qhttpsocketengine_p.h
+++ b/src/network/socket/qhttpsocketengine_p.h
@@ -96,7 +96,7 @@ public:
bool connectToHostByName(const QString &name, quint16 port) override;
bool bind(const QHostAddress &address, quint16 port) override;
bool listen() override;
- int accept() override;
+ qintptr accept() override;
void close() override;
qint64 bytesAvailable() const override;
diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp
index 302b714cb4..7bc500cf98 100644
--- a/src/network/socket/qnativesocketengine.cpp
+++ b/src/network/socket/qnativesocketengine.cpp
@@ -715,7 +715,7 @@ bool QNativeSocketEngine::listen()
\sa bind(), listen()
*/
-int QNativeSocketEngine::accept()
+qintptr QNativeSocketEngine::accept()
{
Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::accept(), -1);
@@ -1291,7 +1291,7 @@ bool QReadNotifier::event(QEvent *e)
class QWriteNotifier : public QSocketNotifier
{
public:
- QWriteNotifier(int fd, QNativeSocketEngine *parent)
+ QWriteNotifier(qintptr fd, QNativeSocketEngine *parent)
: QSocketNotifier(fd, QSocketNotifier::Write, parent) { engine = parent; }
protected:
@@ -1315,7 +1315,7 @@ bool QWriteNotifier::event(QEvent *e)
class QExceptionNotifier : public QSocketNotifier
{
public:
- QExceptionNotifier(int fd, QNativeSocketEngine *parent)
+ QExceptionNotifier(qintptr fd, QNativeSocketEngine *parent)
: QSocketNotifier(fd, QSocketNotifier::Exception, parent) { engine = parent; }
protected:
diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h
index e5f0701d14..0e24ce6cf2 100644
--- a/src/network/socket/qnativesocketengine_p.h
+++ b/src/network/socket/qnativesocketengine_p.h
@@ -139,7 +139,7 @@ public:
bool connectToHostByName(const QString &name, quint16 port) override;
bool bind(const QHostAddress &address, quint16 port) override;
bool listen() override;
- int accept() override;
+ qintptr accept() override;
void close() override;
qint64 bytesAvailable() const override;
@@ -261,7 +261,7 @@ public:
bool nativeConnect(const QHostAddress &address, quint16 port);
bool nativeBind(const QHostAddress &address, quint16 port);
bool nativeListen(int backlog);
- int nativeAccept();
+ qintptr nativeAccept();
#ifndef QT_NO_NETWORKINTERFACE
bool nativeJoinMulticastGroup(const QHostAddress &groupAddress,
const QNetworkInterface &iface);
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 61fa8edbe9..62205b5886 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -592,7 +592,7 @@ bool QNativeSocketEnginePrivate::nativeListen(int backlog)
return true;
}
-int QNativeSocketEnginePrivate::nativeAccept()
+qintptr QNativeSocketEnginePrivate::nativeAccept()
{
int acceptedDescriptor = qt_safe_accept(socketDescriptor, nullptr, nullptr);
if (acceptedDescriptor == -1) {
@@ -638,7 +638,7 @@ int QNativeSocketEnginePrivate::nativeAccept()
}
}
- return acceptedDescriptor;
+ return qintptr(acceptedDescriptor);
}
#ifndef QT_NO_NETWORKINTERFACE
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 7b5e674fbb..29c6f6b481 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -836,10 +836,10 @@ bool QNativeSocketEnginePrivate::nativeListen(int backlog)
return true;
}
-int QNativeSocketEnginePrivate::nativeAccept()
+qintptr QNativeSocketEnginePrivate::nativeAccept()
{
- int acceptedDescriptor = WSAAccept(socketDescriptor, 0,0,0,0);
- if (acceptedDescriptor == -1) {
+ SOCKET acceptedDescriptor = WSAAccept(socketDescriptor, 0,0,0,0);
+ if (acceptedDescriptor == INVALID_SOCKET) {
int err = WSAGetLastError();
switch (err) {
case WSAEACCES:
@@ -873,7 +873,7 @@ int QNativeSocketEnginePrivate::nativeAccept()
setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
break;
}
- } else if (acceptedDescriptor != -1 && QAbstractEventDispatcher::instance()) {
+ } else if (acceptedDescriptor != INVALID_SOCKET && QAbstractEventDispatcher::instance()) {
// Because of WSAAsyncSelect() WSAAccept returns a non blocking socket
// with the same attributes as the listening socket including the current
// WSAAsyncSelect(). To be able to change the socket to blocking mode the
@@ -883,9 +883,9 @@ int QNativeSocketEnginePrivate::nativeAccept()
n.setEnabled(false);
}
#if defined (QNATIVESOCKETENGINE_DEBUG)
- qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor);
+ qDebug("QNativeSocketEnginePrivate::nativeAccept() == %lld", qint64(acceptedDescriptor));
#endif
- return acceptedDescriptor;
+ return qintptr(acceptedDescriptor);
}
static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d,
diff --git a/src/network/socket/qsctpserver.cpp b/src/network/socket/qsctpserver.cpp
index 2aa694b3fd..f291cdabc8 100644
--- a/src/network/socket/qsctpserver.cpp
+++ b/src/network/socket/qsctpserver.cpp
@@ -82,7 +82,7 @@
between endpoints. Call nextPendingDatagramConnection() to accept
the pending datagram-mode connection as a connected QSctpSocket.
- \note This feature is not supported on the Windows platform.
+ \note This class is not supported on the Windows platform.
\sa QTcpServer, QSctpSocket, QAbstractSocket
*/
diff --git a/src/network/socket/qsctpsocket.cpp b/src/network/socket/qsctpsocket.cpp
index fe76f64c42..9a28e5bbe1 100644
--- a/src/network/socket/qsctpsocket.cpp
+++ b/src/network/socket/qsctpsocket.cpp
@@ -110,7 +110,7 @@
etc. is allowed in datagram mode with the same limitations as in
continuous byte stream mode.
- \note This feature is not supported on the Windows platform.
+ \note This class is not supported on the Windows platform.
\sa QSctpServer, QTcpSocket, QAbstractSocket
*/
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index aa9baf01bb..d75934ab8a 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -1412,7 +1412,7 @@ bool QSocks5SocketEngine::listen()
return false;
}
-int QSocks5SocketEngine::accept()
+qintptr QSocks5SocketEngine::accept()
{
Q_D(QSocks5SocketEngine);
// check we are listing ---
diff --git a/src/network/socket/qsocks5socketengine_p.h b/src/network/socket/qsocks5socketengine_p.h
index 77b461b944..7bfff80455 100644
--- a/src/network/socket/qsocks5socketengine_p.h
+++ b/src/network/socket/qsocks5socketengine_p.h
@@ -82,7 +82,7 @@ public:
bool connectToHostByName(const QString &name, quint16 port) override;
bool bind(const QHostAddress &address, quint16 port) override;
bool listen() override;
- int accept() override;
+ qintptr accept() override;
void close() override;
qint64 bytesAvailable() const override;
diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp
index a404350d98..6a662c8867 100644
--- a/src/network/socket/qtcpserver.cpp
+++ b/src/network/socket/qtcpserver.cpp
@@ -205,7 +205,7 @@ void QTcpServerPrivate::readNotification()
return;
}
- int descriptor = socketEngine->accept();
+ qintptr descriptor = socketEngine->accept();
if (descriptor == -1) {
if (socketEngine->error() != QAbstractSocket::TemporaryError) {
q->pauseAccepting();
diff --git a/src/opengl/qopengltextureglyphcache.cpp b/src/opengl/qopengltextureglyphcache.cpp
index 6c8971fddb..085a814601 100644
--- a/src/opengl/qopengltextureglyphcache.cpp
+++ b/src/opengl/qopengltextureglyphcache.cpp
@@ -443,7 +443,10 @@ void QOpenGLTextureGlyphCache::fillTexture(const Coord &c,
int QOpenGLTextureGlyphCache::glyphPadding() const
{
- return 1;
+ if (m_format == QFontEngine::Format_Mono)
+ return 8;
+ else
+ return 1;
}
int QOpenGLTextureGlyphCache::maxTextureWidth() const
diff --git a/src/plugins/platforms/android/androidjniclipboard.cpp b/src/plugins/platforms/android/androidjniclipboard.cpp
index 6178edd675..60f31c69da 100644
--- a/src/plugins/platforms/android/androidjniclipboard.cpp
+++ b/src/plugins/platforms/android/androidjniclipboard.cpp
@@ -71,18 +71,6 @@ namespace QtAndroidClipboard
void setClipboardMimeData(QMimeData *data)
{
clearClipboardData();
- if (data->hasText()) {
- QJniObject::callStaticMethod<void>(applicationClass(),
- "setClipboardText", "(Ljava/lang/String;)V",
- QJniObject::fromString(data->text()).object());
- }
- if (data->hasHtml()) {
- QJniObject::callStaticMethod<void>(applicationClass(),
- "setClipboardHtml",
- "(Ljava/lang/String;Ljava/lang/String;)V",
- QJniObject::fromString(data->text()).object(),
- QJniObject::fromString(data->html()).object());
- }
if (data->hasUrls()) {
QList<QUrl> urls = data->urls();
for (const auto &u : qAsConst(urls)) {
@@ -91,6 +79,16 @@ namespace QtAndroidClipboard
"(Ljava/lang/String;)V",
QJniObject::fromString(u.toEncoded()).object());
}
+ } else if (data->hasText()) { // hasText || hasUrls, so the order matter here.
+ QJniObject::callStaticMethod<void>(applicationClass(),
+ "setClipboardText", "(Ljava/lang/String;)V",
+ QJniObject::fromString(data->text()).object());
+ } else if (data->hasHtml()) {
+ QJniObject::callStaticMethod<void>(applicationClass(),
+ "setClipboardHtml",
+ "(Ljava/lang/String;Ljava/lang/String;)V",
+ QJniObject::fromString(data->text()).object(),
+ QJniObject::fromString(data->html()).object());
}
}
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 8136ecd769..6b8b30c310 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -667,24 +667,27 @@ static void setDisplayMetrics(JNIEnv * /*env*/, jclass /*clazz*/, jint screenWid
jint availableHeightPixels, jdouble xdpi, jdouble ydpi,
jdouble scaledDensity, jdouble density, jfloat refreshRate)
{
+ Q_UNUSED(availableLeftPixels)
+ Q_UNUSED(availableTopPixels)
+
m_availableWidthPixels = availableWidthPixels;
m_availableHeightPixels = availableHeightPixels;
m_scaledDensity = scaledDensity;
m_density = density;
+ const QSize screenSize(screenWidthPixels, screenHeightPixels);
+ // available geometry always starts from top left
+ const QRect availableGeometry(0, 0, availableWidthPixels, availableHeightPixels);
+ const QSize physicalSize(qRound(double(screenWidthPixels) / xdpi * 25.4),
+ qRound(double(screenHeightPixels) / ydpi * 25.4));
+
QMutexLocker lock(&m_platformMutex);
if (!m_androidPlatformIntegration) {
QAndroidPlatformIntegration::setDefaultDisplayMetrics(
- availableLeftPixels, availableTopPixels, availableWidthPixels,
- availableHeightPixels, qRound(double(screenWidthPixels) / xdpi * 25.4),
- qRound(double(screenHeightPixels) / ydpi * 25.4), screenWidthPixels,
- screenHeightPixels);
+ availableGeometry.left(), availableGeometry.top(), availableGeometry.width(),
+ availableGeometry.height(), physicalSize.width(), physicalSize.height(),
+ screenSize.width(), screenSize.height());
} else {
- const QSize physicalSize(qRound(double(screenWidthPixels) / xdpi * 25.4),
- qRound(double(screenHeightPixels) / ydpi * 25.4));
- const QSize screenSize(screenWidthPixels, screenHeightPixels);
- const QRect availableGeometry(availableLeftPixels, availableTopPixels,
- availableWidthPixels, availableHeightPixels);
m_androidPlatformIntegration->setScreenSizeParameters(physicalSize, screenSize,
availableGeometry);
m_androidPlatformIntegration->setRefreshRate(refreshRate);
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp
index 24111fc611..9568801bcf 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp
@@ -466,7 +466,7 @@ QStringList QAndroidPlatformIntegration::themeNames() const
QPlatformTheme *QAndroidPlatformIntegration::createPlatformTheme(const QString &name) const
{
if (androidThemeName == name)
- return new QAndroidPlatformTheme(m_androidPlatformNativeInterface);
+ return QAndroidPlatformTheme::instance(m_androidPlatformNativeInterface);
return 0;
}
@@ -529,6 +529,9 @@ void QAndroidPlatformIntegration::setAppearance(QPlatformTheme::Appearance newAp
if (m_appearance == newAppearance)
return;
m_appearance = newAppearance;
+
+ QMetaObject::invokeMethod(qGuiApp,
+ [] () { QAndroidPlatformTheme::instance()->updateAppearance();});
}
void QAndroidPlatformIntegration::setScreenSizeParameters(const QSize &physicalSize,
diff --git a/src/plugins/platforms/android/qandroidplatformservices.cpp b/src/plugins/platforms/android/qandroidplatformservices.cpp
index 8c2af5fff4..30af140837 100644
--- a/src/plugins/platforms/android/qandroidplatformservices.cpp
+++ b/src/plugins/platforms/android/qandroidplatformservices.cpp
@@ -81,12 +81,13 @@ bool QAndroidPlatformServices::openUrl(const QUrl &theUrl)
// if the file is local, we need to pass the MIME type, otherwise Android
// does not start an Intent to view this file
QLatin1String fileScheme("file");
- if ((url.scheme().isEmpty() || url.scheme() == fileScheme) && QFile::exists(url.path())) {
- // a real URL including the scheme is needed, else the Intent can not be started
+
+ // a real URL including the scheme is needed, else the Intent can not be started
+ if (url.scheme().isEmpty())
url.setScheme(fileScheme);
- QMimeDatabase mimeDb;
- mime = mimeDb.mimeTypeForUrl(url).name();
- }
+
+ if (url.scheme() == fileScheme)
+ mime = QMimeDatabase().mimeTypeForUrl(url).name();
using namespace QNativeInterface;
QJniObject urlString = QJniObject::fromString(url.toString());
diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp
index e51d6a099c..4958800954 100644
--- a/src/plugins/platforms/android/qandroidplatformtheme.cpp
+++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp
@@ -192,6 +192,9 @@ QJsonObject AndroidStyle::loadStyleData()
if (!stylePath.isEmpty() && !stylePath.endsWith(slashChar))
stylePath += slashChar;
+ if (QAndroidPlatformIntegration::appearance() == QPlatformTheme::Appearance::Dark)
+ stylePath += QLatin1String("darkUiMode/");
+
Q_ASSERT(!stylePath.isEmpty());
QString androidTheme = QLatin1String(qgetenv("QT_ANDROID_THEME"));
@@ -219,13 +222,22 @@ QJsonObject AndroidStyle::loadStyleData()
return document.object();
}
-static std::shared_ptr<AndroidStyle> loadAndroidStyle(QPalette *defaultPalette)
+static void loadAndroidStyle(QPalette *defaultPalette, std::shared_ptr<AndroidStyle> &style)
{
double pixelDensity = QHighDpiScaling::isActive() ? QtAndroid::pixelDensity() : 1.0;
- std::shared_ptr<AndroidStyle> style = std::make_shared<AndroidStyle>();
+ if (style) {
+ style->m_standardPalette = QPalette();
+ style->m_palettes.clear();
+ style->m_fonts.clear();
+ style->m_QWidgetsFonts.clear();
+ } else {
+ style = std::make_shared<AndroidStyle>();
+ }
+
style->m_styleData = AndroidStyle::loadStyleData();
+
if (style->m_styleData.isEmpty())
- return std::shared_ptr<AndroidStyle>();
+ return;
{
QFont font(QLatin1String("Droid Sans Mono"), 14.0 * 100 / 72);
@@ -327,11 +339,44 @@ static std::shared_ptr<AndroidStyle> loadAndroidStyle(QPalette *defaultPalette)
// Extract palette information
}
}
- return style;
+}
+
+QAndroidPlatformTheme *QAndroidPlatformTheme::m_instance = nullptr;
+
+QAndroidPlatformTheme *QAndroidPlatformTheme::instance(
+ QAndroidPlatformNativeInterface *androidPlatformNativeInterface)
+{
+ if (androidPlatformNativeInterface && !m_instance) {
+ m_instance = new QAndroidPlatformTheme(androidPlatformNativeInterface);
+ }
+ return m_instance;
}
QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *androidPlatformNativeInterface)
{
+ updateStyle();
+
+ androidPlatformNativeInterface->m_androidStyle = m_androidStyleData;
+
+ // default in case the style has not set a font
+ m_systemFont = QFont(QLatin1String("Roboto"), 14.0 * 100 / 72);
+}
+
+QAndroidPlatformTheme::~QAndroidPlatformTheme()
+{
+ m_instance = nullptr;
+}
+
+void QAndroidPlatformTheme::updateAppearance()
+{
+ updateStyle();
+ for (QWindow *w : QGuiApplication::allWindows())
+ QWindowSystemInterface::handleThemeChange(w);
+}
+
+void QAndroidPlatformTheme::updateStyle()
+{
+ QColor windowText = Qt::black;
QColor background(229, 229, 229);
QColor light = background.lighter(150);
QColor mid(background.darker(130));
@@ -348,7 +393,27 @@ QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *an
QColor highlight(148, 210, 231);
QColor disabledShadow = shadow.lighter(150);
- m_defaultPalette = QPalette(Qt::black,background,light,dark,mid,text,base);
+ if (appearance() == QPlatformTheme::Appearance::Dark) {
+ // Colors were prepared based on Theme.DeviceDefault.DayNight
+ windowText = QColor(250, 250, 250);
+ background = QColor(48, 48, 48);
+ light = background.darker(150);
+ mid = background.lighter(130);
+ midLight = mid.darker(110);
+ base = background;
+ disabledBase = background;
+ dark = background.darker(150);
+ darkDisabled = dark.darker(110);
+ text = QColor(250, 250, 250);
+ highlightedText = QColor(250, 250, 250);
+ disabledText = QColor(96, 96, 96);
+ button = QColor(48, 48, 48);
+ shadow = QColor(32, 32, 32);
+ highlight = QColor(102, 178, 204);
+ disabledShadow = shadow.darker(150);
+ }
+
+ m_defaultPalette = QPalette(windowText,background,light,dark,mid,text,base);
m_defaultPalette.setBrush(QPalette::Midlight, midLight);
m_defaultPalette.setBrush(QPalette::Button, button);
m_defaultPalette.setBrush(QPalette::Shadow, shadow);
@@ -364,12 +429,8 @@ QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *an
m_defaultPalette.setBrush(QPalette::Active, QPalette::Highlight, highlight);
m_defaultPalette.setBrush(QPalette::Inactive, QPalette::Highlight, highlight);
m_defaultPalette.setBrush(QPalette::Disabled, QPalette::Highlight, highlight.lighter(150));
- m_androidStyleData = loadAndroidStyle(&m_defaultPalette);
- QGuiApplication::setPalette(m_defaultPalette);
- androidPlatformNativeInterface->m_androidStyle = m_androidStyleData;
- // default in case the style has not set a font
- m_systemFont = QFont(QLatin1String("Roboto"), 14.0 * 100 / 72); // keep default size the same after changing from 100 dpi to 72 dpi
+ loadAndroidStyle(&m_defaultPalette, m_androidStyleData);
}
QPlatformMenuBar *QAndroidPlatformTheme::createPlatformMenuBar() const
diff --git a/src/plugins/platforms/android/qandroidplatformtheme.h b/src/plugins/platforms/android/qandroidplatformtheme.h
index 6084631e3d..5dda790cca 100644
--- a/src/plugins/platforms/android/qandroidplatformtheme.h
+++ b/src/plugins/platforms/android/qandroidplatformtheme.h
@@ -64,7 +64,9 @@ class QAndroidPlatformNativeInterface;
class QAndroidPlatformTheme: public QPlatformTheme
{
public:
- QAndroidPlatformTheme(QAndroidPlatformNativeInterface * androidPlatformNativeInterface);
+ ~QAndroidPlatformTheme();
+ void updateAppearance();
+ void updateStyle();
QPlatformMenuBar *createPlatformMenuBar() const override;
QPlatformMenu *createPlatformMenu() const override;
QPlatformMenuItem *createPlatformMenuItem() const override;
@@ -77,8 +79,12 @@ public:
bool usePlatformNativeDialog(DialogType type) const override;
QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override;
+ static QAndroidPlatformTheme *instance(
+ QAndroidPlatformNativeInterface * androidPlatformNativeInterface = nullptr);
private:
+ QAndroidPlatformTheme(QAndroidPlatformNativeInterface * androidPlatformNativeInterface);
+ static QAndroidPlatformTheme * m_instance;
std::shared_ptr<AndroidStyle> m_androidStyleData;
QPalette m_defaultPalette;
QFont m_systemFont;
diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
index b21b7c2cc9..46526088fe 100644
--- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
@@ -218,7 +218,17 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
mDialogIsExecuting = false;
mResultSet = false;
mClosingDueToKnownButton = false;
- [mColorPanel makeKeyAndOrderFront:mColorPanel];
+ // Make this an asynchronous call, so the panel is made key only
+ // in the next event loop run. This is to make sure that by
+ // the time the modal loop is run in runModalForWindow below,
+ // which internally also sets the panel to key window,
+ // the panel is not yet key, and the NSApp still has the right
+ // reference to the _previousKeyWindow. Otherwise both NSApp.key
+ // and NSApp._previousKeyWindow would wrongly point to the panel,
+ // loosing any reference to the window that was key before.
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [mColorPanel makeKeyAndOrderFront:mColorPanel];
+ });
}
- (BOOL)runApplicationModalPanel
diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
index 355d658242..91f24e2d5f 100644
--- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
@@ -202,7 +202,17 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
{
mDialogIsExecuting = false;
mResultSet = false;
- [mFontPanel makeKeyAndOrderFront:mFontPanel];
+ // Make this an asynchronous call, so the panel is made key only
+ // in the next event loop run. This is to make sure that by
+ // the time the modal loop is run in runModalForWindow below,
+ // which internally also sets the panel to key window,
+ // the panel is not yet key, and the NSApp still has the right
+ // reference to the _previousKeyWindow. Otherwise both NSApp.key
+ // and NSApp._previousKeyWindow would wrongly point to the panel,
+ // loosing any reference to the window that was key before.
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [mFontPanel makeKeyAndOrderFront:mFontPanel];
+ });
}
- (BOOL)runApplicationModalPanel
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 7a3ab5fd6f..548692a5bb 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -349,7 +349,7 @@ QSendSuperHelper<Args...> qt_objcDynamicSuperHelper(id receiver, SEL selector, A
// -------------------------------------------------------------------------
-struct InputMethodQueryResult : public QHash<Qt::InputMethodQuery, QVariant>
+struct InputMethodQueryResult : public QHash<int, QVariant>
{
operator bool() { return !isEmpty(); }
};
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index a6804accde..7a925081a7 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -486,6 +486,12 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const
return QVariant(bool([[NSApplication sharedApplication] presentationOptions] & NSApplicationPresentationFullScreen));
case QPlatformTheme::InteractiveResizeAcrossScreens:
return !NSScreen.screensHaveSeparateSpaces;
+ case QPlatformTheme::MouseDoubleClickInterval:
+ return NSEvent.doubleClickInterval * 1000;
+ case QPlatformTheme::KeyboardInputInterval:
+ return NSEvent.keyRepeatDelay * 1000;
+ case QPlatformTheme::KeyboardAutoRepeatRate:
+ return 1.0 / NSEvent.keyRepeatInterval;
default:
break;
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 8077c6707c..bf6fa90e88 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -731,9 +731,10 @@ void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState)
switch (currentState) {
case Qt::WindowMinimized:
[nsWindow deminiaturize:sender];
- Q_ASSERT_X(windowState() != Qt::WindowMinimized, "QCocoaWindow",
- "[NSWindow deminiaturize:] is synchronous");
- break;
+ // Deminiaturizing is not synchronous, so we need to wait for the
+ // NSWindowDidMiniaturizeNotification before continuing to apply
+ // the new state.
+ return;
case Qt::WindowFullScreen: {
toggleFullScreen();
// Exiting fullscreen is not synchronous, so we need to wait for the
@@ -904,7 +905,15 @@ void QCocoaWindow::windowDidDeminiaturize()
if (!isContentView())
return;
+ Qt::WindowState requestedState = window()->windowState();
+
handleWindowStateChanged();
+
+ if (requestedState != windowState() && requestedState != Qt::WindowMinimized) {
+ // We were only going out of minimized as an intermediate step before
+ // progressing into the final step, so re-sync the desired state.
+ applyWindowState(requestedState);
+ }
}
void QCocoaWindow::handleWindowStateChanged(HandleFlags flags)
diff --git a/src/plugins/platforms/cocoa/qnsview_keys.mm b/src/plugins/platforms/cocoa/qnsview_keys.mm
index 307d846b1d..62e64b0cef 100644
--- a/src/plugins/platforms/cocoa/qnsview_keys.mm
+++ b/src/plugins/platforms/cocoa/qnsview_keys.mm
@@ -249,9 +249,16 @@ KeyEvent::KeyEvent(NSEvent *nsevent)
default: break; // Must be manually set
}
- if (nsevent.type == NSEventTypeKeyDown || nsevent.type == NSEventTypeKeyUp) {
+ switch (nsevent.type) {
+ case NSEventTypeKeyDown:
+ case NSEventTypeKeyUp:
+ case NSEventTypeFlagsChanged:
nativeVirtualKey = nsevent.keyCode;
+ default:
+ break;
+ }
+ if (nsevent.type == NSEventTypeKeyDown || nsevent.type == NSEventTypeKeyUp) {
NSString *charactersIgnoringModifiers = nsevent.charactersIgnoringModifiers;
NSString *characters = nsevent.characters;
diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm
index 228773d8ec..a35f8cf22a 100644
--- a/src/plugins/platforms/cocoa/qnswindow.mm
+++ b/src/plugins/platforms/cocoa/qnswindow.mm
@@ -328,8 +328,13 @@ OSStatus CGSClearWindowTags(const CGSConnectionID, const CGSWindowID, int *, int
// we assume that if you have translucent content, without a
// frame then you intend to do all background drawing yourself.
const QWindow *window = m_platformWindow ? m_platformWindow->window() : nullptr;
- if (!self.opaque && window && window->flags().testFlag(Qt::FramelessWindowHint))
- return [NSColor clearColor];
+ if (!self.opaque && window) {
+ // Qt::Popup also requires clearColor - in qmacstyle
+ // we fill background using a special path with rounded corners.
+ if (window->flags().testFlag(Qt::FramelessWindowHint)
+ || (window->flags() & Qt::WindowType_Mask) == Qt::Popup)
+ return [NSColor clearColor];
+ }
// This still allows you to have translucent content with a frame,
// where the system background (or color set via NSWindow) will
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
index b5b7811b79..a98ed0b812 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
@@ -83,7 +83,13 @@ bool QEglFSKmsGbmDevice::open()
setFd(fd);
- m_eventReader.create(this);
+ if (usesEventReader()) {
+ qCDebug(qLcEglfsKmsDebug, "Using dedicated drm event reading thread");
+ m_eventReader.create(this);
+ } else {
+ qCDebug(qLcEglfsKmsDebug, "Not using dedicated drm event reading thread; "
+ "threaded multi-screen setups may experience problems");
+ }
return true;
}
@@ -92,7 +98,8 @@ void QEglFSKmsGbmDevice::close()
{
// Note: screens are gone at this stage.
- m_eventReader.destroy();
+ if (usesEventReader())
+ m_eventReader.destroy();
if (m_gbm_device) {
gbm_device_destroy(m_gbm_device);
@@ -174,4 +181,10 @@ void QEglFSKmsGbmDevice::registerScreen(QPlatformScreen *screen,
m_globalCursor->reevaluateVisibilityForScreens();
}
+bool QEglFSKmsGbmDevice::usesEventReader() const
+{
+ static const bool eventReaderThreadDisabled = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_NO_EVENT_READER_THREAD");
+ return !eventReaderThreadDisabled;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h
index bb67d800ee..d7bd1f613c 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h
@@ -55,6 +55,7 @@
#include "qeglfskmsgbmcursor_p.h"
#include <private/qeglfskmsdevice_p.h>
+#include <private/qeglfskmseventreader_p.h>
#include <gbm.h>
@@ -87,11 +88,14 @@ public:
const QPoint &virtualPos,
const QList<QPlatformScreen *> &virtualSiblings) override;
+ bool usesEventReader() const;
+ QEglFSKmsEventReader *eventReader() { return &m_eventReader; }
+
private:
Q_DISABLE_COPY(QEglFSKmsGbmDevice)
gbm_device *m_gbm_device;
-
+ QEglFSKmsEventReader m_eventReader;
QEglFSKmsGbmCursor *m_globalCursor;
};
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
index 301aaf15bf..ba9b35f36f 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
@@ -56,6 +56,8 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+QMutex QEglFSKmsGbmScreen::m_nonThreadedFlipMutex;
+
static inline uint32_t drmFormatToGbmFormat(uint32_t drmFormat)
{
Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888);
@@ -207,8 +209,10 @@ void QEglFSKmsGbmScreen::initCloning(QPlatformScreen *screenThisScreenClones,
qWarning("QEglFSKmsGbmScreen %s cannot be clone source and destination at the same time", qPrintable(name()));
return;
}
- if (clonesAnother)
+ if (clonesAnother) {
m_cloneSource = static_cast<QEglFSKmsGbmScreen *>(screenThisScreenClones);
+ qCDebug(qLcEglfsKmsDebug, "Screen %s clones %s", qPrintable(name()), qPrintable(m_cloneSource->name()));
+ }
// clone sources need to know their additional destinations
for (QPlatformScreen *s : screensCloningThisScreen) {
@@ -263,6 +267,31 @@ void QEglFSKmsGbmScreen::ensureModeSet(uint32_t fb)
}
}
+void QEglFSKmsGbmScreen::nonThreadedPageFlipHandler(int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *user_data)
+{
+ // note that with cloning involved this callback is called also for screens that clone another one
+ Q_UNUSED(fd);
+ Q_UNUSED(sequence);
+ Q_UNUSED(tv_sec);
+ Q_UNUSED(tv_usec);
+ QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(user_data);
+ screen->flipFinished();
+}
+
+void QEglFSKmsGbmScreen::waitForFlipWithEventReader(QEglFSKmsGbmScreen *screen)
+{
+ m_flipMutex.lock();
+ QEglFSKmsGbmDevice *dev = static_cast<QEglFSKmsGbmDevice *>(device());
+ dev->eventReader()->startWaitFlip(screen, &m_flipMutex, &m_flipCond);
+ m_flipCond.wait(&m_flipMutex);
+ m_flipMutex.unlock();
+ screen->flipFinished();
+}
+
void QEglFSKmsGbmScreen::waitForFlip()
{
if (m_headless || m_cloneSource)
@@ -272,18 +301,69 @@ void QEglFSKmsGbmScreen::waitForFlip()
if (!m_gbm_bo_next)
return;
- m_flipMutex.lock();
- device()->eventReader()->startWaitFlip(this, &m_flipMutex, &m_flipCond);
- m_flipCond.wait(&m_flipMutex);
- m_flipMutex.unlock();
-
- flipFinished();
+ QEglFSKmsGbmDevice *dev = static_cast<QEglFSKmsGbmDevice *>(device());
+ if (dev->usesEventReader()) {
+ waitForFlipWithEventReader(this);
+ // Now, unlike on the other code path, we need to ensure the
+ // flips have completed for the screens that just scan out
+ // this one's content, because the eventReader's wait is
+ // per-output.
+ for (CloneDestination &d : m_cloneDests) {
+ if (d.screen != this)
+ waitForFlipWithEventReader(d.screen);
+ }
+ } else {
+ QMutexLocker lock(&m_nonThreadedFlipMutex);
+ while (m_gbm_bo_next) {
+ drmEventContext drmEvent;
+ memset(&drmEvent, 0, sizeof(drmEvent));
+ drmEvent.version = 2;
+ drmEvent.vblank_handler = nullptr;
+ drmEvent.page_flip_handler = nonThreadedPageFlipHandler;
+ drmHandleEvent(device()->fd(), &drmEvent);
+ }
+ }
#if QT_CONFIG(drm_atomic)
device()->threadLocalAtomicReset();
#endif
}
+#if QT_CONFIG(drm_atomic)
+static void addAtomicFlip(drmModeAtomicReq *request, const QKmsOutput &output, uint32_t fb)
+{
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->framebufferPropertyId, fb);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->crtcPropertyId, output.crtc_id);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->srcwidthPropertyId, output.size.width() << 16);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->srcXPropertyId, 0);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->srcYPropertyId, 0);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->srcheightPropertyId, output.size.height() << 16);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->crtcXPropertyId, 0);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->crtcYPropertyId, 0);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->crtcwidthPropertyId, output.modes[output.mode].hdisplay);
+
+ drmModeAtomicAddProperty(request, output.eglfs_plane->id,
+ output.eglfs_plane->crtcheightPropertyId, output.modes[output.mode].vdisplay);
+}
+#endif
+
void QEglFSKmsGbmScreen::flip()
{
// For headless screen just return silently. It is not necessarily an error
@@ -303,14 +383,14 @@ void QEglFSKmsGbmScreen::flip()
m_gbm_bo_next = gbm_surface_lock_front_buffer(m_gbm_surface);
if (!m_gbm_bo_next) {
- qWarning("Could not lock GBM surface front buffer!");
+ qWarning("Could not lock GBM surface front buffer for screen %s", qPrintable(name()));
return;
}
FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next);
ensureModeSet(fb->fb);
- QKmsOutput &op(output());
+ const QKmsOutput &thisOutput(output());
const int fd = device()->fd();
m_flipPending = true;
@@ -318,35 +398,25 @@ void QEglFSKmsGbmScreen::flip()
#if QT_CONFIG(drm_atomic)
drmModeAtomicReq *request = device()->threadLocalAtomicRequest();
if (request) {
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->framebufferPropertyId, fb->fb);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcPropertyId, op.crtc_id);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcwidthPropertyId,
- op.size.width() << 16);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcXPropertyId, 0);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcYPropertyId, 0);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcheightPropertyId,
- op.size.height() << 16);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcXPropertyId, 0);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcYPropertyId, 0);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcwidthPropertyId,
- m_output.modes[m_output.mode].hdisplay);
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcheightPropertyId,
- m_output.modes[m_output.mode].vdisplay);
-
+ addAtomicFlip(request, thisOutput, fb->fb);
static int zpos = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_ZPOS");
- if (zpos)
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->zposPropertyId, zpos);
+ if (zpos) {
+ drmModeAtomicAddProperty(request, thisOutput.eglfs_plane->id,
+ thisOutput.eglfs_plane->zposPropertyId, zpos);
+ }
static uint blendOp = uint(qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_BLEND_OP"));
- if (blendOp)
- drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->blendOpPropertyId, blendOp);
+ if (blendOp) {
+ drmModeAtomicAddProperty(request, thisOutput.eglfs_plane->id,
+ thisOutput.eglfs_plane->blendOpPropertyId, blendOp);
+ }
}
#endif
} else {
int ret = drmModePageFlip(fd,
- op.crtc_id,
- fb->fb,
- DRM_MODE_PAGE_FLIP_EVENT,
- this);
+ thisOutput.crtc_id,
+ fb->fb,
+ DRM_MODE_PAGE_FLIP_EVENT,
+ this);
if (ret) {
qErrnoWarning("Could not queue DRM page flip on screen %s", qPrintable(name()));
m_flipPending = false;
@@ -360,17 +430,20 @@ void QEglFSKmsGbmScreen::flip()
if (d.screen != this) {
d.screen->ensureModeSet(fb->fb);
d.cloneFlipPending = true;
- QKmsOutput &destOutput(d.screen->output());
+ const QKmsOutput &destOutput(d.screen->output());
if (device()->hasAtomicSupport()) {
#if QT_CONFIG(drm_atomic)
drmModeAtomicReq *request = device()->threadLocalAtomicRequest();
- if (request) {
- drmModeAtomicAddProperty(request, destOutput.eglfs_plane->id,
- destOutput.eglfs_plane->framebufferPropertyId, fb->fb);
- drmModeAtomicAddProperty(request, destOutput.eglfs_plane->id,
- destOutput.eglfs_plane->crtcPropertyId, destOutput.crtc_id);
- }
+ if (request)
+ addAtomicFlip(request, destOutput, fb->fb);
+
+ // ### This path is broken. On the other branch we can easily
+ // pass in d.screen as the user_data for drmModePageFlip, but
+ // using one atomic request breaks down here since we get events
+ // with the same user_data passed to drmModeAtomicCommit. Until
+ // this gets reworked (multiple requests?) screen cloning is not
+ // compatible with atomic.
#endif
} else {
int ret = drmModePageFlip(fd,
@@ -379,7 +452,9 @@ void QEglFSKmsGbmScreen::flip()
DRM_MODE_PAGE_FLIP_EVENT,
d.screen);
if (ret) {
- qErrnoWarning("Could not queue DRM page flip for clone screen %s", qPrintable(name()));
+ qErrnoWarning("Could not queue DRM page flip for screen %s (clones screen %s)",
+ qPrintable(d.screen->name()),
+ qPrintable(name()));
d.cloneFlipPending = false;
}
}
@@ -415,8 +490,11 @@ void QEglFSKmsGbmScreen::cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScre
void QEglFSKmsGbmScreen::updateFlipStatus()
{
- Q_ASSERT(!m_cloneSource);
+ // only for 'real' outputs that own the color buffer, i.e. that are not cloning another one
+ if (m_cloneSource)
+ return;
+ // proceed only if flips for both this and all others that clone this have finished
if (m_flipPending)
return;
@@ -425,9 +503,10 @@ void QEglFSKmsGbmScreen::updateFlipStatus()
return;
}
- if (m_gbm_bo_current)
+ if (m_gbm_bo_current) {
gbm_surface_release_buffer(m_gbm_surface,
m_gbm_bo_current);
+ }
m_gbm_bo_current = m_gbm_bo_next;
m_gbm_bo_next = nullptr;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h
index ae12e95e62..d7cf0a28be 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h
@@ -88,6 +88,12 @@ protected:
void flipFinished();
void ensureModeSet(uint32_t fb);
void cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScreen);
+ void waitForFlipWithEventReader(QEglFSKmsGbmScreen *screen);
+ static void nonThreadedPageFlipHandler(int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *user_data);
gbm_surface *m_gbm_surface;
@@ -97,6 +103,7 @@ protected:
QMutex m_flipMutex;
QWaitCondition m_flipCond;
+ static QMutex m_nonThreadedFlipMutex;
QScopedPointer<QEglFSKmsGbmCursor> m_cursor;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h
index 006f4a656e..0a7679f765 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h
@@ -53,7 +53,6 @@
//
#include "private/qeglfsglobal_p.h"
-#include "qeglfskmseventreader_p.h"
#include <QtKmsSupport/private/qkmsdevice_p.h>
QT_BEGIN_NAMESPACE
@@ -67,11 +66,6 @@ public:
bool isPrimary,
const QPoint &virtualPos,
const QList<QPlatformScreen *> &virtualSiblings) override;
-
- QEglFSKmsEventReader *eventReader() { return &m_eventReader; }
-
-protected:
- QEglFSKmsEventReader m_eventReader;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index af09704a21..de6b724742 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -160,7 +160,7 @@ static QUIView *focusView()
return;
// Enable hide-keyboard gesture
- self.enabled = YES;
+ self.enabled = m_context->isInputPanelVisible();
m_context->scrollToCursor();
}
@@ -402,7 +402,7 @@ void QIOSInputContext::updateKeyboardState(NSNotification *notification)
// The isInputPanelVisible() property is based on whether or not the virtual keyboard
// is visible on screen, and does not follow the logic of the iOS WillShow and WillHide
// notifications which are not emitted for undocked keyboards, and are buggy when dealing
- // with input-accesosory-views. The reason for using frameEnd here (the future state),
+ // with input-accessory-views. The reason for using frameEnd here (the future state),
// instead of the current state reflected in frameBegin, is that QInputMethod::isVisible()
// is documented to reflect the future state in the case of animated transitions.
m_keyboardState.keyboardVisible = CGRectIntersectsRect(frameEnd, [UIScreen mainScreen].bounds);
diff --git a/src/plugins/platforms/ios/qiosmessagedialog.mm b/src/plugins/platforms/ios/qiosmessagedialog.mm
index 254922701a..773b034e2a 100644
--- a/src/plugins/platforms/ios/qiosmessagedialog.mm
+++ b/src/plugins/platforms/ios/qiosmessagedialog.mm
@@ -47,6 +47,7 @@
#include "qiosglobal.h"
#include "quiview.h"
+#include "qiosscreen.h"
#include "qiosmessagedialog.h"
QIOSMessageDialog::QIOSMessageDialog()
@@ -147,6 +148,25 @@ bool QIOSMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality win
}
UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window : qt_apple_sharedApplication().keyWindow;
+ if (!window) {
+ qCDebug(lcQpaWindow, "Attempting to exec a dialog without any window/widget visible.");
+
+ auto *primaryScreen = static_cast<QIOSScreen*>(QGuiApplication::primaryScreen()->handle());
+ Q_ASSERT(primaryScreen);
+
+ window = primaryScreen->uiWindow();
+ if (window.hidden) {
+ // With a window hidden, an attempt to present view controller
+ // below fails with a warning, that a view "is not a part of
+ // any view hierarchy". The UIWindow is initially hidden,
+ // as unhiding it is what hides the splash screen.
+ window.hidden = NO;
+ }
+ }
+
+ if (!window)
+ return false;
+
[window.rootViewController presentViewController:m_alertController animated:YES completion:nil];
return true;
}
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index 4c79dcc34c..915fc4791f 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -288,7 +288,7 @@ QIOSScreen::QIOSScreen(UIScreen *screen)
if (!qt_apple_isApplicationExtension()) {
for (UIWindow *existingWindow in qt_apple_sharedApplication().windows) {
if (existingWindow.screen == m_uiScreen) {
- m_uiWindow = [m_uiWindow retain];
+ m_uiWindow = [existingWindow retain];
break;
}
}
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index a65f8bbaa1..30ce9b8a83 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -889,20 +889,20 @@
[self sendEventToFocusObject:e];
}
-- (void)setBaseWritingDirection:(UITextWritingDirection)writingDirection forRange:(UITextRange *)range
+- (void)setBaseWritingDirection:(NSWritingDirection)writingDirection forRange:(UITextRange *)range
{
Q_UNUSED(writingDirection);
Q_UNUSED(range);
// Writing direction is handled by QLocale
}
-- (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
+- (NSWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
{
Q_UNUSED(position);
Q_UNUSED(direction);
if (QLocale::system().textDirection() == Qt::RightToLeft)
- return UITextWritingDirectionRightToLeft;
- return UITextWritingDirectionLeftToRight;
+ return NSWritingDirectionRightToLeft;
+ return NSWritingDirectionLeftToRight;
}
- (UITextRange *)characterRangeByExtendingPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 4f3ed7dadf..c5e80e0a32 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -630,13 +630,33 @@ inline ulong getTimeStamp(UIEvent *event)
return Qt::Key_unknown;
}
-- (bool)processPresses:(NSSet *)presses withType:(QEvent::Type)type {
+- (bool)isControlKey:(Qt::Key)key
+{
+ switch (key) {
+ case Qt::Key_Up:
+ case Qt::Key_Down:
+ case Qt::Key_Left:
+ case Qt::Key_Right:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+- (bool)handlePresses:(NSSet<UIPress *> *)presses eventType:(QEvent::Type)type
+{
// Presses on Menu button will generate a Menu key event. By default, not handling
// this event will cause the application to return to Headboard (tvOS launcher).
// When handling the event (for example, as a back button), both press and
// release events must be handled accordingly.
+ if (!qApp->focusWindow())
+ return false;
+
+ bool eventHandled = false;
+ const bool imEnabled = QIOSInputContext::instance()->inputMethodAccepted();
- bool handled = false;
for (UIPress* press in presses) {
Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
if (@available(ios 13.4, *))
@@ -645,26 +665,15 @@ inline ulong getTimeStamp(UIEvent *event)
int key = [self mapPressTypeToKey:press withModifiers:qtModifiers text:text];
if (key == Qt::Key_unknown)
continue;
- if (QWindowSystemInterface::handleKeyEvent(self.platformWindow->window(), type, key,
- qtModifiers, text)) {
- handled = true;
- }
- }
-
- return handled;
-}
+ if (imEnabled && ![self isControlKey:Qt::Key(key)])
+ continue;
-- (BOOL)handlePresses:(NSSet<UIPress *> *)presses eventType:(QEvent::Type)type
-{
- bool handlePress = false;
- if (qApp->focusWindow()) {
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (qApp->focusObject() && QCoreApplication::sendEvent(qApp->focusObject(), &queryEvent))
- handlePress = queryEvent.value(Qt::ImEnabled).toBool();
- if (!handlePress && [self processPresses:presses withType:type])
- return true;
+ bool keyHandled = QWindowSystemInterface::handleKeyEvent(
+ self.platformWindow->window(), type, key, qtModifiers, text);
+ eventHandled = eventHandled || keyHandled;
}
- return false;
+
+ return eventHandled;
}
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
@@ -676,14 +685,14 @@ inline ulong getTimeStamp(UIEvent *event)
- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
if (![self handlePresses:presses eventType:QEvent::KeyPress])
- [super pressesBegan:presses withEvent:event];
+ [super pressesChanged:presses withEvent:event];
[super pressesChanged:presses withEvent:event];
}
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
if (![self handlePresses:presses eventType:QEvent::KeyRelease])
- [super pressesBegan:presses withEvent:event];
+ [super pressesEnded:presses withEvent:event];
[super pressesEnded:presses withEvent:event];
}
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index 3853a0afa4..93b240c29c 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -93,7 +93,7 @@ QT_BEGIN_NAMESPACE
namespace QtWindows
{
-enum
+enum WindowsEventTypeFlags
{
WindowEventFlag = 0x10000,
MouseEventFlag = 0x20000,
@@ -174,6 +174,8 @@ enum WindowsEventType // Simplify event types
GestureEvent = 124,
UnknownEvent = 542
};
+Q_DECLARE_MIXED_ENUM_OPERATORS(bool, WindowsEventTypeFlags, WindowsEventType);
+Q_DECLARE_MIXED_ENUM_OPERATORS(bool, WindowsEventType, WindowsEventTypeFlags);
// Matches Process_DPI_Awareness (Windows 8.1 onwards), used for SetProcessDpiAwareness()
enum ProcessDpiAwareness
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index e7a5fb300d..24d4cf3043 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -680,6 +680,84 @@ IDropTargetHelper* QWindowsDrag::dropHelper() {
return m_cachedDropTargetHelper;
}
+// Workaround for DoDragDrop() not working with touch/pen input, causing DnD to hang until the mouse is moved.
+// We process pointer messages for touch/pen and generate mouse input through SendInput() to trigger DoDragDrop()
+static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource, DWORD dwOKEffects, LPDWORD pdwEffect)
+{
+ HWND hwnd = ::GetFocus();
+ bool starting = false;
+
+ for (;;) {
+ MSG msg{};
+ if (::GetMessage(&msg, hwnd, 0, 0) > 0) {
+
+ if (msg.message == WM_MOUSEMOVE) {
+
+ // Only consider the first simulated event, or actual mouse messages.
+ if (!starting && (msg.wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | MK_XBUTTON1 | MK_XBUTTON2)) == 0)
+ return E_FAIL;
+
+ return ::DoDragDrop(pDataObj, pDropSource, dwOKEffects, pdwEffect);
+ }
+
+ if (msg.message == WM_POINTERUPDATE) {
+
+ const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
+
+ POINTER_INFO pointerInfo{};
+ if (!GetPointerInfo(pointerId, &pointerInfo))
+ return E_FAIL;
+
+ if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
+
+ DWORD flags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK | MOUSEEVENTF_MOVE;
+ if (IS_POINTER_FIRSTBUTTON_WPARAM(msg.wParam))
+ flags |= MOUSEEVENTF_LEFTDOWN;
+ if (IS_POINTER_SECONDBUTTON_WPARAM(msg.wParam))
+ flags |= MOUSEEVENTF_RIGHTDOWN;
+ if (IS_POINTER_THIRDBUTTON_WPARAM(msg.wParam))
+ flags |= MOUSEEVENTF_MIDDLEDOWN;
+
+ if (!starting) {
+ POINT pt{};
+ if (::GetCursorPos(&pt)) {
+
+ // Send mouse input that can generate a WM_MOUSEMOVE message.
+ if ((flags & MOUSEEVENTF_LEFTDOWN || flags & MOUSEEVENTF_RIGHTDOWN || flags & MOUSEEVENTF_MIDDLEDOWN)
+ && (pt.x != pointerInfo.ptPixelLocation.x || pt.y != pointerInfo.ptPixelLocation.y)) {
+
+ const int origin_x = ::GetSystemMetrics(SM_XVIRTUALSCREEN);
+ const int origin_y = ::GetSystemMetrics(SM_YVIRTUALSCREEN);
+ const int virt_w = ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ const int virt_h = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
+ const int virt_x = pointerInfo.ptPixelLocation.x - origin_x;
+ const int virt_y = pointerInfo.ptPixelLocation.y - origin_y;
+
+ INPUT input{};
+ input.type = INPUT_MOUSE;
+ input.mi.dx = static_cast<DWORD>(virt_x * (65535.0 / virt_w));
+ input.mi.dy = static_cast<DWORD>(virt_y * (65535.0 / virt_h));
+ input.mi.dwFlags = flags;
+
+ ::SendInput(1, &input, sizeof(input));
+ starting = true;
+ }
+ }
+ }
+ }
+ } else {
+ // Handle other messages.
+ qWindowsWndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
+
+ if (msg.message == WM_POINTERLEAVE)
+ return E_FAIL;
+ }
+ } else {
+ return E_FAIL;
+ }
+ }
+}
+
Qt::DropAction QWindowsDrag::drag(QDrag *drag)
{
// TODO: Accessibility handling?
@@ -697,7 +775,7 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag)
<< Qt::hex << int(possibleActions) << "effects=0x" << allowedEffects << Qt::dec;
// Indicate message handlers we are in DoDragDrop() event loop.
QWindowsDrag::m_dragging = true;
- const HRESULT r = DoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
+ const HRESULT r = startDoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
QWindowsDrag::m_dragging = false;
const DWORD reportedPerformedEffect = dropDataObject->reportedPerformedEffect();
if (r == DRAGDROP_S_DROP) {
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index e7296c65a6..38e39edbcc 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -264,6 +264,7 @@ void QWindowsIntegrationPrivate::parseOptions(QWindowsIntegration *q, const QStr
QCoreApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents);
else
m_context.initTablet();
+ QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
if (!dpiAwarenessSet) { // Set only once in case of repeated instantiations of QGuiApplication.
if (!QCoreApplication::testAttribute(Qt::AA_PluginApplication)) {
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 5954f35b07..13a50f27a0 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -1403,7 +1403,7 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
// Shift+9 over Alt + Shift + 9) resulting in more missing modifiers.
if (it == result.end())
result << matchedKey;
- else if (missingMods > (*it & Qt::KeyboardModifierMask))
+ else if (missingMods > Qt::KeyboardModifiers(*it & Qt::KeyboardModifierMask))
*it = matchedKey;
}
}
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index 7f8d0e54de..223e98a5b3 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -837,8 +837,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
break;
case QT_PT_PEN:
#if QT_CONFIG(tabletevent)
- if (!m_activeTabletDevice.isNull())
- device = m_activeTabletDevice.data();
+ qCDebug(lcQpaTablet) << "ignoring synth-mouse event for tablet event from" << device;
+ return false;
#endif
break;
}
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 2544dd6200..64abaf4cd1 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -204,11 +204,8 @@ static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
// EnumDisplayMonitors (as opposed to EnumDisplayDevices) enumerates only
// virtual desktop screens.
data->flags |= QWindowsScreenData::VirtualDesktop;
- if (info.dwFlags & MONITORINFOF_PRIMARY) {
+ if (info.dwFlags & MONITORINFOF_PRIMARY)
data->flags |= QWindowsScreenData::PrimaryScreen;
- if ((data->flags & QWindowsScreenData::LockScreen) == 0)
- QWindowsFontDatabase::setDefaultVerticalDPI(data->dpi.second);
- }
return true;
}
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index fa7a8be6a9..bb639a59bc 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -62,7 +62,6 @@
#include <QtCore/qvariant.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdebug.h>
-#include <QtCore/qtextstream.h>
#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qsysinfo.h>
#include <QtCore/qcache.h>
@@ -94,17 +93,6 @@ static inline QColor COLORREFToQColor(COLORREF cr)
return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr));
}
-static inline QTextStream& operator<<(QTextStream &str, const QColor &c)
-{
- str.setIntegerBase(16);
- str.setFieldWidth(2);
- str.setPadChar(u'0');
- str << " rgb: #" << c.red() << c.green() << c.blue();
- str.setIntegerBase(10);
- str.setFieldWidth(0);
- return str;
-}
-
static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue)
{
BOOL result;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index ff4d6d77d4..3f6a63bb9e 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -107,10 +107,11 @@ QWindowsUiaMainProvider::~QWindowsUiaMainProvider()
void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *event)
{
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
- // If this is a table/tree/list, raise event for the focused cell/item instead.
- if (accessible->tableInterface())
+ // If this is a complex element, raise event for the focused child instead.
+ if (accessible->childCount()) {
if (QAccessibleInterface *child = accessible->focusChild())
accessible = child;
+ }
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible))
QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_AutomationFocusChangedEventId);
}
diff --git a/src/plugins/platforms/xcb/CMakeLists.txt b/src/plugins/platforms/xcb/CMakeLists.txt
index 392b2c6cb6..c9dd456ab3 100644
--- a/src/plugins/platforms/xcb/CMakeLists.txt
+++ b/src/plugins/platforms/xcb/CMakeLists.txt
@@ -83,6 +83,8 @@ qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_draganddrop
)
qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_xcb_xlib
+ SOURCES
+ qt_xlib_wrapper.c qt_xlib_wrapper.h
PUBLIC_LIBRARIES
X11::XCB
# special case begin
diff --git a/src/plugins/platforms/xcb/qt_xlib_wrapper.c b/src/plugins/platforms/xcb/qt_xlib_wrapper.c
new file mode 100644
index 0000000000..3ff7120291
--- /dev/null
+++ b/src/plugins/platforms/xcb/qt_xlib_wrapper.c
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:COMM$
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** $QT_END_LICENSE$
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+******************************************************************************/
+
+#include "qt_xlib_wrapper.h"
+
+#include <X11/Xlib.h>
+
+void qt_XFlush(Display *dpy) { XFlush(dpy); }
diff --git a/src/plugins/platforms/xcb/qt_xlib_wrapper.h b/src/plugins/platforms/xcb/qt_xlib_wrapper.h
new file mode 100644
index 0000000000..3f77068348
--- /dev/null
+++ b/src/plugins/platforms/xcb/qt_xlib_wrapper.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:COMM$
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** $QT_END_LICENSE$
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+**
+******************************************************************************/
+
+#ifndef QT_XLIB_WRAPPER_H
+#define QT_XLIB_WRAPPER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct _XDisplay Display;
+ void qt_XFlush(Display *dpy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // QT_XLIB_WRAPPER_H
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 9bb069b70c..f4b829350a 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -71,6 +71,10 @@
#undef explicit
#include <xcb/xinput.h>
+#if QT_CONFIG(xcb_xlib)
+#include "qt_xlib_wrapper.h"
+#endif
+
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaXInput, "qt.qpa.input")
@@ -1105,6 +1109,10 @@ void QXcbConnection::processXcbEvents(QEventLoop::ProcessEventsFlags flags)
m_eventQueue->flushBufferedEvents();
}
+#if QT_CONFIG(xcb_xlib)
+ qt_XFlush(static_cast<Display *>(xlib_display()));
+#endif
+
xcb_flush(xcb_connection());
}
diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
index 2df8de650c..6533288b2f 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
+++ b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
@@ -116,6 +116,20 @@ QGtk3Theme::QGtk3Theme()
/* Use our custom log handler. */
g_log_set_handler("Gtk", G_LOG_LEVEL_MESSAGE, gtkMessageHandler, nullptr);
+
+ /* Set XCURSOR_SIZE and XCURSOR_THEME for Wayland sessions */
+ if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"))) {
+ if (qEnvironmentVariableIsEmpty("XCURSOR_SIZE")) {
+ const int cursorSize = gtkSetting<gint>("gtk-cursor-theme-size");
+ if (cursorSize > 0)
+ qputenv("XCURSOR_SIZE", QString::number(cursorSize).toUtf8());
+ }
+ if (qEnvironmentVariableIsEmpty("XCURSOR_THEME")) {
+ const QString cursorTheme = gtkSetting("gtk-cursor-theme-name");
+ if (!cursorTheme.isEmpty())
+ qputenv("XCURSOR_THEME", cursorTheme.toUtf8());
+ }
+ }
}
static inline QVariant gtkGetLongPressTime()
@@ -190,7 +204,7 @@ QPlatformTheme::Appearance QGtk3Theme::appearance() const
gtk-theme-name provides both light and dark variants. We can save a
regex check by testing this property first.
*/
- const auto preferDark = gtkSetting<bool>("gtk-application-prefer-dark-theme");
+ const auto preferDark = gtkSetting<gboolean>("gtk-application-prefer-dark-theme");
if (preferDark)
return Appearance::Dark;
diff --git a/src/plugins/sqldrivers/.cmake.conf b/src/plugins/sqldrivers/.cmake.conf
index b9c40d1839..f6f7fed367 100644
--- a/src/plugins/sqldrivers/.cmake.conf
+++ b/src/plugins/sqldrivers/.cmake.conf
@@ -1 +1 @@
-set(QT_REPO_MODULE_VERSION "6.2.6")
+set(QT_REPO_MODULE_VERSION "6.2.7")
diff --git a/src/plugins/sqldrivers/oci/qsql_oci_p.h b/src/plugins/sqldrivers/oci/qsql_oci_p.h
index a3366abb77..ddd1fd88b5 100644
--- a/src/plugins/sqldrivers/oci/qsql_oci_p.h
+++ b/src/plugins/sqldrivers/oci/qsql_oci_p.h
@@ -78,7 +78,7 @@ public:
explicit QOCIDriver(QObject *parent = nullptr);
QOCIDriver(OCIEnv *env, OCISvcCtx *ctx, QObject *parent = nullptr);
~QOCIDriver();
- bool hasFeature(DriverFeature f) const;
+ bool hasFeature(DriverFeature f) const override;
bool open(const QString &db,
const QString &user,
const QString &password,
diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
index dc65e3a4e4..a789ebf5a1 100644
--- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
@@ -404,7 +404,7 @@ static QMetaType qDecodeODBCType(SQLSMALLINT sqltype, bool isSigned = true)
return QMetaType(type);
}
-static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool unicode = false)
+static QVariant qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool unicode)
{
QString fieldVal;
SQLRETURN r = SQL_ERROR;
@@ -438,8 +438,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
&lengthIndicator);
if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
if (lengthIndicator == SQL_NULL_DATA) {
- fieldVal.clear();
- break;
+ return {};
}
// starting with ODBC Native Client 2012, SQL_NO_TOTAL is returned
// instead of the length (which sometimes was wrong in older versions)
@@ -465,8 +464,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
break;
} else {
qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
- fieldVal.clear();
- break;
+ return {};
}
}
} else {
@@ -488,8 +486,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
&lengthIndicator);
if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
- fieldVal.clear();
- break;
+ return {};
}
// if SQL_SUCCESS_WITH_INFO is returned, indicating that
// more data can be fetched, the length indicator does NOT
@@ -509,8 +506,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
break;
} else {
qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
- fieldVal.clear();
- break;
+ return {};
}
}
}
@@ -654,7 +650,7 @@ static QSqlField qMakeFieldInfo(const SQLHANDLE hStmt, int i, QString *errorMess
// by SQLColumns. The hStmt has to point to a valid position.
static QSqlField qMakeFieldInfo(const SQLHANDLE hStmt, const QODBCDriverPrivate* p)
{
- QString fname = qGetStringData(hStmt, 3, -1, p->unicode);
+ QString fname = qGetStringData(hStmt, 3, -1, p->unicode).toString();
int type = qGetIntData(hStmt, 4).toInt(); // column type
QSqlField f(fname, qDecodeODBCType(type, p));
QVariant var = qGetIntData(hStmt, 6);
@@ -1295,7 +1291,7 @@ QVariant QODBCResult::data(int field)
}
break;
default:
- d->fieldCache[i] = QVariant(qGetStringData(d->hStmt, i, info.length(), false));
+ d->fieldCache[i] = qGetStringData(d->hStmt, i, info.length(), false);
break;
}
d->fieldCacheIdx = field + 1;
@@ -1308,7 +1304,7 @@ bool QODBCResult::isNull(int field)
Q_D(const QODBCResult);
if (field < 0 || field >= d->fieldCache.size())
return true;
- if (field <= d->fieldCacheIdx) {
+ if (field >= d->fieldCacheIdx) {
// since there is no good way to find out whether the value is NULL
// without fetching the field we'll fetch it here.
// (data() also sets the NULL flag)
@@ -2426,8 +2422,7 @@ QStringList QODBCDriver::tables(QSql::TableType type) const
}
while (r == SQL_SUCCESS) {
- QString fieldVal = qGetStringData(hStmt, 2, -1, d->unicode);
- tl.append(fieldVal);
+ tl.append(qGetStringData(hStmt, 2, -1, d->unicode).toString());
if (d->hasSQLFetchScroll)
r = SQLFetchScroll(hStmt,
@@ -2524,11 +2519,11 @@ QSqlIndex QODBCDriver::primaryIndex(const QString& tablename) const
// Store all fields in a StringList because some drivers can't detail fields in this FETCH loop
while (r == SQL_SUCCESS) {
if (usingSpecialColumns) {
- cName = qGetStringData(hStmt, 1, -1, d->unicode); // column name
+ cName = qGetStringData(hStmt, 1, -1, d->unicode).toString(); // column name
idxName = QString::number(fakeId++); // invent a fake index name
} else {
- cName = qGetStringData(hStmt, 3, -1, d->unicode); // column name
- idxName = qGetStringData(hStmt, 5, -1, d->unicode); // pk index name
+ cName = qGetStringData(hStmt, 3, -1, d->unicode).toString(); // column name
+ idxName = qGetStringData(hStmt, 5, -1, d->unicode).toString(); // pk index name
}
index.append(rec.field(cName));
index.setName(idxName);
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index a20030f1a6..ae0029d415 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -468,7 +468,9 @@ static bool setupSlider(NSSlider *slider, const QStyleOptionSlider *sl)
// NSSlider seems to cache values based on tracking and the last layout of the
// NSView, resulting in incorrect knob rects that break the interaction with
// multiple sliders. So completely reinitialize the slider.
+ const auto controlSize = slider.controlSize;
[slider initWithFrame:sl->rect.toCGRect()];
+ slider.controlSize = controlSize;
slider.minValue = sl->minimum;
slider.maxValue = sl->maximum;
@@ -1828,10 +1830,6 @@ QRectF QMacStylePrivate::comboboxEditBounds(const QRectF &outerBounds, const Coc
QMacStylePrivate::QMacStylePrivate()
: backingStoreNSView(nil)
{
- if (auto *ssf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::SmallFont))
- smallSystemFont = *ssf;
- if (auto *msf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::MiniFont))
- miniSystemFont = *msf;
}
QMacStylePrivate::~QMacStylePrivate()
@@ -2126,6 +2124,14 @@ void QMacStyle::unpolish(QApplication *)
void QMacStyle::polish(QWidget* w)
{
+ Q_D(QMacStyle);
+ if (!d->smallSystemFont && QGuiApplicationPrivate::platformTheme()) {
+ if (auto *ssf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::SmallFont))
+ d->smallSystemFont = *ssf;
+ else
+ d->smallSystemFont = QFont();
+ }
+
if (false
#if QT_CONFIG(menu)
|| qobject_cast<QMenu*>(w)
@@ -3996,8 +4002,13 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
pb.enabled = isEnabled;
[pb highlight:isPressed];
+
// Set off state when inactive. See needsInactiveHack for when it's selected
- pb.state = (isActive && isSelected && !isPressed) ? NSControlStateValueOn : NSControlStateValueOff;
+ // On macOS 12, don't set the Off state for selected tabs as it draws a gray backgorund even when highlighted
+ if (QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSBigSur)
+ pb.state = (isActive && isSelected) ? NSControlStateValueOn : NSControlStateValueOff;
+ else
+ pb.state = (isActive && isSelected && !isPressed) ? NSControlStateValueOn : NSControlStateValueOff;
const auto drawBezelBlock = ^(CGContextRef ctx, const CGRect &r) {
CGContextClipToRect(ctx, opt->rect.toCGRect());
@@ -5746,8 +5757,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const bool rtl = groupBox.direction == Qt::RightToLeft;
const int alignment = Qt::TextHideMnemonic | (rtl ? Qt::AlignRight : Qt::AlignLeft);
const QFont savedFont = p->font();
- if (!flat)
- p->setFont(d->smallSystemFont);
+ if (!flat && d->smallSystemFont)
+ p->setFont(*d->smallSystemFont);
proxy()->drawItemText(p, rect, alignment, groupBox.palette, groupBox.state & State_Enabled, groupBox.text, QPalette::WindowText);
if (!flat)
p->setFont(savedFont);
@@ -6111,7 +6122,9 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
const int margin = flat || hasNoText ? 0 : 9;
ret = groupBox->rect.adjusted(margin, 0, -margin, 0);
- const QFontMetricsF fm = flat || fontIsSet ? QFontMetricsF(groupBox->fontMetrics) : QFontMetricsF(d->smallSystemFont);
+ const QFontMetricsF fm = flat || fontIsSet || !d->smallSystemFont
+ ? QFontMetricsF(groupBox->fontMetrics)
+ : QFontMetricsF(*d->smallSystemFont);
const QSizeF s = fm.size(Qt::AlignHCenter | Qt::AlignVCenter, qt_mac_removeMnemonics(groupBox->text), 0, nullptr);
const int tw = qCeil(s.width());
const int h = qCeil(fm.height());
diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
index 6305a0ea1f..a069a8f56f 100644
--- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h
+++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
@@ -298,8 +298,7 @@ public:
mutable QHash<CocoaControl, NSView *> cocoaControls;
mutable QHash<CocoaControl, NSCell *> cocoaCells;
- QFont smallSystemFont;
- QFont miniSystemFont;
+ std::optional<QFont> smallSystemFont;
QMacKeyValueObserver appearanceObserver;
};
diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
index 67d6b0c460..4ae5ad24b9 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
@@ -86,6 +86,12 @@ bool QWindowsVistaStylePrivate::useVista()
return QWindowsVistaStylePrivate::useXP();
}
+namespace QOSWorkaround {
+ // Qt 6.2's QOperatingSystemVersion doesn't know about Windows 11
+ static const QOperatingSystemVersion Windows11(QOperatingSystemVersion::Windows,
+ 10, 0, 22000);
+}
+
/* \internal
Checks and returns the style object
*/
@@ -1261,6 +1267,9 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
else
theme.stateId = bullet ? MC_BULLETNORMAL: MC_CHECKMARKNORMAL;
d->drawBackground(theme);
+ } else if (QOperatingSystemVersion::current() >= QOSWorkaround::Windows11
+ && !act) {
+ painter->fillRect(checkRect, menuitem->palette.highlight().color().lighter(200));
}
}
diff --git a/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp b/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp
index 9a4dcb6861..d6e3c5c37c 100644
--- a/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp
+++ b/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp
@@ -676,6 +676,12 @@ static QStringList findAllLibCrypto()
}
# endif
+#if (OPENSSL_VERSION_NUMBER >> 28) < 3
+#define QT_OPENSSL_VERSION "1_1"
+#elif OPENSSL_VERSION_MAJOR == 3 // Starting with 3.0 this define is available
+#define QT_OPENSSL_VERSION "3"
+#endif // > 3 intentionally left undefined
+
#ifdef Q_OS_WIN
struct LoadedOpenSsl {
@@ -707,12 +713,6 @@ static LoadedOpenSsl loadOpenSsl()
// MSVC and GCC. For 3.0 the version suffix changed again, to just '3'.
// For non-x86 builds, an architecture suffix is also appended.
-#if (OPENSSL_VERSION_NUMBER >> 28) < 3
-#define QT_OPENSSL_VERSION "1_1"
-#elif OPENSSL_VERSION_MAJOR == 3 // Starting with 3.0 this define is available
-#define QT_OPENSSL_VERSION "3"
-#endif // > 3 intentionally left undefined
-
#if defined(Q_PROCESSOR_X86_64)
#define QT_SSL_SUFFIX "-x64"
#elif defined(Q_PROCESSOR_ARM_64)
@@ -729,7 +729,7 @@ static LoadedOpenSsl loadOpenSsl()
#undef QT_SSL_SUFFIX
return result;
}
-#else
+#else // !Q_OS_WIN:
struct LoadedOpenSsl {
std::unique_ptr<QLibrary> ssl, crypto;
@@ -808,7 +808,7 @@ static LoadedOpenSsl loadOpenSsl()
return suffix;
};
- static QString suffix = QString::fromLatin1(openSSLSuffix("_1_1"));
+ static QString suffix = QString::fromLatin1(openSSLSuffix("_" QT_OPENSSL_VERSION));
libssl->setFileNameAndVersion(QLatin1String("ssl") + suffix, -1);
libcrypto->setFileNameAndVersion(QLatin1String("crypto") + suffix, -1);
diff --git a/src/testlib/doc/src/qttest-best-practices.qdoc b/src/testlib/doc/src/qttest-best-practices.qdoc
index 788380652a..daaca940ae 100644
--- a/src/testlib/doc/src/qttest-best-practices.qdoc
+++ b/src/testlib/doc/src/qttest-best-practices.qdoc
@@ -232,6 +232,9 @@
mac*: SUBDIRS -= someclass
\endcode
+ See also \l {Chapter 6: Skipping Tests with QSKIP}
+ {Skipping Tests with QSKIP}.
+
\section2 Avoid Q_ASSERT
The \l Q_ASSERT macro causes a program to abort whenever the asserted
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index 77e2b55a4b..1461f27642 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -134,7 +134,6 @@ struct Options
, internalSf(false)
, sectionsOnly(false)
, protectedAuthenticationPath(false)
- , jarSigner(false)
, installApk(false)
, uninstallApk(false)
, qmlImportScannerBinaryPath()
@@ -224,7 +223,6 @@ struct Options
bool internalSf;
bool sectionsOnly;
bool protectedAuthenticationPath;
- bool jarSigner;
QString apkPath;
// Installation information
@@ -436,7 +434,6 @@ Options parseOptions()
} else if (argument.compare(QLatin1String("--aab"), Qt::CaseInsensitive) == 0) {
options.buildAAB = true;
options.build = true;
- options.jarSigner = true;
} else if (!options.buildAAB && argument.compare(QLatin1String("--no-build"), Qt::CaseInsensitive) == 0) {
options.build = false;
} else if (argument.compare(QLatin1String("--install"), Qt::CaseInsensitive) == 0) {
@@ -570,8 +567,6 @@ Options parseOptions()
options.sectionsOnly = true;
} else if (argument.compare(QLatin1String("--protected"), Qt::CaseInsensitive) == 0) {
options.protectedAuthenticationPath = true;
- } else if (argument.compare(QLatin1String("--jarsigner"), Qt::CaseInsensitive) == 0) {
- options.jarSigner = true;
} else if (argument.compare(QLatin1String("--aux-mode"), Qt::CaseInsensitive) == 0) {
options.auxMode = true;
} else if (argument.compare(QLatin1String("--qml-importscanner-binary"), Qt::CaseInsensitive) == 0) {
@@ -656,8 +651,7 @@ void printHelp()
" --internalsf: Include the .SF file inside the signature block.\n"
" --sectionsonly: Don't compute hash of entire manifest.\n"
" --protected: Keystore has protected authentication path.\n"
- " --jarsigner: Force jarsigner usage, otherwise apksigner will be\n"
- " used if available.\n"
+ " --jarsigner: Deprecated, ignored.\n"
"\n"
" NOTE: To conceal the keystore information, the environment variables\n"
" QT_ANDROID_KEYSTORE_PATH, and QT_ANDROID_KEYSTORE_ALIAS are used to\n"
@@ -2204,7 +2198,7 @@ bool readDependencies(Options *options)
}
}
- if ((!options->rootPaths.empty() || options->qrcFiles.isEmpty()) &&
+ if ((!options->rootPaths.empty() || !options->qrcFiles.isEmpty()) &&
!scanImports(options, &usedDependencies))
return false;
@@ -2543,6 +2537,24 @@ void checkAndWarnGradleLongPaths(const QString &outputDirectory)
}
#endif
+bool gradleSetsLegacyPackagingProperty(const QString &path)
+{
+ QFile file(path);
+ if (!file.open(QIODevice::ReadOnly))
+ return false;
+
+ const auto lines = file.readAll().split('\n');
+ for (const auto &line : lines) {
+ if (line.contains("useLegacyPackaging")) {
+ const auto trimmed = line.trimmed();
+ if (!trimmed.startsWith("//") && !trimmed.startsWith('*') && !trimmed.startsWith("/*"))
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool buildAndroidProject(const Options &options)
{
GradleProperties localProperties;
@@ -2551,9 +2563,13 @@ bool buildAndroidProject(const Options &options)
if (!mergeGradleProperties(localPropertiesPath, localProperties))
return false;
- QString gradlePropertiesPath = options.outputDirectory + QLatin1String("gradle.properties");
+ const QString gradlePropertiesPath = options.outputDirectory + QLatin1String("gradle.properties");
GradleProperties gradleProperties = readGradleProperties(gradlePropertiesPath);
- gradleProperties["android.bundle.enableUncompressedNativeLibs"] = "false";
+
+ const QString gradleBuildFilePath = options.outputDirectory + QLatin1String("build.gradle");
+ if (!gradleSetsLegacyPackagingProperty(gradleBuildFilePath))
+ gradleProperties["android.bundle.enableUncompressedNativeLibs"] = "false";
+
gradleProperties["buildDir"] = "build";
gradleProperties["qtAndroidDir"] = (options.qtInstallDirectory + QLatin1String("/src/android/java")).toUtf8();
// The following property "qt5AndroidDir" is only for compatibility.
@@ -2759,7 +2775,7 @@ bool copyStdCpp(Options *options)
return copyFileIfNewer(stdCppPath, destinationFile, *options);
}
-bool jarSignerSignPackage(const Options &options)
+bool signAAB(const Options &options)
{
if (options.verbose)
fprintf(stdout, "Signing Android package.\n");
@@ -2818,7 +2834,7 @@ bool jarSignerSignPackage(const Options &options)
if (options.protectedAuthenticationPath)
jarSignerTool += QLatin1String(" -protected");
- auto signPackage = [&](const QString &file) {
+ auto jarSignPackage = [&](const QString &file) {
fprintf(stdout, "Signing file %s\n", qPrintable(file));
fflush(stdout);
QString command = jarSignerTool
@@ -2848,52 +2864,9 @@ bool jarSignerSignPackage(const Options &options)
return true;
};
- if (!signPackage(packagePath(options, UnsignedAPK)))
- return false;
- if (options.buildAAB && !signPackage(packagePath(options, AAB)))
+ if (options.buildAAB && !jarSignPackage(packagePath(options, AAB)))
return false;
-
- QString zipAlignTool = options.sdkPath + QLatin1String("/tools/zipalign");
-#if defined(Q_OS_WIN32)
- zipAlignTool += QLatin1String(".exe");
-#endif
-
- if (!QFile::exists(zipAlignTool)) {
- zipAlignTool = options.sdkPath + QLatin1String("/build-tools/") + options.sdkBuildToolsVersion + QLatin1String("/zipalign");
-#if defined(Q_OS_WIN32)
- zipAlignTool += QLatin1String(".exe");
-#endif
- if (!QFile::exists(zipAlignTool)) {
- fprintf(stderr, "zipalign tool not found: %s\n", qPrintable(zipAlignTool));
- return false;
- }
- }
-
- zipAlignTool = QLatin1String("%1%2 -f 4 %3 %4")
- .arg(shellQuote(zipAlignTool),
- options.verbose ? QLatin1String(" -v") : QLatin1String(),
- shellQuote(packagePath(options, UnsignedAPK)),
- shellQuote(packagePath(options, SignedAPK)));
-
- FILE *zipAlignCommand = openProcess(zipAlignTool);
- if (zipAlignCommand == 0) {
- fprintf(stderr, "Couldn't run zipalign.\n");
- return false;
- }
-
- char buffer[512];
- while (fgets(buffer, sizeof(buffer), zipAlignCommand) != 0)
- fprintf(stdout, "%s", buffer);
-
- int errorCode = pclose(zipAlignCommand);
- if (errorCode != 0) {
- fprintf(stderr, "zipalign command failed.\n");
- if (!options.verbose)
- fprintf(stderr, " -- Run with --verbose for more information.\n");
- return false;
- }
-
- return QFile::remove(packagePath(options, UnsignedAPK));
+ return true;
}
bool signPackage(const Options &options)
@@ -2903,11 +2876,6 @@ bool signPackage(const Options &options)
apksignerTool += QLatin1String(".bat");
#endif
- if (options.jarSigner || !QFile::exists(apksignerTool))
- return jarSignerSignPackage(options);
-
- // APKs signed with apksigner must not be changed after they're signed, therefore we need to zipalign it before we sign it.
-
QString zipAlignTool = options.sdkPath + QLatin1String("/tools/zipalign");
#if defined(Q_OS_WIN32)
zipAlignTool += QLatin1String(".exe");
@@ -3020,6 +2988,9 @@ bool signPackage(const Options &options)
QLatin1String("%1 verify --verbose %2")
.arg(shellQuote(apksignerTool), shellQuote(packagePath(options, SignedAPK)));
+ if (options.buildAAB && !signAAB(options))
+ return false;
+
// Verify the package and remove the unsigned apk
return apkSignerRunner(apkVerifyCommand, true) && QFile::remove(packagePath(options, UnsignedAPK));
}
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 366db24078..15e56d3721 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -618,6 +618,12 @@ void Moc::parse()
QByteArray nsName = lexem();
QByteArrayList nested;
while (test(SCOPE)) {
+ /* treat (C++20's) namespace A::inline B {} as A::B
+ this is mostly to not break compilation when encountering such
+ a construct in a header; the interaction of Qt's meta-macros with
+ inline namespaces is still rather poor.
+ */
+ test(INLINE);
next(IDENTIFIER);
nested.append(nsName);
nsName = lexem();
diff --git a/src/widgets/accessible/complexwidgets.cpp b/src/widgets/accessible/complexwidgets.cpp
index 63836015dd..097c589306 100644
--- a/src/widgets/accessible/complexwidgets.cpp
+++ b/src/widgets/accessible/complexwidgets.cpp
@@ -354,6 +354,16 @@ int QAccessibleComboBox::indexOfChild(const QAccessibleInterface *child) const
return -1;
}
+QAccessibleInterface *QAccessibleComboBox::focusChild() const
+{
+ // The editable combobox is the focus proxy of its lineedit, so the
+ // lineedit itself never gets focus. But it is the accessible focus
+ // child of an editable combobox.
+ if (comboBox()->isEditable())
+ return child(1);
+ return nullptr;
+}
+
/*! \reimp */
QString QAccessibleComboBox::text(QAccessible::Text t) const
{
diff --git a/src/widgets/accessible/complexwidgets_p.h b/src/widgets/accessible/complexwidgets_p.h
index 1c138e6af2..f6d5226f9b 100644
--- a/src/widgets/accessible/complexwidgets_p.h
+++ b/src/widgets/accessible/complexwidgets_p.h
@@ -135,6 +135,7 @@ public:
QAccessibleInterface *childAt(int x, int y) const override;
int indexOfChild(const QAccessibleInterface *child) const override;
QAccessibleInterface* child(int index) const override;
+ QAccessibleInterface* focusChild() const override;
QString text(QAccessible::Text t) const override;
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index 0bf8f2440b..6d8e91a223 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -227,7 +227,7 @@ Q_GLOBAL_STATIC(QUrl, lastVisitedDir)
\value DontConfirmOverwrite Don't ask for confirmation if an
existing file is selected. By default confirmation is requested.
- Note: This opption is not supported on macOS when using the
+ Note: This option is not supported on macOS when using the
native file dialog.
\value DontUseNativeDialog Don't use the native file dialog. By
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index 8fc0df84e2..7dc2c06860 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -1797,21 +1797,27 @@ bool QHeaderView::restoreState(const QByteArray &state)
Q_D(QHeaderView);
if (state.isEmpty())
return false;
- QByteArray data = state;
- QDataStream stream(&data, QIODevice::ReadOnly);
- int marker;
- int ver;
- stream >> marker;
- stream >> ver;
- if (stream.status() != QDataStream::Ok
+
+ for (const auto dataStreamVersion : {QDataStream::Qt_5_0, QDataStream::Qt_6_0}) {
+
+ QByteArray data = state;
+ QDataStream stream(&data, QIODevice::ReadOnly);
+ stream.setVersion(dataStreamVersion);
+ int marker;
+ int ver;
+ stream >> marker;
+ stream >> ver;
+ if (stream.status() != QDataStream::Ok
|| marker != QHeaderViewPrivate::VersionMarker
- || ver != 0) // current version is 0
- return false;
+ || ver != 0) { // current version is 0
+ return false;
+ }
- if (d->read(stream)) {
- emit sortIndicatorChanged(d->sortIndicatorSection, d->sortIndicatorOrder );
- d->viewport->update();
- return true;
+ if (d->read(stream)) {
+ emit sortIndicatorChanged(d->sortIndicatorSection, d->sortIndicatorOrder );
+ d->viewport->update();
+ return true;
+ }
}
return false;
}
@@ -4165,6 +4171,15 @@ bool QHeaderViewPrivate::read(QDataStream &in)
in >> global;
+ // Check parameter consistency
+ // Global orientation out of bounds?
+ if (global < 0 || global > QHeaderView::ResizeToContents)
+ return false;
+
+ // Alignment out of bounds?
+ if (align < 0 || align > Qt::AlignVertical_Mask)
+ return false;
+
in >> sectionItemsIn;
// In Qt4 we had a vector of spans where one span could hold information on more sections.
// Now we have an itemvector where one items contains information about one section
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 500a6152d8..bd7f48d878 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -1695,8 +1695,11 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
}
}
- // ### special case: treeviews with multiple columns draw
- // the selections differently than with only one column
+ // ### special case: if we select entire rows, then we need to draw the
+ // selection in the first column all the way to the second column, rather
+ // than just around the item text. We abuse showDecorationSelected to
+ // indicate this to the style. Below we will reset this value temporarily
+ // to only respect the styleHint while we are rendering the decoration.
opt.showDecorationSelected = (d->selectionBehavior & SelectRows)
|| option.showDecorationSelected;
@@ -1781,8 +1784,16 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
}
// draw background for the branch (selection + alternate row)
opt.rect = branches;
- if (style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, &opt, this))
- style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, this);
+
+ // We use showDecorationSelected both to store the style hint, and to indicate
+ // that the entire row has to be selected (see overrides of the value if
+ // selectionBehavior == SelectRow).
+ // While we are only painting the background we don't care for the
+ // selectionBehavior factor, so respect only the style value, and reset later.
+ const bool oldShowDecorationSelected = opt.showDecorationSelected;
+ opt.showDecorationSelected = style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected,
+ &opt, this);
+ style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, this);
// draw background of the item (only alternate row). rest of the background
// is provided by the delegate
@@ -1791,6 +1802,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
opt.rect.setRect(reverse ? position : i + position, y, width - i, height);
style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, this);
opt.state = oldState;
+ opt.showDecorationSelected = oldShowDecorationSelected;
if (d->indent != 0)
drawBranches(painter, branches, index);
diff --git a/src/widgets/kernel/qtestsupport_widgets.cpp b/src/widgets/kernel/qtestsupport_widgets.cpp
index c9116fcef6..1d39285670 100644
--- a/src/widgets/kernel/qtestsupport_widgets.cpp
+++ b/src/widgets/kernel/qtestsupport_widgets.cpp
@@ -52,9 +52,16 @@ QT_BEGIN_NAMESPACE
/*!
\since 5.0
- Waits for \a timeout milliseconds or until the \a widget's window is active.
+ Returns \c true if \a widget is active within \a timeout milliseconds. Otherwise returns \c false.
- Returns \c true if \c widget's window is active within \a timeout milliseconds, otherwise returns \c false.
+ The method is useful in tests that call QWidget::show() and rely on the widget actually being
+ active (i.e. being visible and having focus) before proceeding.
+
+ \note The method will time out and return \c false if another window prevents \a widget from
+ becoming active.
+
+ \note Since focus is an exclusive property, \a widget may loose its focus to another window at
+ any time - even after the method has returned \c true.
\sa qWaitForWindowExposed(), QWidget::isActiveWindow()
*/
@@ -68,20 +75,16 @@ Q_WIDGETS_EXPORT bool QTest::qWaitForWindowActive(QWidget *widget, int timeout)
/*!
\since 5.0
- Waits for \a timeout milliseconds or until the \a widget's window is exposed.
- Returns \c true if \c widget's window is exposed within \a timeout milliseconds, otherwise returns \c false.
-
- This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
- time after being asked to show itself on the screen.
+ Returns \c true if \a widget is exposed within \a timeout milliseconds. Otherwise returns \c false.
- Note that a window that is mapped to screen may still not be considered exposed if the window client
- area is completely covered by other windows, or if the window is otherwise not visible. This function
- will then time out when waiting for such a window.
+ The method is useful in tests that call QWidget::show() and rely on the widget actually being
+ being visible before proceeding.
- A specific configuration where this happens is when using QGLWidget as a viewport widget on macOS:
- The viewport widget gets the expose event, not the parent widget.
+ \note A window mapped to screen may still not be considered exposed, if the window client area is
+ not visible, e.g. because it is completely covered by other windows.
+ In such cases, the method will time out and return \c false.
- \sa qWaitForWindowActive()
+ \sa qWaitForWindowActive(), QWidget::isVisible(), QWindow::isExposed()
*/
Q_WIDGETS_EXPORT bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout)
{
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 79c6c89db2..c2672933ac 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -6263,6 +6263,33 @@ void QWidget::setFocusProxy(QWidget * w)
d->createExtra();
d->extra->focus_proxy = w;
+ if (w && isAncestorOf(w)) {
+ // If the focus proxy is a child of this (so this is a compound widget), then
+ // we need to make sure that this widget is immediately in front of its own children
+ // in the focus chain. Otherwise focusNextPrev_helper might jump over unrelated
+ // widgets that are positioned between this compound widget, and its proxy in
+ // the focus chain.
+ const QWidget *parentOfW = w->parentWidget();
+ Q_ASSERT(parentOfW); // can't be nullptr since we are an ancestor of w
+ QWidget *firstChild = nullptr;
+ const auto childList = children();
+ for (QObject *child : childList) {
+ if ((firstChild = qobject_cast<QWidget *>(child)))
+ break;
+ }
+ Q_ASSERT(firstChild); // can't be nullptr since w is a child
+ QWidget *oldNext = d->focus_next;
+ QWidget *oldPrev = d->focus_prev;
+ oldNext->d_func()->focus_prev = oldPrev;
+ oldPrev->d_func()->focus_next = oldNext;
+
+ oldPrev = firstChild->d_func()->focus_prev;
+ d->focus_next = firstChild;
+ d->focus_prev = oldPrev;
+ oldPrev->d_func()->focus_next = this;
+ firstChild->d_func()->focus_prev = this;
+ }
+
if (moveFocusToProxy)
setFocus(Qt::OtherFocusReason);
}
@@ -6954,8 +6981,8 @@ void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw)
n->d_func()->focus_next = topLevel;
} else {
//repair the new list
- n->d_func()->focus_next = q;
- focus_prev = n;
+ n->d_func()->focus_next = q;
+ focus_prev = n;
}
}
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index dfee61fa74..538c934c0f 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -711,7 +711,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
cg = QPalette::Inactive;
- if ((vopt->state & QStyle::State_Selected) && proxy()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, opt, widget))
+ if ((vopt->state & QStyle::State_Selected) && vopt->showDecorationSelected)
p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::Highlight));
else if (vopt->features & QStyleOptionViewItem::Alternate)
p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::AlternateBase));
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 78503e07c4..40bde5e066 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -1508,7 +1508,11 @@ void QRenderRule::configurePalette(QPalette *p, QPalette::ColorGroup cg, const Q
p->setBrush(cg, w->foregroundRole(), pal->foreground);
p->setBrush(cg, QPalette::WindowText, pal->foreground);
p->setBrush(cg, QPalette::Text, pal->foreground);
- p->setBrush(cg, QPalette::PlaceholderText, pal->foreground);
+ QColor phColor(pal->foreground.color());
+ phColor.setAlpha((phColor.alpha() + 1) / 2);
+ QBrush placeholder = pal->foreground;
+ placeholder.setColor(phColor);
+ p->setBrush(cg, QPalette::PlaceholderText, placeholder);
}
if (pal->selectionBackground.style() != Qt::NoBrush)
p->setBrush(cg, QPalette::Highlight, pal->selectionBackground);
@@ -4742,10 +4746,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {
QRenderRule subRule = renderRule(w, opt, PseudoElement_TreeViewBranch);
if (subRule.hasDrawable()) {
- if ((vopt->state & QStyle::State_Selected) && vopt->showDecorationSelected)
- p->fillRect(vopt->rect, vopt->palette.highlight());
- else if (vopt->features & QStyleOptionViewItem::Alternate)
- p->fillRect(vopt->rect, vopt->palette.alternateBase());
+ proxy()->drawPrimitive(PE_PanelItemViewRow, vopt, p, w);
subRule.drawRule(p, opt->rect);
} else {
baseStyle()->drawPrimitive(pe, vopt, p, w);
@@ -4813,6 +4814,17 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
pseudoElement = PseudoElement_DockWidgetSeparator;
break;
+ case PE_PanelItemViewRow:
+ // For compatibility reasons, QTreeView draws different parts of
+ // the background of an item row separately, before calling the
+ // delegate to draw the item. The row background of an item is
+ // however not separately styleable through a style sheet, but
+ // only indirectly through the background of the item. To get the
+ // same background for all parts drawn by QTreeView, we have to
+ // use the background rule for the item here.
+ if (renderRule(w, opt, PseudoElement_ViewItem).hasBackground())
+ pseudoElement = PseudoElement_ViewItem;
+ break;
case PE_PanelItemViewItem:
pseudoElement = PseudoElement_ViewItem;
break;
diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp
index cce7b202a0..80e2cb0825 100644
--- a/src/widgets/util/qsystemtrayicon.cpp
+++ b/src/widgets/util/qsystemtrayicon.cpp
@@ -128,7 +128,9 @@ static QIcon messageIcon2qIcon(QSystemTrayIcon::MessageIcon icon)
Only on X11, when a tooltip is requested, the QSystemTrayIcon receives a QHelpEvent
of type QEvent::ToolTip. Additionally, the QSystemTrayIcon receives wheel events of
- type QEvent::Wheel. These are not supported on any other platform.
+ type QEvent::Wheel. These are not supported on any other platform. Note: Since GNOME
+ Shell version 3.26, not all QSystemTrayIcon::ActivationReason are supported by the
+ system without shell extensions installed.
\sa QDesktopServices, {Desktop Integration}, {System Tray Icon Example}
*/
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index 8c327026ff..3374315d88 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -1044,12 +1044,18 @@ bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event)
pos = event->globalPosition().toPoint() - state->pressPos - windowMarginOffset;
}
+ // If the newly floating dock widget has got a native title bar,
+ // offset the position by the native title bar's height or width
+ const int dx = q->geometry().x() - q->x();
+ const int dy = q->geometry().y() - q->y();
+ pos.rx() += dx;
+ pos.ry() += dy;
+
QDockWidgetGroupWindow *floatingTab = qobject_cast<QDockWidgetGroupWindow*>(parent);
if (floatingTab && !q->isFloating())
floatingTab->move(pos);
else
q->move(pos);
-
if (state && !state->ctrlDrag)
mwlayout->hover(state->widgetItem, event->globalPosition().toPoint());
diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp
index 412c0294f7..27a67ea988 100644
--- a/src/widgets/widgets/qmainwindowlayout.cpp
+++ b/src/widgets/widgets/qmainwindowlayout.cpp
@@ -2625,6 +2625,21 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group)
} else
#endif // QT_CONFIG(tabwidget)
{
+ // Dock widget is unplugged from the main window
+ // => geometry needs to be adjusted by separator size
+ switch (dockWidgetArea(dw)) {
+ case Qt::LeftDockWidgetArea:
+ case Qt::RightDockWidgetArea:
+ r.adjust(0, 0, 0, -sep);
+ break;
+ case Qt::TopDockWidgetArea:
+ case Qt::BottomDockWidgetArea:
+ r.adjust(0, 0, -sep, 0);
+ break;
+ case Qt::NoDockWidgetArea:
+ case Qt::DockWidgetArea_Mask:
+ break;
+ }
dw->d_func()->unplug(r);
}
}
diff --git a/tests/auto/cmake/mockplugins/.cmake.conf b/tests/auto/cmake/mockplugins/.cmake.conf
index b9c40d1839..f6f7fed367 100644
--- a/tests/auto/cmake/mockplugins/.cmake.conf
+++ b/tests/auto/cmake/mockplugins/.cmake.conf
@@ -1 +1 @@
-set(QT_REPO_MODULE_VERSION "6.2.6")
+set(QT_REPO_MODULE_VERSION "6.2.7")
diff --git a/tests/auto/cmake/test_static_resources/.cmake.conf b/tests/auto/cmake/test_static_resources/.cmake.conf
index b9c40d1839..f6f7fed367 100644
--- a/tests/auto/cmake/test_static_resources/.cmake.conf
+++ b/tests/auto/cmake/test_static_resources/.cmake.conf
@@ -1 +1 @@
-set(QT_REPO_MODULE_VERSION "6.2.6")
+set(QT_REPO_MODULE_VERSION "6.2.7")
diff --git a/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp b/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp
index 540856ad6e..87ab016fe6 100644
--- a/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp
+++ b/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp
@@ -33,9 +33,7 @@
#include <QTest>
#include <QTimer>
-#if __has_include(<chrono>)
-# include <chrono>
-#endif
+#include <chrono>
static const int minResolution = 400; // the minimum resolution for the tests
@@ -520,9 +518,6 @@ void tst_QDeadlineTimer::expire()
void tst_QDeadlineTimer::stdchrono()
{
-#if !__has_include(<chrono>)
- QSKIP("std::chrono not found on this system");
-#else
using namespace std::chrono;
QFETCH_GLOBAL(Qt::TimerType, timerType);
@@ -722,7 +717,6 @@ void tst_QDeadlineTimer::stdchrono()
QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + seconds(1) + milliseconds(minResolution)));
QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + seconds(1) - milliseconds(minResolution)));
QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + seconds(1) + milliseconds(minResolution)));
-#endif
}
QTEST_MAIN(tst_QDeadlineTimer)
diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
index b3a500fbd8..6cc9dd9220 100644
--- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
+++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
@@ -265,19 +265,14 @@ void tst_QTimer::remainingTimeDuringActivation()
namespace {
-#if __has_include(<chrono>)
template <typename T>
std::chrono::milliseconds to_ms(T t)
{ return std::chrono::duration_cast<std::chrono::milliseconds>(t); }
-#endif
} // unnamed namespace
void tst_QTimer::basic_chrono()
{
-#if !__has_include(<chrono>)
- QSKIP("This test requires C++11 <chrono> support");
-#else
// duplicates zeroTimer, singleShotTimeout, interval and remainingTime
using namespace std::chrono;
QTimer timer;
@@ -318,7 +313,6 @@ void tst_QTimer::basic_chrono()
QCOMPARE(timeoutSpy.count(), 1);
QTest::qWait(500);
QCOMPARE(timeoutSpy.count(), 1);
-#endif
}
void tst_QTimer::livelock_data()
@@ -915,9 +909,6 @@ void tst_QTimer::singleShotToFunctors()
void tst_QTimer::singleShot_chrono()
{
-#if !__has_include(<chrono>)
- QSKIP("This test requires C++11 <chrono> support");
-#else
// duplicates singleShotStaticFunctionZeroTimeout and singleShotToFunctors
using namespace std::chrono;
{
@@ -954,7 +945,6 @@ void tst_QTimer::singleShot_chrono()
QTRY_COMPARE(count, 3);
_e.reset();
-#endif
}
class DontBlockEvents : public QObject
diff --git a/tests/auto/corelib/platform/android/CMakeLists.txt b/tests/auto/corelib/platform/android/CMakeLists.txt
index c2749825ac..6c08080e6a 100644
--- a/tests/auto/corelib/platform/android/CMakeLists.txt
+++ b/tests/auto/corelib/platform/android/CMakeLists.txt
@@ -7,6 +7,10 @@
qt_internal_add_test(tst_android
SOURCES
tst_android.cpp
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::Gui
+ Qt::GuiPrivate
)
if(ANDROID)
diff --git a/tests/auto/corelib/platform/android/tst_android.cpp b/tests/auto/corelib/platform/android/tst_android.cpp
index 710e5b2ecf..7e66e1fd3b 100644
--- a/tests/auto/corelib/platform/android/tst_android.cpp
+++ b/tests/auto/corelib/platform/android/tst_android.cpp
@@ -29,8 +29,12 @@
#include <jni.h>
#include <QTest>
+#include <QGuiApplication>
#include <QtCore/qnativeinterface.h>
#include <QtCore/qjniobject.h>
+#include <QScreen>
+#include <qpa/qplatformscreen.h>
+#include <qpa/qplatformnativeinterface.h>
class tst_Android : public QObject
{
@@ -41,6 +45,7 @@ private slots:
void testAndroidSdkVersion();
void testAndroidActivity();
void testRunOnAndroidMainThread();
+ void testFullScreenDimensions();
};
void tst_Android::assetsRead()
@@ -189,6 +194,103 @@ void tst_Android::testRunOnAndroidMainThread()
}
}
+void setSystemUiVisibility(int visibility)
+{
+ QNativeInterface::QAndroidApplication::runOnAndroidMainThread([visibility] {
+ QJniObject::callStaticMethod<void>("org/qtproject/qt/android/QtNative",
+ "setSystemUiVisibility", "(I)V", visibility);
+ }).waitForFinished();
+}
+
+// QTBUG-107604
+void tst_Android::testFullScreenDimensions()
+{
+ static int SYSTEM_UI_VISIBILITY_NORMAL = 0;
+ static int SYSTEM_UI_VISIBILITY_FULLSCREEN = 1;
+ static int SYSTEM_UI_VISIBILITY_TRANSLUCENT = 2;
+
+ // this will trigger new layout updates
+ setSystemUiVisibility(SYSTEM_UI_VISIBILITY_FULLSCREEN);
+ setSystemUiVisibility(SYSTEM_UI_VISIBILITY_NORMAL);
+
+ QJniObject activity = QNativeInterface::QAndroidApplication::context();
+ QVERIFY(activity.isValid());
+
+ QJniObject windowManager =
+ activity.callObjectMethod("getWindowManager", "()Landroid/view/WindowManager;");
+ QVERIFY(windowManager.isValid());
+
+ QJniObject display = windowManager.callObjectMethod("getDefaultDisplay", "()Landroid/view/Display;");
+ QVERIFY(display.isValid());
+
+ QJniObject appSize("android/graphics/Point");
+ QVERIFY(appSize.isValid());
+
+ display.callMethod<void>("getSize", "(Landroid/graphics/Point;)V", appSize.object());
+
+ QJniObject realSize("android/graphics/Point");
+ QVERIFY(realSize.isValid());
+
+ display.callMethod<void>("getRealSize", "(Landroid/graphics/Point;)V", realSize.object());
+
+ QPlatformScreen *screen = QGuiApplication::primaryScreen()->handle();
+
+ {
+ // Normal -
+ // available geometry == app size (system bars visible and removed from available geometry)
+ QCoreApplication::processEvents();
+ QJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
+ QVERIFY(window.isValid());
+
+ QJniObject decorView = window.callObjectMethod("getDecorView", "()Landroid/view/View;");
+ QVERIFY(decorView.isValid());
+
+ QJniObject insets =
+ decorView.callObjectMethod("getRootWindowInsets", "()Landroid/view/WindowInsets;");
+ QVERIFY(insets.isValid());
+
+ int insetsWidth = insets.callMethod<jint>("getSystemWindowInsetRight")
+ + insets.callMethod<jint>("getSystemWindowInsetLeft");
+
+ int insetsHeight = insets.callMethod<jint>("getSystemWindowInsetTop")
+ + insets.callMethod<jint>("getSystemWindowInsetBottom");
+
+ QTRY_COMPARE(screen->availableGeometry().width(),
+ int(appSize.getField<jint>("x")) - insetsWidth);
+ QTRY_COMPARE(screen->availableGeometry().height(),
+ int(appSize.getField<jint>("y")) - insetsHeight);
+
+ QTRY_COMPARE(screen->geometry().width(), int(realSize.getField<jint>("x")));
+ QTRY_COMPARE(screen->geometry().height(), int(realSize.getField<jint>("y")));
+ }
+
+ {
+ setSystemUiVisibility(SYSTEM_UI_VISIBILITY_FULLSCREEN);
+
+ // Fullscreen
+ // available geometry == full display size (system bars hidden)
+ QCoreApplication::processEvents();
+ QTRY_COMPARE(screen->availableGeometry().width(), int(realSize.getField<jint>("x")));
+ QTRY_COMPARE(screen->availableGeometry().height(), int(realSize.getField<jint>("y")));
+
+ QTRY_COMPARE(screen->geometry().width(), int(realSize.getField<jint>("x")));
+ QTRY_COMPARE(screen->geometry().height(), int(realSize.getField<jint>("y")));
+ }
+
+ {
+ setSystemUiVisibility(SYSTEM_UI_VISIBILITY_TRANSLUCENT);
+
+ // Translucent
+ // available geometry == full display size (system bars visible but drawable under)
+ QCoreApplication::processEvents();
+ QTRY_COMPARE(screen->availableGeometry().width(), int(realSize.getField<jint>("x")));
+ QTRY_COMPARE(screen->availableGeometry().height(), int(realSize.getField<jint>("y")));
+
+ QTRY_COMPARE(screen->geometry().width(), int(realSize.getField<jint>("x")));
+ QTRY_COMPARE(screen->geometry().height(), int(realSize.getField<jint>("y")));
+ }
+}
+
QTEST_MAIN(tst_Android)
#include "tst_android.moc"
diff --git a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
index 72a6427930..fc7247b733 100644
--- a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
+++ b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
@@ -35,6 +35,7 @@
#include <limits.h>
#include <private/qtools_p.h>
+#include <iterator>
#include <stdexcept>
#include <string_view>
@@ -53,6 +54,7 @@ private slots:
void qCompress();
void qUncompressCorruptedData_data();
void qUncompressCorruptedData();
+ void qUncompress4GiBPlus();
void qCompressionZeroTermination();
#endif
void constByteArray();
@@ -343,6 +345,79 @@ void tst_QByteArray::qUncompressCorruptedData()
#endif
}
+void tst_QByteArray::qUncompress4GiBPlus()
+{
+ // after three rounds, this decompresses to 4GiB + 1 'X' bytes:
+ constexpr uchar compressed_3x[] = {
+ 0x00, 0x00, 0x1a, 0x76, 0x78, 0x9c, 0x63, 0xb0, 0xdf, 0xb4, 0xad, 0x62,
+ 0xce, 0xdb, 0x3b, 0x0b, 0xf3, 0x26, 0x27, 0x4a, 0xb4, 0x3d, 0x34, 0x5b,
+ 0xed, 0xb4, 0x41, 0xf1, 0xc0, 0x99, 0x2f, 0x02, 0x05, 0x67, 0x26, 0x88,
+ 0x6c, 0x66, 0x71, 0x34, 0x62, 0x9c, 0x75, 0x26, 0xb1, 0xa0, 0xe5, 0xcc,
+ 0xda, 0x94, 0x83, 0xc9, 0x05, 0x73, 0x0e, 0x3c, 0x39, 0xc2, 0xc7, 0xd0,
+ 0xae, 0x38, 0x53, 0x7b, 0x87, 0xdc, 0x01, 0x91, 0x45, 0x59, 0x4f, 0xda,
+ 0xbf, 0xca, 0xcc, 0x52, 0xdb, 0xbb, 0xde, 0xbb, 0xf6, 0xd3, 0x55, 0xff,
+ 0x7d, 0x77, 0x0e, 0x1b, 0xf0, 0xa4, 0xdf, 0xcf, 0xdb, 0x5f, 0x2f, 0xf5,
+ 0xd7, 0x7c, 0xfe, 0xbf, 0x3f, 0xbf, 0x3f, 0x9d, 0x7c, 0xda, 0x2c, 0xc8,
+ 0xc0, 0xc0, 0xb0, 0xe1, 0xf1, 0xb3, 0xfd, 0xfa, 0xdf, 0x8e, 0x7d, 0xef,
+ 0x7f, 0xb9, 0xc1, 0xc2, 0xae, 0x92, 0x19, 0x28, 0xf2, 0x66, 0xd7, 0xe5,
+ 0xbf, 0xed, 0x93, 0xbf, 0x6a, 0x14, 0x7c, 0xff, 0xf6, 0xe1, 0xe8, 0xb6,
+ 0x7e, 0x46, 0xa0, 0x90, 0xd9, 0xbb, 0xcf, 0x9f, 0x17, 0x37, 0x7f, 0xe5,
+ 0x6f, 0xb4, 0x7f, 0xfe, 0x5e, 0xfd, 0xb6, 0x1d, 0x1b, 0x50, 0xe8, 0xc6,
+ 0x8e, 0xe3, 0xab, 0x9f, 0xe6, 0xec, 0x65, 0xfd, 0x23, 0xb1, 0x4e, 0x7e,
+ 0xef, 0xbd, 0x6f, 0xa6, 0x40, 0xa1, 0x03, 0xc7, 0xfe, 0x0a, 0xf1, 0x00,
+ 0xe9, 0x06, 0x91, 0x83, 0x40, 0x92, 0x21, 0x43, 0x10, 0xcc, 0x11, 0x03,
+ 0x73, 0x3a, 0x90, 0x39, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32,
+ 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32,
+ 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32,
+ 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32,
+ 0xa3, 0x32, 0xa3, 0x32, 0xa3, 0x32, 0x34, 0x90, 0x99, 0xb6, 0x7e, 0xf5,
+ 0xd3, 0xe9, 0xbf, 0x35, 0x13, 0xca, 0x8c, 0x75, 0xec, 0xec, 0xa4, 0x2f,
+ 0x7e, 0x2d, 0xf9, 0xf3, 0xf0, 0xee, 0xea, 0xd5, 0xf5, 0xd3, 0x14, 0x57,
+ 0x06, 0x00, 0x00, 0xb9, 0x1e, 0x35, 0xce
+ };
+
+ constexpr qint64 GiB = 1024LL * 1024 * 1024;
+
+ if constexpr (sizeof(qsizetype) == sizeof(int)) {
+ QSKIP("This is a 64-bit-only test.");
+ } else {
+
+ // 1st
+ auto c = ::qUncompress(std::data(compressed_3x), qsizetype(std::size(compressed_3x)));
+ QVERIFY(!c.isNull()); // check for decompression error
+
+ // 2nd
+ c = ::qUncompress(c);
+ QVERIFY(!c.isNull());
+
+ // 3rd
+ try {
+ c = ::qUncompress(c);
+ if (c.isNull()) // this step (~18MiB -> 4GiB) might have run out of memory
+ QSKIP("Failed to allocate enough memory.");
+ } catch (const std::bad_alloc &) {
+ QSKIP("Failed to allocate enough memory.");
+ }
+
+ QCOMPARE(c.size(), 4 * GiB + 1);
+ QCOMPARE(std::string_view{c}.find_first_not_of('X'),
+ std::string_view::npos);
+
+ // re-compress once
+ // (produces 18MiB, we shouldn't use much more than that in allocated capacity)
+ c = ::qCompress(c);
+ QVERIFY(!c.isNull());
+
+ // and un-compress again, to make sure compression worked (we
+ // can't compare with compressed_3x, because zlib may change):
+ c = ::qUncompress(c);
+
+ QCOMPARE(c.size(), 4 * GiB + 1);
+ QCOMPARE(std::string_view{c}.find_first_not_of('X'),
+ std::string_view::npos);
+ }
+}
+
void tst_QByteArray::qCompressionZeroTermination()
{
QString s = "Hello, I'm a string.";
diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp
index d105f32912..2a9b0ba189 100644
--- a/tests/auto/corelib/text/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp
@@ -1361,6 +1361,43 @@ void tst_QString::asprintf()
double d = -514.25683;
QCOMPARE(QString::asprintf("%f", d), QLatin1String("-514.256830"));
+ QCOMPARE(QString::asprintf("%.f", d), QLatin1String("-514"));
+ QCOMPARE(QString::asprintf("%.0f", d), QLatin1String("-514"));
+ QCOMPARE(QString::asprintf("%1f", d), QLatin1String("-514.256830"));
+ QCOMPARE(QString::asprintf("%1.f", d), QLatin1String("-514"));
+ QCOMPARE(QString::asprintf("%1.0f", d), QLatin1String("-514"));
+ QCOMPARE(QString::asprintf("%1.6f", d), QLatin1String("-514.256830"));
+ QCOMPARE(QString::asprintf("%1.10f", d), QLatin1String("-514.2568300000"));
+ QCOMPARE(QString::asprintf("%-1f", d), QLatin1String("-514.256830"));
+ QCOMPARE(QString::asprintf("%-1.f", d), QLatin1String("-514"));
+ QCOMPARE(QString::asprintf("%-1.0f", d), QLatin1String("-514"));
+ QCOMPARE(QString::asprintf("%-1.6f", d), QLatin1String("-514.256830"));
+ QCOMPARE(QString::asprintf("%-1.10f", d), QLatin1String("-514.2568300000"));
+ QCOMPARE(QString::asprintf("%10f", d), QLatin1String("-514.256830"));
+ QCOMPARE(QString::asprintf("%10.f", d), QLatin1String(" -514"));
+ QCOMPARE(QString::asprintf("%10.0f", d), QLatin1String(" -514"));
+ QCOMPARE(QString::asprintf("%-10f", d), QLatin1String("-514.256830"));
+ QCOMPARE(QString::asprintf("%-10.f", d), QLatin1String("-514 "));
+ QCOMPARE(QString::asprintf("%-10.0f", d), QLatin1String("-514 "));
+ QCOMPARE(QString::asprintf("%010f", d), QLatin1String("-514.256830"));
+ QCOMPARE(QString::asprintf("%010.f", d), QLatin1String("-000000514"));
+ QCOMPARE(QString::asprintf("%010.0f", d), QLatin1String("-000000514"));
+ QCOMPARE(QString::asprintf("%15f", d), QLatin1String(" -514.256830"));
+ QCOMPARE(QString::asprintf("%15.6f", d), QLatin1String(" -514.256830"));
+ QCOMPARE(QString::asprintf("%15.10f", d), QLatin1String("-514.2568300000"));
+ QCOMPARE(QString::asprintf("%-15f", d), QLatin1String("-514.256830 "));
+ QCOMPARE(QString::asprintf("%-15.6f", d), QLatin1String("-514.256830 "));
+ QCOMPARE(QString::asprintf("%-15.10f", d), QLatin1String("-514.2568300000"));
+ QCOMPARE(QString::asprintf("%015f", d), QLatin1String("-0000514.256830"));
+ QCOMPARE(QString::asprintf("%015.6f", d), QLatin1String("-0000514.256830"));
+ QCOMPARE(QString::asprintf("%015.10f", d), QLatin1String("-514.2568300000"));
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wformat")
+QT_WARNING_DISABLE_CLANG("-Wformat") // Flag '0' ignored when flag '-' is present
+ QCOMPARE(QString::asprintf("%-015f", d), QLatin1String("-514.256830 "));
+ QCOMPARE(QString::asprintf("%-015.6f", d), QLatin1String("-514.256830 "));
+ QCOMPARE(QString::asprintf("%-015.10f", d), QLatin1String("-514.2568300000"));
+QT_WARNING_POP
{
/* This code crashed. I don't know how to reduce it further. In other words,
diff --git a/tests/auto/corelib/thread/CMakeLists.txt b/tests/auto/corelib/thread/CMakeLists.txt
index 356ae0346c..d51d108d83 100644
--- a/tests/auto/corelib/thread/CMakeLists.txt
+++ b/tests/auto/corelib/thread/CMakeLists.txt
@@ -5,7 +5,7 @@ if(QT_FEATURE_thread)
add_subdirectory(qatomicinteger)
add_subdirectory(qatomicpointer)
add_subdirectory(qresultstore)
- if(NOT INTEGRITY)
+ if(QT_FEATURE_concurrent AND NOT INTEGRITY)
add_subdirectory(qfuture)
endif()
add_subdirectory(qfuturesynchronizer)
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index 7b508b8a22..603d2eb21a 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -2157,6 +2157,26 @@ void tst_QFuture::then()
QVERIFY(threadId1 != QThread::currentThreadId());
QVERIFY(threadId2 != QThread::currentThreadId());
}
+
+ // QTBUG-106083 & QTBUG-105182
+ {
+ QThread thread;
+ thread.start();
+
+ QObject context;
+ context.moveToThread(&thread);
+
+ auto future = QtConcurrent::run([] {
+ return 42;
+ }).then([] (int result) {
+ return result + 1;
+ }).then(&context, [] (int result) {
+ return result + 1;
+ });
+ QCOMPARE(future.result(), 44);
+ thread.quit();
+ thread.wait();
+ }
}
template<class Type, class Callable>
@@ -3033,6 +3053,57 @@ void tst_QFuture::cancelContinuations()
QCOMPARE(checkpoint, 3);
}
#endif // QT_NO_EXCEPTIONS
+
+ // Check notifications from QFutureWatcher
+ {
+ QPromise<void> p;
+ auto f = p.future();
+
+ auto f1 = f.then([] {});
+ auto f2 = f1.then([] {});
+
+ QFutureWatcher<void> watcher1, watcher2;
+ int state = 0;
+ QObject::connect(&watcher1, &QFutureWatcher<void>::started, [&] {
+ QCOMPARE(state, 0);
+ ++state;
+ });
+ QObject::connect(&watcher1, &QFutureWatcher<void>::canceled, [&] {
+ QCOMPARE(state, 1);
+ ++state;
+ });
+ QObject::connect(&watcher1, &QFutureWatcher<void>::finished, [&] {
+ QCOMPARE(state, 2);
+ ++state;
+ });
+ QObject::connect(&watcher2, &QFutureWatcher<void>::started, [&] {
+ QCOMPARE(state, 3);
+ ++state;
+ });
+ QObject::connect(&watcher2, &QFutureWatcher<void>::canceled, [&] {
+ QCOMPARE(state, 4);
+ ++state;
+ });
+ QObject::connect(&watcher2, &QFutureWatcher<int>::finished, [&] {
+ QCOMPARE(state, 5);
+ ++state;
+ });
+
+ watcher1.setFuture(f1);
+ watcher2.setFuture(f2);
+
+ p.start();
+ f.cancel();
+ p.finish();
+
+ qApp->processEvents();
+
+ QCOMPARE(state, 6);
+ QVERIFY(watcher1.isFinished());
+ QVERIFY(watcher1.isCanceled());
+ QVERIFY(watcher2.isFinished());
+ QVERIFY(watcher2.isCanceled());
+ }
}
void tst_QFuture::continuationsWithContext()
diff --git a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
index fb080a1a12..24e8fad4cc 100644
--- a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
+++ b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
@@ -90,9 +90,7 @@ enum {
waitTime = 100
};
-#if __has_include(<chrono>)
static constexpr std::chrono::milliseconds waitTimeAsDuration(waitTime);
-#endif
void tst_QMutex::convertToMilliseconds_data()
{
@@ -101,10 +99,6 @@ void tst_QMutex::convertToMilliseconds_data()
QTest::addColumn<qint64>("intValue");
QTest::addColumn<qint64>("expected");
-#if !__has_include(<chrono>)
- QSKIP("This test requires <chrono>");
-#endif
-
auto add = [](TimeUnit unit, double d, long long i, qint64 expected) {
const QScopedArrayPointer<char> enumName(QTest::toString(unit));
QTest::addRow("%s:%f:%lld", enumName.data(), d, i)
@@ -157,9 +151,6 @@ void tst_QMutex::convertToMilliseconds_data()
void tst_QMutex::convertToMilliseconds()
{
-#if !__has_include(<chrono>)
- QSKIP("This test requires <chrono>");
-#else
QFETCH(TimeUnit, unit);
QFETCH(double, doubleValue);
QFETCH(qint64, intValue);
@@ -197,7 +188,6 @@ void tst_QMutex::convertToMilliseconds()
#undef DO
#undef CASE
}
-#endif
}
void tst_QMutex::tryLock_non_recursive()
@@ -325,10 +315,8 @@ void tst_QMutex::tryLock_non_recursive()
thread.wait();
}
-void tst_QMutex::try_lock_for_non_recursive() {
-#if !__has_include(<chrono>)
- QSKIP("This test requires <chrono>");
-#else
+void tst_QMutex::try_lock_for_non_recursive()
+{
class Thread : public QThread
{
public:
@@ -450,14 +438,10 @@ void tst_QMutex::try_lock_for_non_recursive() {
testsTurn.acquire();
threadsTurn.release();
thread.wait();
-#endif
}
void tst_QMutex::try_lock_until_non_recursive()
{
-#if !__has_include(<chrono>)
- QSKIP("This test requires <chrono>");
-#else
class Thread : public QThread
{
public:
@@ -579,7 +563,6 @@ void tst_QMutex::try_lock_until_non_recursive()
testsTurn.acquire();
threadsTurn.release();
thread.wait();
-#endif
}
void tst_QMutex::tryLock_recursive()
@@ -708,9 +691,6 @@ void tst_QMutex::tryLock_recursive()
void tst_QMutex::try_lock_for_recursive()
{
-#if !__has_include(<chrono>)
- QSKIP("This test requires <chrono>");
-#else
class Thread : public QThread
{
public:
@@ -831,14 +811,10 @@ void tst_QMutex::try_lock_for_recursive()
testsTurn.acquire();
threadsTurn.release();
thread.wait();
-#endif
}
void tst_QMutex::try_lock_until_recursive()
{
-#if !__has_include(<chrono>)
- QSKIP("This test requires <chrono>");
-#else
class Thread : public QThread
{
public:
@@ -960,7 +936,6 @@ void tst_QMutex::try_lock_until_recursive()
testsTurn.acquire();
threadsTurn.release();
thread.wait();
-#endif
}
class mutex_Thread : public QThread
diff --git a/tests/auto/corelib/tools/collections/tst_collections.cpp b/tests/auto/corelib/tools/collections/tst_collections.cpp
index be2a4dbc05..6c0f0f86ac 100644
--- a/tests/auto/corelib/tools/collections/tst_collections.cpp
+++ b/tests/auto/corelib/tools/collections/tst_collections.cpp
@@ -63,6 +63,9 @@ void foo()
#include <QTest>
#include <QVector>
+#include <QScopedPointer>
+#include <QThread>
+#include <QSemaphore>
#include <algorithm>
@@ -123,6 +126,15 @@ private slots:
void foreach_2();
void insert_remove_loop();
+
+ void detachAssociativeContainerQMap() { detachAssociativeContainerImpl<QMap>(); }
+ void detachAssociativeContainerQMultiMap() { detachAssociativeContainerImpl<QMultiMap>(); }
+ void detachAssociativeContainerQHash() { detachAssociativeContainerImpl<QHash>(); }
+ void detachAssociativeContainerQMultiHash() { detachAssociativeContainerImpl<QMultiHash>(); }
+
+private:
+ template <template<typename, typename> typename Container>
+ void detachAssociativeContainerImpl();
};
struct LargeStatic {
@@ -3547,7 +3559,63 @@ void tst_Collections::insert_remove_loop()
insert_remove_loop_impl<QVarLengthArray<std::string, 15>>();
}
+template <template<typename, typename> typename Container>
+void tst_Collections::detachAssociativeContainerImpl()
+{
+ constexpr int RUNS = 50;
+
+ for (int run = 0; run < RUNS; ++run) {
+ Container<int, int> container;
+
+ for (int i = 0; i < 1'000; ++i) {
+ container.insert(i, i);
+ container.insert(i, i); // for multi-keyed containers
+ }
+
+ const auto it = container.constBegin();
+ const auto &key = it.key();
+ const auto &value = it.value();
+ const auto keyCopy = key;
+ const auto valueCopy = value;
+
+ QSemaphore sem1, sem2;
+ auto detachInAnotherThread = [&sem1, &sem2, copy = container]() mutable {
+ sem1.release();
+ sem2.acquire();
+ copy.clear(); // <==
+ };
+ QScopedPointer thread(QThread::create(std::move(detachInAnotherThread)));
+ thread->start();
+
+ sem2.release();
+ sem1.acquire();
+
+ // The following call may detach (because the container is
+ // shared), and then use key/value to search+insert.
+ //
+ // This means that key/value, as references, have to be valid
+ // throughout the insertion procedure. Note that they are
+ // references into the container *itself*; and that the
+ // insertion procedure is working on a new (detached) copy of
+ // the container's payload.
+ //
+ // There is now a possible scenario in which the clear() above
+ // finds the copy's refcount at 1, hence not perform a detach,
+ // and destroy its payload. But key/value were references into
+ // *that* payload (it's the payload that `container` itself
+ // used to share). If inside insert() we don't take extra
+ // measures to keep the payload alive, now they're dangling and
+ // the insertion will malfunction.
+
+ container.insert(key, value);
+
+ QVERIFY(container.contains(keyCopy));
+ QCOMPARE(container.value(keyCopy), valueCopy);
+
+ thread->wait();
+ }
+}
QTEST_APPLESS_MAIN(tst_Collections)
#include "tst_collections.moc"
diff --git a/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp b/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp
index 263083972c..79943a99eb 100644
--- a/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp
+++ b/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp
@@ -168,6 +168,7 @@ void tst_QBitArray::countBits()
bits.setBit(i);
}
+ QCOMPARE(bits.size(), numBits);
QCOMPARE(bits.count(), numBits);
QCOMPARE(bits.count(true), onBits);
QCOMPARE(bits.count(false), numBits - onBits);
diff --git a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
index b25ed55648..59cb9648b7 100644
--- a/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
+++ b/tests/auto/corelib/tools/qcontiguouscache/tst_qcontiguouscache.cpp
@@ -75,10 +75,12 @@ void tst_QContiguousCache::empty()
{
QContiguousCache<int> c(10);
QCOMPARE(c.capacity(), 10);
+ QCOMPARE(c.size(), 0);
QCOMPARE(c.count(), 0);
QVERIFY(c.isEmpty());
c.append(1);
QCOMPARE(c.count(), 1);
+ QCOMPARE(c.size(), 1);
QVERIFY(!c.isEmpty());
c.clear();
QCOMPARE(c.capacity(), 10);
diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp
index 2dd5db6e8a..3febe1a73f 100644
--- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp
+++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp
@@ -1866,12 +1866,6 @@ void tst_QMap::equal_range()
QCOMPARE(map.count(1), 2);
}
-template <class T>
-const T &const_(const T &t)
-{
- return t;
-}
-
void tst_QMap::insert()
{
QMap<QString, float> map;
diff --git a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp
index dcc966fc2f..d1e89d407b 100644
--- a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp
+++ b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp
@@ -36,6 +36,7 @@ class tst_QTaggedPointer : public QObject
private Q_SLOTS:
void constExpr();
void construction();
+ void assignment();
void dereferenceOperator();
void pointerOperator();
void negationOperator();
@@ -105,6 +106,47 @@ void tst_QTaggedPointer::construction()
}
}
+void tst_QTaggedPointer::assignment()
+{
+ QScopedPointer<int> rawPointer(new int(5));
+ QTaggedPointer<int> p(rawPointer.data(), 0x1);
+ QTaggedPointer<int> p2(rawPointer.data(), 0x2);
+
+ QCOMPARE(p.data(), rawPointer.data());
+ QCOMPARE(p.tag(), quintptr(0x1));
+
+ QCOMPARE(p2.data(), rawPointer.data());
+ QCOMPARE(p2.tag(), quintptr(0x2));
+
+ p = nullptr;
+ QCOMPARE(p.data(), nullptr);
+ QCOMPARE(p.tag(), quintptr(0x1));
+
+ p = rawPointer.data();
+ QCOMPARE(p.data(), rawPointer.data());
+ QCOMPARE(p.tag(), quintptr(0x1));
+
+ p = {};
+ QCOMPARE(p.data(), nullptr);
+ QCOMPARE(p.tag(), quintptr(0x0));
+
+ p = p2;
+ QCOMPARE(p.data(), rawPointer.data());
+ QCOMPARE(p.tag(), quintptr(0x2));
+
+ p = nullptr;
+ QCOMPARE(p.data(), nullptr);
+ QCOMPARE(p.tag(), quintptr(0x2));
+
+ p = {};
+ QCOMPARE(p.data(), nullptr);
+ QCOMPARE(p.tag(), quintptr(0x0));
+
+ p = rawPointer.data();
+ QCOMPARE(p.data(), rawPointer.data());
+ QCOMPARE(p.tag(), quintptr(0x0));
+}
+
class AbstractClass
{
public:
diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
index b0c59245b1..b504cf1561 100644
--- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
+++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
@@ -1038,8 +1038,6 @@ void tst_QGuiApplication::genericPluginsAndWindowSystemEvents()
QVERIFY(QGuiApplication::primaryScreen());
QCOMPARE(QGuiApplication::primaryScreen()->orientation(), testOrientationToSend);
- if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
- QEXPECT_FAIL("", "Wayland: This fails. See QTBUG-100891.", Abort);
QCOMPARE(testReceiver.customEvents, 0);
QCoreApplication::sendPostedEvents(&testReceiver);
QCOMPARE(testReceiver.customEvents, 1);
diff --git a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
index a81e6187e5..13365b01fe 100644
--- a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
+++ b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
@@ -47,6 +47,7 @@ private Q_SLOTS:
void noBrushesSetForDefaultPalette();
void cannotCheckIfInvalidBrushSet();
void checkIfBrushForCurrentGroupSet();
+ void cacheKey();
};
void tst_QPalette::roleValues_data()
@@ -290,5 +291,61 @@ void tst_QPalette::checkIfBrushForCurrentGroupSet()
QVERIFY(p.isBrushSet(QPalette::Current, QPalette::Link));
}
+void tst_QPalette::cacheKey()
+{
+ const QPalette defaultPalette;
+ // precondition: all palettes are expected to have contrasting text on base
+ QVERIFY(defaultPalette.base() != defaultPalette.text());
+ const auto defaultCacheKey = defaultPalette.cacheKey();
+ const auto defaultSerNo = defaultCacheKey >> 32;
+ const auto defaultDetachNo = defaultCacheKey & 0xffffffff;
+
+ QPalette copyDifferentData(defaultPalette);
+ QPalette copyDifferentMask(defaultPalette);
+ QPalette copyDifferentMaskAndData(defaultPalette);
+
+ QCOMPARE(defaultPalette.cacheKey(), copyDifferentData.cacheKey());
+
+ // deep detach of both private and data
+ copyDifferentData.setBrush(QPalette::Base, defaultPalette.text());
+ const auto differentDataKey = copyDifferentData.cacheKey();
+ const auto differentDataSerNo = differentDataKey >> 32;
+ const auto differentDataDetachNo = differentDataKey & 0xffffffff;
+
+ QVERIFY(copyDifferentData.cacheKey() != defaultCacheKey);
+ QCOMPARE(defaultPalette.cacheKey(), defaultCacheKey);
+
+ // shallow detach, both privates reference the same data
+ copyDifferentMask.setResolveMask(0xffffffffffffffff);
+ const auto differentMaskKey = copyDifferentMask.cacheKey();
+ const auto differentMaskSerNo = differentMaskKey >> 32;
+ const auto differentMaskDetachNo = differentMaskKey & 0xffffffff;
+ QCOMPARE(differentMaskSerNo, defaultSerNo);
+ QVERIFY(differentMaskSerNo != defaultDetachNo);
+ QVERIFY(differentMaskKey != defaultCacheKey);
+ QVERIFY(differentMaskKey != differentDataKey);
+
+ // shallow detach, both privates reference the same data
+ copyDifferentMaskAndData.setResolveMask(0xeeeeeeeeeeeeeeee);
+ const auto modifiedCacheKey = copyDifferentMaskAndData.cacheKey();
+ QVERIFY(modifiedCacheKey != copyDifferentMask.cacheKey());
+ QVERIFY(modifiedCacheKey != defaultCacheKey);
+ QVERIFY(modifiedCacheKey != copyDifferentData.cacheKey());
+ QVERIFY(copyDifferentMask.cacheKey() != defaultCacheKey);
+
+ // full detach - both key elements are different
+ copyDifferentMaskAndData.setBrush(QPalette::Base, defaultPalette.text());
+ const auto modifiedAllKey = copyDifferentMaskAndData.cacheKey();
+ const auto modifiedAllSerNo = modifiedAllKey >> 32;
+ const auto modifiedAllDetachNo = modifiedAllKey & 0xffffffff;
+ QVERIFY(modifiedAllSerNo != defaultSerNo);
+ QVERIFY(modifiedAllDetachNo != defaultDetachNo);
+
+ QVERIFY(modifiedAllKey != copyDifferentMask.cacheKey());
+ QVERIFY(modifiedAllKey != defaultCacheKey);
+ QVERIFY(modifiedAllKey != differentDataKey);
+ QVERIFY(modifiedAllKey != modifiedCacheKey);
+}
+
QTEST_MAIN(tst_QPalette)
#include "tst_qpalette.moc"
diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
index 8deb4589c6..7310cb5596 100644
--- a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
+++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp
@@ -39,6 +39,8 @@
#include <private/qevent_p.h>
#include <private/qhighdpiscaling_p.h>
#include <private/qpointingdevice_p.h>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
Q_LOGGING_CATEGORY(lcTests, "qt.gui.tests")
@@ -1149,6 +1151,9 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad()
QSKIP("The macOS mouse cursor interferes with this test can cannot be moved away");
#endif
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
tst_QTouchEventWidget touchWidget;
touchWidget.setObjectName("touchWidget");
touchWidget.setWindowTitle(QTest::currentTestFunction());
diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
index 5e7cd0f801..17e812297f 100644
--- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
+++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
@@ -95,6 +95,7 @@ private slots:
void modalWithChildWindow();
void modalWindowModallity();
void modalWindowPosition();
+ void modalCloseWhileBlocked();
#ifndef QT_NO_CURSOR
void modalWindowEnterEventOnHide_QTBUG35109();
void spuriousMouseMove();
@@ -2305,6 +2306,22 @@ void tst_QWindow::modalWindowPosition()
QCOMPARE(window.geometry(), origGeo);
}
+void tst_QWindow::modalCloseWhileBlocked()
+{
+ QWindow first;
+ first.setModality(Qt::ApplicationModal);
+ first.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&first));
+
+ QWindow second;
+ second.setModality(Qt::ApplicationModal);
+ second.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&first));
+
+ first.close();
+ QTRY_VERIFY(!first.isVisible());
+}
+
#ifndef QT_NO_CURSOR
void tst_QWindow::modalWindowEnterEventOnHide_QTBUG35109()
{
diff --git a/tests/auto/gui/qopengl/tst_qopengl.cpp b/tests/auto/gui/qopengl/tst_qopengl.cpp
index 5d9053fb92..34bd12fdb1 100644
--- a/tests/auto/gui/qopengl/tst_qopengl.cpp
+++ b/tests/auto/gui/qopengl/tst_qopengl.cpp
@@ -1651,8 +1651,6 @@ void tst_QOpenGL::bufferMapRange()
buf.unmap();
p = (char *) buf.mapRange(0, sizeof(data), QOpenGLBuffer::RangeRead);
- if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
- QEXPECT_FAIL("", "This fails on Wayland, see QTBUG-100918.", Abort);
QVERIFY(!strcmp(p, "sOMe data"));
buf.unmap();
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 550284c9a0..4c599ba258 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -280,6 +280,7 @@ private Q_SLOTS:
void ioGetFromFileSpecial();
void ioGetFromFile_data();
void ioGetFromFile();
+ void ioGetFromFileUrl();
void ioGetFromFtp_data();
void ioGetFromFtp();
void ioGetFromFtpWithReuse();
@@ -3315,6 +3316,18 @@ void tst_QNetworkReply::ioGetFromFile()
QCOMPARE(reader.data, data);
}
+void tst_QNetworkReply::ioGetFromFileUrl()
+{
+ // This immediately fails on non-windows platforms:
+ QNetworkRequest request(QUrl("file://unc-server/some/path"));
+ QNetworkReplyPtr reply(manager.get(request));
+ QSignalSpy finishedSpy(reply.get(), &QNetworkReply::finished);
+ // QTBUG-105618: This would, on non-Windows platforms, never happen because the signal
+ // was emitted before the constructor finished, leaving no chance at all to connect to the
+ // signal
+ QVERIFY(finishedSpy.wait());
+}
+
void tst_QNetworkReply::ioGetFromFtp_data()
{
if (!ftpSupported)
diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp
index 78f072fb54..ef45561f1a 100644
--- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp
+++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp
@@ -351,6 +351,12 @@ void tst_QHostAddress::isEqual_data()
QTest::newRow("anyv6-anyv4-local") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::ConvertLocalHost << false;
QTest::newRow("any-anyv4-local") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::ConvertLocalHost << false;
QTest::newRow("any-anyv6-local") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv6) << (int)QHostAddress::ConvertLocalHost << false;
+ QTest::newRow("localhostv6-any-tolerant") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::Any) << (int)QHostAddress::TolerantConversion << false;
+ QTest::newRow("localhostv4-any-tolerant") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::Any) << (int)QHostAddress::TolerantConversion << false;
+ QTest::newRow("localhostv6-anyv6-tolerant") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::AnyIPv6) << (int)QHostAddress::TolerantConversion << false;
+ QTest::newRow("localhostv4-anyv6-tolerant") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::AnyIPv6) << (int)QHostAddress::TolerantConversion << false;
+ QTest::newRow("localhostv6-anyv4-tolerant") << QHostAddress(QHostAddress::LocalHostIPv6) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::TolerantConversion << false;
+ QTest::newRow("localhostv4-anyv4-tolerant") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::AnyIPv4) << (int)QHostAddress::TolerantConversion << false;
}
void tst_QHostAddress::isEqual()
diff --git a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
index a9a591d5ca..479d0f878f 100644
--- a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
+++ b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST
@@ -1,8 +1,7 @@
[udpTest]
*
[passwordAuth]
-ubuntu-18.04
-ubuntu-20.04
+ubuntu
# QTBUG-101274
qnx ci
# QTBUG-74162
diff --git a/tests/auto/network/socket/qtcpserver/BLACKLIST b/tests/auto/network/socket/qtcpserver/BLACKLIST
index ecca156cef..339987046c 100644
--- a/tests/auto/network/socket/qtcpserver/BLACKLIST
+++ b/tests/auto/network/socket/qtcpserver/BLACKLIST
@@ -15,4 +15,3 @@ windows-10
[linkLocal]
macos arm
-
diff --git a/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp b/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp
index 7cb65cd1a3..758a396a35 100644
--- a/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp
+++ b/tests/auto/network/socket/qtcpserver/crashingServer/main.cpp
@@ -32,6 +32,9 @@
#if defined(Q_OS_WIN) && defined(Q_CC_MSVC)
# include <crtdbg.h>
#endif
+#ifdef Q_OS_UNIX
+# include <unistd.h>
+#endif
int main(int argc, char *argv[])
{
@@ -40,10 +43,26 @@ int main(int argc, char *argv[])
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
#endif
QCoreApplication app(argc, argv);
+ if (argc < 1) {
+ fprintf(stderr, "Need a port number\n");
+ return 1;
+ }
+ int port = QByteArray(argv[1]).toInt();
QTcpServer server;
- if (!server.listen(QHostAddress::LocalHost, 49199)) {
- qDebug("Failed to listen: %s", server.errorString().toLatin1().constData());
+ if (!server.listen(QHostAddress::LocalHost, port)) {
+ fprintf(stderr, "Failed to listen: %s\n", server.errorString().toLatin1().constData());
+ if (server.serverError() == QTcpSocket::AddressInUseError) {
+ // let's see if we can find the process that would be holding this
+ // still open
+#ifdef Q_OS_LINUX
+ static const char *ss_args[] = {
+ "ss", "-nap", "sport", "=", argv[1], nullptr
+ };
+ dup2(STDERR_FILENO, STDOUT_FILENO);
+ execvp(ss_args[0], const_cast<char **>(ss_args));
+#endif
+ }
return 1;
}
diff --git a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
index 5c2849249d..2ae629315b 100644
--- a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
+++ b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp
@@ -598,9 +598,6 @@ void tst_QTcpServer::addressReusable()
#if !QT_CONFIG(process)
QSKIP("No qprocess support", SkipAll);
#else
-#ifdef Q_OS_LINUX
- QSKIP("The addressReusable test is unstable on Linux. See QTBUG-39985.");
-#endif
QFETCH_GLOBAL(bool, setProxy);
if (setProxy) {
#ifndef QT_NO_NETWORKPROXY
@@ -611,16 +608,25 @@ void tst_QTcpServer::addressReusable()
QSKIP("No proxy support");
#endif // QT_NO_NETWORKPROXY
}
+
+ QTcpServer server;
+ QVERIFY(server.listen(QHostAddress::LocalHost, 0));
+ quint16 serverPort = server.serverPort();
+ qDebug() << "Got port" << serverPort;
+ server.close(); // cleanly close
+
+ QTest::qSleep(10);
+
// The crashingServer process will crash once it gets a connection.
QProcess process;
QString processExe = crashingServerDir + "/crashingServer";
- process.start(processExe);
+ process.start(processExe, { QString::number(serverPort) });
QVERIFY2(process.waitForStarted(), qPrintable(
QString::fromLatin1("Could not start %1: %2").arg(processExe, process.errorString())));
- QVERIFY(process.waitForReadyRead(5000));
+ QVERIFY2(process.waitForReadyRead(5000), qPrintable(process.readAllStandardError()));
QTcpSocket socket;
- socket.connectToHost(QHostAddress::LocalHost, 49199);
+ socket.connectToHost(QHostAddress::LocalHost, serverPort);
QVERIFY(socket.waitForConnected(5000));
QVERIFY(process.waitForFinished(30000));
@@ -628,8 +634,9 @@ void tst_QTcpServer::addressReusable()
// Give the system some time.
QTest::qSleep(10);
- QTcpServer server;
- QVERIFY(server.listen(QHostAddress::LocalHost, 49199));
+ // listen again
+ QVERIFY2(server.listen(QHostAddress::LocalHost, serverPort),
+ qPrintable(server.errorString()));
#endif
}
diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
index 7e5666decd..f2c6b0871f 100644
--- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
+++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp
@@ -653,7 +653,7 @@ void tst_QUdpSocket::dualStack()
QCOMPARE(dgram.senderAddress(), makeNonAny(v4Sock.localAddress(), QHostAddress::Null));
if (dgram.destinationPort() != -1) {
QCOMPARE(dgram.destinationPort(), int(dualSock.localPort()));
- QVERIFY(dgram.destinationAddress().isEqual(dualSock.localAddress()));
+ QVERIFY(dgram.destinationAddress().isEqual(makeNonAny(dualSock.localAddress(), QHostAddress::LocalHost)));
} else {
qInfo("Getting IPv4 destination address failed.");
}
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index bd3816378e..afcf5fe722 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -1455,7 +1455,7 @@ public:
config(QSslConfiguration::defaultConfiguration()),
ignoreSslErrors(true),
peerVerifyMode(QSslSocket::AutoVerifyPeer),
- protocol(QSsl::TlsV1_0),
+ protocol(QSsl::TlsV1_2),
m_keyFile(keyFile),
m_certFile(certFile),
m_interFile(interFile)
diff --git a/tests/auto/other/android/CMakeLists.txt b/tests/auto/other/android/CMakeLists.txt
deleted file mode 100644
index c2749825ac..0000000000
--- a/tests/auto/other/android/CMakeLists.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-# Generated from android.pro.
-
-#####################################################################
-## tst_android Test:
-#####################################################################
-
-qt_internal_add_test(tst_android
- SOURCES
- tst_android.cpp
-)
-
-if(ANDROID)
- set_property(TARGET tst_android APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
- ${CMAKE_CURRENT_SOURCE_DIR}/testdata
- )
- # QTBUG-88840 # special case
- qt_android_generate_deployment_settings(tst_android) # special case
-endif()
-
-#### Keys ignored in scope 1:.:.:android.pro:<TRUE>:
-# DISTFILES = "testdata/assets/test.txt"
diff --git a/tests/auto/other/android/testdata/assets/test.txt b/tests/auto/other/android/testdata/assets/test.txt
deleted file mode 100644
index 61e2c47c25..0000000000
--- a/tests/auto/other/android/testdata/assets/test.txt
+++ /dev/null
@@ -1 +0,0 @@
-FooBar \ No newline at end of file
diff --git a/tests/auto/other/android/tst_android.cpp b/tests/auto/other/android/tst_android.cpp
deleted file mode 100644
index 3a00d9414b..0000000000
--- a/tests/auto/other/android/tst_android.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <jni.h>
-
-#include <QTest>
-#include <QtCore/qnativeinterface.h>
-#include <QtCore/qjniobject.h>
-
-class tst_Android : public QObject
-{
-Q_OBJECT
-private slots:
- void assetsRead();
- void assetsNotWritable();
- void testAndroidSdkVersion();
- void testAndroidActivity();
-};
-
-void tst_Android::assetsRead()
-{
- {
- QFile file(QStringLiteral("assets:/test.txt"));
- QVERIFY(file.open(QIODevice::ReadOnly));
- QCOMPARE(file.readAll(), QByteArray("FooBar"));
- }
-
- {
- QFile file(QStringLiteral("assets:/test.txt"));
- QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
- QCOMPARE(file.readAll(), QByteArray("FooBar"));
- }
-}
-
-void tst_Android::assetsNotWritable()
-{
- QFile file(QStringLiteral("assets:/test.txt"));
- QVERIFY(!file.open(QIODevice::WriteOnly));
- QVERIFY(!file.open(QIODevice::ReadWrite));
- QVERIFY(!file.open(QIODevice::Append));
-}
-
-void tst_Android::testAndroidSdkVersion()
-{
- QVERIFY(QNativeInterface::QAndroidApplication::sdkVersion() > 0);
-}
-
-void tst_Android::testAndroidActivity()
-{
- QJniObject activity = QNativeInterface::QAndroidApplication::context();
- QVERIFY(activity.isValid());
- QVERIFY(activity.callMethod<jboolean>("isTaskRoot"));
-}
-
-QTEST_MAIN(tst_Android)
-#include "tst_android.moc"
-
diff --git a/tests/auto/other/gestures/BLACKLIST b/tests/auto/other/gestures/BLACKLIST
index 5b4f12b80d..494005abf3 100644
--- a/tests/auto/other/gestures/BLACKLIST
+++ b/tests/auto/other/gestures/BLACKLIST
@@ -1,32 +1,10 @@
-[]
-rhel
-centos
-ubuntu-18.04
-ubuntu-20.04
[customGesture]
opensuse-leap
# QTBUG-67254
opensuse-42.3
-[graphicsItemGesture]
-ubuntu-18.04
-ubuntu-20.04
-rhel
-centos
-[graphicsItemTreeGesture]
-ubuntu-18.04
-ubuntu-20.04
-[graphicsView]
-ubuntu-18.04
-ubuntu-20.04
-rhel
-centos
-[explicitGraphicsObjectTarget]
-ubuntu-18.04
+[panelPropagation]
ubuntu-20.04
-rhel
-centos
-[autoCancelGestures2]
-ubuntu-18.04
+ubuntu-22.04 ci
+[panelStacksBehindParent]
ubuntu-20.04
-rhel
-centos
+ubuntu-22.04 ci
diff --git a/tests/auto/other/gestures/tst_gestures.cpp b/tests/auto/other/gestures/tst_gestures.cpp
index 48cd355554..1fb7b5c343 100644
--- a/tests/auto/other/gestures/tst_gestures.cpp
+++ b/tests/auto/other/gestures/tst_gestures.cpp
@@ -342,6 +342,8 @@ private slots:
void testQGestureRecognizerCleanup();
void testReuseCanceledGestures();
void bug_13501_gesture_not_accepted();
+private:
+ QPoint m_availableTopLeft;
};
void tst_Gestures::initTestCase()
@@ -349,6 +351,8 @@ void tst_Gestures::initTestCase()
CustomGesture::GestureType = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
QVERIFY(CustomGesture::GestureType != Qt::GestureType(0));
QVERIFY(CustomGesture::GestureType != Qt::CustomGesture);
+ const QScreen *screen = QGuiApplication::primaryScreen();
+ m_availableTopLeft = screen->availableGeometry().topLeft();
}
void tst_Gestures::cleanupTestCase()
@@ -824,6 +828,7 @@ void tst_Gestures::graphicsItemGesture()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.move(m_availableTopLeft);
GestureItem *item = new GestureItem("item");
scene.addItem(item);
@@ -886,6 +891,7 @@ void tst_Gestures::graphicsView()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.move(m_availableTopLeft);
GestureItem *item = new GestureItem("item");
scene.addItem(item);
@@ -951,6 +957,7 @@ void tst_Gestures::graphicsItemTreeGesture()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.move(m_availableTopLeft);
GestureItem *item1 = new GestureItem("item1");
item1->setPos(100, 100);
@@ -1008,6 +1015,7 @@ void tst_Gestures::explicitGraphicsObjectTarget()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.move(m_availableTopLeft);
GestureItem *item1 = new GestureItem("item1");
scene.addItem(item1);
@@ -1557,6 +1565,7 @@ void tst_Gestures::autoCancelGestures2()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.move(m_availableTopLeft);
MockItem *parent = new MockItem("parent");
GestureItem *child = new GestureItem("child");
@@ -1593,6 +1602,7 @@ void tst_Gestures::graphicsViewParentPropagation()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.move(m_availableTopLeft);
GestureItem *item0 = new GestureItem("item0");
scene.addItem(item0);
@@ -1653,6 +1663,7 @@ void tst_Gestures::panelPropagation()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.move(m_availableTopLeft);
GestureItem *item0 = new GestureItem("item0");
scene.addItem(item0);
@@ -1777,6 +1788,7 @@ void tst_Gestures::panelStacksBehindParent()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.move(m_availableTopLeft);
GestureItem *item1 = new GestureItem("item1");
item1->grabGesture(CustomGesture::GestureType);
@@ -1964,6 +1976,7 @@ void tst_Gestures::partialGesturePropagation()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.move(m_availableTopLeft);
GestureItem *item1 = new GestureItem("item1");
item1->grabGesture(CustomGesture::GestureType);
@@ -2176,6 +2189,7 @@ void tst_Gestures::testReuseCanceledGestures()
mw.setWindowFlags(Qt::X11BypassWindowManagerHint);
QGraphicsView *gv = new QGraphicsView(&mw);
QGraphicsScene *scene = new QGraphicsScene;
+ mw.move(m_availableTopLeft);
gv->setScene(scene);
scene->setSceneRect(0,0,100,100);
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index b7b50ccf4f..6f6bbb8ae1 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -4225,6 +4225,47 @@ void tst_QAccessibility::focusChild()
QVERIFY(child);
QCOMPARE(child->text(QAccessible::Name), QStringLiteral("Klimt"));
}
+ {
+ QWidget window;
+ // takes the initial focus
+ QLineEdit lineEdit;
+ QComboBox comboBox;
+ comboBox.addItems({"One", "Two", "Three"});
+ QComboBox editableComboBox;
+ editableComboBox.setEditable(true);
+ editableComboBox.addItems({"A", "B", "C"});
+ QVBoxLayout vbox;
+ vbox.addWidget(&lineEdit);
+ vbox.addWidget(&comboBox);
+ vbox.addWidget(&editableComboBox);
+ window.setLayout(&vbox);
+
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QTestAccessibility::clearEvents();
+ QAccessibleInterface *iface = nullptr;
+
+ comboBox.setFocus();
+ {
+ QAccessibleEvent focusEvent(&comboBox, QAccessible::Focus);
+ QVERIFY(QTestAccessibility::containsEvent(&focusEvent));
+ }
+ iface = QAccessible::queryAccessibleInterface(&comboBox);
+ QVERIFY(iface);
+ QCOMPARE(iface->focusChild(), nullptr);
+
+ editableComboBox.setFocus();
+ // Qt updates about the editable combobox, not the lineedit, as the
+ // combobox is the lineedit's focus proxy.
+ {
+ QAccessibleEvent focusEvent(&editableComboBox, QAccessible::Focus);
+ QVERIFY(QTestAccessibility::containsEvent(&focusEvent));
+ }
+ iface = QAccessible::queryAccessibleInterface(&editableComboBox);
+ QVERIFY(iface);
+ QVERIFY(iface->focusChild());
+ QCOMPARE(iface->focusChild()->role(), QAccessible::EditableText);
+ }
}
diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h
index 74fa06ab29..642d4af9cf 100644
--- a/tests/auto/sql/kernel/qsqldatabase/tst_databases.h
+++ b/tests/auto/sql/kernel/qsqldatabase/tst_databases.h
@@ -207,6 +207,14 @@ public:
if ( port > 0 )
cName += QLatin1Char(':') + QString::number( port );
+ if (driver == "QSQLITE") {
+ // Since the database for sqlite is generated at runtime it's always
+ // available, but we use QTempDir so it's always in a different
+ // location. Thus, let's ignore the path completely.
+ cName = "SQLite";
+ qInfo("SQLite will use the database located at %ls", qUtf16Printable(dbName));
+ }
+
db = QSqlDatabase::addDatabase( driver, cName );
if ( !db.isValid() ) {
@@ -275,7 +283,7 @@ public:
}
QTemporaryDir *sqLiteDir = dbDir();
if (sqLiteDir) {
- addDb(QStringLiteral("QSQLITE"), QDir::toNativeSeparators(sqLiteDir->path() + QStringLiteral("/foo.db")));
+ addDb(QStringLiteral("QSQLITE"), QDir::toNativeSeparators(sqLiteDir->path() + QStringLiteral("/sqlite.db")));
added = true;
}
return added;
diff --git a/tests/auto/testlib/selftests/catch_p_p.h b/tests/auto/testlib/selftests/catch_p_p.h
index 9034ac2204..f22183557d 100644
--- a/tests/auto/testlib/selftests/catch_p_p.h
+++ b/tests/auto/testlib/selftests/catch_p_p.h
@@ -1,6 +1,6 @@
/*
- * Catch v2.13.9
- * Generated: 2022-04-12 22:37:23.260201
+ * Catch v2.13.10
+ * Generated: 2022-10-16 11:01:23.452308
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved.
@@ -15,7 +15,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 13
-#define CATCH_VERSION_PATCH 9
+#define CATCH_VERSION_PATCH 10
#ifdef __clang__
# pragma clang system_header
@@ -7395,8 +7395,6 @@ namespace Catch {
template <typename T, bool Destruct>
struct ObjectStorage
{
- using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
-
ObjectStorage() : data() {}
ObjectStorage(const ObjectStorage& other)
@@ -7439,7 +7437,7 @@ namespace Catch {
return *static_cast<T*>(static_cast<void*>(&data));
}
- TStorage data;
+ struct { alignas(T) unsigned char data[sizeof(T)]; } data;
};
}
@@ -7949,7 +7947,7 @@ namespace Catch {
#if defined(__i386__) || defined(__x86_64__)
#define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
#elif defined(__aarch64__)
- #define CATCH_TRAP() __asm__(".inst 0xd4200000")
+ #define CATCH_TRAP() __asm__(".inst 0xd43e0000")
#endif
#elif defined(CATCH_PLATFORM_IPHONE)
@@ -13560,7 +13558,7 @@ namespace Catch {
// Handle list request
if( Option<std::size_t> listed = list( m_config ) )
- return static_cast<int>( *listed );
+ return (std::min) (MaxExitCode, static_cast<int>(*listed));
TestGroup tests { m_config };
auto const totals = tests.execute();
@@ -15393,7 +15391,7 @@ namespace Catch {
}
Version const& libraryVersion() {
- static Version version( 2, 13, 9, "", 0 );
+ static Version version( 2, 13, 10, "", 0 );
return version;
}
@@ -17528,12 +17526,20 @@ namespace Catch {
#ifndef __OBJC__
+#ifndef CATCH_INTERNAL_CDECL
+#ifdef _MSC_VER
+#define CATCH_INTERNAL_CDECL __cdecl
+#else
+#define CATCH_INTERNAL_CDECL
+#endif
+#endif
+
#if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
// Standard C/C++ Win32 Unicode wmain entry point
-extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
+extern "C" int CATCH_INTERNAL_CDECL wmain (int argc, wchar_t * argv[], wchar_t * []) {
#else
// Standard C/C++ main entry point
-int main (int argc, char * argv[]) {
+int CATCH_INTERNAL_CDECL main (int argc, char * argv[]) {
#endif
return Catch::Session().run( argc, argv );
diff --git a/tests/auto/testlib/selftests/qt_attribution.json b/tests/auto/testlib/selftests/qt_attribution.json
index 6c483749a1..3a126f59ed 100644
--- a/tests/auto/testlib/selftests/qt_attribution.json
+++ b/tests/auto/testlib/selftests/qt_attribution.json
@@ -8,7 +8,7 @@
"Description": "Catch2 is a multi-paradigm test framework for C++.",
"Homepage": "https://github.com/catchorg/Catch2",
- "Version": "2.13.8",
+ "Version": "2.13.10",
"License": "Boost Software License 1.0",
"LicenseId": "BSL-1.0",
"LicenseFile": "CATCH_LICENSE.txt",
diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp
index 69853f3d95..f8461b1b5c 100644
--- a/tests/auto/testlib/selftests/tst_selftests.cpp
+++ b/tests/auto/testlib/selftests/tst_selftests.cpp
@@ -660,6 +660,11 @@ bool TestLogger::shouldIgnoreTest(const QString &test) const
return true;
#endif
+ if (!qEnvironmentVariableIsEmpty("WAYLAND_DISPLAY")) {
+ qDebug() << "TestLogger::shouldIgnoreTest() ignore" << test << "on wayland/xwayland!";
+ return true;
+ }
+
if (test == "deleteLater" || test == "deleteLater_noApp" || test == "mouse")
return true; // Missing expectation files
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index c9c80f1e3b..9227cc26d3 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -87,6 +87,15 @@
const char *string_hash_hash = STRING_HASH_HASH("baz");
#endif
+#if defined(Q_MOC_RUN) || __cplusplus > 202002L
+/* Check that nested inline namespaces are at least not causing moc to break.
+ Check it even outside of C++20 mode as moc gets passed the wrong __cplusplus version
+ and also to increase coverage, given how few C++20 configurations exist in the CI at the time
+ of writing this comment.
+*/
+namespace A::inline B {}
+#endif
+
Q_DECLARE_METATYPE(const QMetaObject*);
namespace TestNonQNamespace {
diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
index 6d1e48fd88..1af016e4f0 100644
--- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
+++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
@@ -46,6 +46,7 @@
#include <private/qguiapplication_p.h>
#include <qpa/qplatformtheme.h>
#include <qpa/qplatformtheme_p.h>
+#include <qpa/qplatformintegration.h>
QT_FORWARD_DECLARE_CLASS(QDialog)
@@ -309,6 +310,10 @@ void tst_QDialog::showAsTool()
{
if (QStringList{"xcb", "offscreen"}.contains(QGuiApplication::platformName()))
QSKIP("activeWindow() is not respected by all Xcb window managers and the offscreen plugin");
+
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
DummyDialog testWidget;
testWidget.resize(200, 200);
testWidget.setWindowTitle(QTest::currentTestFunction());
diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
index 043e7e6365..aecee0500b 100644
--- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
@@ -133,6 +133,10 @@ private slots:
void dontShowCompleterOnRoot();
void nameFilterParsing_data();
void nameFilterParsing();
+#if QT_CONFIG(settings)
+ void settingsCompatibility_data();
+ void settingsCompatibility();
+#endif
private:
void cleanupSettingsFile();
@@ -473,6 +477,47 @@ void tst_QFileDialog2::task180459_lastDirectory()
delete dlg;
}
+#if QT_CONFIG(settings)
+void tst_QFileDialog2::settingsCompatibility_data()
+{
+ QTest::addColumn<QString>("qtVersion");
+ QTest::addColumn<QDataStream::Version>("dsVersion");
+ QTest::newRow("6.2.3") << "6.2.3" << QDataStream::Qt_6_0;
+ QTest::newRow("6.5") << "6.5" << QDataStream::Qt_5_0;
+ QTest::newRow("15.5.2") << "5.15.2" << QDataStream::Qt_5_15;
+ QTest::newRow("15.5.9") << "5.15.9" << QDataStream::Qt_5_15;
+}
+
+void tst_QFileDialog2::settingsCompatibility()
+{
+ static const QByteArray ba32 = QByteArrayLiteral("\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xF7\x00\x00\x00\x04\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00""d\xFF\xFF\xFF\xFF\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x01\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00""B\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00n\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\xE8\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00");
+ static const QByteArray ba64 = QByteArrayLiteral("\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xF7\x00\x00\x00\x04\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00""d\xFF\xFF\xFF\xFF\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x01\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00""B\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00n\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\xE8\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00");
+ QFETCH(QString, qtVersion);
+ QFETCH(QDataStream::Version, dsVersion);
+ // Create a header view, convert template to target format and store it in settings
+ {
+ QSettings settings(QSettings::UserScope, "QtProject");
+ settings.beginGroup("FileDialog");
+ settings.setValue("sidebarWidth", 93); // random value
+ settings.setValue("shortcuts", QStringList({settings.fileName(), "/tmp"}));
+ settings.setValue("qtVersion", qtVersion);
+ settings.setValue("treeViewHeader", dsVersion < QDataStream::Qt_6_0 ? ba32 : ba64);
+ settings.endGroup();
+ }
+ // Create a file dialog, read settings write them back
+ {
+ QFileDialog fd;
+ }
+ // Read back settings and compare byte array
+ QSettings settings(QSettings::UserScope, "QtProject");
+ settings.beginGroup("FileDialog");
+ const QByteArray savedState = settings.value("treeViewHeader").toByteArray();
+ if (QT_VERSION_MAJOR == 6 && QT_VERSION_MINOR == 2)
+ QCOMPARE(savedState, ba64);
+ else
+ QCOMPARE(savedState, ba32);
+}
+#endif
class FilterDirModel : public QSortFilterProxyModel
diff --git a/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp b/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp
index ba8a309674..fe491179d2 100644
--- a/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp
@@ -179,11 +179,11 @@ void tst_QGraphicsEffectSource::init()
QVERIFY(effect);
QVERIFY(item);
QVERIFY(effect->source());
- effect->reset();
effect->storeDeviceDependentStuff = false;
effect->doNothingInDraw = false;
- item->reset();
QCoreApplication::processEvents(); // Process all queued paint events
+ effect->reset();
+ item->reset();
}
void tst_QGraphicsEffectSource::graphicsItem()
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
index ae94c9bda4..1988a9cca7 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -829,6 +829,9 @@ void tst_QGraphicsProxyWidget::focusProxy_QTBUG_51856()
}
};
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QGraphicsScene scene;
QGraphicsView view(&scene);
SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
@@ -1346,6 +1349,9 @@ static QList<QRect> rects(const QRegion &region)
void tst_QGraphicsProxyWidget::scrollUpdate()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
ScrollWidget *widget = new ScrollWidget;
QGraphicsScene scene;
@@ -3088,6 +3094,9 @@ void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget_data()
void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QFETCH(bool, bypass);
std::unique_ptr<QWidget> widgetGuard(new QWidget);
@@ -3301,6 +3310,9 @@ public:
void tst_QGraphicsProxyWidget::inputMethod()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QGraphicsScene scene;
// check that the proxy is initialized with the correct input method sensitivity
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index 8e44912d37..817677dfc5 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -3548,6 +3548,9 @@ void tst_QGraphicsView::embeddedViewsWithFocus()
void focusOutEvent(QFocusEvent *) override { --focusCount; }
};
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QGraphicsScene innerScene;
FocusWidget *innerWidget = new FocusWidget;
innerScene.addWidget(innerWidget);
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
index ba0e4b223c..782cb1b2f5 100644
--- a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -42,6 +42,8 @@
#include <qstylefactory.h>
#include <qscreen.h>
#include <qsignalspy.h>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
typedef QList<QGraphicsItem *> QGraphicsItemList;
@@ -169,8 +171,16 @@ private slots:
void QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems();
void QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems();
void QTBUG_45867_send_itemChildAddedChange_to_parent();
+
+private:
+ static bool hasWindowActivation();
};
+bool tst_QGraphicsWidget::hasWindowActivation()
+{
+ return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation));
+}
+
// Subclass that exposes the protected functions.
class SubQGraphicsWidget : public QGraphicsWidget {
public:
@@ -1074,7 +1084,10 @@ void tst_QGraphicsWidget::initStyleOption()
QGraphicsView view(&scene);
view.resize(300, 300);
view.show();
- QVERIFY(QTest::qWaitForWindowActive(&view));
+ if (hasWindowActivation())
+ QVERIFY(QTest::qWaitForWindowActive(&view));
+ else
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
view.setAlignment(Qt::AlignTop | Qt::AlignLeft);
SubQGraphicsWidget *widget = new SubQGraphicsWidget;
@@ -1088,10 +1101,12 @@ void tst_QGraphicsWidget::initStyleOption()
QFETCH(bool, enabled);
widget->setEnabled(enabled);
QFETCH(bool, focus);
- if (focus) {
- widget->setFlag(QGraphicsItem::ItemIsFocusable, true);
- widget->setFocus();
- QVERIFY(widget->hasFocus());
+ if (hasWindowActivation()) {
+ if (focus) {
+ widget->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ widget->setFocus();
+ QVERIFY(widget->hasFocus());
+ }
}
QFETCH(bool, underMouse);
if (underMouse) {
@@ -1110,8 +1125,10 @@ void tst_QGraphicsWidget::initStyleOption()
bool isEnabled = option.state & QStyle::State_Enabled;
QCOMPARE(isEnabled, enabled);
- bool hasFocus = option.state & QStyle::State_HasFocus;
- QCOMPARE(hasFocus, focus);
+ if (hasWindowActivation()) {
+ bool hasFocus = option.state & QStyle::State_HasFocus;
+ QCOMPARE(hasFocus, focus);
+ }
bool isUnderMouse = option.state & QStyle::State_MouseOver;
QCOMPARE(isUnderMouse, underMouse);
// if (layoutDirection != Qt::LeftToRight)
@@ -1738,6 +1755,9 @@ void tst_QGraphicsWidget::verifyFocusChain()
void tst_QGraphicsWidget::updateFocusChainWhenChildDie()
{
+ if (!hasWindowActivation())
+ QSKIP("Window activation is not supported");
+
const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
QGraphicsScene scene;
QGraphicsView view(&scene);
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
index ec37a53263..47f8ab4be8 100644
--- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
+++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
@@ -3103,6 +3103,9 @@ void tst_QAbstractItemView::mouseSelection()
*/
void tst_QAbstractItemView::scrollerSmoothScroll()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QListWidget view;
view.setAutoScroll(true);
view.setVerticalScrollMode(QListView::ScrollPerPixel);
@@ -3172,6 +3175,9 @@ void tst_QAbstractItemView::inputMethodOpensEditor_data()
void tst_QAbstractItemView::inputMethodOpensEditor()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QTableWidget tableWidget(50, 50);
tableWidget.setEditTriggers(QAbstractItemView::AnyKeyPressed);
for (int r = 0; r < 50; ++r) {
diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
index 025cebb15f..2574a89112 100644
--- a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
+++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
@@ -437,6 +437,9 @@ void tst_QAction::disableShortcutInMenuAction_data()
void tst_QAction::disableShortcutInMenuAction()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QFETCH(QByteArray, property);
QMainWindow mw;
diff --git a/tests/auto/widgets/kernel/qapplication/BLACKLIST b/tests/auto/widgets/kernel/qapplication/BLACKLIST
index 364a2abe4f..7f4dd88261 100644
--- a/tests/auto/widgets/kernel/qapplication/BLACKLIST
+++ b/tests/auto/widgets/kernel/qapplication/BLACKLIST
@@ -1,6 +1,7 @@
[sendEventsOnProcessEvents]
ubuntu-20.04
ubuntu-22.04
+rhel-9.0
[touchEventPropagation]
# QTBUG-66745
opensuse-leap
diff --git a/tests/auto/widgets/kernel/qapplication/CMakeLists.txt b/tests/auto/widgets/kernel/qapplication/CMakeLists.txt
index 3bb7e31691..ab87a66a8b 100644
--- a/tests/auto/widgets/kernel/qapplication/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qapplication/CMakeLists.txt
@@ -3,3 +3,8 @@
add_subdirectory(desktopsettingsaware)
add_subdirectory(modal)
add_subdirectory(test)
+
+add_dependencies(tst_qapplication
+ desktopsettingsaware_helper
+ modal_helper
+)
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
index d5f107a5fa..ee7475ae37 100644
--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -1602,6 +1602,9 @@ void tst_QApplication::activateDeactivateEvent()
int argc = 0;
QApplication app(argc, nullptr);
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
Window w1;
Window w2;
diff --git a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
index 2cf2462fd5..cd57c90f29 100644
--- a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
+++ b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
@@ -235,6 +235,9 @@ void tst_QGridLayout::badDistributionBug()
void tst_QGridLayout::setMinAndMaxSize()
{
+ if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
+ QSKIP("This test crashes on Wayland, see also QTBUG-107184");
+
QWidget widget;
setFrameless(&widget);
QGridLayout layout(&widget);
diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST
index 24387635b4..7bd4c0a304 100644
--- a/tests/auto/widgets/kernel/qwidget/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST
@@ -3,11 +3,6 @@
ubuntu-16.04
[restoreVersion1Geometry]
ubuntu-16.04
-[focusProxyAndInputMethods]
-rhel-7.6
-centos
-opensuse-leap
-ubuntu
[raise]
opensuse-leap
# QTBUG-68175
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index e36f6334c9..67a671ed41 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -189,6 +189,7 @@ private slots:
void reverseTabOrder();
void tabOrderWithProxy();
void tabOrderWithProxyDisabled();
+ void tabOrderWithProxyOutOfOrder();
void tabOrderWithCompoundWidgets();
void tabOrderWithCompoundWidgetsNoFocusPolicy();
void tabOrderNoChange();
@@ -387,7 +388,6 @@ private slots:
void openModal_taskQTBUG_5804();
void focusProxy();
- void focusProxyAndInputMethods();
#ifdef QT_BUILD_INTERNAL
void scrollWithoutBackingStore();
#endif
@@ -1848,8 +1848,11 @@ public:
setObjectName(name);
lineEdit1 = new QLineEdit;
+ lineEdit1->setObjectName(name + "/lineEdit1");
lineEdit2 = new QLineEdit;
+ lineEdit2->setObjectName(name + "/lineEdit2");
lineEdit3 = new QLineEdit;
+ lineEdit3->setObjectName(name + "/lineEdit3");
lineEdit3->setEnabled(false);
QHBoxLayout* hbox = new QHBoxLayout(this);
@@ -2095,6 +2098,24 @@ void tst_QWidget::tabOrderWithProxyDisabled()
qPrintable(QApplication::focusWidget()->objectName()));
}
+//#define DEBUG_FOCUS_CHAIN
+static void dumpFocusChain(QWidget *start, bool bForward, const char *desc = nullptr)
+{
+#ifdef DEBUG_FOCUS_CHAIN
+ qDebug() << "Dump focus chain, start:" << start << "isForward:" << bForward << desc;
+ QWidget *cur = start;
+ do {
+ qDebug() << "-" << cur;
+ auto widgetPrivate = static_cast<QWidgetPrivate *>(qt_widget_private(cur));
+ cur = bForward ? widgetPrivate->focus_next : widgetPrivate->focus_prev;
+ } while (cur != start);
+#else
+ Q_UNUSED(start);
+ Q_UNUSED(bForward);
+ Q_UNUSED(desc);
+#endif
+}
+
void tst_QWidget::tabOrderWithCompoundWidgets()
{
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
@@ -2198,22 +2219,65 @@ static QList<QWidget *> getFocusChain(QWidget *start, bool bForward)
return ret;
}
-//#define DEBUG_FOCUS_CHAIN
-static void dumpFocusChain(QWidget *start, bool bForward, const char *desc = nullptr)
+void tst_QWidget::tabOrderWithProxyOutOfOrder()
{
-#ifdef DEBUG_FOCUS_CHAIN
- qDebug() << "Dump focus chain, start:" << start << "isForward:" << bForward << desc;
- QWidget *cur = start;
- do {
- qDebug() << cur;
- auto widgetPrivate = static_cast<QWidgetPrivate *>(qt_widget_private(cur));
- cur = bForward ? widgetPrivate->focus_next : widgetPrivate->focus_prev;
- } while (cur != start);
-#else
- Q_UNUSED(start);
- Q_UNUSED(bForward);
- Q_UNUSED(desc);
-#endif
+ Container container;
+ container.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
+
+ // important to create the widgets with parent so that they are
+ // added to the focus chain already now, and with the buttonBox
+ // before the outsideButton.
+ QWidget buttonBox(&container);
+ buttonBox.setObjectName("buttonBox");
+ QPushButton outsideButton(&container);
+ outsideButton.setObjectName("outsideButton");
+
+ container.box->addWidget(&outsideButton);
+ container.box->addWidget(&buttonBox);
+ QCOMPARE(getFocusChain(&container, true),
+ QList<QWidget*>({&container, &buttonBox, &outsideButton}));
+
+ // this now adds okButon and cancelButton to the focus chain,
+ // after the outsideButton - so the outsideButton is in between
+ // the buttonBox and the children of the buttonBox!
+ QPushButton okButton(&buttonBox);
+ okButton.setObjectName("okButton");
+ QPushButton cancelButton(&buttonBox);
+ cancelButton.setObjectName("cancelButton");
+ QCOMPARE(getFocusChain(&container, true),
+ QList<QWidget*>({&container, &buttonBox, &outsideButton, &okButton, &cancelButton}));
+
+ // by setting the okButton as the focusProxy, the outsideButton becomes
+ // unreachable when navigating the focus chain as the buttonBox is in front
+ // of, and proxies to the okButton behind the outsideButton. setFocusProxy
+ // must fix that by moving the buttonBox in front of the first sibling of
+ // the proxy.
+ buttonBox.setFocusProxy(&okButton);
+ QCOMPARE(getFocusChain(&container, true),
+ QList<QWidget*>({&container, &outsideButton, &buttonBox, &okButton, &cancelButton}));
+
+ container.show();
+ container.activateWindow();
+ QApplication::setActiveWindow(&container);
+ if (!QTest::qWaitForWindowActive(&container))
+ QSKIP("Window failed to activate, skipping test");
+
+ QCOMPARE(QApplication::focusWidget(), &outsideButton);
+ container.tab();
+ QCOMPARE(QApplication::focusWidget(), &okButton);
+ container.tab();
+ QCOMPARE(QApplication::focusWidget(), &cancelButton);
+ container.tab();
+ QCOMPARE(QApplication::focusWidget(), &outsideButton);
+
+ container.backTab();
+ QCOMPARE(QApplication::focusWidget(), &cancelButton);
+ container.backTab();
+ QCOMPARE(QApplication::focusWidget(), &okButton);
+ container.backTab();
+ QCOMPARE(QApplication::focusWidget(), &outsideButton);
+ container.backTab();
+ QCOMPARE(QApplication::focusWidget(), &cancelButton);
}
void tst_QWidget::tabOrderWithCompoundWidgetsNoFocusPolicy()
@@ -3494,7 +3558,8 @@ void tst_QWidget::raise()
for (int i = 0; i < 5; ++i)
child2->raise();
- QTest::qWait(50);
+ QVERIFY(QTest::qWaitForWindowExposed(child2));
+ QApplication::processEvents(); // process events that could be triggered by raise();
for (UpdateWidget *child : qAsConst(allChildren)) {
int expectedPaintEvents = child == child2 ? 1 : 0;
@@ -3523,6 +3588,7 @@ void tst_QWidget::raise()
onTop->show();
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
QTRY_VERIFY(onTop->numPaintEvents > 0);
+ QApplication::processEvents(); // process remaining paint events if there's more than one
onTop->reset();
// Reset all the children.
@@ -3531,7 +3597,8 @@ void tst_QWidget::raise()
for (int i = 0; i < 5; ++i)
child3->raise();
- QTest::qWait(50);
+ QVERIFY(QTest::qWaitForWindowExposed(child3));
+ QApplication::processEvents(); // process events that could be triggered by raise();
QCOMPARE(onTop->numPaintEvents, 0);
QCOMPARE(onTop->numZOrderChangeEvents, 0);
@@ -3797,6 +3864,13 @@ void tst_QWidget::saveRestoreGeometry()
QVERIFY(QTest::qWaitForWindowExposed(&widget));
QApplication::processEvents();
+
+ /* ---------------------------------------------------------------------
+ * This test function is likely to flake when debugged with Qt Creator.
+ * (29px offset making the following QTRY_VERIFY2 fail)
+ * ---------------------------------------------------------------------
+ */
+
QTRY_VERIFY2(HighDpi::fuzzyCompare(widget.pos(), position, m_fuzz),
qPrintable(HighDpi::msgPointMismatch(widget.pos(), position)));
QCOMPARE(widget.size(), size);
@@ -5373,8 +5447,8 @@ void tst_QWidget::setWindowGeometry_data()
void tst_QWidget::setWindowGeometry()
{
- if (m_platform == QStringLiteral("xcb"))
- QSKIP("X11: Skip this test due to Window manager positioning issues.");
+ if (m_platform == QStringLiteral("xcb") || m_platform.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
+ QSKIP("X11/Wayland: Skip this test due to Window manager positioning issues.");
QFETCH(Rects, rects);
QFETCH(int, windowFlags);
@@ -7296,6 +7370,9 @@ void tst_QWidget::renderInvisible()
if (m_platform == QStringLiteral("xcb"))
QSKIP("QTBUG-26424");
+ if (m_platform.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
+ QSKIP("Wayland: Skip this test, see also QTBUG-107157");
+
QScopedPointer<QCalendarWidget> calendar(new QCalendarWidget);
calendar->move(m_availableTopLeft + QPoint(100, 100));
calendar->setWindowTitle(QLatin1String(QTest::currentTestFunction()));
@@ -9909,6 +9986,9 @@ void tst_QWidget::enterLeaveOnWindowShowHide_data()
*/
void tst_QWidget::enterLeaveOnWindowShowHide()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QFETCH(Qt::WindowType, windowType);
class Widget : public QWidget
{
@@ -10683,34 +10763,6 @@ void tst_QWidget::focusProxy()
QCOMPARE(container2->focusOutCount, 1);
}
-void tst_QWidget::focusProxyAndInputMethods()
-{
- if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
- QSKIP("Window activation is not supported.");
- QScopedPointer<QWidget> toplevel(new QWidget(nullptr, Qt::X11BypassWindowManagerHint));
- toplevel->setWindowTitle(QLatin1String(QTest::currentTestFunction()));
- toplevel->resize(200, 200);
- toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
-
- QWidget *child = new QWidget(toplevel.data());
- child->setFocusProxy(toplevel.data());
- child->setAttribute(Qt::WA_InputMethodEnabled, true);
-
- toplevel->setFocusPolicy(Qt::WheelFocus);
- child->setFocusPolicy(Qt::WheelFocus);
-
- QVERIFY(!child->hasFocus());
- QVERIFY(!toplevel->hasFocus());
-
- toplevel->show();
- QVERIFY(QTest::qWaitForWindowExposed(toplevel.data()));
- QApplication::setActiveWindow(toplevel.data());
- QVERIFY(QTest::qWaitForWindowActive(toplevel.data()));
- QVERIFY(toplevel->hasFocus());
- QVERIFY(child->hasFocus());
- QCOMPARE(qApp->focusObject(), toplevel.data());
-}
-
#ifdef QT_BUILD_INTERNAL
class scrollWidgetWBS : public QWidget
{
@@ -11198,6 +11250,9 @@ public:
void tst_QWidget::touchEventSynthesizedMouseEvent()
{
+ if (m_platform.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
+ QSKIP("This test failed on Wayland. See also QTBUG-107157.");
+
{
// Simple case, we ignore the touch events, we get mouse events instead
TouchMouseWidget widget;
@@ -12450,6 +12505,9 @@ void tst_QWidget::setParentChangesFocus()
void tst_QWidget::activateWhileModalHidden()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QDialog dialog;
dialog.setWindowModality(Qt::ApplicationModal);
dialog.show();
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
index f4a6380caa..498bd5c268 100644
--- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -1475,6 +1475,9 @@ void tst_QWidget_window::mouseMoveWithPopup_data()
void tst_QWidget_window::mouseMoveWithPopup()
{
+ if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
+ QSKIP("Wayland: Skip this test, see also QTBUG-107154");
+
QFETCH(Qt::WindowType, windowType);
class Window : public QWidget
@@ -1652,6 +1655,9 @@ void tst_QWidget_window::mouseMoveWithPopup()
void tst_QWidget_window::resetFocusObjectOnDestruction()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
+
QSignalSpy focusObjectChangedSpy(qApp, &QGuiApplication::focusObjectChanged);
// single top level widget that has focus
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
index f355ea6e2c..0585d03983 100644
--- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
+++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
@@ -2350,11 +2350,19 @@ void tst_QStyleSheetStyle::placeholderColor()
QLineEdit le2;
le2.setEnabled(false);
le1.ensurePolished();
- QCOMPARE(le1.palette().placeholderText(), red);
+ QColor phColor = le1.palette().placeholderText().color();
+ QCOMPARE(phColor.rgb(), red.rgb());
+ QVERIFY(phColor.alpha() < red.alpha());
+
le2.ensurePolished();
- QCOMPARE(le2.palette().placeholderText(), red);
+ phColor = le2.palette().placeholderText().color();
+ QCOMPARE(phColor.rgb(), red.rgb());
+ QVERIFY(phColor.alpha() < red.alpha());
+
le2.setEnabled(true);
- QCOMPARE(le2.palette().placeholderText(), red);
+ phColor = le2.palette().placeholderText().color();
+ QCOMPARE(phColor.rgb(), red.rgb());
+ QVERIFY(phColor.alpha() < red.alpha());
}
void tst_QStyleSheetStyle::enumPropertySelector_data()
diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
index 3dad8968fb..575847db91 100644
--- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
+++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
@@ -1250,21 +1250,33 @@ void tst_QDockWidget::unplugAndResize(QMainWindow* mainWindow, QDockWidget* dw,
return;
}
+ // Remember size for comparison with unplugged object
+#ifdef Q_OS_LINUX
+ const int pluggedWidth = dw->width();
+ const int pluggedHeight = dw->height();
+#endif
+
// unplug and resize a dock Widget
qCDebug(lcTestDockWidget) << "*** unplug and resize" << dw->objectName();
QPoint pos1 = dw->mapToGlobal(dw->rect().center());
pos1.rx() += mx;
pos1.ry() += my;
moveDockWidget(dw, pos1, dw->mapToGlobal(dw->rect().center()));
- //QTest::mousePress(dw, Qt::LeftButton, Qt::KeyboardModifiers(), dw->mapFromGlobal(pos1));
QTRY_VERIFY(dw->isFloating());
+ // Unplugged object's size may differ max. by 2x frame size
+#ifdef Q_OS_LINUX
+ const int xMargin = 2 * dw->frameSize().width();
+ const int yMargin = 2 * dw->frameSize().height();
+ QVERIFY(dw->height() - pluggedHeight <= xMargin);
+ QVERIFY(dw->width() - pluggedWidth <= yMargin);
+#endif
+
qCDebug(lcTestDockWidget) << "Resizing" << dw->objectName() << "to" << size;
dw->setFixedSize(size);
QTest::qWait(waitingTime);
qCDebug(lcTestDockWidget) << "Move" << dw->objectName() << "to its home" << dw->mapFromGlobal(home);
dw->move(home);
- //moveDockWidget(dw, home);
}
bool tst_QDockWidget::checkFloatingTabs(QMainWindow* mainWindow, QPointer<QDockWidgetGroupWindow> &ftabs, const QList<QDockWidget*> &dwList) const
@@ -1330,6 +1342,8 @@ void tst_QDockWidget::xcbMessageHandler(QtMsgType type, const QMessageLogContext
// test floating tabs and item_tree consistency
void tst_QDockWidget::floatingTabs()
{
+ if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
+ QSKIP("Test skipped on Wayland.");
#ifdef Q_OS_WIN
QSKIP("Test skipped on Windows platforms");
#endif // Q_OS_WIN
diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
index 4942c52b95..e9aa9205c6 100644
--- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
+++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
@@ -635,7 +635,7 @@ void tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible()
// Switch to the QOpenGLWidget.
stack.setCurrentIndex(1);
- QTRY_COMPARE(clearWidget->m_paintCalled, true);
+ QTRY_VERIFY(clearWidget->m_paintCalled);
// Resize the tested region to be half size in the middle, because some OSes make the widget
// have rounded corners (e.g. OSX), and the grabbed window pixmap will not coincide perfectly
@@ -743,10 +743,10 @@ void tst_QOpenGLWidget::paintWhileHidden()
// on-screen at the point when update() is called.
w->setVisible(false);
- w->m_paintCalled = 0;
+ w->m_paintCalled = false;
w->update();
w->setVisible(true);
- QTRY_VERIFY(w->m_paintCalled > 0);
+ QTRY_VERIFY(w->m_paintCalled);
}
class StaticTextPainterWidget : public QOpenGLWidget
diff --git a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp
index 9438ea5322..37a80ee281 100644
--- a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp
+++ b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp
@@ -933,55 +933,56 @@ void tst_QSplitter::rubberBandNotInSplitter()
void tst_QSplitter::task187373_addAbstractScrollAreas_data()
{
- QTest::addColumn<QString>("className");
+ QTest::addColumn<QByteArray>("className");
QTest::addColumn<bool>("addInConstructor");
QTest::addColumn<bool>("addOutsideConstructor");
- QStringList classNames;
- classNames << QLatin1String("QGraphicsView");
- classNames << QLatin1String("QMdiArea");
- classNames << QLatin1String("QScrollArea");
- classNames << QLatin1String("QTextEdit");
- classNames << QLatin1String("QTreeView");
-
- foreach (QString className, classNames) {
- QTest::newRow(qPrintable(className + QLatin1String(" 1"))) << className << false << true;
- QTest::newRow(qPrintable(className + QLatin1String(" 2"))) << className << true << false;
- QTest::newRow(qPrintable(className + QLatin1String(" 3"))) << className << true << true;
+ QList<QByteArray> classNames{
+ "QGraphicsView",
+ "QMdiArea",
+ "QScrollArea",
+ "QTextEdit",
+ "QTreeView"
+ };
+
+ for (const auto &className : qAsConst(classNames)) {
+ QTest::newRow(qPrintable(className + " 1")) << className << false << true;
+ QTest::newRow(qPrintable(className + " 2")) << className << true << false;
+ QTest::newRow(qPrintable(className + " 3")) << className << true << true;
}
}
static QAbstractScrollArea *task187373_createScrollArea(
- QSplitter *splitter, const QString &className, bool addInConstructor)
+ QSplitter *splitter, const QByteArray &className, bool addInConstructor)
{
- if (className == QLatin1String("QGraphicsView"))
+ if (className == "QGraphicsView")
return new QGraphicsView(addInConstructor ? splitter : 0);
- if (className == QLatin1String("QMdiArea"))
+ if (className == "QMdiArea")
return new QMdiArea(addInConstructor ? splitter : 0);
- if (className == QLatin1String("QScrollArea"))
+ if (className == "QScrollArea")
return new QScrollArea(addInConstructor ? splitter : 0);
- if (className == QLatin1String("QTextEdit"))
+ if (className == "QTextEdit")
return new QTextEdit(addInConstructor ? splitter : 0);
- if (className == QLatin1String("QTreeView"))
+ if (className == "QTreeView")
return new QTreeView(addInConstructor ? splitter : 0);
return 0;
}
void tst_QSplitter::task187373_addAbstractScrollAreas()
{
- QFETCH(QString, className);
+ QFETCH(QByteArray, className);
QFETCH(bool, addInConstructor);
QFETCH(bool, addOutsideConstructor);
QVERIFY(addInConstructor || addOutsideConstructor);
- QSplitter *splitter = new QSplitter;
- splitter->show();
- QVERIFY(splitter->isVisible());
+ QSplitter splitter;
+ splitter.show();
+ QVERIFY(splitter.isVisible());
- QAbstractScrollArea *w = task187373_createScrollArea(splitter, className, addInConstructor);
+ QAbstractScrollArea *w = task187373_createScrollArea(&splitter, className, addInConstructor);
QVERIFY(w);
if (addOutsideConstructor)
- splitter->addWidget(w);
+ splitter.addWidget(w);
QTRY_VERIFY(w->isVisible());
QVERIFY(!w->isHidden());
diff --git a/tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss b/tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss
new file mode 100644
index 0000000000..7d54a74fe5
--- /dev/null
+++ b/tests/baseline/stylesheet/qss/qtreeview/styledSelection.qss
@@ -0,0 +1,10 @@
+QTreeView {
+ alternate-background-color: yellow;
+ show-decoration-selected: 1;
+}
+QTreeView::item:selected:active {
+ background: qlineargradient(x1:0, y1:0 x2: 0, y2: 1, stop: 0 #fea1f1 stop: 1 #567dbc)
+}
+QTreeView::branch {
+ border: 2px
+}
diff --git a/tests/benchmarks/CMakeLists.txt b/tests/benchmarks/CMakeLists.txt
index a59ba35e50..b6f45aab4f 100644
--- a/tests/benchmarks/CMakeLists.txt
+++ b/tests/benchmarks/CMakeLists.txt
@@ -1,7 +1,6 @@
# Generated from benchmarks.pro.
add_subdirectory(corelib)
-add_subdirectory(sql)
if(TARGET Qt::DBus)
add_subdirectory(dbus)
endif()
@@ -11,6 +10,9 @@ endif()
if(TARGET Qt::Network)
add_subdirectory(network)
endif()
+if(TARGET Qt::Sql)
+ add_subdirectory(sql)
+endif()
if(TARGET Qt::Test)
add_subdirectory(testlib)
endif()
diff --git a/tests/benchmarks/corelib/text/qlocale/main.cpp b/tests/benchmarks/corelib/text/qlocale/main.cpp
index 887053ae4a..b9a6ec0a19 100644
--- a/tests/benchmarks/corelib/text/qlocale/main.cpp
+++ b/tests/benchmarks/corelib/text/qlocale/main.cpp
@@ -28,6 +28,7 @@
#include <QLocale>
#include <QTest>
+#include <limits>
class tst_QLocale : public QObject
{
@@ -54,6 +55,12 @@ private Q_SLOTS:
void toUpper_QLocale_2();
void toUpper_QString();
void number_QString();
+ void toLongLong_data();
+ void toLongLong();
+ void toULongLong_data();
+ void toULongLong();
+ void toDouble_data();
+ void toDouble();
};
static QString data()
@@ -392,6 +399,270 @@ void tst_QLocale::number_QString()
}
}
+template <typename Integer>
+void toWholeCommon_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QString>("locale");
+ QTest::addColumn<bool>("good");
+ QTest::addColumn<Integer>("expected");
+
+ QTest::newRow("C: empty")
+ << QStringLiteral("") << QStringLiteral("C") << false << Integer(0ull);
+ QTest::newRow("C: 0") << QStringLiteral("0") << QStringLiteral("C") << true << Integer(0ull);
+ QTest::newRow("C: 1234")
+ << QStringLiteral("1234") << QStringLiteral("C") << true << Integer(1234ull);
+ // C locale omits grouping, but doesn't reject it.
+ QTest::newRow("C: 1,234")
+ << QStringLiteral("1,234") << QStringLiteral("C") << true << Integer(1234ull);
+ QTest::newRow("C: 123456789")
+ << QStringLiteral("123456789") << QStringLiteral("C") << true << Integer(123456789ull);
+ QTest::newRow("C: 123,456,789")
+ << QStringLiteral("123,456,789")
+ << QStringLiteral("C") << true << Integer(123456789ull);
+
+ QTest::newRow("en: empty")
+ << QStringLiteral("") << QStringLiteral("en") << false << Integer(0ull);
+ QTest::newRow("en: 0") << QStringLiteral("0") << QStringLiteral("en") << true << Integer(0ull);
+ QTest::newRow("en: 1234")
+ << QStringLiteral("1234") << QStringLiteral("en") << true << Integer(1234ull);
+ QTest::newRow("en: 1,234")
+ << QStringLiteral("1,234") << QStringLiteral("en") << true << Integer(1234ull);
+ QTest::newRow("en: 123,456,789")
+ << QStringLiteral("123,456,789")
+ << QStringLiteral("en") << true << Integer(123456789ull);
+ QTest::newRow("en: 123456789")
+ << QStringLiteral("123456789")
+ << QStringLiteral("en") << true << Integer(123456789ull);
+
+ QTest::newRow("de: empty")
+ << QStringLiteral("") << QStringLiteral("de") << false << Integer(0ull);
+ QTest::newRow("de: 0") << QStringLiteral("0") << QStringLiteral("de") << true << Integer(0ull);
+ QTest::newRow("de: 1234")
+ << QStringLiteral("1234") << QStringLiteral("de") << true << Integer(1234ull);
+ QTest::newRow("de: 1.234")
+ << QStringLiteral("1.234") << QStringLiteral("de") << true << Integer(1234ull);
+ QTest::newRow("de: 123.456.789")
+ << QStringLiteral("123.456.789")
+ << QStringLiteral("de") << true << Integer(123456789ull);
+ QTest::newRow("de: 123456789")
+ << QStringLiteral("123456789") << QStringLiteral("de") << true << Integer(123456789ull);
+
+ // Locales with non-single-character signs:
+ QTest::newRow("ar_EG: +403") // Arabic, Egypt
+ << QStringLiteral("\u061c+\u0664\u0660\u0663")
+ << QStringLiteral("ar_EG") << true << Integer(403ull);
+ QTest::newRow("ar_EG: !403") // Only first character of the sign
+ << QStringLiteral("\u061c\u0664\u0660\u0663")
+ << QStringLiteral("ar_EG") << false << Integer(0ull);
+ QTest::newRow("fa_IR: +403") // Farsi, Iran
+ << QStringLiteral("\u200e+\u06f4\u06f0\u06f3")
+ << QStringLiteral("fa_IR") << true << Integer(403ull);
+ QTest::newRow("fa_IR: !403") // Only first character of sign
+ << QStringLiteral("\u200e\u06f4\u06f0\u06f3")
+ << QStringLiteral("fa_IR") << false << Integer(0ull);
+}
+
+void tst_QLocale::toLongLong_data()
+{
+ toWholeCommon_data<qlonglong>();
+
+ QTest::newRow("C: -1234") << QStringLiteral("-1234") << QStringLiteral("C") << true << -1234ll;
+ QTest::newRow("C: -123456789")
+ << QStringLiteral("-123456789") << QStringLiteral("C") << true << -123456789ll;
+ QTest::newRow("C: qlonglong-max")
+ << QStringLiteral("9223372036854775807") << QStringLiteral("C") << true
+ << std::numeric_limits<qlonglong>::max();
+ QTest::newRow("C: qlonglong-min")
+ << QStringLiteral("-9223372036854775808") << QStringLiteral("C") << true
+ << std::numeric_limits<qlonglong>::min();
+
+ // Locales with multi-character signs:
+ QTest::newRow("ar_EG: -403") // Arabic, Egypt
+ << QStringLiteral("\u061c-\u0664\u0660\u0663")
+ << QStringLiteral("ar_EG") << true << -403ll;
+ QTest::newRow("fa_IR: -403") // Farsi, Iran
+ << QStringLiteral("\u200e\u2212\u06f4\u06f0\u06f3")
+ << QStringLiteral("fa_IR") << true << -403ll;
+}
+
+void tst_QLocale::toLongLong()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, locale);
+ QFETCH(bool, good);
+ QFETCH(qlonglong, expected);
+
+ const QLocale loc(locale);
+ qlonglong actual = expected;
+ bool ok = false;
+ QBENCHMARK {
+ actual = loc.toLongLong(text, &ok);
+ }
+ QEXPECT_FAIL("ar_EG: +403", "Code wrongly assumes single character, QTBUG-107801", Abort);
+ QEXPECT_FAIL("ar_EG: -403", "Code wrongly assumes single character, QTBUG-107801", Abort);
+ QEXPECT_FAIL("fa_IR: +403", "Code wrongly assumes single character, QTBUG-107801", Abort);
+ QEXPECT_FAIL("fa_IR: -403", "Code wrongly assumes single character, QTBUG-107801", Abort);
+ QCOMPARE(ok, good);
+ QCOMPARE(actual, expected);
+}
+
+void tst_QLocale::toULongLong_data()
+{
+ toWholeCommon_data<qulonglong>();
+
+ QTest::newRow("C: qlonglong-max + 1")
+ << QStringLiteral("9223372036854775808") << QStringLiteral("C") << true
+ << (qulonglong(std::numeric_limits<qlonglong>::max()) + 1);
+ QTest::newRow("C: qulonglong-max")
+ << QStringLiteral("18446744073709551615") << QStringLiteral("C") << true
+ << std::numeric_limits<qulonglong>::max();
+}
+
+void tst_QLocale::toULongLong()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, locale);
+ QFETCH(bool, good);
+ QFETCH(qulonglong, expected);
+
+ const QLocale loc(locale);
+ qulonglong actual = expected;
+ bool ok = false;
+ QBENCHMARK {
+ actual = loc.toULongLong(text, &ok);
+ }
+ QEXPECT_FAIL("ar_EG: +403", "Code wrongly assumes single character, QTBUG-107801", Abort);
+ QEXPECT_FAIL("fa_IR: +403", "Code wrongly assumes single character, QTBUG-107801", Abort);
+ QCOMPARE(ok, good);
+ QCOMPARE(actual, expected);
+}
+
+
+void tst_QLocale::toDouble_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QString>("locale");
+ QTest::addColumn<bool>("good");
+ QTest::addColumn<double>("expected");
+
+ QTest::newRow("C: empty") << QStringLiteral("") << QStringLiteral("C") << false << 0.0;
+ QTest::newRow("C: 0") << QStringLiteral("0") << QStringLiteral("C") << true << 0.0;
+ QTest::newRow("C: 0.12340")
+ << QStringLiteral("0.12340") << QStringLiteral("C") << true << 0.12340;
+ QTest::newRow("C: -0.12340")
+ << QStringLiteral("-0.12340") << QStringLiteral("C") << true << -0.12340;
+ QTest::newRow("C: &minus;0.12340")
+ << QStringLiteral("\u2212" "0.12340") << QStringLiteral("C") << true << -0.12340;
+ QTest::newRow("C: 1.0e-4") << QStringLiteral("1.0e-4") << QStringLiteral("C") << true << 1.0e-4;
+ QTest::newRow("C: 1.0e&minus;4")
+ << QStringLiteral("1.0e\u2212" "4") << QStringLiteral("C") << true << 1.0e-4;
+ QTest::newRow("C: 1.0e+4") << QStringLiteral("1.0e+4") << QStringLiteral("C") << true << 1.0e+4;
+ QTest::newRow("C: 10.e+3") << QStringLiteral("10.e+3") << QStringLiteral("C") << true << 1.0e+4;
+ QTest::newRow("C: 10e+3.")
+ << QStringLiteral("10e+3.") << QStringLiteral("C") << false << 0.0; // exp...dot
+ QTest::newRow("C: 1e4") << QStringLiteral("1e4") << QStringLiteral("C") << true << 1.0e+4;
+
+ // NaN and infinity:
+ QTest::newRow("C: nan") << QStringLiteral("nan") << QStringLiteral("C") << true << qQNaN();
+ QTest::newRow("C: NaN") << QStringLiteral("NaN") << QStringLiteral("C") << true << qQNaN();
+ QTest::newRow("C: -nan") << QStringLiteral("-nan") << QStringLiteral("C") << false << 0.0;
+ QTest::newRow("C: +nan") << QStringLiteral("+nan") << QStringLiteral("C") << false << 0.0;
+ QTest::newRow("C: inf") << QStringLiteral("inf") << QStringLiteral("C") << true << qInf();
+ QTest::newRow("C: Inf") << QStringLiteral("Inf") << QStringLiteral("C") << true << qInf();
+ QTest::newRow("C: +inf") << QStringLiteral("+inf") << QStringLiteral("C") << true << qInf();
+ QTest::newRow("C: -inf") << QStringLiteral("-inf") << QStringLiteral("C") << true << -qInf();
+
+ // Wantonly long-form representations, with trailing and leading zeros:
+ QTest::newRow("C: 1e-64 long-form")
+ << (QStringLiteral("0.") + QString(63, u'0') + u'1' + QString(962, u'0'))
+ << QStringLiteral("C") << true << 1e-64;
+ QTest::newRow("C: 1e+64 long-form")
+ << (QString(961, u'0') + u'1' + QString(64, u'0') + QStringLiteral(".0"))
+ << QStringLiteral("C") << true << 1e+64;
+ QTest::newRow("C: long-form 1 via e+64")
+ << (QStringLiteral("0.") + QString(63, u'0') + u'1' + QString(962, u'0')
+ + QStringLiteral("e+64"))
+ << QStringLiteral("C") << true << 1.0;
+ QTest::newRow("C: long-form 1 via e-64")
+ << (QString(961, u'0') + u'1' + QString(64, u'0') + QStringLiteral(".0e-64"))
+ << QStringLiteral("C") << true << 1.0;
+ QTest::newRow("C: 12345678.9")
+ << QStringLiteral("12345678.9") << QStringLiteral("C") << true << 12345678.9;
+
+ // With and without grouping, en vs de for flipped separators:
+ QTest::newRow("en: 12345678.9")
+ << QStringLiteral("12345678.9") << QStringLiteral("en") << true << 12345678.9;
+ QTest::newRow("en: 12,345,678.9")
+ << QStringLiteral("12,345,678.9") << QStringLiteral("en") << true << 12'345'678.9;
+ QTest::newRow("de: 12345678,9")
+ << QStringLiteral("12345678,9") << QStringLiteral("de") << true << 12345678.9;
+ QTest::newRow("de: 12.345.678,9")
+ << QStringLiteral("12.345.678,9") << QStringLiteral("de") << true << 12'345'678.9;
+
+ // NaN and infinity are locale-independent (for now - QTBUG-95460)
+ QTest::newRow("cy: nan") << QStringLiteral("nan") << QStringLiteral("cy") << true << qQNaN();
+ QTest::newRow("cy: NaN") << QStringLiteral("NaN") << QStringLiteral("cy") << true << qQNaN();
+ QTest::newRow("cy: -nan") << QStringLiteral("-nan") << QStringLiteral("cy") << false << 0.0;
+ QTest::newRow("cy: +nan") << QStringLiteral("+nan") << QStringLiteral("cy") << false << 0.0;
+ QTest::newRow("cy: inf") << QStringLiteral("inf") << QStringLiteral("cy") << true << qInf();
+ QTest::newRow("cy: Inf") << QStringLiteral("Inf") << QStringLiteral("cy") << true << qInf();
+ QTest::newRow("cy: +inf") << QStringLiteral("+inf") << QStringLiteral("cy") << true << qInf();
+ QTest::newRow("cy: -inf") << QStringLiteral("-inf") << QStringLiteral("cy") << true << -qInf();
+ // Samples ready for QTBUG-95460:
+ QTest::newRow("en: &infin;")
+ << QStringLiteral("\u221e") << QStringLiteral("en") << true << qInf();
+ QTest::newRow("ga: Nuimh")
+ << QStringLiteral("Nuimh") << QStringLiteral("ga") << true << qQNaN();
+
+ // Locales with multi-character exponents:
+ QTest::newRow("sv_SE: 4e-3") // Swedish, Sweden
+ << QStringLiteral("4\u00d7" "10^\u2212" "03")
+ << QStringLiteral("sv_SE") << true << 4e-3;
+ QTest::newRow("sv_SE: 4x-3") // Only first character of exponent
+ << QStringLiteral("4\u00d7\u2212" "03") << QStringLiteral("sv_SE") << false << 0.0;
+ QTest::newRow("se_NO: 4e-3") // Northern Sami, Norway
+ << QStringLiteral("4\u00b7" "10^\u2212" "03")
+ << QStringLiteral("se_NO") << true << 4e-3;
+ QTest::newRow("se_NO: 4x-3") // Only first character of exponent
+ << QStringLiteral("4\u00b7\u2212" "03")
+ << QStringLiteral("se_NO") << false << 0.0;
+ QTest::newRow("ar_EG: 4e-3") // Arabic, Egypt
+ << QStringLiteral("\u0664\u0627\u0633\u061c-\u0660\u0663")
+ << QStringLiteral("ar_EG") << true << 4e-3;
+ QTest::newRow("ar_EG: 4x-3") // Only first character of exponent
+ << QStringLiteral("\u0664\u0627\u061c-\u0660\u0663")
+ << QStringLiteral("ar_EG") << false << 0.0;
+ QTest::newRow("ar_EG: 4e!3") // Only first character of sign
+ << QStringLiteral("\u0664\u0627\u0633\u061c\u0660\u0663")
+ << QStringLiteral("ar_EG") << false << 0.0;
+ QTest::newRow("ar_EG: 4x!3") // Only first character of sign and exponent
+ << QStringLiteral("\u0664\u0627\u061c\u0660\u0663")
+ << QStringLiteral("ar_EG") << false << 0.0;
+}
+
+void tst_QLocale::toDouble()
+{
+ QFETCH(QString, text);
+ QFETCH(QString, locale);
+ QFETCH(bool, good);
+ QFETCH(double, expected);
+
+ const QLocale loc(locale);
+ double actual = expected;
+ bool ok = false;
+ QBENCHMARK {
+ actual = loc.toDouble(text, &ok);
+ }
+ QEXPECT_FAIL("sv_SE: 4e-3", "Code wrongly assumes single character, QTBUG-107801", Abort);
+ QEXPECT_FAIL("se_NO: 4e-3", "Code wrongly assumes single character, QTBUG-107801", Abort);
+ QEXPECT_FAIL("ar_EG: 4e-3", "Code wrongly assumes single character, QTBUG-107801", Abort);
+ QEXPECT_FAIL("en: &infin;", "Localized infinity support missing: QTBUG-95460", Abort);
+ QEXPECT_FAIL("ga: Nuimh", "Localized NaN support missing: QTBUG-95460", Abort);
+ QCOMPARE(ok, good);
+ QCOMPARE(actual, expected);
+}
+
QTEST_MAIN(tst_QLocale)
#include "main.moc"
diff --git a/tests/benchmarks/corelib/text/qstring/main.cpp b/tests/benchmarks/corelib/text/qstring/main.cpp
index 0214931b71..ff47ee1a2a 100644
--- a/tests/benchmarks/corelib/text/qstring/main.cpp
+++ b/tests/benchmarks/corelib/text/qstring/main.cpp
@@ -28,6 +28,7 @@
#include <QStringList>
#include <QFile>
#include <QTest>
+#include <limits>
class tst_QString: public QObject
{
@@ -48,6 +49,14 @@ private slots:
void toCaseFolded_data();
void toCaseFolded();
+ // Parsing:
+ void toLongLong_data();
+ void toLongLong();
+ void toULongLong_data();
+ void toULongLong();
+ void toDouble_data();
+ void toDouble();
+
private:
void section_data_impl(bool includeRegExOnly = true);
template <typename RX> void section_impl();
@@ -187,6 +196,155 @@ void tst_QString::toCaseFolded()
}
}
+template <typename Integer>
+void toWholeCommon_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("base");
+ QTest::addColumn<bool>("good");
+ QTest::addColumn<Integer>("expected");
+
+ QTest::newRow("empty") << QStringLiteral("") << 10 << false << Integer(0ull);
+ QTest::newRow("0") << QStringLiteral("0") << 10 << true << Integer(0ull);
+ QTest::newRow("1234") << QStringLiteral("1234") << 10 << true << Integer(1234ull);
+ QTest::newRow("1,234") << QStringLiteral("1,234") << 10 << false << Integer(0ull);
+ QTest::newRow("123456789")
+ << QStringLiteral("123456789") << 10 << true << Integer(123456789ull);
+ QTest::newRow("bad1dea, base 16")
+ << QStringLiteral("bad1dea") << 16 << true << Integer(0xBAD1DEAull);
+ QTest::newRow("bad1dea, base 10") << QStringLiteral("bad1dea") << 10 << false << Integer(0ull);
+ QTest::newRow("42, base 13") << QStringLiteral("42") << 13 << true << Integer(6ull * 9ull);
+ QTest::newRow("242, base 8") << QStringLiteral("242") << 8 << true << Integer(0242ull);
+ QTest::newRow("495, base 8") << QStringLiteral("495") << 8 << false << Integer(0ull);
+ QTest::newRow("101101, base 2")
+ << QStringLiteral("101101") << 2 << true << Integer(0b101101ull);
+ QTest::newRow("ad, base 30") << QStringLiteral("ad") << 30 << true << Integer(313ull);
+}
+
+void tst_QString::toLongLong_data()
+{
+ toWholeCommon_data<qlonglong>();
+
+ QTest::newRow("-1234") << QStringLiteral("-1234") << 10 << true << -1234ll;
+ QTest::newRow("-123456789") << QStringLiteral("-123456789") << 10 << true << -123456789ll;
+ QTest::newRow("-bad1dea, base 16") << QStringLiteral("-bad1dea") << 16 << true << -0xBAD1DEAll;
+ QTest::newRow("-242, base 8") << QStringLiteral("-242") << 8 << true << -0242ll;
+ QTest::newRow("-101101, base 2") << QStringLiteral("-101101") << 2 << true << -0b101101ll;
+ QTest::newRow("-ad, base 30") << QStringLiteral("-ad") << 30 << true << -313ll;
+
+ QTest::newRow("qlonglong-max")
+ << QStringLiteral("9223372036854775807") << 10 << true
+ << std::numeric_limits<qlonglong>::max();
+ QTest::newRow("qlonglong-min")
+ << QStringLiteral("-9223372036854775808") << 10 << true
+ << std::numeric_limits<qlonglong>::min();
+ QTest::newRow("qlonglong-max, base 2")
+ << QString(63, u'1') << 2 << true << std::numeric_limits<qlonglong>::max();
+ QTest::newRow("qlonglong-min, base 2")
+ << (QStringLiteral("-1") + QString(63, u'0')) << 2 << true
+ << std::numeric_limits<qlonglong>::min();
+ QTest::newRow("qlonglong-max, base 16")
+ << (QChar(u'7') + QString(15, u'f')) << 16 << true
+ << std::numeric_limits<qlonglong>::max();
+ QTest::newRow("qlonglong-min, base 16")
+ << (QStringLiteral("-8") + QString(15, u'0')) << 16 << true
+ << std::numeric_limits<qlonglong>::min();
+}
+
+void tst_QString::toLongLong()
+{
+ QFETCH(QString, text);
+ QFETCH(int, base);
+ QFETCH(bool, good);
+ QFETCH(qlonglong, expected);
+
+ qlonglong actual = expected;
+ bool ok = false;
+ QBENCHMARK {
+ actual = text.toLongLong(&ok, base);
+ }
+ QCOMPARE(ok, good);
+ QCOMPARE(actual, expected);
+}
+
+void tst_QString::toULongLong_data()
+{
+ toWholeCommon_data<qulonglong>();
+
+ QTest::newRow("qlonglong-max + 1")
+ << QStringLiteral("9223372036854775808") << 10 << true
+ << (qulonglong(std::numeric_limits<qlonglong>::max()) + 1);
+ QTest::newRow("qulonglong-max")
+ << QStringLiteral("18446744073709551615") << 10 << true
+ << std::numeric_limits<qulonglong>::max();
+ QTest::newRow("qulonglong-max, base 2")
+ << QString(64, u'1') << 2 << true << std::numeric_limits<qulonglong>::max();
+ QTest::newRow("qulonglong-max, base 16")
+ << QString(16, u'f') << 16 << true << std::numeric_limits<qulonglong>::max();
+}
+
+void tst_QString::toULongLong()
+{
+ QFETCH(QString, text);
+ QFETCH(int, base);
+ QFETCH(bool, good);
+ QFETCH(qulonglong, expected);
+
+ qulonglong actual = expected;
+ bool ok = false;
+ QBENCHMARK {
+ actual = text.toULongLong(&ok, base);
+ }
+ QCOMPARE(ok, good);
+ QCOMPARE(actual, expected);
+}
+
+void tst_QString::toDouble_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<bool>("good");
+ QTest::addColumn<double>("expected");
+
+ QTest::newRow("empty") << QStringLiteral("") << false << 0.0;
+ QTest::newRow("0") << QStringLiteral("0") << true << 0.0;
+ QTest::newRow("0.12340") << QStringLiteral("0.12340") << true << 0.12340;
+ QTest::newRow("-0.12340") << QStringLiteral("-0.12340") << true << -0.12340;
+ QTest::newRow("epsilon")
+ << QStringLiteral("2.220446049e-16") << true << std::numeric_limits<double>::epsilon();
+ QTest::newRow("1.0e-4") << QStringLiteral("1.0e-4") << true << 1.0e-4;
+ QTest::newRow("1.0e+4") << QStringLiteral("1.0e+4") << true << 1.0e+4;
+ QTest::newRow("10.e+3") << QStringLiteral("10.e+3") << true << 1.0e+4;
+ QTest::newRow("10e+3.") << QStringLiteral("10e+3.") << false << 0.0;
+ QTest::newRow("1e4") << QStringLiteral("1e4") << true << 1.0e+4;
+ QTest::newRow("1.0e-8") << QStringLiteral("1.0e-8") << true << 1.0e-8;
+ QTest::newRow("1.0e+8") << QStringLiteral("1.0e+8") << true << 1.0e+8;
+
+ // NaN and infinity:
+ QTest::newRow("nan") << QStringLiteral("nan") << true << qQNaN();
+ QTest::newRow("NaN") << QStringLiteral("NaN") << true << qQNaN();
+ QTest::newRow("-nan") << QStringLiteral("-nan") << false << 0.0;
+ QTest::newRow("+nan") << QStringLiteral("+nan") << false << 0.0;
+ QTest::newRow("inf") << QStringLiteral("inf") << true << qInf();
+ QTest::newRow("Inf") << QStringLiteral("Inf") << true << qInf();
+ QTest::newRow("+inf") << QStringLiteral("+inf") << true << qInf();
+ QTest::newRow("-inf") << QStringLiteral("-inf") << true << -qInf();
+}
+
+void tst_QString::toDouble()
+{
+ QFETCH(QString, text);
+ QFETCH(bool, good);
+ QFETCH(double, expected);
+
+ double actual = expected;
+ bool ok = false;
+ QBENCHMARK {
+ actual = text.toDouble(&ok);
+ }
+ QCOMPARE(ok, good);
+ QCOMPARE(actual, expected);
+}
+
QTEST_APPLESS_MAIN(tst_QString)
#include "main.moc"
diff --git a/tests/benchmarks/corelib/tools/qhash/main.h b/tests/benchmarks/corelib/tools/qhash/main.h
index eca4b61d58..9ba0bcce34 100644
--- a/tests/benchmarks/corelib/tools/qhash/main.h
+++ b/tests/benchmarks/corelib/tools/qhash/main.h
@@ -35,7 +35,7 @@ struct Qt4String : QString
};
QT_BEGIN_NAMESPACE
-uint qHash(const Qt4String &);
+size_t qHash(const Qt4String &);
QT_END_NAMESPACE
struct Qt50String : QString
@@ -45,7 +45,7 @@ struct Qt50String : QString
};
QT_BEGIN_NAMESPACE
-uint qHash(const Qt50String &, uint seed = 0);
+size_t qHash(const Qt50String &, size_t seed = 0);
QT_END_NAMESPACE
@@ -56,6 +56,6 @@ struct JavaString : QString
};
QT_BEGIN_NAMESPACE
-uint qHash(const JavaString &);
+size_t qHash(const JavaString &);
QT_END_NAMESPACE
diff --git a/tests/benchmarks/corelib/tools/qhash/outofline.cpp b/tests/benchmarks/corelib/tools/qhash/outofline.cpp
index 4e449e76b4..b23774fc07 100644
--- a/tests/benchmarks/corelib/tools/qhash/outofline.cpp
+++ b/tests/benchmarks/corelib/tools/qhash/outofline.cpp
@@ -30,9 +30,9 @@
QT_BEGIN_NAMESPACE
-uint qHash(const Qt4String &str)
+size_t qHash(const Qt4String &str)
{
- int n = str.length();
+ qsizetype n = str.length();
const QChar *p = str.unicode();
uint h = 0;
@@ -44,11 +44,11 @@ uint qHash(const Qt4String &str)
return h;
}
-uint qHash(const Qt50String &key, uint seed)
+size_t qHash(const Qt50String &key, size_t seed)
{
const QChar *p = key.unicode();
- int len = key.size();
- uint h = seed;
+ qsizetype len = key.size();
+ size_t h = seed;
for (int i = 0; i < len; ++i)
h = 31 * h + p[i].unicode();
return h;
@@ -65,10 +65,10 @@ uint qHash(const Qt50String &key, uint seed)
// Still, we can avoid writing the multiplication as "(h << 5) - h"
// -- the compiler will turn it into a shift and an addition anyway
// (for instance, gcc 4.4 does that even at -O0).
-uint qHash(const JavaString &str)
+size_t qHash(const JavaString &str)
{
const unsigned short *p = (unsigned short *)str.constData();
- const int len = str.size();
+ const qsizetype len = str.size();
uint h = 0;
diff --git a/util/cmake/pro2cmake.py b/util/cmake/pro2cmake.py
index 73686cb105..5b12e075d4 100755
--- a/util/cmake/pro2cmake.py
+++ b/util/cmake/pro2cmake.py
@@ -4423,7 +4423,7 @@ def create_top_level_cmake_conf():
conf_file_name = ".cmake.conf"
try:
with open(conf_file_name, "x") as file:
- file.write('set(QT_REPO_MODULE_VERSION "6.2.6")\n')
+ file.write('set(QT_REPO_MODULE_VERSION "6.2.7")\n')
except FileExistsError:
pass